speechd-discuss
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 2/2] add pico


From: Andrei Kholodnyi
Subject: [PATCH 2/2] add pico
Date: Tue, 28 Sep 2010 00:22:52 +0200

Speech Dispatcher output module for SVOX pico synth
---
 config/modules/Makefile.am |    5 +
 config/modules/pico.conf   |    2 +
 config/speechd.conf        |    1 +
 configure.ac               |   15 +
 src/modules/Makefile.am    |    8 +
 src/modules/pico.c         |  609 ++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 640 insertions(+), 0 deletions(-)
 create mode 100644 config/modules/pico.conf
 create mode 100644 src/modules/pico.c

diff --git a/config/modules/Makefile.am b/config/modules/Makefile.am
index 50e853a..8632db8 100644
--- a/config/modules/Makefile.am
+++ b/config/modules/Makefile.am
@@ -11,3 +11,8 @@ dist_moduleconforig_DATA = cicero.conf espeak.conf 
festival.conf flite.conf \
                            epos-generic.conf espeak-generic.conf \
                            espeak-mbrola-generic.conf llia_phon-generic.conf \
                            swift-generic.conf
+
+if pico_support
+dist_moduleconf_DATA += pico.conf
+dist_moduleconforig_DATA += pico.conf
+endif
diff --git a/config/modules/pico.conf b/config/modules/pico.conf
new file mode 100644
index 0000000..b73e218
--- /dev/null
+++ b/config/modules/pico.conf
@@ -0,0 +1,2 @@
+#PicoLingwarePath "/usr/share/pico/lang/"
+
diff --git a/config/speechd.conf b/config/speechd.conf
index 6eec028..c4eff67 100644
--- a/config/speechd.conf
+++ b/config/speechd.conf
@@ -210,6 +210,7 @@ AddModule "espeak"       "sd_espeak"   "espeak.conf"
 AddModule "festival"     "sd_festival"  "festival.conf"
 #AddModule "flite"        "sd_flite"     "flite.conf"
 #AddModule "ivona"      "sd_ivona"    "ivona.conf"
+AddModule "pico"        "sd_pico"     "pico.conf"
 #AddModule "espeak-generic" "sd_generic" "espeak-generic.conf"
 #AddModule "espeak-mbrola-generic" "sd_generic" "espeak-mbrola-generic.conf"
 #AddModule "swift-generic" "sd_generic" "swift-generic.conf"
diff --git a/configure.ac b/configure.ac
index 814d944..296205c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -225,6 +225,21 @@ AC_ARG_WITH(ivona, AS_HELP_STRING(--with-ivona, Compile 
with ivona support),
 
 AM_CONDITIONAL(ivona_support, test $ivona_ok = "true")
 
+AC_ARG_WITH([pico],
+       [AS_HELP_STRING([--with-pico], [include pico SVOX support])],
+       [],
+       [with_pico=check])
+
+# check for pico SVOX support
+AS_IF([test $with_pico != "no"],
+       [AC_CHECK_LIB([ttspico],
+               [pico_initialize],
+               [with_pico=yes],
+               [AS_IF([test $with_pico = "yes"],
+                       [AC_MSG_FAILURE([pico SVOX is not available])])])])
+
+AM_CONDITIONAL(pico_support, test $with_pico = "yes")
+
 STATIC_AUDIO_PLUGINS_LIST=""
 SPD_AUDIO_LIBS=
 
diff --git a/src/modules/Makefile.am b/src/modules/Makefile.am
index b01b0e0..4359b3a 100644
--- a/src/modules/Makefile.am
+++ b/src/modules/Makefile.am
@@ -70,3 +70,11 @@ sd_ivona_LDADD = $(top_builddir)/src/common/libcommon.la 
-lsdaudio \
        -ldumbtts -lpthread $(SNDFILE_LIBS) $(DOTCONF_LIBS) $(GLIB_LIBS) \
        $(GTHREAD_LIBS)
 endif
+
+if pico_support
+modulebin_PROGRAMS += sd_pico
+sd_pico_SOURCES = pico.c $(common_SOURCES)
+sd_pico_LDFLAGS = $(RPATH) '$(spdlibdir)' $(lib_audio)
+sd_pico_LDADD = $(top_builddir)/src/common/libcommon.la -lsdaudio -lttspico \
+       $(DOTCONF_LIBS) $(GLIB_LIBS) $(GTHREAD_LIBS)
+endif
diff --git a/src/modules/pico.c b/src/modules/pico.c
new file mode 100644
index 0000000..32c6850
--- /dev/null
+++ b/src/modules/pico.c
@@ -0,0 +1,609 @@
+/*
+ * pico.c - Speech Dispatcher pico SVOX output module
+ *
+ * A pico SVOX output module
+ *
+ * Copyright (C) 2010 Andrei Kholodnyi <andrei.kholodnyi at gmail.com>
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this package; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <signal.h>
+#include <string.h>
+
+#include <glib.h>
+#include <semaphore.h>
+
+#include <picoapi.h>
+
+#include "spd_audio.h"
+#include <speechd_types.h>
+#include "module_utils.h"
+
+#define MODULE_NAME     "pico"
+#define MODULE_VERSION  "0.1"
+
+#define MAX_OUTBUF_SIZE                (128)
+#define PICO_MEM_SIZE                  (10000000)
+
+#define PICO_VOICE_SPEED_MIN           (20)
+#define PICO_VOICE_SPEED_MAX           (500)
+#define PICO_VOICE_SPEED_DEFAULT       (100)
+
+#define PICO_VOICE_PITCH_MIN           (50)
+#define PICO_VOICE_PITCH_MAX           (200)
+#define PICO_VOICE_PITCH_DEFAULT       (100)
+
+#define PICO_VOICE_VOLUME_MIN          (0)
+#define PICO_VOICE_VOLUME_MAX          (500)
+#define PICO_VOICE_VOLUME_DEFAULT      (100)
+
+static pico_System     picoSystem;
+static pico_Resource   picoTaResource;
+static pico_Resource   picoSgResource;
+static pico_Engine     picoEngine;
+static pico_Char       *picoInp;
+
+static const char * PICO_LINGWARE_PATH = "/usr/share/pico/lang/";
+static const int PICO_SAMPLE_RATE = 16000;
+static const char * picoInternalTaLingware[] = {
+       "en-US_ta.bin",
+       "en-GB_ta.bin",
+       "de-DE_ta.bin",
+       "es-ES_ta.bin",
+       "fr-FR_ta.bin",
+       "it-IT_ta.bin" };
+static const char * picoInternalSgLingware[] = {
+       "en-US_lh0_sg.bin",
+       "en-GB_kh0_sg.bin",
+       "de-DE_gl0_sg.bin",
+       "es-ES_zl0_sg.bin",
+       "fr-FR_nk0_sg.bin",
+       "it-IT_cm0_sg.bin" };
+
+static const VoiceDescription pico_voices[] = {
+       {"samantha", "en", "en-US"},
+       {"serena", "en", "en-GB"},
+       {"sabrina", "de", "de-DE"},
+       {"isabel", "es", "es-ES"},
+       {"virginie", "fr", "fr-FR"},
+       {"silvia", "it", "it-IT"}
+};
+
+static const VoiceDescription *pico_voices_list[] = {
+       &pico_voices[0],
+       &pico_voices[1],
+       &pico_voices[2],
+       &pico_voices[3],
+       &pico_voices[4],
+       &pico_voices[5],
+       NULL
+};
+
+static GThread *pico_play_thread;
+static sem_t *pico_play_semaphore;
+
+enum states {STATE_IDLE, STATE_PLAY, STATE_PAUSE, STATE_STOP, STATE_CLOSE};
+static enum states pico_state;
+
+/* Module configuration options */
+MOD_OPTION_1_STR(PicoLingwarePath)
+
+static int pico_set_rate(signed int value)
+{
+       int speed;
+
+       if (value < 0)
+               speed = PICO_VOICE_SPEED_MIN + (value - (-100))
+               * (PICO_VOICE_SPEED_DEFAULT - PICO_VOICE_SPEED_MIN)
+               / (0 - (-100));
+       else
+               speed = PICO_VOICE_SPEED_DEFAULT + (value - 0)
+               * (PICO_VOICE_SPEED_MAX - PICO_VOICE_SPEED_DEFAULT)
+               / (100 - 0);
+
+       return speed;
+}
+
+static int pico_set_volume(signed int value)
+{
+       int volume;
+
+       if (value < 0)
+               volume = PICO_VOICE_VOLUME_MIN + (value - (-100))
+               * (PICO_VOICE_VOLUME_DEFAULT - PICO_VOICE_VOLUME_MIN)
+               / (0 - (-100));
+       else
+               volume = PICO_VOICE_VOLUME_DEFAULT + (value - 0)
+               * (PICO_VOICE_VOLUME_MAX - PICO_VOICE_VOLUME_DEFAULT)
+               / (100 - 0);
+
+       return volume;
+}
+
+static int pico_set_pitch(signed int value)
+{
+       int pitch;
+
+       if (value < 0)
+               pitch = PICO_VOICE_PITCH_MIN + (value - (-100))
+               * (PICO_VOICE_PITCH_DEFAULT - PICO_VOICE_PITCH_MIN)
+               / (0 - (-100));
+       else
+               pitch = PICO_VOICE_PITCH_DEFAULT + (value - 0)
+               * (PICO_VOICE_PITCH_MAX - PICO_VOICE_PITCH_DEFAULT)
+               / (100 - 0);
+
+       return pitch;
+}
+
+static int pico_process_tts(void)
+{
+       pico_Int16 bytes_sent, bytes_recv, text_remaining, out_data_type;
+       int ret, getstatus;
+       short outbuf[MAX_OUTBUF_SIZE];
+       pico_Retstring outMessage;
+       AudioTrack track;
+       pico_Char *buf = picoInp;
+
+       text_remaining = strlen((const char *) buf) + 1;
+
+       DBG(MODULE_NAME " Text: %s\n", picoInp);
+
+       /* synthesis loop   */
+       while (text_remaining) {
+               /* Feed the text into the engine.   */
+               if((ret = pico_putTextUtf8(picoEngine, buf, text_remaining,
+                                          &bytes_sent))) {
+                       pico_getSystemStatusMessage(picoSystem, ret, 
outMessage);
+                       DBG(MODULE_NAME
+                               "Cannot put Text (%i): %s\n", ret, outMessage);
+                       return -1;
+               }
+
+               text_remaining -= bytes_sent;
+               buf += bytes_sent;
+
+               do {
+                       /* Retrieve the samples and add them to the buffer.
+                          SVOX pico TTS sample rate is 16K */
+                       getstatus = pico_getData(picoEngine, (void *) outbuf,
+                               MAX_OUTBUF_SIZE, &bytes_recv, &out_data_type );
+                       if((getstatus != PICO_STEP_BUSY)
+                          && (getstatus != PICO_STEP_IDLE)){
+                               pico_getSystemStatusMessage(picoSystem, 
getstatus, outMessage);
+                               DBG(MODULE_NAME
+                                       "Cannot get Data (%i): %s\n", getstatus,
+                                       outMessage);
+                               return -1;
+                       }
+
+                       if (bytes_recv) {
+                               track.num_samples = bytes_recv / 2;
+                               track.samples = (short *) 
g_memdup((gconstpointer) outbuf, bytes_recv);
+                               track.num_channels = 1;
+                               track.sample_rate = PICO_SAMPLE_RATE;
+                               track.bits = 16;
+                               DBG(MODULE_NAME
+                                       ": Sending %i samples to audio.", 
track.num_samples);
+
+                               spd_audio_set_volume(module_audio_id, 85);
+                               if (spd_audio_play(module_audio_id, track,
+                                                      module_audio_id->format) 
< 0) {
+                                       DBG(MODULE_NAME
+                                               "Can't play track for unknown 
reason.");
+                                       return -1;
+                               }
+                       }
+               } while (PICO_STEP_BUSY == getstatus
+                        && g_atomic_int_get(&pico_state) == STATE_PLAY);
+
+       }
+
+       g_free(picoInp);
+       picoInp = NULL;
+       return 0;
+}
+
+/* Playback thread. */
+static gpointer
+pico_play_func(gpointer nothing)
+{
+       DBG(MODULE_NAME ": Playback thread starting");
+
+       set_speaking_thread_parameters();
+
+       while (g_atomic_int_get(&pico_state) != STATE_CLOSE) {
+
+               sem_wait(pico_play_semaphore);
+               if (g_atomic_int_get(&pico_state) != STATE_PLAY)
+                       continue;
+
+               DBG(MODULE_NAME ": Sending to TTS engine");
+               module_report_event_begin();
+
+               if (0 != pico_process_tts()) {
+                       DBG(MODULE_NAME ": ERROR in TTS");
+               }
+
+
+               if (g_atomic_int_get(&pico_state) == STATE_PLAY) {
+                       module_report_event_end();
+                       g_atomic_int_set(&pico_state, STATE_IDLE);
+               }
+
+               if (g_atomic_int_get(&pico_state) == STATE_STOP) {
+                       module_report_event_stop();
+                       g_atomic_int_set(&pico_state, STATE_IDLE);
+               }
+
+               if (g_atomic_int_get(&pico_state) == STATE_PAUSE) {
+                       module_report_event_pause();
+                       g_atomic_int_set(&pico_state, STATE_IDLE);
+               }
+
+               DBG(MODULE_NAME ": state %d", pico_state);
+
+       }
+       return 0;
+}
+
+/* Public functions */
+int module_load(void)
+{
+       INIT_SETTINGS_TABLES();
+
+       MOD_OPTION_1_STR_REG(PicoLingwarePath,PICO_LINGWARE_PATH);
+
+       module_audio_id = NULL;
+
+       return 0;
+}
+
+int pico_init_voice (int voice_index) {
+       int ret;
+       pico_Retstring outMessage;
+       pico_Char picoTaFileName[PICO_MAX_DATAPATH_NAME_SIZE + 
PICO_MAX_FILE_NAME_SIZE];
+       pico_Char picoSgFileName[PICO_MAX_DATAPATH_NAME_SIZE + 
PICO_MAX_FILE_NAME_SIZE];
+       pico_Char picoTaResourceName[PICO_MAX_RESOURCE_NAME_SIZE];
+       pico_Char picoSgResourceName[PICO_MAX_RESOURCE_NAME_SIZE];
+
+       /* Load the text analysis Lingware resource file.   */
+       strcpy((char *) picoTaFileName, PicoLingwarePath);
+       strcat((char *) picoTaFileName,
+              (const char *) picoInternalTaLingware[voice_index]);
+       if((ret = pico_loadResource(picoSystem, picoTaFileName, 
&picoTaResource))) {
+               pico_getSystemStatusMessage(picoSystem, ret, outMessage);
+               DBG(MODULE_NAME
+                       "Cannot load TA Lingware resource file (%i): %s\n", ret,
+                       outMessage);
+               return -1;
+       }
+
+       /* Load the signal generation Lingware resource file.   */
+       strcpy((char *) picoSgFileName, PicoLingwarePath);
+       strcat((char *) picoSgFileName,
+              (const char *) picoInternalSgLingware[voice_index]);
+       if((ret = pico_loadResource(picoSystem, picoSgFileName, 
&picoSgResource))) {
+               pico_getSystemStatusMessage(picoSystem, ret, outMessage);
+               DBG(MODULE_NAME
+                       "Cannot load SG Lingware resource file (%i): %s\n", ret,
+                       outMessage);
+               return -1;
+       }
+
+       /* Get the text analysis resource name.     */
+       if((ret = pico_getResourceName(picoSystem, picoTaResource,
+                                      (char *) picoTaResourceName))) {
+               pico_getSystemStatusMessage(picoSystem, ret, outMessage);
+               DBG(MODULE_NAME
+                       "Cannot get TA resource name (%i): %s\n", ret,
+                       outMessage);
+               return -1;
+       }
+
+       /* Get the signal generation resource name. */
+       if((ret = pico_getResourceName(picoSystem, picoSgResource,
+                                      (char *) picoSgResourceName))) {
+               pico_getSystemStatusMessage(picoSystem, ret, outMessage);
+               DBG(MODULE_NAME
+                       "Cannot get SG resource name (%i): %s\n", ret,
+                       outMessage);
+               return -1;
+       }
+
+       /* Create a voice definition.   */
+       if((ret = pico_createVoiceDefinition(picoSystem,
+                       (const pico_Char *) pico_voices[voice_index].name))) {
+               pico_getSystemStatusMessage(picoSystem, ret, outMessage);
+               DBG(MODULE_NAME
+                       "Cannot create voice definition (%i): %s\n", ret,
+                       outMessage);
+               return -1;
+       }
+
+       /* Add the text analysis resource to the voice. */
+       if((ret = pico_addResourceToVoiceDefinition(picoSystem,
+                       (const pico_Char *)pico_voices[voice_index].name,
+                       picoTaResourceName))) {
+               pico_getSystemStatusMessage(picoSystem, ret, outMessage);
+               DBG(MODULE_NAME
+                       "Cannot add TA resource to the voice (%i): %s\n",
+                       ret, outMessage);
+               return -1;
+       }
+
+       /* Add the signal generation resource to the voice. */
+       if((ret = pico_addResourceToVoiceDefinition(picoSystem,
+                       (const pico_Char *)pico_voices[voice_index].name,
+                       picoSgResourceName))) {
+               pico_getSystemStatusMessage(picoSystem, ret, outMessage);
+               DBG(MODULE_NAME
+                       "Cannot add SG resource to the voice (%i): %s\n",
+                       ret, outMessage);
+               return -1;
+       }
+
+       return 0;
+}
+
+int module_init(char **status_info)
+{
+       int ret, i;
+       pico_Retstring outMessage;
+        void * pmem;
+       GError *error = NULL;
+
+       if (!g_thread_supported())
+               g_thread_init(NULL);
+
+       pico_play_semaphore = module_semaphore_init();
+       if (pico_play_semaphore == NULL) {
+               *status_info = g_strdup_printf(MODULE_NAME
+                       "Failed to initialize play thread semaphore!");
+               DBG(MODULE_NAME": %s", *status_info);
+               return -1;
+       }
+
+       if ((pico_play_thread = g_thread_create((GThreadFunc)pico_play_func,
+                                               NULL, TRUE, &error)) == NULL) {
+               *status_info = g_strdup_printf(MODULE_NAME
+                       "Failed to create a play thread : %s\n",
+                       error->message );
+               DBG(MODULE_NAME": %s", *status_info);
+               g_error_free(error);
+               return -1;
+       }
+
+       pmem = g_malloc(PICO_MEM_SIZE);
+       if((ret = pico_initialize(pmem, PICO_MEM_SIZE, &picoSystem))) {
+               pico_getSystemStatusMessage(picoSystem, ret, outMessage);
+               *status_info = g_strdup_printf(MODULE_NAME
+                       ": Cannot initialize (%i): %s\n", ret, outMessage);
+               g_free(pmem);
+               return -1;
+       }
+
+       /* load resource for all language, probably need only one */
+       for (i = 0; i < sizeof(pico_voices)/sizeof(VoiceDescription); i++) {
+               if (0 != pico_init_voice(i)) {
+                       g_free(pmem);
+                       *status_info = g_strdup_printf(MODULE_NAME
+                               ": fail init voice (%s)\n", 
pico_voices[i].name);
+                       return -1;
+               }
+       }
+
+       /* Create a new Pico engine, english default */
+       if((ret = pico_newEngine(picoSystem,
+                                (const pico_Char *)pico_voices[0].name,
+                                &picoEngine))) {
+               pico_getSystemStatusMessage(picoSystem, ret, outMessage);
+               DBG(MODULE_NAME
+                       "Cannot create a new pico engine (%i): %s\n", ret,
+                       outMessage);
+               return -1;
+       }
+
+       *status_info = g_strdup(MODULE_NAME ": Initialized successfully.");
+
+       g_atomic_int_set(&pico_state, STATE_IDLE);
+       return 0;
+}
+
+int module_audio_init(char **status_info)
+{
+       return module_audio_init_spd(status_info);
+}
+
+VoiceDescription **module_list_voices(void)
+{
+       return pico_voices_list;
+}
+
+void pico_set_synthesis_voice(char *voice_name)
+{
+       int ret;
+       pico_Retstring outMessage;
+
+       /* Create a new Pico engine, english default */
+       if((ret = pico_disposeEngine(picoSystem, &picoEngine))) {
+               pico_getSystemStatusMessage(picoSystem, ret, outMessage);
+               DBG(MODULE_NAME
+                       "Cannot dispose pico engine (%i): %s\n", ret,
+                       outMessage);
+               return;
+       }
+
+       /* Create a new Pico engine, english default */
+       if((ret = pico_newEngine(picoSystem, (const pico_Char *)voice_name,
+                                &picoEngine))) {
+               pico_getSystemStatusMessage(picoSystem, ret, outMessage);
+               DBG(MODULE_NAME
+                       "Cannot create a new pico engine (%i): %s\n", ret,
+                       outMessage);
+               return;
+       }
+
+       return;
+}
+
+static void pico_set_language(char *lang)
+{
+       int i;
+
+       /* get voice name based on language */
+       for (i = 0; i < sizeof(pico_voices)/sizeof(VoiceDescription); i++) {
+               if (!strcmp(pico_voices[i].language,lang)) {
+                       pico_set_synthesis_voice(pico_voices[i].name);
+                       return;
+               }
+       }
+       return;
+}
+
+int module_speak(char * data, size_t bytes, EMessageType msgtype)
+{
+       int value;
+       static pico_Char *tmp;
+
+       if (g_atomic_int_get(&pico_state) != STATE_IDLE){
+               DBG(MODULE_NAME
+                       ": module still speaking state = %d", pico_state);
+               return 0;
+       }
+
+       /* Setting speech parameters. */
+
+       UPDATE_STRING_PARAMETER(synthesis_voice, pico_set_synthesis_voice);
+/*     UPDATE_PARAMETER(voice_type, pico_set_voice);*/
+       UPDATE_STRING_PARAMETER(language, pico_set_language);
+
+       picoInp = (pico_Char *) module_strip_ssml(data);
+
+       value = pico_set_rate(msg_settings.rate);
+       if (PICO_VOICE_SPEED_DEFAULT != value) {
+               tmp = picoInp;
+               picoInp = (pico_Char *) g_strdup_printf(
+                               "<speed level='%d'>%s</speed>", value, tmp);
+               g_free(tmp);
+       }
+
+       value = pico_set_volume(msg_settings.volume);
+       if (PICO_VOICE_VOLUME_DEFAULT != value) {
+               tmp = picoInp;
+               picoInp = (pico_Char *) g_strdup_printf(
+                               "<volume level='%d'>%s</volume>", value, tmp);
+               g_free(tmp);
+       }
+
+       value = pico_set_pitch(msg_settings.pitch);
+       if (PICO_VOICE_PITCH_DEFAULT != value) {
+               tmp = picoInp;
+               picoInp = (pico_Char *) g_strdup_printf(
+                               "<pitch level='%d'>%s</pitch>", value, tmp);
+               g_free(tmp);
+       }
+
+/*     switch (msgtype) {
+               case SPD_MSGTYPE_CHAR:
+               case SPD_MSGTYPE_KEY:
+               case SPD_MSGTYPE_TEXT:
+               case SPD_MSGTYPE_SOUND_ICON:
+               default:
+                       DBG(MODULE_NAME
+                               ": msgtype = %d", msgtype);
+                       break;
+       }
+*/
+       g_atomic_int_set(&pico_state, STATE_PLAY);
+       sem_post(pico_play_semaphore);
+       return bytes;
+}
+
+int module_stop(void)
+{
+       pico_Status ret;
+       pico_Retstring outMessage;
+
+       if (g_atomic_int_get(&pico_state) != STATE_PLAY){
+               DBG(MODULE_NAME
+                       ": STOP called when not in PLAY state");
+               return -1;
+       }
+
+       g_atomic_int_set(&pico_state, STATE_STOP);
+
+       /* reset Pico engine. */
+       if((ret = pico_resetEngine(picoEngine, PICO_RESET_SOFT))) {
+               pico_getSystemStatusMessage(picoSystem, ret, outMessage);
+               DBG(MODULE_NAME
+                       "Cannot reset pico engine (%i): %s\n", ret, outMessage);
+               return -1;
+       }
+
+       return 0;
+}
+
+size_t module_pause(void)
+{
+       pico_Status ret;
+       pico_Retstring outMessage;
+
+       if (g_atomic_int_get(&pico_state) != STATE_PLAY){
+               DBG(MODULE_NAME
+                       ": PAUSE called when not in PLAY state");
+               return -1;
+       }
+
+       g_atomic_int_set(&pico_state, STATE_PAUSE);
+
+       /* reset Pico engine. */
+       if((ret = pico_resetEngine(picoEngine, PICO_RESET_SOFT))) {
+               pico_getSystemStatusMessage(picoSystem, ret, outMessage);
+               DBG(MODULE_NAME
+                       "Cannot reset pico engine (%i): %s\n", ret, outMessage);
+               return -1;
+       }
+
+       return 0;
+}
+
+void module_close(int status)
+{
+       if (module_audio_id) {
+               spd_audio_close(module_audio_id);
+       }
+
+       g_atomic_int_set(&pico_state, STATE_CLOSE);
+       sem_post(pico_play_semaphore);
+
+       g_thread_join(pico_play_thread);
+
+       if (picoSystem) {
+               pico_terminate(&picoSystem);
+               picoSystem = NULL;
+       }
+
+       g_free(pico_play_semaphore);
+}
-- 
1.6.0.4




reply via email to

[Prev in Thread] Current Thread [Next in Thread]