void swfdec_playback_close (SwfdecPlayback *sound) { pa_operation *op; #define REMOVE_HANDLER_FULL(obj,func,data,count) G_STMT_START {\ if (g_signal_handlers_disconnect_by_func ((obj), \ G_CALLBACK (func), (data)) != (count)) { \ g_assert_not_reached (); \ } \ } G_STMT_END #define REMOVE_HANDLER(obj,func,data) REMOVE_HANDLER_FULL (obj, func, data, 1) while (sound->streams) swfdec_playback_stream_close (sound->streams->data); REMOVE_HANDLER (sound->player, advance_before, sound); REMOVE_HANDLER (sound->player, audio_added, sound); REMOVE_HANDLER (sound->player, audio_removed, sound); if (sound->pa != NULL) { op = pa_context_drain (sound->pa, context_drain_complete, NULL); if (op == NULL) { pa_context_disconnect (sound->pa); pa_context_unref (sound->pa); } else { pa_operation_unref (op); } pa_glib_mainloop_free (sound->pa_mainloop); } g_main_context_unref (sound->context); g_free (sound); }
static void audio_removed (SwfdecPlayer *player, SwfdecAudio *audio, SwfdecPlayback *sound) { GList *walk; for (walk = sound->streams; walk; walk = walk->next) { Stream *stream = walk->data; if (stream->audio == audio) { swfdec_playback_stream_close (stream); return; } } }
void swfdec_playback_close (SwfdecPlayback *sound) { #define REMOVE_HANDLER_FULL(obj,func,data,count) G_STMT_START {\ if (g_signal_handlers_disconnect_by_func ((obj), \ G_CALLBACK (func), (data)) != (count)) { \ g_assert_not_reached (); \ } \ } G_STMT_END #define REMOVE_HANDLER(obj,func,data) REMOVE_HANDLER_FULL (obj, func, data, 1) while (sound->streams) swfdec_playback_stream_close (sound->streams->data); REMOVE_HANDLER (sound->player, advance_before, sound); REMOVE_HANDLER (sound->player, audio_added, sound); REMOVE_HANDLER (sound->player, audio_removed, sound); g_main_context_unref (sound->context); g_free (sound); }
static void swfdec_playback_stream_open (SwfdecPlayback *sound, SwfdecAudio *audio) { Stream *stream; pa_sample_spec spec = { .format = PA_SAMPLE_S16LE, .rate = 44100, .channels = CHANNELS, }; int err; stream = g_new0 (Stream, 1); stream->sound = sound; stream->audio = g_object_ref (audio); sound->streams = g_list_prepend (sound->streams, stream); /* If we failed to initialize the context, don't try to create the stream. * We still have to get put in the list, because swfdec_playback.c expects * to find it in the list for removal later. */ if (sound->pa == NULL) return; /* Create our stream */ stream->pa = pa_stream_new(sound->pa, "swfdec stream", &spec, NULL /* Default channel map */ ); if (stream->pa == NULL) { g_printerr("Failed to create PA stream\n"); swfdec_playback_stream_close(stream); return; } /* Start at default volume */ pa_cvolume_set(&stream->volume, CHANNELS, PA_VOLUME_NORM); /* Hook up our stream write callback for when new data is needed */ pa_stream_set_state_callback(stream->pa, stream_state_callback, stream); pa_stream_set_write_callback(stream->pa, stream_write_callback, stream); /* Connect it up as a playback stream. */ err = pa_stream_connect_playback(stream->pa, NULL, /* Default device */ NULL /* Default buffering */, 0, /* No flags */ &stream->volume, NULL /* Don't sync to any stream */ ); if (err != 0) { g_printerr ("Failed to connect PA stream: %s\n", pa_strerror(pa_context_errno(sound->pa))); swfdec_playback_stream_close(stream); return; } } /*** SOUND ***/ static void advance_before (SwfdecPlayer *player, guint msecs, guint audio_samples, gpointer data) { SwfdecPlayback *sound = data; GList *walk; for (walk = sound->streams; walk; walk = walk->next) { Stream *stream = walk->data; if (audio_samples >= stream->offset) { stream->offset = 0; } else { stream->offset -= audio_samples; } } }