Asynchronous functions?

Hey guys,

Im building a little app that utilises the speech synthesizer on OSX.

When I use the system command to call the osascript it hangs the app until the process is finished. Does anyone know how to do this asynchronously? I’m thinking I need to start a new thread for this process?

Any help would be greatly appreciated!

Here’s the function I need to call async:

  
  
void testApp::textToSpeech(string wordstoSpeak, string voice){  
	  
	_wordstoSpeak = wordstoSpeak;  
	_voice = voice;  
  
	_speak = "osascript -e 'say \" " + _wordstoSpeak + "\" using \"" + _voice + "\" '";  
	const char * speakChar = _speak.c_str();  
	    
	/* Perl script way  
	_speak = "perl " + _pathDirectory + "/data/perl/tts.pl BLA";  
	const char * speakChar = _speak.c_str();  
 */  
	  
	system(speakChar);  
}  
  

and there’s the rest:

  
  
#include "testApp.h"  
#include <sstream>  
  
//--------------------------------------------------------------  
void testApp::setup(){  
	  
	  
	// Get the path the correct apple way - returns path to inside .app directory  
	CFURLRef mainRef = CFBundleCopyBundleURL(CFBundleGetMainBundle());  
	CFStringRef macPath = CFURLCopyFileSystemPath(mainRef, kCFURLPOSIXPathStyle);  
	const char *pathPtr = CFStringGetCStringPtr(macPath, CFStringGetSystemEncoding());  
	string pathDirectory (pathPtr);  
	  
	size_t found;  
	found=pathDirectory.find_last_of("/\\");  
	pathDirectory = pathDirectory.substr(0,found+1);  
	_pathDirectory = pathDirectory;  
	  
	// Default SoundPlayer vars  
	play = false;  
	  
	// Load Lyrics  
	_xmlLoader.load(pathDirectory+"/data/xml/portal-still-alive.xml");  
	  
	// Load track  
	soundplayer.setVolume(100);  
	soundplayer.loadSound(pathDirectory+"/data/sound/portal/portal.mp3", "false");  
  
	if(soundplayer.bLoadedOk){  
		  
		this->playSong();  
		  
	} else{  
		  
		printf("\nUnable to load music track");  
		  
	}  
	  
	// Add event listener to return track VO  
	  
}  
  
//--------------------------------------------------------------  
void testApp::update(){  
  
	// Play the track  
	if(play) {  
		  
		ofSoundUpdate();  
  
		//printf("\n track pos: %f", soundplayer.getPosition());  
		musicPosition = soundplayer.getPosition();  
	}  
	  
}  
  
//--------------------------------------------------------------  
void testApp::draw(){  
	  
	char tempStr[255];  
	ofSetColor(255, 0, 0);  
	  
	sprintf(tempStr, "track pos: %f", soundplayer.getPosition());  
	ofDrawBitmapString(tempStr, 100, 100);  
  
}  
  
//--------------------------------------------------------------  
void testApp::playSong(){  
	soundplayer.play();  
	play = true;  
}  
  
void testApp::textToSpeech(string wordstoSpeak, string voice){  
	  
	_wordstoSpeak = wordstoSpeak;  
	_voice = voice;  
  
	_speak = "osascript -e 'say \" " + _wordstoSpeak + "\" using \"" + _voice + "\" '";  
	const char * speakChar = _speak.c_str();  
	    
	/* Perl script way  
	_speak = "perl " + _pathDirectory + "/data/perl/tts.pl BLA";  
	const char * speakChar = _speak.c_str();  
 */  
	  
	system(speakChar);  
}  
  
//--------------------------------------------------------------  
void testApp::keyPressed(int key){  
  
	if (key == 's') {  
		this->textToSpeech("Hi", "Cellos");  
	}  
	  
	// Play pause toggle  
	if(key == 'p'){  
		if (!soundplayer.bPaused) {  
			soundplayer.setPaused(true);  
		} else {  
			soundplayer.setPaused(false);  
		}  
	}  
  
}  
  

1 Like

Hi. yes, you probably have to start a thread. look at the ofxThread library.

I think something like this might work:

  
class Blah: public ofxThread{  
    void threadedFunction(){  
		//do the system call  
               stopThread();  
     }  
}  

alternatively I think there might be a different call than system() that won’t wait for the called process to finish. Not sure about that one though…

just add a & at the end of the command that will start it in the background. like:

  
system("command blah &");  

Thanks for the reply guys.

Arturo, that works like a treat!