/** * Program entry point. Initializes gtk+, calls the widget creating * functions and starts the main loop. Also connects 'popup-menu', * 'activate' and 'button-release-event' to the tray_icon. * * @param argc count of arguments * @param argv string array of arguments * @return 0 for success, otherwise error code */ int main (int argc, char *argv[]) { GError *error = NULL; GOptionContext *context; #ifdef ENABLE_NLS bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR); bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); textdomain (GETTEXT_PACKAGE); #endif DEBUG_PRINT("[Debugging Mode Build]\n"); setlocale(LC_ALL, ""); context = g_option_context_new (_("- A mixer for the system tray.")); g_option_context_add_main_entries (context, args, GETTEXT_PACKAGE); g_option_context_add_group (context, gtk_get_option_group (TRUE)); g_option_context_parse (context, &argc, &argv, &error); gtk_init (&argc, &argv); g_option_context_free(context); if (version) { printf(_("%s version: %s\n"),PACKAGE,VERSION); exit(0); } popup_window = NULL; status_icons[0] = status_icons[1] = status_icons[2] = status_icons[3] = NULL; add_pixmap_directory (PACKAGE_DATA_DIR "/" PACKAGE "/pixmaps"); add_pixmap_directory ("./pixmaps"); ensure_prefs_dir(); load_prefs(); cards = NULL; // so we don't try and free on first run alsa_init(); init_libnotify(); create_popups(); add_filter(); tray_icon = create_tray_icon(); apply_prefs(0); g_signal_connect(G_OBJECT(tray_icon), "popup-menu",G_CALLBACK(popup_callback), popup_menu); g_signal_connect(G_OBJECT(tray_icon), "activate", G_CALLBACK(tray_icon_on_click), NULL); g_signal_connect(G_OBJECT(tray_icon), "button-release-event", G_CALLBACK(tray_icon_button), NULL); gtk_main (); uninit_libnotify(); alsa_close(); return 0; }
void sound_close(int outp) { switch (outp) { case ALSA: alsa_close(); break; case DSP: dsp_close(); break; case STDOUT: stdout_close(); break; default: fprintf(stderr, "Unknown output method\n"); } }
/* open callback */ int alsa_open(int rate, int nch, int width) { inputf = snd_format_alloc(rate, nch); if(alsa_setup(inputf) < 0) { alsa_close(); return 0; } output_time_offset = 0; alsa_total_written = alsa_hw_written = 0; going = true; prebuffer = true; remove_prebuffer = false; thread_buffer_size = (u_int) alsa_cb.thread_buffer_time * inputf->bps / 1000; if(thread_buffer_size < hw_buffer_size) thread_buffer_size = hw_buffer_size * 2; if(thread_buffer_size < width) thread_buffer_size = width; prebuffer_size = thread_buffer_size / 2; if(prebuffer_size < width) prebuffer_size = width; thread_buffer_size += hw_buffer_size; thread_buffer_size -= thread_buffer_size % hw_period_size; thread_buffer = calloc(1, thread_buffer_size); wr_index = rd_index = 0; flush_request = -1; pthread_create(&audio_thread, NULL, alsa_loop, NULL); return 1; }
int Atcleci_Init(Tcl_Interp *interp) { int rc; size_t chunk_bytes = 0; void *eciHandle; void *eciLib; //< configure shared library symbols eciLib = dlopen(ECILIBRARYNAME, RTLD_LAZY); if (eciLib == NULL) { Tcl_AppendResult(interp, "Could not load ", ECILIBRARYNAME, "\n", dlerror(), "\nPlease install the IBM ViaVoice Outloud RTK", NULL); return TCL_ERROR; } _eciVersion = (void (*)(char *))(unsigned long)dlsym(eciLib, "eciVersion"); _eciGetAvailableLanguages = (int (*)(enum ECILanguageDialect *, int *))( unsigned long)dlsym(eciLib, "eciGetAvailableLanguages"); _eciNewEx = (void *(*)(enum ECILanguageDialect))(unsigned long)dlsym( eciLib, "eciNewEx"); _eciDelete = (void (*)(void *))(unsigned long)dlsym(eciLib, "eciDelete"); _eciReset = (int (*)(void *))(unsigned long)dlsym(eciLib, "eciReset"); _eciStop = (int (*)(void *))(unsigned long)dlsym(eciLib, "eciStop"); _eciClearInput = (int (*)(void *))(unsigned long)dlsym(eciLib, "eciClearInput"); _eciPause = (int (*)(void *, int))(unsigned long)dlsym(eciLib, "eciPause"); _eciSynthesize = (int (*)(void *))(unsigned long)dlsym(eciLib, "eciSynthesize"); _eciSynchronize = (int (*)(void *))(unsigned long)dlsym(eciLib, "eciSynchronize"); _eciSpeaking = (int (*)(void *))(unsigned long)dlsym(eciLib, "eciSpeaking"); _eciInsertIndex = (int (*)(void *, int))(unsigned long)dlsym(eciLib, "eciInsertIndex"); _eciAddText = (int (*)(void *, char *))(unsigned long)dlsym(eciLib, "eciAddText"); _eciSetParam = (int (*)(void *, int, int))(unsigned long)dlsym(eciLib, "eciSetParam"); _eciGetVoiceParam = (int (*)(void *, int, int))(unsigned long)dlsym( eciLib, "eciGetVoiceParam"); _eciSetVoiceParam = (int (*)(void *, int, int, int))(unsigned long)dlsym( eciLib, "eciSetVoiceParam"); _eciRegisterCallback = (void (*)(void *, int (*)(void *, int, long, void *), void *))( unsigned long)dlsym(eciLib, "eciRegisterCallback"); _eciSetOutputBuffer = (int (*)(void *, int, short *))(unsigned long)dlsym( eciLib, "eciSetOutputBuffer"); _eciSetOutputDevice = (int (*)(void *, int))(unsigned long)dlsym(eciLib, "eciSetOutputDevice"); //> //< check for needed symbols int okay = 1; if (!_eciNewEx) { okay = 0; Tcl_AppendResult(interp, "eciNewEx undef\n", NULL); } if (!_eciDelete) { okay = 0; Tcl_AppendResult(interp, "eciDelete undef\n", NULL); } if (!_eciReset) { okay = 0; Tcl_AppendResult(interp, "eciReset undef\n", NULL); } if (!_eciStop) { okay = 0; Tcl_AppendResult(interp, "eciStop undef\n", NULL); } if (!_eciClearInput) { okay = 0; Tcl_AppendResult(interp, "eciClearInput undef\n", NULL); } if (!_eciPause) { okay = 0; Tcl_AppendResult(interp, "eciPause undef\n", NULL); } if (!_eciSynthesize) { okay = 0; Tcl_AppendResult(interp, "eciSynthesize undef\n", NULL); } if (!_eciSpeaking) { okay = 0; Tcl_AppendResult(interp, "eciSpeaking undef\n", NULL); } if (!_eciInsertIndex) { okay = 0; Tcl_AppendResult(interp, "eciInsertIndex undef\n", NULL); } if (!_eciAddText) { okay = 0; Tcl_AppendResult(interp, "eciAddText undef\n", NULL); } if (!_eciSetParam) { okay = 0; Tcl_AppendResult(interp, "eciSetParam undef\n", NULL); } if (!_eciSetParam) { okay = 0; Tcl_AppendResult(interp, "eciSetParam undef\n", NULL); } if (!_eciGetVoiceParam) { okay = 0; Tcl_AppendResult(interp, "eciGetVoiceParam undef\n", NULL); } if (!_eciSetVoiceParam) { okay = 0; Tcl_AppendResult(interp, "eciSetVoiceParam undef\n", NULL); } if (!_eciRegisterCallback) { okay = 0; Tcl_AppendResult(interp, "eciRegisterCallback undef\n", NULL); } if (!_eciSetOutputBuffer) { okay = 0; Tcl_AppendResult(interp, "eciSetOutputBuffer undef\n", NULL); } if (!_eciSetOutputDevice) { okay = 0; Tcl_AppendResult(interp, "eciSetOutputDevice undef\n", NULL); } if (!_eciGetAvailableLanguages) { okay = 0; Tcl_AppendResult(interp, "_eciGetAvailableLanguages undef\n", NULL); } if (!okay) { Tcl_AppendResult(interp, "Missing symbols from ", ECILIBRARYNAME, NULL); return TCL_ERROR; } //> //<setup package, create tts handle if (Tcl_PkgProvide(interp, PACKAGENAME, PACKAGEVERSION) != TCL_OK) { Tcl_AppendResult(interp, "Error loading ", PACKAGENAME, NULL); return TCL_ERROR; } static enum ECILanguageDialect aLanguages[LANG_INFO_MAX]; int nLanguages = LANG_INFO_MAX; _eciGetAvailableLanguages(aLanguages, &nLanguages); enum ECILanguageDialect aDefaultLanguage = initLanguage(interp, aLanguages, nLanguages); if (aDefaultLanguage == NODEFINEDCODESET) { Tcl_AppendResult(interp, "No language found", PACKAGENAME, NULL); return TCL_ERROR; } fprintf(stderr, "Found %d languages.\n", nLanguages); eciHandle = _eciNewEx(aDefaultLanguage); if (eciHandle == 0) { Tcl_AppendResult(interp, "Could not open text-to-speech engine", NULL); return TCL_ERROR; } //> //<initialize alsa chunk_bytes = alsa_init(); //<Finally, allocate waveBuffer fprintf(stderr, "allocating %d samples\n", (int)chunk_bytes); waveBuffer = (short *)malloc(chunk_bytes * sizeof(short)); if (waveBuffer == NULL) { fprintf(stderr, "not enough memory"); alsa_close(); exit(EXIT_FAILURE); } //> //> //<initialize TTS if ((_eciSetParam(eciHandle, eciInputType, 1) == -1) || (_eciSetParam(eciHandle, eciSynthMode, 1) == -1) || (_eciSetParam(eciHandle, eciSampleRate, 1) == -1)) { Tcl_AppendResult(interp, "Could not initialized tts", NULL); _eciDelete(eciHandle); return TCL_ERROR; } _eciRegisterCallback(eciHandle, eciCallback, interp); //> //<set output to buffer rc = _eciSynchronize(eciHandle); if (!rc) { Tcl_AppendResult(interp, "Error resetting TTS engine.\n", NULL); return TCL_ERROR; } rc = _eciSetOutputBuffer(eciHandle, chunk_bytes, waveBuffer); if (!rc) { Tcl_AppendResult(interp, "Error setting output buffer.\n", NULL); return TCL_ERROR; } fprintf(stderr, "output buffered to waveBuffer with size %d\n", (int)chunk_bytes); //> //<register tcl commands Tcl_CreateObjCommand(interp, "setRate", SetRate, (ClientData)eciHandle, TclEciFree); Tcl_CreateObjCommand(interp, "getRate", GetRate, (ClientData)eciHandle, TclEciFree); Tcl_CreateObjCommand(interp, "ttsVersion", getTTSVersion, (ClientData)eciHandle, TclEciFree); Tcl_CreateObjCommand(interp, "alsaState", showAlsaState, (ClientData)NULL, TclEciFree); Tcl_CreateObjCommand(interp, "say", Say, (ClientData)eciHandle, TclEciFree); Tcl_CreateObjCommand(interp, "synth", Say, (ClientData)eciHandle, NULL); Tcl_CreateObjCommand(interp, "synchronize", Synchronize, (ClientData)eciHandle, TclEciFree); Tcl_CreateObjCommand(interp, "stop", Stop, (ClientData)eciHandle, TclEciFree); Tcl_CreateObjCommand(interp, "speakingP", SpeakingP, (ClientData)eciHandle, TclEciFree); Tcl_CreateObjCommand(interp, "pause", Pause, (ClientData)eciHandle, TclEciFree); Tcl_CreateObjCommand(interp, "resume", Resume, (ClientData)eciHandle, TclEciFree); Tcl_CreateObjCommand(interp, "setLanguage", SetLanguage, (ClientData)eciHandle, TclEciFree); //> //<set up index processing rc = Tcl_Eval(interp, "proc index x {global tts; \ set tts(last_index) $x}");
void close_local_sound() { alsa_close(); }
static int alsa_open(const char *device, unsigned sample_rate, unsigned alsa_buffer, unsigned alsa_period) { int err; snd_pcm_hw_params_t *hw_params; snd_pcm_hw_params_alloca(&hw_params); // close if already open if (pcmp) alsa_close(); // reset params alsa.rate = 0; alsa.period_size = 0; strcpy(alsa.device, device); if (strlen(device) > MAX_DEVICE_LEN - 4 - 1) { LOG_ERROR("device name too long: %s", device); return -1; } LOG_INFO("opening device at: %u", sample_rate); bool retry; do { // open device if ((err = snd_pcm_open(&pcmp, alsa.device, SND_PCM_STREAM_PLAYBACK, 0)) < 0) { LOG_ERROR("playback open error: %s", snd_strerror(err)); return err; } // init params memset(hw_params, 0, snd_pcm_hw_params_sizeof()); if ((err = snd_pcm_hw_params_any(pcmp, hw_params)) < 0) { LOG_ERROR("hwparam init error: %s", snd_strerror(err)); return err; } // open hw: devices without resampling, if sample rate fails try plughw: with resampling bool hw = !strncmp(alsa.device, "hw:", 3); retry = false; if ((err = snd_pcm_hw_params_set_rate_resample(pcmp, hw_params, !hw)) < 0) { LOG_ERROR("resampling setup failed: %s", snd_strerror(err)); return err; } if ((err = snd_pcm_hw_params_set_rate(pcmp, hw_params, sample_rate, 0)) < 0) { if (hw) { strcpy(alsa.device + 4, device); memcpy(alsa.device, "plug", 4); LOG_INFO("reopening device %s in plug mode as %s for resampling", device, alsa.device); snd_pcm_close(pcmp); retry = true; } } } while (retry); // set access if (!alsa.mmap || snd_pcm_hw_params_set_access(pcmp, hw_params, SND_PCM_ACCESS_MMAP_INTERLEAVED) < 0) { if ((err = snd_pcm_hw_params_set_access(pcmp, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) { LOG_ERROR("access type not available: %s", snd_strerror(err)); return err; } alsa.mmap = false; } // set the sample format snd_pcm_format_t *fmt = alsa.format ? &alsa.format : (snd_pcm_format_t *)fmts; do { if (snd_pcm_hw_params_set_format(pcmp, hw_params, *fmt) >= 0) { LOG_INFO("opened device %s using format: %s sample rate: %u mmap: %u", alsa.device, snd_pcm_format_name(*fmt), sample_rate, alsa.mmap); alsa.format = *fmt; break; } if (alsa.format) { LOG_ERROR("unable to open audio device requested format: %s", snd_pcm_format_name(alsa.format)); return -1; } ++fmt; if (*fmt == SND_PCM_FORMAT_UNKNOWN) { LOG_ERROR("unable to open audio device with any supported format"); return -1; } } while (*fmt != SND_PCM_FORMAT_UNKNOWN); // set the output format to be used by _scale_and_pack switch(alsa.format) { case SND_PCM_FORMAT_S32_LE: output.format = S32_LE; break; case SND_PCM_FORMAT_S24_LE: output.format = S24_LE; break; case SND_PCM_FORMAT_S24_3LE: output.format = S24_3LE; break; case SND_PCM_FORMAT_S16_LE: output.format = S16_LE; break; default: break; } // set channels if ((err = snd_pcm_hw_params_set_channels (pcmp, hw_params, 2)) < 0) { LOG_ERROR("channel count not available: %s", snd_strerror(err)); return err; } // set period size - value of < 50 treated as period count, otherwise size in bytes if (alsa_period < 50) { unsigned count = alsa_period; if ((err = snd_pcm_hw_params_set_periods_near(pcmp, hw_params, &count, 0)) < 0) { LOG_ERROR("unable to set period count %s", snd_strerror(err)); return err; } } else { snd_pcm_uframes_t size = alsa_period; int dir = 0; if ((err = snd_pcm_hw_params_set_period_size_near(pcmp, hw_params, &size, &dir)) < 0) { LOG_ERROR("unable to set period size %s", snd_strerror(err)); return err; } } // set buffer size - value of < 500 treated as buffer time in ms, otherwise size in bytes if (alsa_buffer < 500) { unsigned time = alsa_buffer * 1000; int dir = 0; if ((err = snd_pcm_hw_params_set_buffer_time_near(pcmp, hw_params, &time, &dir)) < 0) { LOG_ERROR("unable to set buffer time %s", snd_strerror(err)); return err; } } else { snd_pcm_uframes_t size = alsa_buffer; if ((err = snd_pcm_hw_params_set_buffer_size_near(pcmp, hw_params, &size)) < 0) { LOG_ERROR("unable to set buffer size %s", snd_strerror(err)); return err; } } // get period_size if ((err = snd_pcm_hw_params_get_period_size(hw_params, &alsa.period_size, 0)) < 0) { LOG_ERROR("unable to get period size: %s", snd_strerror(err)); return err; } // get buffer_size if ((err = snd_pcm_hw_params_get_buffer_size(hw_params, &alsa.buffer_size)) < 0) { LOG_ERROR("unable to get buffer size: %s", snd_strerror(err)); return err; } LOG_INFO("buffer: %u period: %u -> buffer size: %u period size: %u", alsa_buffer, alsa_period, alsa.buffer_size, alsa.period_size); // ensure we have two buffer sizes of samples before starting output output.start_frames = alsa.buffer_size * 2; // create an intermediate buffer for non mmap case for all but NATIVE_FORMAT // this is used to pack samples into the output format before calling writei if (!alsa.mmap && !alsa.write_buf && alsa.format != NATIVE_FORMAT) { alsa.write_buf = malloc(alsa.buffer_size * BYTES_PER_FRAME); if (!alsa.write_buf) { LOG_ERROR("unable to malloc write_buf"); return -1; } } // set params if ((err = snd_pcm_hw_params(pcmp, hw_params)) < 0) { LOG_ERROR("unable to set hw params: %s", snd_strerror(err)); return err; } // dump info if (loglevel == lSDEBUG) { static snd_output_t *debug_output; snd_output_stdio_attach(&debug_output, stderr, 0); snd_pcm_dump(pcmp, debug_output); } // this indicates we have opened the device ok alsa.rate = sample_rate; return 0; }