#include #include static GMainLoop *main_loop; static GstElement *playbin; static void check_position (void) { static gint64 last_position = -1; GstFormat format = GST_FORMAT_TIME; gint64 position; if (gst_element_query_position (playbin, &format, &position)) if (format == GST_FORMAT_TIME && position != last_position) { last_position = position; g_print ("position %f\n", position * 1.0 / GST_SECOND); } } static void check_duration (void) { static gint64 last_duration = 0; GstFormat format = GST_FORMAT_TIME; gint64 duration; if (gst_element_query_duration (playbin, &format, &duration)) if (format == GST_FORMAT_TIME && duration != last_duration) { last_duration = duration; g_print ("duration %f\n", duration * 1.0 / GST_SECOND); } } static guint current_timer_index = 0; static gboolean handle_timer_tick (gpointer timer_index) { if (GPOINTER_TO_UINT (timer_index) != current_timer_index) return FALSE; else { check_position (); check_duration (); return TRUE; } } static gboolean start_timer (void) { ++current_timer_index; g_timeout_add (500, handle_timer_tick, GUINT_TO_POINTER (current_timer_index)); } const gchar * state_name (GstState state) { switch (state) { case GST_STATE_VOID_PENDING: return "void_pending"; case GST_STATE_NULL: return "null"; case GST_STATE_READY: return "ready"; case GST_STATE_PAUSED: return "paused"; case GST_STATE_PLAYING: return "playing"; default: return "(unknown)"; } } gboolean handle_message (GstBus *bus, GstMessage *message, gpointer user_data) { if (message -> src != GST_OBJECT (playbin)) return; switch (GST_MESSAGE_TYPE (message)) { case GST_MESSAGE_STATE_CHANGED: { GstState old, new, pending; gst_message_parse_state_changed (message, &old, &new, &pending); if (pending == GST_STATE_VOID_PENDING) { check_position (); g_print ("state %s\n", state_name (new)); } } break; case GST_MESSAGE_CLOCK_PROVIDE: case GST_MESSAGE_NEW_CLOCK: break; default: g_print ("%s\n", GST_MESSAGE_TYPE_NAME (message)); } return TRUE; } static void pause_playback (void) { gst_element_set_state (playbin, GST_STATE_PAUSED); } static void resume_playback (void) { gst_element_set_state (playbin, GST_STATE_PLAYING); } static void seek_to_position (gdouble position) { gst_element_seek_simple (playbin, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, (gint64) (position * GST_SECOND)); } static void interpret_command_line (const char *line) { static GScannerConfig config; static gboolean config_initialized = FALSE; if (config_initialized == FALSE) { config.cset_skip_characters = " \t\n"; config.cset_identifier_first = G_CSET_a_2_z G_CSET_A_2_Z; config.cset_identifier_nth = G_CSET_a_2_z G_CSET_A_2_Z "_0123456789"; config.scan_identifier = TRUE; config.scan_identifier_1char = TRUE; config_initialized = TRUE; } GScanner *scanner = g_scanner_new (&config); g_scanner_input_text (scanner, line, strlen (line)); if (g_scanner_get_next_token (scanner) == G_TOKEN_IDENTIFIER) { gchar *command = g_scanner_cur_value (scanner).v_string; if (strcmp (command, "quit") == 0) g_main_loop_quit (main_loop); else if (strcmp (command, "pause") == 0) pause_playback (); else if (strcmp (command, "resume") == 0) resume_playback (); else if (strcmp (command, "seek") == 0) { switch (g_scanner_get_next_token (scanner)) { case G_TOKEN_INT: seek_to_position (g_scanner_cur_value (scanner).v_int); break; case G_TOKEN_FLOAT: seek_to_position (g_scanner_cur_value (scanner).v_float); break; } } else g_print ("unknown-command %s\n", command); } } gboolean read_input (GIOChannel *channel, GIOCondition condition, gpointer user_data) { gchar *line = NULL; switch (g_io_channel_read_line (channel, &line, NULL, NULL, NULL)) { case G_IO_STATUS_NORMAL: interpret_command_line (line); g_free (line); break; } } gint main (gint argc, gchar *argv []) { GstBus *bus; gst_init (&argc, &argv); main_loop = g_main_loop_new (NULL, FALSE); if (argc != 2) { g_print ("Usage: %s URI\n", argv[0]); return EXIT_FAILURE; } playbin = gst_element_factory_make ("playbin", "play"); g_object_set (G_OBJECT (playbin), "uri", argv[1], NULL); { GstElement *audio_sink = gst_element_factory_make ("gconfaudiosink", "audio-sink"); g_object_set (playbin, "audio-sink", audio_sink, NULL); } bus = gst_pipeline_get_bus (GST_PIPELINE (playbin)); gst_bus_add_watch (bus, handle_message, main_loop); gst_object_unref (bus); gst_element_set_state (playbin, GST_STATE_PLAYING); { GIOChannel *channel = g_io_channel_unix_new (0); g_io_add_watch (channel, G_IO_IN, read_input, NULL); } start_timer (); g_main_loop_run (main_loop); gst_element_set_state (playbin, GST_STATE_NULL); gst_object_unref (GST_OBJECT (playbin)); return EXIT_SUCCESS; }