Only pause/play with spacebar for now.
gst_discoverer_@GST_API_VERSION@_SOURCES = gst-discoverer.c
-gst_play_@GST_API_VERSION@_SOURCES = gst-play.c
+gst_play_@GST_API_VERSION@_SOURCES = gst-play.c gst-play-kb.c gst-play-kb.h
+
+noinst_HEADERS = gst-play-kb.h
CLEANFILES = $(bin_SCRIPTS) $(bin_PROGRAMS)
--- /dev/null
+/* GStreamer command line playback testing utility - keyboard handling helpers
+ *
+ * Copyright (C) 2013 Tim-Philipp Müller <tim centricular net>
+ * Copyright (C) 2013 Centricular Ltd
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "gst-play-kb.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#ifdef G_OS_UNIX
+#include <unistd.h>
+#include <termios.h>
+#endif
+
+#include <gst/gst.h>
+
+/* This is all not thread-safe, but doesn't have to be really */
+
+#ifdef G_OS_UNIX
+
+static struct termios term_settings;
+static gboolean term_settings_saved = FALSE;
+static GstPlayKbFunc kb_callback;
+static gpointer kb_callback_data;
+static gulong io_watch_id;
+
+static gboolean
+gst_play_kb_io_cb (GIOChannel * ioc, GIOCondition cond, gpointer user_data)
+{
+ GIOStatus status;
+
+ if (cond & G_IO_IN) {
+ gchar buf[16] = { 0, };
+ gsize read;
+
+ status = g_io_channel_read_chars (ioc, buf, sizeof (buf) - 1, &read, NULL);
+ if (status == G_IO_STATUS_ERROR)
+ return FALSE;
+ if (status == G_IO_STATUS_NORMAL) {
+ if (kb_callback)
+ kb_callback (buf, kb_callback_data);
+ }
+ }
+
+ return TRUE; /* call us again */
+}
+
+gboolean
+gst_play_kb_set_key_handler (GstPlayKbFunc kb_func, gpointer user_data)
+{
+ GIOChannel *ioc;
+ int flags;
+
+ if (!isatty (STDIN_FILENO)) {
+ GST_INFO ("stdin is not connected to a terminal");
+ return FALSE;
+ }
+
+ if (io_watch_id > 0) {
+ g_source_remove (io_watch_id);
+ io_watch_id = 0;
+ }
+
+ if (kb_func == NULL && term_settings_saved) {
+ /* restore terminal settings */
+ if (tcsetattr (STDIN_FILENO, TCSAFLUSH, &term_settings) == 0)
+ term_settings_saved = FALSE;
+ else
+ g_warning ("could not restore terminal attributes");
+
+ setvbuf (stdin, NULL, _IOLBF, 0);
+ }
+
+ if (kb_func != NULL) {
+ struct termios new_settings;
+
+ if (!term_settings_saved) {
+ if (tcgetattr (STDIN_FILENO, &term_settings) != 0) {
+ g_warning ("could not save terminal attributes");
+ return FALSE;
+ }
+ term_settings_saved = TRUE;
+
+ /* Echo off, canonical mode off, extended input processing off */
+ new_settings = term_settings;
+ new_settings.c_lflag &= ~(ECHO | ICANON | IEXTEN);
+
+ if (tcsetattr (STDIN_FILENO, TCSAFLUSH, &new_settings) != 0) {
+ g_warning ("Could not set terminal state");
+ return FALSE;
+ }
+ setvbuf (stdin, NULL, _IONBF, 0);
+ }
+ }
+
+ ioc = g_io_channel_unix_new (STDIN_FILENO);
+
+ /* make non-blocking */
+ flags = g_io_channel_get_flags (ioc);
+ g_io_channel_set_flags (ioc, flags | G_IO_FLAG_NONBLOCK, NULL);
+
+ io_watch_id = g_io_add_watch_full (ioc, G_PRIORITY_DEFAULT, G_IO_IN,
+ (GIOFunc) gst_play_kb_io_cb, user_data, NULL);
+ g_io_channel_unref (ioc);
+
+ kb_callback = kb_func;
+ kb_callback_data = user_data;
+
+ return TRUE;
+}
+
+#else /* !G_OS_UNIX */
+
+gboolean
+gst_play_kb_set_key_handler (GstPlayKbFunc key_func, gpointer user_data)
+{
+ GST_FIXME ("Keyboard handling for this OS needs to be implemented");
+}
+
+#endif /* !G_OS_UNIX */
--- /dev/null
+/* GStreamer command line playback testing utility - keyboard handling helpers
+ *
+ * Copyright (C) 2013 Tim-Philipp Müller <tim centricular net>
+ * Copyright (C) 2013 Centricular Ltd
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+#ifndef __GST_PLAY_KB_INCLUDED__
+#define __GST_PLAY_KB_INCLUDED__
+
+#include <glib.h>
+
+#define GST_PLAY_KB_KEY_UP "\033[A"
+#define GST_PLAY_KB_KEY_DOWN "\033[B"
+#define GST_PLAY_KB_KEY_RIGHT "\033[C"
+#define GST_PLAY_KB_KEY_LEFT "\033[D"
+
+typedef void (*GstPlayKbFunc) (const gchar * kb_input, gpointer user_data);
+
+gboolean gst_play_kb_set_key_handler (GstPlayKbFunc kb_func, gpointer user_data);
+
+#endif /* __GST_PLAY_KB_INCLUDED__ */
#include <gst/gst-i18n-app.h>
#include <gst/pbutils/pbutils.h>
#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "gst-play-kb.h"
GST_DEBUG_CATEGORY (play_debug);
#define GST_CAT_DEFAULT play_debug
gboolean buffering;
gboolean is_live;
+ GstState desired_state; /* as per user interaction, PAUSED or PLAYING */
+
/* configuration */
gboolean gapless;
} GstPlay;
play->buffering = FALSE;
play->is_live = FALSE;
+ play->desired_state = GST_STATE_PLAYING;
+
play->gapless = gapless;
if (gapless) {
g_signal_connect (play->playbin, "about-to-finish",
/* a 100% message means buffering is done */
if (play->buffering) {
play->buffering = FALSE;
- gst_element_set_state (play->playbin, GST_STATE_PLAYING);
+ gst_element_set_state (play->playbin, play->desired_state);
}
} else {
/* buffering... */
{
GstPlay *play = user_data;
gint64 pos = -1, dur = -1;
+ gchar status[64] = { 0, };
if (play->buffering)
return TRUE;
gst_element_query_position (play->playbin, GST_FORMAT_TIME, &pos);
gst_element_query_duration (play->playbin, GST_FORMAT_TIME, &dur);
+ if (play->desired_state == GST_STATE_PAUSED)
+ g_snprintf (status, sizeof (status), "Paused");
+ else
+ memset (status, ' ', sizeof (status) - 1);
+
if (pos >= 0 && dur > 0) {
gchar dstr[32], pstr[32];
pstr[9] = '\0';
g_snprintf (dstr, 32, "%" GST_TIME_FORMAT, GST_TIME_ARGS (dur));
dstr[9] = '\0';
- g_print ("%s / %s\r", pstr, dstr);
+ g_print ("%s / %s %s\r", pstr, dstr, status);
}
return TRUE;
g_object_set (play->playbin, "uri", next_uri, NULL);
- sret = gst_element_set_state (play->playbin, GST_STATE_PLAYING);
+ sret = gst_element_set_state (play->playbin, play->desired_state);
switch (sret) {
case GST_STATE_CHANGE_FAILURE:
/* ignore, we should get an error message posted on the bus */
}
}
+static void
+restore_terminal (void)
+{
+ gst_play_kb_set_key_handler (NULL, NULL);
+}
+
+static void
+toggle_paused (GstPlay * play)
+{
+ if (play->desired_state == GST_STATE_PLAYING)
+ play->desired_state = GST_STATE_PAUSED;
+ else
+ play->desired_state = GST_STATE_PLAYING;
+
+ if (!play->buffering) {
+ gst_element_set_state (play->playbin, play->desired_state);
+ } else if (play->desired_state == GST_STATE_PLAYING) {
+ g_print ("\nWill play as soon as buffering finishes)\n");
+ }
+}
+
+static void
+keyboard_cb (const gchar * key_input, gpointer user_data)
+{
+ GstPlay *play = (GstPlay *) user_data;
+
+ switch (g_ascii_tolower (key_input[0])) {
+ case ' ':
+ toggle_paused (play);
+ break;
+ case 27: /* ESC */
+ default:
+ GST_INFO ("keyboard input:");
+ while (*key_input)
+ GST_INFO (" code %3d", *key_input++);
+ break;
+ }
+}
+
int
main (int argc, char **argv)
{
GstPlay *play;
GPtrArray *playlist;
gboolean print_version = FALSE;
+ gboolean interactive = FALSE; /* FIXME: maybe enable by default? */
gboolean gapless = FALSE;
gboolean shuffle = FALSE;
gchar **filenames = NULL;
N_("Enable gapless playback"), NULL},
{"shuffle", 0, 0, G_OPTION_ARG_NONE, &shuffle,
N_("Shuffle playlist"), NULL},
+ {"interactive", 0, 0, G_OPTION_ARG_NONE, &interactive,
+ N_("interactive"), NULL},
{G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &filenames, NULL},
{NULL}
};
if (shuffle)
shuffle_uris (uris, num);
- /* play */
+ /* prepare */
play = play_new (uris, audio_sink, video_sink, gapless);
+ if (interactive) {
+ if (gst_play_kb_set_key_handler (keyboard_cb, play)) {
+ atexit (restore_terminal);
+ } else {
+ g_print ("Interactive keyboard handling in terminal not available.\n");
+ }
+ }
+
+ /* play */
do_play (play);
/* clean up */