From 43f6060c4fcf81a9a925cdf45d99136419ac064a Mon Sep 17 00:00:00 2001 From: Christian Pointner Date: Fri, 1 Jul 2011 02:55:58 +0000 Subject: [PATCH] first working version --- dart-sounds/src/dart-sounds.c | 190 ++++++++++++++++++++++++++++++++++------- 1 file changed, 157 insertions(+), 33 deletions(-) diff --git a/dart-sounds/src/dart-sounds.c b/dart-sounds/src/dart-sounds.c index 6d11df8..d22ac51 100644 --- a/dart-sounds/src/dart-sounds.c +++ b/dart-sounds/src/dart-sounds.c @@ -20,32 +20,48 @@ * along with dart-sounds. If not, see . */ - +#include +#include +#include +#include +#include +#include #include #include -static gboolean bus_call(GstBus *bus, GstMessage *msg, gpointer data) +struct bus_call_param { - GMainLoop *loop = (GMainLoop *) data; - + GMainLoop *loop; + gint* sval; + GCond* cond; + GMutex* mutex; +}; + +static gboolean bus_call(GstBus *bus, GstMessage *msg, gpointer data) +{ + struct bus_call_param* p = (struct bus_call_param *)data; + switch(GST_MESSAGE_TYPE(msg)) { case GST_MESSAGE_EOS: - g_print("End of stream\n"); -// g_main_loop_quit(loop); + g_mutex_lock(p->mutex); + (*(p->sval))++; + g_mutex_unlock(p->mutex); + g_cond_signal(p->cond); break; case GST_MESSAGE_ERROR: { - gchar *debug; GError *error; - - gst_message_parse_error(msg, &error, &debug); - g_free(debug); - + gst_message_parse_error(msg, &error, NULL); g_printerr("Error: %s\n", error->message); - g_error_free(error); + if(error->domain = GST_RESOURCE_ERROR) { + g_mutex_lock(p->mutex); + (*(p->sval))++; + g_mutex_unlock(p->mutex); + g_cond_signal(p->cond); + } else g_main_loop_quit(p->loop); - g_main_loop_quit(loop); + g_error_free(error); break; } default: @@ -65,42 +81,131 @@ static void on_pad_added(GstElement *element, GstPad *pad, gpointer data) gst_object_unref(sinkpad); } -GstElement* init(GMainLoop *loop, int pipe_out) +GstElement* init(GMainLoop *loop, gint* sval, GCond* cond, GMutex* mutex, GstElement** source) { GstElement *pipeline = gst_pipeline_new("dart-sounds"); - GstElement *source = gst_element_factory_make("filesrc", "source"); + *source = gst_element_factory_make("filesrc", "source"); GstElement *demuxer = gst_element_factory_make("oggdemux", "demuxer"); GstElement *decoder = gst_element_factory_make("vorbisdec", "decoder"); GstElement *conv = gst_element_factory_make("audioconvert", "converter"); GstElement *sink = gst_element_factory_make("autoaudiosink", "sink"); - if (!pipeline || !source || !demuxer || !decoder || !conv || !sink) { + if (!pipeline || !(*source) || !demuxer || !decoder || !conv || !sink) { g_printerr("One element could not be created. Exiting.\n"); return NULL; } - g_object_set(G_OBJECT(source), "location", "../media/bull.ogg", NULL); - GstBus *bus = gst_pipeline_get_bus(GST_PIPELINE (pipeline)); - gst_bus_add_watch(bus, bus_call, loop); + struct bus_call_param* data = malloc(sizeof(struct bus_call_param)); + if(!data) { + g_printerr("Memory error\n"); + return NULL; + } + data->loop = loop; + data->sval = sval; + data->cond = cond; + data->mutex = mutex; + gst_bus_add_watch(bus, bus_call, data); gst_object_unref(bus); - gst_bin_add_many(GST_BIN(pipeline), source, demuxer, decoder, conv, sink, NULL); + gst_bin_add_many(GST_BIN(pipeline), *source, demuxer, decoder, conv, sink, NULL); - gst_element_link(source, demuxer); + gst_element_link(*source, demuxer); gst_element_link_many(decoder, conv, sink, NULL); g_signal_connect(demuxer, "pad-added", G_CALLBACK(on_pad_added), decoder); - gst_element_set_state(pipeline, GST_STATE_PLAYING); - return pipeline; } -static void stdin_read(gpointer data) +struct play_file_param +{ + char* name; + GstElement *pipeline; + GstElement *source; + gint* sval; + GCond* cond; + GMutex* mutex; +}; + +static gpointer play_file(gpointer data) +{ + struct play_file_param *p = (struct play_file_param*)data; + char* name = p->name; + GstElement* pipeline = p->pipeline; + GstElement* source = p->source; + gint* sval = p->sval; + GCond* cond = p->cond; + GMutex* mutex = p->mutex; + free(p); + + g_print("playing '../media/%s.ogg'\n", name); + char* path; + asprintf(&path, "../media/%s.ogg", name); + if(!path) + return NULL; + + g_mutex_lock(mutex); + while((*sval) < 1) + g_cond_wait(cond, mutex); + (*sval)--; + g_mutex_unlock(mutex); + gst_element_set_state(pipeline, GST_STATE_READY); + + g_object_set(G_OBJECT(source), "location", path, NULL); + free(path); + gst_element_set_state(pipeline, GST_STATE_PLAYING); +} + +struct stdin_read_param +{ + GMainLoop *loop; + GstElement *pipeline; + GstElement *source; + gint* sval; + GCond* cond; + GMutex* mutex; +}; + +static gboolean stdin_read(GIOChannel* src, GIOCondition cond, gpointer data) { - u_int8_t buf[100]; - int len = read(0, buf, sizeof(buf)); - g_print("read %d bytes from stdin\n", len); + struct stdin_read_param *p = (struct stdin_read_param*)data; + static size_t offset = 0; + static u_int8_t buf[100]; + + int len = read(0, &(buf[offset]), sizeof(buf) - offset); + if(len <= 0) { + if(len) g_printerr("Error on STDIN\n"); + else g_print("EOF on STDIN\n"); + g_main_loop_quit(p->loop); + } + + offset+=len; + if(offset > sizeof(buf)) offset = sizeof(buf); + + size_t i; + for(i=0; i < offset; ++i) { + if(buf[i] == '\n') { + buf[i] = 0; + + struct play_file_param* data = malloc(sizeof(struct play_file_param)); + if(data) { + data->name = buf; + data->pipeline = p->pipeline; + data->source = p->source; + data->sval = p->sval; + data->cond = p->cond; + data->mutex = p->mutex; + g_thread_create(play_file, data, 0, NULL); + } + + if(i < offset) { + memmove(buf, &(buf[i+1]), offset - (i+1)); + offset -= i+1; + } else offset = 0; + } + } + + return 1; } int main(int argc, char *argv[]) @@ -109,21 +214,40 @@ int main(int argc, char *argv[]) GMainLoop *loop = g_main_loop_new(NULL, FALSE); - GstElement *pipeline = init(loop, 0); + gint sval = 1; + GCond* cond = g_cond_new(); + if(!cond) { + g_printerr("Condition could not be created.\n"); + return 1; + } + GMutex* mutex = g_mutex_new(); + if(!cond) { + g_printerr("Mutex could not be created.\n"); + return 1; + } + + GstElement *source; + GstElement *pipeline = init(loop, &sval, cond, mutex, &source); if(!pipeline) return 1; GMainContext *ctx = g_main_loop_get_context(loop); - GIOChannel* chan = g_io_channel_unix_new(0); if(!chan) { g_printerr("IO Channel could not be created.\n"); return 1; } - GSource* src = g_io_create_watch(chan, G_IO_IN); - - g_source_set_callback(src, (GSourceFunc)stdin_read, (gpointer)pipeline, NULL); - g_source_attach(src, ctx); + struct stdin_read_param p; + p.loop = loop; + p.pipeline = pipeline; + p.source = source; + p.sval = &sval; + p.cond = cond; + p.mutex = mutex; + if(!g_io_add_watch(chan, G_IO_IN, (GIOFunc)stdin_read, &p)) { + g_printerr("watch for IO Channel could not be added.\n"); + return 1; + } g_print("Running...\n"); g_main_loop_run(loop); -- 1.7.10.4