CMD* make_andor(token_list** list_ref) { token_list* list = *list_ref; if (!list) return make_error_cmd("could not form and-or (no tokens)"); CMD* andor_tree = make_pipeline(&list); if (andor_tree->type == ERROR) return andor_tree; int next_type = type(list); if (next_type == SEP_AND || next_type == SEP_OR) { advance(&list); CMD* parent = mallocCMD(); // TODO: make sure all initialized to NULL parent->type = next_type; parent->left = andor_tree; andor_tree = parent; CMD* sub_andor = make_andor(&list); if (sub_andor->type == ERROR) { freeCMD(andor_tree); return sub_andor; } andor_tree->right = sub_andor; } *list_ref = list; return andor_tree; }
CMD* make_pipeline(token_list** list_ref) { token_list* list = *list_ref; if (!list) return make_error_cmd("could not form pipeline (no tokens)"); CMD* pipeline_tree = make_stage(&list); if (pipeline_tree->type == ERROR) return pipeline_tree; int next_type = type(list); if (next_type == PIPE || next_type == PIPE_ERR) { advance(&list); CMD* parent = mallocCMD(); parent->type = next_type; parent->left = pipeline_tree; pipeline_tree = parent; CMD* sub_pipeline = make_pipeline(&list); if (sub_pipeline->type == ERROR) { freeCMD(pipeline_tree); return sub_pipeline; } pipeline_tree->right = sub_pipeline; } *list_ref = list; return pipeline_tree; }
gint main (int argc, char *argv[]) { options(argc, argv); loop = g_main_loop_new(NULL, FALSE); GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL); /*Tell gstreamer to look locally for the plugin*/ GstRegistry *registry; registry = gst_registry_get(); gst_registry_scan_path(registry, "plugins"); GError *parse_error = NULL; GstElement *pipeline = make_pipeline(&parse_error, loop); DEBUG("pipeline is %p", pipeline); DEBUG("template is '%s'", PIPELINE_TEMPLATE); GstBus *bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline)); gst_bus_set_sync_handler(bus, (GstBusSyncHandler)sync_bus_call, NULL, NULL); gst_bus_add_watch(bus, (GstBusFunc)bus_callback, pipeline); gst_object_unref(bus); gst_element_set_state(pipeline, GST_STATE_PLAYING); g_signal_connect(G_OBJECT(window), "key-press-event", G_CALLBACK(key_press_event_cb), pipeline); STDERR_DEBUG("pipeline is %p", pipeline); g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(destroy_cb), loop); g_signal_connect(window, "realize", G_CALLBACK(video_widget_realize_cb), NULL); gtk_widget_show_all(window); g_main_loop_run(loop); gst_element_set_state (pipeline, GST_STATE_NULL); gst_object_unref (pipeline); return 0; }
gint main (gint argc, gchar * argv[]) { GstElement *pipeline; GstBus *bus; GMainLoop *loop; /* init GStreamer */ gst_init (&argc, &argv); loop = g_main_loop_new (NULL, FALSE); /* set up */ pipeline = make_pipeline (); g_signal_connect (pipeline, "deep_notify", G_CALLBACK (gst_object_default_deep_notify), NULL); bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); gst_bus_add_watch (bus, my_bus_callback, loop); gst_object_unref (bus); g_print ("Starting pipeline\n"); gst_element_set_state (pipeline, GST_STATE_PLAYING); /* add a timeout to cycle between the formats */ g_timeout_add (1000, (GSourceFunc) do_switch, pipeline); /* now run */ g_main_loop_run (loop); g_print ("Nulling pipeline\n"); /* also clean up */ gst_element_set_state (pipeline, GST_STATE_NULL); gst_object_unref (pipeline); return 0; }
int main (int argc, char **argv) { GstElement *pipe, *crop; gint left, right; gint top, bottom; gint ldir, rdir; gint tdir, bdir; gint round, type, stop; gst_init (&argc, &argv); type = 0; stop = -1; if (argc > 1) { type = atoi (argv[1]); stop = type + 1; } while (TRUE) { GstMessage *message; pipe = make_pipeline (type); if (pipe == NULL) break; crop = gst_bin_get_by_name (GST_BIN (pipe), "crop"); g_assert (crop); top = bottom = left = right = 0; tdir = bdir = 10; ldir = rdir = 10; for (round = 0; round < MAX_ROUND; round++) { g_print ("crop to %4d %4d %4d %4d (%d/%d) \r", top, bottom, left, right, round, MAX_ROUND); g_object_set (crop, "top", top, "bottom", bottom, "left", left, "right", right, NULL); if (round == 0) gst_element_set_state (pipe, GST_STATE_PLAYING); top += tdir; if (top >= 80) tdir = -10; else if (top < 10) tdir = 10; bottom += bdir; if (bottom >= 60) bdir = -10; else if (bottom < 10) bdir = 10; left += ldir; if (left >= 100) ldir = -10; else if (left < 10) ldir = 10; right += rdir; if (right >= 80) rdir = -10; else if (right < 10) rdir = 10; message = gst_bus_poll (GST_ELEMENT_BUS (pipe), GST_MESSAGE_ERROR, 50 * GST_MSECOND); if (message) { g_print ("got error \n"); gst_message_unref (message); } } g_print ("test %d done \n", type); gst_object_unref (crop); gst_element_set_state (pipe, GST_STATE_NULL); gst_object_unref (pipe); type++; if (type == stop) break; } return 0; }
/* * get uri * create playbin * check that we have video * for each potential location * check for cancel * grab snapshot * interesting? * return if so, other spin loop * * for future, check metadata for artwork and don't reject non-video streams (see totem) * * TODO: all error paths leak */ static void gst_thumbnailer_create (TumblerAbstractThumbnailer *thumbnailer, GCancellable *cancellable, TumblerFileInfo *info) { /* These positions are taken from Totem */ const double positions[] = { 1.0 / 3.0, 2.0 / 3.0, 0.1, 0.9, 0.5 }; GstElement *playbin; gint64 duration; unsigned int i; GstBuffer *frame; GdkPixbuf *shot; TumblerThumbnail *thumbnail; TumblerThumbnailFlavor *flavour; TumblerImageData data; GError *error = NULL; g_return_if_fail (IS_GST_THUMBNAILER (thumbnailer)); g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable)); g_return_if_fail (TUMBLER_IS_FILE_INFO (info)); /* Check for early cancellation */ if (g_cancellable_is_cancelled (cancellable)) return; playbin = make_pipeline (info, cancellable); if (playbin == NULL) { /* TODO: emit an error, but the specification won't let me. */ return; } duration = get_duration (playbin); /* Now we have a pipeline that we know has video and is paused, ready for seeking */ for (i = 0; i < G_N_ELEMENTS (positions); i++) { /* Check if we've been cancelled */ if (g_cancellable_is_cancelled (cancellable)) { gst_element_set_state (playbin, GST_STATE_NULL); g_object_unref (playbin); return; } LOG ("trying position %f", positions[i]); gst_element_seek_simple (playbin, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT, (gint64)(positions[i] * duration)); if (gst_element_get_state (playbin, NULL, NULL, 1 * GST_SECOND) == GST_STATE_CHANGE_FAILURE) { LOG ("Could not seek"); return; } g_object_get (playbin, "frame", &frame, NULL); if (frame == NULL) { LOG ("No frame found!"); continue; } thumbnail = tumbler_file_info_get_thumbnail (info); flavour = tumbler_thumbnail_get_flavor (thumbnail); /* This frees the buffer for us */ shot = convert_buffer_to_pixbuf (frame, cancellable, flavour); g_object_unref (flavour); /* If it's not interesting, throw it away and try again*/ if (is_interesting (shot)) { /* Got an interesting image, break out */ LOG ("Found an interesting image"); break; } /* * If we've still got positions to try, free the current uninteresting * shot. Otherwise we'll make do with what we have. */ if (i + 1 < G_N_ELEMENTS (positions) && shot) { g_object_unref (shot); shot = NULL; } /* Spin mainloop so we can pick up the cancels */ while (g_main_context_pending (NULL)) { g_main_context_iteration (NULL, FALSE); } } gst_element_set_state (playbin, GST_STATE_NULL); g_object_unref (playbin); if (shot) { data.data = gdk_pixbuf_get_pixels (shot); data.has_alpha = gdk_pixbuf_get_has_alpha (shot); data.bits_per_sample = gdk_pixbuf_get_bits_per_sample (shot); data.width = gdk_pixbuf_get_width (shot); data.height = gdk_pixbuf_get_height (shot); data.rowstride = gdk_pixbuf_get_rowstride (shot); data.colorspace = (TumblerColorspace) gdk_pixbuf_get_colorspace (shot); tumbler_thumbnail_save_image_data (thumbnail, &data, tumbler_file_info_get_mtime (info), NULL, &error); g_object_unref (shot); if (error != NULL) { g_signal_emit_by_name (thumbnailer, "error", tumbler_file_info_get_uri (info), error->code, error->message); g_error_free (error); } else { g_signal_emit_by_name (thumbnailer, "ready", tumbler_file_info_get_uri (info)); } } }