--- /dev/null
+#include <gst/gst.h>
+#include <glib.h>
+
+#include <string.h>
+#include <stdlib.h>
+
+#include <sound_manager.h>
+#include <sound_manager_internal.h>
+
+#define MAX_STRING_LEN 1024
+
+typedef struct _AppData {
+ GstElement *pipeline;
+ GstElement *source;
+ GstElement *queue;
+ GstElement *parser;
+ GstElement *compressed_sink;
+
+ GMainLoop *main_loop;
+ guint progress_timer_id;
+ gint64 duration;
+ gchar *file_path;
+
+ sound_stream_info_h stream_info_h;
+ virtual_sound_stream_h vstream_h;
+} AppData;
+
+
+enum {
+ CURRENT_STATUS_MAINMENU,
+ CURRENT_STATUS_POSITION
+};
+
+int sub_menu = CURRENT_STATUS_MAINMENU;
+static void print_menu (void)
+{
+ g_print ("=========================================\n");
+ g_print ("'s' - Start\n");
+ g_print ("'p' - Pause\n");
+ g_print ("'r' - Resume\n");
+ g_print ("'x' - Stop\n");
+ g_print ("'q' - Quit\n");
+ g_print ("'e' - Seek\n");
+ g_print ("=========================================\n");
+ g_print (">>> ");
+}
+
+#define GST_TIME_SHORT_FORMAT "u:%02u:%02u.%02u"
+
+gboolean _timeout_cb(gpointer user_data)
+{
+ AppData *adata = (AppData *)user_data;
+ gint64 current = -1;
+
+ /* Query the current position of the stream */
+ if (!gst_element_query_position (adata->pipeline, GST_FORMAT_TIME, ¤t)) {
+ g_printerr ("Could not query current position.\n");
+ }
+
+ /* If we didn't know it yet, query the stream duration */
+ if (!GST_CLOCK_TIME_IS_VALID (adata->duration)) {
+ g_print("query duration\n");
+ if (!gst_element_query_duration (adata->pipeline, GST_FORMAT_TIME, &adata->duration)) {
+ g_printerr ("Could not query current duration.\n");
+ }
+ }
+
+ /* Print current position and total duration */
+ g_print ("[%s] Position %" GST_TIME_SHORT_FORMAT " / %" GST_TIME_SHORT_FORMAT "\r",
+ adata->file_path, GST_TIME_ARGS (current), GST_TIME_ARGS (adata->duration));
+
+ return TRUE;
+}
+
+void _start_progress(AppData *adata)
+{
+ if (adata && adata->progress_timer_id > 0) {
+ g_printerr("already timer %d exists\n", adata->progress_timer_id);
+ return;
+ }
+
+ adata->progress_timer_id = g_timeout_add(100, _timeout_cb, adata);
+}
+
+void _stop_progress(AppData *adata)
+{
+ if (adata && adata->progress_timer_id > 0) {
+ if (!g_source_remove(adata->progress_timer_id))
+ g_printerr("failed to remove source %d\n", adata->progress_timer_id);
+
+ adata->progress_timer_id = 0;
+ }
+}
+
+static gboolean _bus_cb (GstBus *bus, GstMessage *message, gpointer data)
+{
+ AppData *adata = (AppData *) data;
+ //g_print ("Got %s message\n", GST_MESSAGE_TYPE_NAME (message));
+
+ switch (GST_MESSAGE_TYPE (message)) {
+ case GST_MESSAGE_ERROR: {
+ GError *err;
+ gchar *debug;
+
+ gst_message_parse_error (message, &err, &debug);
+ g_print ("Error: %s\n", err->message);
+ g_error_free (err);
+ g_free (debug);
+
+ g_main_loop_quit (adata->main_loop);
+ break;
+ }
+ case GST_MESSAGE_EOS:
+ /* end-of-stream */
+ g_print("EOS!!!\n");
+// g_main_loop_quit (loop);
+ break;
+
+ default:
+ /* unhandled message */
+ break;
+ }
+
+ /* we want to be notified again the next time there is a message
+ * on the bus, so returning TRUE (FALSE means we want to stop watching
+ * for messages on the bus and our callback should not be called again)
+ */
+ return TRUE;
+}
+
+static void _focus_cb(sound_stream_info_h stream_info,
+ sound_stream_focus_mask_e focus_mask,
+ sound_stream_focus_state_e focus_state,
+ sound_stream_focus_change_reason_e reason,
+ int sound_behavior,
+ const char *extra_info,
+ void *user_data)
+{
+ int ret = SOUND_MANAGER_ERROR_NONE;
+
+ g_print("\n*** FOCUS callback is called, stream_info(%p) ***\n", stream_info);
+
+ g_print(" - changed focus: mask(%x), state(%d) (0:released, 1:acquired)\n", focus_mask, focus_state);
+ g_print(" - change_reason(%d), behavior(0x%x), extra_info(%s), user_data(%p)\n", reason, sound_behavior, extra_info, user_data);
+
+ g_print("*** FOCUS callback is ended, stream_info(%p) ****\n\n", stream_info);
+
+ return;
+}
+
+static void _prepare_stream(AppData *adata)
+{
+ int ret = 0;
+
+ ret = sound_manager_create_stream_information_internal(SOUND_STREAM_TYPE_MEDIA_COMPRESSED, _focus_cb, NULL, &adata->stream_info_h);
+ if (ret) {
+ g_printerr("failed to create stream information internal (MEDIA_COMPRESSED) : 0x%X\n", ret);
+ return;
+ }
+
+ ret = sound_manager_create_virtual_stream(adata->stream_info_h, &adata->vstream_h);
+ if (ret) {
+ g_printerr("failed to create virtual stream : 0x%X\n", ret);
+ return;
+ }
+}
+
+static void _unprepare_stream(AppData *adata)
+{
+ if (adata->vstream_h) {
+ sound_manager_destroy_virtual_stream(adata->vstream_h);
+ adata->vstream_h = NULL;
+ }
+
+ if (adata->stream_info_h) {
+ sound_manager_destroy_stream_information(adata->stream_info_h);
+ adata->stream_info_h = NULL;
+ }
+}
+
+static void _start_stream(AppData *adata)
+{
+ int ret = 0;
+
+ if (!adata->vstream_h) {
+ g_printerr("invalid vstream\n");
+ return;
+ }
+
+ ret = sound_manager_acquire_focus(adata->stream_info_h, SOUND_STREAM_FOCUS_FOR_BOTH,
+ SOUND_BEHAVIOR_NONE, "compress test(acquire_focus)");
+ if (ret)
+ g_printerr("fail to sound_manager_acquire_focus(), ret(0x%x)\n", ret);
+
+ ret = sound_manager_start_virtual_stream(adata->vstream_h);
+ if (ret)
+ g_print("fail to sound_manager_start_virtual_stream(), ret(0x%x)\n", ret);
+ else
+ g_print("success to sound_manager_start_virtual_stream(), ret(0x%x)\n", ret);
+
+}
+
+static void _stop_stream(AppData *adata)
+{
+ int ret = 0;
+
+ if (!adata->vstream_h) {
+ g_printerr("invalid vstream\n");
+ return;
+ }
+
+ ret = sound_manager_stop_virtual_stream(adata->vstream_h);
+ if (ret)
+ g_print("fail to sound_manager_stop_virtual_stream(), ret(0x%x)\n", ret);
+ else
+ g_print("success to sound_manager_stop_virtual_stream(), ret(0x%x)\n", ret);
+
+ ret = sound_manager_release_focus(adata->stream_info_h, SOUND_STREAM_FOCUS_FOR_BOTH,
+ SOUND_BEHAVIOR_NONE, "compress test(release_focus)");
+ if (ret)
+ g_printerr("fail to sound_manager_release_focus(), ret(0x%x)\n", ret);
+}
+
+
+static void interpret (char *cmd, gpointer data)
+{
+ GstStateChangeReturn ret;
+ AppData *adata = (AppData *) data;
+
+ if (strncmp (cmd, "s", 1) == 0) {
+ _start_stream(adata);
+
+ // Play
+ g_print ("Start pipeline...\n");
+ ret = gst_element_set_state (adata->pipeline, GST_STATE_PLAYING);
+ if (ret == GST_STATE_CHANGE_FAILURE) {
+ g_printerr ("Unable to set pipeline state to the playing state\n");
+ }
+
+ _start_progress(adata);
+ } else if (strncmp (cmd, "p", 1) == 0) {
+ _stop_progress(adata);
+
+ // Pause
+ g_print ("Pause pipeline...\n");
+ ret = gst_element_set_state (adata->pipeline, GST_STATE_PAUSED);
+ if (ret == GST_STATE_CHANGE_FAILURE) {
+ g_printerr ("Unable to set pipeline state to the paused state\n");
+ }
+
+ _stop_stream(adata);
+ } else if (strncmp (cmd, "r", 1) == 0) {
+ _start_stream(adata);
+
+ // Resume
+ g_print ("Resume pipeline...\n");
+ ret = gst_element_set_state (adata->pipeline, GST_STATE_PLAYING);
+ if (ret == GST_STATE_CHANGE_FAILURE) {
+ g_printerr ("Unable to resume pipeline\n");
+ }
+
+ _start_progress(adata);
+ } else if (strncmp (cmd, "x", 1) == 0) {
+ _stop_progress(adata);
+
+ // Stop
+ g_print ("Stop pipeline...\n");
+ ret = gst_element_set_state (adata->pipeline, GST_STATE_NULL);
+ if (ret == GST_STATE_CHANGE_FAILURE) {
+ g_printerr ("Unable to set pipeline state to the null state\n");
+ }
+
+ _stop_stream(adata);
+ } else if (strncmp (cmd, "q", 1) == 0) {
+ GstState state, pending;
+
+ ret = gst_element_get_state (adata->pipeline, &state, &pending, GST_CLOCK_TIME_NONE);
+ if (ret == GST_STATE_CHANGE_FAILURE) {
+ g_printerr ("Unable to get pipeline state\n");
+ }
+
+ if (state != GST_STATE_NULL) {
+ _stop_progress(adata);
+ g_print ("Stop pipeline here......\n");
+ ret = gst_element_set_state (adata->pipeline, GST_STATE_NULL);
+ if (ret == GST_STATE_CHANGE_FAILURE) {
+ g_printerr ("Unable to set pipeline state to the null state\n");
+ }
+ _stop_stream(adata);
+ }
+
+ // Quit
+ g_print ("Quiting\n");
+ g_main_loop_quit (adata->main_loop);
+ } else if (strncmp (cmd, "e", 1) == 0) {
+ // Seek
+ g_print ("Seek\n");
+ sub_menu = CURRENT_STATUS_POSITION;
+ g_print ("Input seek position:\n");
+ return;
+ } else if (sub_menu == CURRENT_STATUS_POSITION) {
+ GstSeekFlags seek_flag = TRUE;
+ gboolean result = FALSE;
+ GstEvent *event = NULL;
+ gint64 g_time = atoi(cmd);
+ g_time = g_time * GST_MSECOND;
+
+ if (seek_flag)
+ seek_flag = GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE;
+ else
+ seek_flag = GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT;
+
+ event = gst_event_new_seek(1.0, GST_FORMAT_TIME, seek_flag,
+ GST_SEEK_TYPE_SET, g_time,
+ GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
+ if (event)
+ result = gst_element_send_event(adata->pipeline, event);
+ if (result)
+ g_print ("send seek event\n");
+
+ sub_menu = CURRENT_STATUS_MAINMENU;
+ } else {
+ g_printerr ("Unknown command!\n");
+ }
+
+ print_menu();
+}
+
+static gboolean input (GIOChannel * channel, GIOCondition condition,
+ gpointer data)
+{
+ gchar buf[MAX_STRING_LEN];
+ gsize read;
+ GError *error = NULL;
+
+ g_io_channel_read_chars (channel, buf, MAX_STRING_LEN, &read, &error);
+ buf[read] = '\0';
+ g_strstrip (buf);
+ g_print ("Typed %s\n", buf);
+ interpret (buf, data);
+
+ return TRUE;
+}
+
+int main (int argc, char *argv[])
+{
+ AppData adata;
+ GIOChannel *stdin_channel;
+ GstBus *bus;
+ guint bus_watch_id;
+
+ memset (&adata, 0, sizeof (adata));
+ adata.duration = GST_CLOCK_TIME_NONE;
+
+ _prepare_stream(&adata);
+
+ // Create and form pipeline
+ gst_init (&argc, &argv);
+
+ adata.pipeline = gst_pipeline_new ("test-pipeline");
+
+ bus = gst_pipeline_get_bus (GST_PIPELINE (adata.pipeline));
+ bus_watch_id = gst_bus_add_watch (bus, _bus_cb, &adata);
+ gst_object_unref (bus);
+
+ adata.source = gst_element_factory_make ("filesrc", "source");
+ adata.queue = gst_element_factory_make ("queue", "queue");
+
+#ifdef IS_AAC
+ adata.parser = gst_element_factory_make ("aacparse", "parser");
+#else /* IS_MP3 */
+ adata.parser = gst_element_factory_make ("mpegaudioparse", "parser");
+#endif
+
+ adata.compressed_sink = gst_element_factory_make ("tinycompresssink", "compressed_sink");
+ if (!adata.compressed_sink) {
+ g_printerr ("Compressed elements were not created\n");
+ return -1;
+ }
+
+ adata.file_path = argv[1];
+ g_object_set (G_OBJECT (adata.source), "location", argv[1], NULL);
+ g_object_set (G_OBJECT (adata.compressed_sink), "sync", TRUE, NULL);
+
+ if (!adata.pipeline || !adata.source || !adata.queue || !adata.parser) {
+ g_printerr ("Not all elements were created\n");
+ return -1;
+ }
+
+ gst_bin_add_many (GST_BIN (adata.pipeline), adata.source, adata.queue,
+ adata.parser, adata.compressed_sink, NULL);
+ if (gst_element_link_many (adata.source, adata.queue, adata.parser,
+ adata.compressed_sink, NULL) != TRUE) {
+ g_printerr ("Elements could not be linked\n");
+ return -1;
+ }
+
+ print_menu ();
+
+ adata.main_loop = g_main_loop_new (NULL, FALSE);
+ stdin_channel = g_io_channel_unix_new (0);
+
+ g_io_channel_set_flags (stdin_channel, G_IO_FLAG_NONBLOCK, NULL);
+ g_io_add_watch (stdin_channel, G_IO_IN, (GIOFunc) input, &adata);
+
+ g_main_loop_run (adata.main_loop);
+
+ gst_element_set_state(adata.pipeline, GST_STATE_NULL);
+ g_source_remove (bus_watch_id);
+
+ g_main_loop_unref(adata.main_loop);
+
+ _unprepare_stream(&adata);
+
+ return 0;
+}