+ 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);
+
+ if(!name)
+ return NULL;
+
+ g_print("playing '../media/%s.ogg'\n", name);
+ char* path;
+ asprintf(&path, "../media/%s.ogg", name);
+ free(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)
+{
+ 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);
+ }
+
+ g_print("read %d bytes from STDIN\n", len);
+
+ offset+=len;
+ if(offset > sizeof(buf)) offset = sizeof(buf);
+
+ size_t i = 0;
+ for(;i < offset;) {
+ if(buf[i] == '\n') {
+ buf[i] = 0;
+
+ struct play_file_param* data = malloc(sizeof(struct play_file_param));
+ if(data) {
+ data->name = strdup(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;
+ i = 0;
+ } else {
+ offset = 0;
+ break;
+ }
+ }
+ else i++;
+ }
+
+ return 1;