The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
/* $Header: /cvsroot/macperl/perl/macos/ext/Mac/Speech/Speech.xs,v 1.6 2009/09/17 06:57:18 pudge Exp $
 *
 *    Copyright (c) 1996 Matthias Neeracher
 *
 *    You may distribute under the terms of the Perl Artistic License,
 *    as specified in the README file.
 *
 * $Log: Speech.xs,v $
 * Revision 1.6  2009/09/17 06:57:18  pudge
 * Bunch of fixes and changes for release
 *   Add notes for 64-bit perl
 *
 *   Bump all the version numbers
 *
 *   Fix a bunch of tests (nothing major, just make them work better)
 *
 *   Fix sound-env-var checking code for tests (no more sound tests
 *   unless you ask for them with MAC_CARBON_SOUND, which was in the
 *   last version, but the logic was broken)
 *
 *   Make CFStringRef typemap better
 *
 *   Remove high-bit characters from source files
 *
 *   Add new system version gestalt constants
 *
 *   Fix leaks in Mac::Processes and Mac::Speech
 *
 * Revision 1.5  2006/07/07 06:40:26  pudge
 * Add SpeechToFile
 *
 * Revision 1.4  2002/12/19 17:45:53  pudge
 * GetVoiceDesciption and NewSpeechChannel use default voice if no parameter given
 * %Voice hash returns default voice if key is false (undef, '', 0)
 * Added accessor methods for VoiceDescription and VoiceSpec structures
 *
 * Revision 1.3  2002/11/13 02:04:53  pudge
 * Aieeeeee!  Big ol' Carbon update.
 *
 * Revision 1.2  2000/09/09 22:18:28  neeri
 * Dynamic libraries compile under 5.6
 *
 * Revision 1.1  2000/08/14 03:39:33  neeri
 * Checked into Sourceforge
 *
 * Revision 1.4  1998/04/07 01:03:15  neeri
 * MacPerl 5.2.0r4b1
 *
 * Revision 1.3  1997/11/18 00:53:21  neeri
 * MacPerl 5.1.5
 *
 * Revision 1.2  1997/08/08 16:39:30  neeri
 * MacPerl 5.1.4b1 + time() fix
 *
 * Revision 1.1  1997/04/07 20:50:45  neeri
 * Synchronized with MacPerl 5.1.4a1
 *
 */

#define MAC_CONTEXT

#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#ifndef MACOS_TRADITIONAL
#include "../Carbon.h"
#endif
#include <Types.h>
#include <Memory.h>
#include <Speech.h>

#ifndef __CFM68K__
#include <FixMath.h>
#else
#define fixed1				((Fixed) 0x00010000L)
#define fract1				((Fract) 0x40000000L)
#define positiveInfinity	((long)  0x7FFFFFFFL)
#define negativeInfinity	((long)  0x80000000L)

extern pascal long double Frac2X(Fract x) = 0xA845;
extern pascal long double Fix2X(Fixed x) = 0xA843;
extern pascal Fixed X2Fix(long double x) = 0xA844;
extern pascal Fract X2Frac(long double x) = 0xA846;
#endif

#ifdef __CFM68K__

#undef FOURWORDINLINE
#define FOURWORDINLINE(w1,w2,w3,w4)  = {w1,w2,w3,w4}

extern pascal NumVersion SpeechManagerVersion(void)
 FOURWORDINLINE(0x203C, 0x0000, 0x000C, 0xA800);

extern pascal OSErr MakeVoiceSpec(OSType creator, OSType id, VoiceSpec *voice)
 FOURWORDINLINE(0x203C, 0x0604, 0x000C, 0xA800);

extern pascal OSErr CountVoices(short *numVoices)
 FOURWORDINLINE(0x203C, 0x0108, 0x000C, 0xA800);

extern pascal OSErr GetIndVoice(short index, VoiceSpec *voice)
 FOURWORDINLINE(0x203C, 0x030C, 0x000C, 0xA800);

extern pascal OSErr GetVoiceDescription(const VoiceSpec *voice, VoiceDescription *info, long infoLength)
 FOURWORDINLINE(0x203C, 0x0610, 0x000C, 0xA800);

extern pascal OSErr GetVoiceInfo(const VoiceSpec *voice, OSType selector, void *voiceInfo)
 FOURWORDINLINE(0x203C, 0x0614, 0x000C, 0xA800);

extern pascal OSErr NewSpeechChannel(VoiceSpec *voice, SpeechChannel *chan)
 FOURWORDINLINE(0x203C, 0x0418, 0x000C, 0xA800);

extern pascal OSErr DisposeSpeechChannel(SpeechChannel chan)
 FOURWORDINLINE(0x203C, 0x021C, 0x000C, 0xA800);

extern pascal OSErr SpeakString(ConstStr255Param s)
 FOURWORDINLINE(0x203C, 0x0220, 0x000C, 0xA800);

extern pascal OSErr SpeakText(SpeechChannel chan, const void * textBuf, unsigned long textBytes)
 FOURWORDINLINE(0x203C, 0x0624, 0x000C, 0xA800);

extern pascal OSErr SpeakBuffer(SpeechChannel chan, const void * textBuf, unsigned long textBytes, long controlFlags)
 FOURWORDINLINE(0x203C, 0x0828, 0x000C, 0xA800);

extern pascal OSErr StopSpeech(SpeechChannel chan)
 FOURWORDINLINE(0x203C, 0x022C, 0x000C, 0xA800);

extern pascal OSErr StopSpeechAt(SpeechChannel chan, long whereToStop)
 FOURWORDINLINE(0x203C, 0x0430, 0x000C, 0xA800);

extern pascal OSErr PauseSpeechAt(SpeechChannel chan, long whereToPause)
 FOURWORDINLINE(0x203C, 0x0434, 0x000C, 0xA800);

extern pascal OSErr ContinueSpeech(SpeechChannel chan)
 FOURWORDINLINE(0x203C, 0x0238, 0x000C, 0xA800);

extern pascal short SpeechBusy(void)
 FOURWORDINLINE(0x203C, 0x003C, 0x000C, 0xA800);

extern pascal short SpeechBusySystemWide(void)
 FOURWORDINLINE(0x203C, 0x0040, 0x000C, 0xA800);

extern pascal OSErr SetSpeechRate(SpeechChannel chan, Fixed rate)
 FOURWORDINLINE(0x203C, 0x0444, 0x000C, 0xA800);

extern pascal OSErr GetSpeechRate(SpeechChannel chan, Fixed *rate)
 FOURWORDINLINE(0x203C, 0x0448, 0x000C, 0xA800);

extern pascal OSErr SetSpeechPitch(SpeechChannel chan, Fixed pitch)
 FOURWORDINLINE(0x203C, 0x044C, 0x000C, 0xA800);

extern pascal OSErr GetSpeechPitch(SpeechChannel chan, Fixed *pitch)
 FOURWORDINLINE(0x203C, 0x0450, 0x000C, 0xA800);

extern pascal OSErr SetSpeechInfo(SpeechChannel chan, OSType selector, const void *speechInfo)
 FOURWORDINLINE(0x203C, 0x0654, 0x000C, 0xA800);

extern pascal OSErr GetSpeechInfo(SpeechChannel chan, OSType selector, void *speechInfo)
 FOURWORDINLINE(0x203C, 0x0658, 0x000C, 0xA800);

extern pascal OSErr TextToPhonemes(SpeechChannel chan, const void * textBuf, unsigned long textBytes, Handle phonemeBuf, long *phonemeBytes)
 FOURWORDINLINE(0x203C, 0x0A5C, 0x000C, 0xA800);

extern pascal OSErr UseDictionary(SpeechChannel chan, Handle dictionary)
 FOURWORDINLINE(0x203C, 0x0460, 0x000C, 0xA800);

#endif

#define SpeechFail(error)	if (gMacPerl_OSErr = (error)) { XSRETURN_UNDEF; } else 0

MODULE = Mac::Speech	PACKAGE = Mac::Speech

=head2 Types

=over 4

=item VoiceDescription

Voice Description Record.

	long        length              size of structure--set by application
	VoiceSpec   voice               voice synthesizer and ID info
	long        version             version number of voice
	Str63       name                name of voice
	Str255      comment             text information about voice
	short       gender              neuter, male, or female
	short       age                 approximate age in years
	short       script              script code of text voice can process
	short       language            language code of voice output
	short       region              region code of voice output

=cut
STRUCT VoiceDescription
	long        length;              /*size of structure--set by application*/
	VoiceSpec   voice;               /*voice synthesizer and ID info*/
	long        version;             /*version number of voice*/
	Str63       name;                /*name of voice*/
	Str255      comment;             /*text information about voice*/
	short       gender;              /*neuter, male, or female*/
	short       age;                 /*approximate age in years*/
	short       script;              /*script code of text voice can process*/
	short       language;            /*language code of voice output*/
	short       region;              /*region code of voice output*/

=item VoiceSpec

Voice Specification Record.

	OSType      creator             ID of required synthesizer
	OSType      id                  ID of voice on the synthesizer


=cut
STRUCT VoiceSpec
	OSType      creator;             /*ID of required synthesizer*/
	OSType      id;                  /*ID of voice on the synthesizer*/

=back

=head2 Functions

=over 4

=item SpeechManagerVersion 

=cut
NumVersion 
SpeechManagerVersion()


=item CountVoices 

=cut
short
CountVoices()
	CODE:
	SpeechFail(CountVoices(&RETVAL));
	OUTPUT:
	RETVAL


=item GetIndVoice INDEX 

=cut
VoiceSpec
GetIndVoice(index)
	short index
	CODE:
	SpeechFail(GetIndVoice(index, &RETVAL));
	OUTPUT:
	RETVAL
	

=item GetVoiceDescription VOICE 

=cut
VoiceDescription
GetVoiceDescription(voice=NO_INIT)
	VoiceSpec &voice
	CODE:
	if (items >= 1)
		SpeechFail(GetVoiceDescription(&voice, &RETVAL, sizeof(RETVAL)));
	else
		SpeechFail(GetVoiceDescription(NULL, &RETVAL, sizeof(RETVAL)));
	OUTPUT:
	RETVAL


=item NewSpeechChannel VOICE 

=cut
SpeechChannel
NewSpeechChannel(voice=NO_INIT)
	VoiceSpec &voice
	CODE:
	if (items >= 1)
		SpeechFail(NewSpeechChannel(&voice, &RETVAL));
	else
		SpeechFail(NewSpeechChannel(NULL, &RETVAL));
	OUTPUT:
	RETVAL


=item DisposeSpeechChannel CHAN 

=cut
MacOSRet
DisposeSpeechChannel(chan)
	SpeechChannel chan


=item SpeakString S 

=cut
MacOSRet
SpeakString(s)
	Str255 s;


=item SpeakText CHAN, TEXT 

=cut
MacOSRet
SpeakText(chan, text)
	SpeechChannel 	chan
	SV *			text
	CODE:
	{
		void *	textPtr;
		STRLEN	textSize;
		
		textPtr = 	SvPV(text, textSize);
		RETVAL	= 	SpeakText(chan, textPtr, textSize);
	}
	OUTPUT:
	RETVAL


=item SpeakBuffer CHAN, TEXT, CONTROLFLAGS 

=cut
MacOSRet
SpeakBuffer(chan, text, controlFlags)
	SpeechChannel 	chan
	SV *			text
	long			controlFlags
	CODE:
	{
		void *	textPtr;
		STRLEN	textSize;
		
		textPtr = 	SvPV(text, textSize);
		RETVAL	= 	SpeakBuffer(chan, textPtr, textSize, controlFlags);
	}
	OUTPUT:
	RETVAL


=item StopSpeech CHAN 

=cut
MacOSRet
StopSpeech(chan)
	SpeechChannel chan


=item StopSpeechAt CHAN, WHERETOSTOP 

=cut
MacOSRet
StopSpeechAt(chan, whereToStop)
	SpeechChannel 	chan
	long		  	whereToStop


=item PauseSpeechAt CHAN, WHERETOPAUSE 

=cut
MacOSRet
PauseSpeechAt(chan, whereToPause)
	SpeechChannel 	chan
	long		  	whereToPause


=item ContinueSpeech CHAN 

=cut
MacOSRet
ContinueSpeech(chan)
	SpeechChannel chan


=item SpeechBusy 

=cut
int
SpeechBusy()


=item SpeechBusySystemWide 

=cut
int
SpeechBusySystemWide()


=item SetSpeechRate CHAN, RATE 

=cut
MacOSRet
SetSpeechRate(chan, rate)
	SpeechChannel 	chan
	Fixed 			rate


=item GetSpeechRate CHAN 

=cut
Fixed
GetSpeechRate(chan)
	SpeechChannel	chan
	CODE:
	SpeechFail(GetSpeechRate(chan, &RETVAL));
	OUTPUT:
	RETVAL


=item SetSpeechPitch CHAN, PITCH 

=cut
MacOSRet
SetSpeechPitch(chan, pitch)
	SpeechChannel 	chan
	Fixed 			pitch


=item GetSpeechPitch CHAN 

=cut
Fixed
GetSpeechPitch(chan)
	SpeechChannel	chan
	CODE:
	SpeechFail(GetSpeechPitch(chan, &RETVAL));
	OUTPUT:
	RETVAL

=item TextToPhonemes CHAN, TEXT

=cut
SV *
TextToPhonemes(chan, text)
	SpeechChannel 	chan
	SV *			text
	CODE:
	{
		void *	textPtr;
		STRLEN	textSize;
		long	phonSize;
		Handle	h;
		
		textPtr = 	SvPV(text, textSize);
		h = NewHandle(textSize*3+1024);
		SpeechFail(TextToPhonemes(chan, textPtr, textSize, h, &phonSize));
		HLock(h);
		RETVAL	= 	newSVpv(*h, phonSize);
		DisposeHandle(h);
	}
	OUTPUT:
	RETVAL

=item SpeechToFile CHAN, PATH

Set speech channel CHAN to output to file PATH.

=cut
MacOSRet
SpeechToFile(chan, path)
	SpeechChannel	chan
	CFStringRef	path
	CODE:
	{
		CFURLRef cfurlr = CFURLCreateWithFileSystemPath(
			kCFAllocatorDefault, path,
#ifdef MACOS_TRADITIONAL
			kCFURLHFSPathStyle,
#else
			kCFURLPOSIXPathStyle,
#endif
			false
		);
		RETVAL = SetSpeechInfo(chan, soOutputToFileWithCFURL, cfurlr);
		CFRelease(path);
		CFRelease(cfurlr);
	}
	OUTPUT:
	RETVAL


=back

=cut