diff --git a/Makefile.am b/Makefile.am
index b6ca254..1189184 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -6,6 +6,9 @@ ACLOCAL_AMFLAGS = -Wno-portability
EXTRA_DIST += TODO
SUBDIRS = src docs
+desktopdir = $(datadir)/applications
+dist_desktop_DATA = gst123.desktop
+
# === Release auxillary rule configuration ===
RELEASE_DESTHOST = space.twc.de
RELEASE_DESTPATH = public_html/gst123
diff --git a/configure.ac b/configure.ac
index 35058d2..8121d72 100644
--- a/configure.ac
+++ b/configure.ac
@@ -60,7 +60,7 @@ AC_DEFUN([AC_GSTREAMER_REQUIREMENTS],
if test x$GST_1_0 = x1; then
AC_MSG_NOTICE([Building gst123 using gstreamer version 1.0])
- PKG_CHECK_MODULES(GSTREAMER, gstreamer-1.0 gstreamer-base-1.0 gstreamer-video-1.0)
+ PKG_CHECK_MODULES(GSTREAMER, gstreamer-1.0 gstreamer-base-1.0 gstreamer-video-1.0 gstreamer-audio-1.0 gstreamer-tag-1.0)
else
dnl gstreamer-0.10 development package installed?
PKG_CHECK_MODULES(GSTREAMER_0_10, gstreamer-0.10, GST_0_10=1, GST_0_10=0)
@@ -82,7 +82,7 @@ dnl
AC_DEFUN([AC_GSTREAMER_GTK_REQUIREMENTS],
[
dnl We need GLib with friends
- PKG_CHECK_MODULES(GSTREAMER_GTK, gtk+-2.0)
+ PKG_CHECK_MODULES(GSTREAMER_GTK, gtk+-3.0)
AC_SUBST(GSTREAMER_GTK_CFLAGS)
AC_SUBST(GSTREAMER_GTKLIBS)
])
diff --git a/docs/gst123.1 b/docs/gst123.1
index 9f2064d..e77b279 100644
--- a/docs/gst123.1
+++ b/docs/gst123.1
@@ -2,12 +2,12 @@
.\" Title: gst123
.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author]
.\" Generator: DocBook XSL Stylesheets v1.79.1
-.\" Date: 07/18/2017
+.\" Date: 12/11/2019
.\" Manual: \ \&
.\" Source: \ \&
.\" Language: English
.\"
-.TH "GST123" "1" "07/18/2017" "\ \&" "\ \&"
+.TH "GST123" "1" "12/11/2019" "\ \&" "\ \&"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
@@ -219,7 +219,7 @@ Show keyboard help\&.
.RE
.SH "CONFIGURATION FILE"
.sp
-During start, gst123 will read ~/\&.gst123rc, if this file exists\&. Empty lines and lines starting with a # are ignored\&. The following commands are available:
+During start, gst123 will read ~/\&.config/gst123rc, if this file exists\&. Empty lines and lines starting with a # are ignored\&. The following commands are available:
.PP
audio_output [=]
.RS 4
diff --git a/docs/gst123.1.txt b/docs/gst123.1.txt
index 719da47..a544b0f 100644
--- a/docs/gst123.1.txt
+++ b/docs/gst123.1.txt
@@ -149,8 +149,9 @@ q::
CONFIGURATION FILE
------------------
-During start, gst123 will read ~/.gst123rc, if this file exists. Empty lines
-and lines starting with a # are ignored. The following commands are available:
+During start, gst123 will read ~/.config/gst123rc, if this file exists. Empty
+lines and lines starting with a # are ignored. The following commands are
+available:
audio_output [=]::
This sets the default audio driver and the default audio device. It has
diff --git a/gst123.desktop b/gst123.desktop
new file mode 100644
index 0000000..572f7fd
--- /dev/null
+++ b/gst123.desktop
@@ -0,0 +1,17 @@
+[Desktop Entry]
+Encoding=UTF-8
+Name=gst123
+GenericName=Multimedia player
+GenericName[ru]=Проигрыватель мультимедия
+GenericName[uk]=Програвач мультимедіа
+Comment=Simple multimedia player based on gstreamer
+Comment[ru]=Простой проигрыватель мультимедиа
+Comment[uk]=Простий програвач мультимедіа
+Categories=AudioVideo;
+Exec=gst123 --quiet %U
+Icon=multimedia-player
+Terminal=false
+Type=Application
+MimeType=video/dv;video/mpeg;video/x-mpeg;video/msvideo;video/quicktime;video/x-anim;video/x-avi;video/x-ms-asf;video/x-ms-wmv;video/x-msvideo;video/x-nsv;video/x-flc;video/x-fli;application/ogg;application/x-ogg;video/x-ogm+ogg;audio/x-vorbis+ogg;application/x-matroska;audio/x-matroska;video/x-matroska;video/webm;audio/webm;audio/x-mp3;audio/x-mpeg;audio/mpeg;audio/x-wav;audio/x-mpegurl;audio/x-scpls;audio/x-m4a;audio/x-ms-asf;audio/x-ms-asx;audio/x-ms-wax;application/vnd.rn-realmedia;audio/x-real-audio;audio/x-pn-realaudio;application/x-flac;audio/x-flac;application/x-shockwave-flash;misc/ultravox;audio/vnd.rn-realaudio;audio/x-pn-aiff;audio/x-pn-au;audio/x-pn-wav;audio/x-pn-windows-acm;image/vnd.rn-realpix;video/vnd.rn-realvideo;audio/x-pn-realaudio-plugin;application/x-extension-mp4;audio/mp4;video/mp4;video/mp4v-es;x-content/video-vcd;x-content/video-svcd;x-content/video-dvd;x-content/audio-cdda;x-content/audio-player;video/x-flv;application/xspf+xml;
+StartupNotify=false
+NoDisplay=true
diff --git a/src/configfile.cc b/src/configfile.cc
index a7f998d..7514192 100644
--- a/src/configfile.cc
+++ b/src/configfile.cc
@@ -48,12 +48,22 @@ ConfigFile::visualization() const
ConfigFile::ConfigFile()
{
- char *home = getenv ("HOME");
- if (!home)
- return;
+ char *home = getenv ("XDG_CONFIG_HOME");
+ string filename;
- string filename = home;
- filename += "/.gst123rc";
+ if (home)
+ {
+ filename = home;
+ filename += "/gst123rc";
+ }
+ else
+ {
+ home = getenv ("HOME");
+ if (!home)
+ return;
+ filename = home;
+ filename += "/.config/gst123rc";
+ }
MicroConf cfg (filename);
if (!cfg.open_ok())
diff --git a/src/gst123.cc b/src/gst123.cc
index 3f14cec..5690ac9 100644
--- a/src/gst123.cc
+++ b/src/gst123.cc
@@ -18,10 +18,11 @@
* Boston, MA 02111-1307, USA.
*/
#include
+#include
#include
+#include
#include
#include
-#include
#include
#include
#include
@@ -469,17 +470,23 @@ struct Player : public KeyHandler
}
}
+#define VOLUME_STEPS 20
+
void
set_volume (gdouble volume_change)
{
gdouble cur_volume;
- g_object_get (G_OBJECT (playbin), "volume", &cur_volume, NULL);
- cur_volume += volume_change;
- Msg::update_status ("Volume: %4.1f%%", cur_volume * 100);
+ cur_volume = gst_stream_volume_get_volume (GST_STREAM_VOLUME (playbin),
+ GST_STREAM_VOLUME_FORMAT_CUBIC);
+
+ cur_volume = round ((cur_volume + volume_change) * VOLUME_STEPS) / VOLUME_STEPS;
+ cur_volume = CLAMP (cur_volume, 0.0, 10.0);
- if ((cur_volume >= 0) && (cur_volume <= 10))
- g_object_set (G_OBJECT (playbin), "volume", cur_volume, NULL);
+ gst_stream_volume_set_volume (GST_STREAM_VOLUME (playbin),
+ GST_STREAM_VOLUME_FORMAT_CUBIC, cur_volume);
+
+ Msg::update_status ("Volume: %4.1f%%", cur_volume * 100);
}
void
@@ -1204,9 +1211,11 @@ main (gint argc,
g_usignal_add (SIGINT, sigint_usr_code, &player);
/* now run */
- terminal.init (player.loop, &player);
+ if (isatty(0))
+ terminal.init (player.loop, &player);
g_main_loop_run (player.loop);
- terminal.end();
+ if (isatty(0))
+ terminal.end();
gtk_interface.end();
/* also clean up */
diff --git a/src/gtkinterface.cc b/src/gtkinterface.cc
index 06c7ce1..d4e3e90 100644
--- a/src/gtkinterface.cc
+++ b/src/gtkinterface.cc
@@ -39,6 +39,14 @@ key_press_event_cb (GtkWidget *widget, GdkEventKey *event, gpointer data)
return gtk_interface->handle_keypress_event (event);
}
+static gboolean
+button_press_event_cb (GtkWidget *widget, GdkEventButton *event, gpointer data)
+{
+ GtkInterface *gtk_interface = static_cast (data);
+
+ return gtk_interface->handle_buttonpress_event (event);
+}
+
static gboolean
motion_notify_event_cb (GtkWidget *widget, GdkEventMotion *event, gpointer data)
{
@@ -106,7 +114,9 @@ GtkInterface::init (int *argc, char ***argv, KeyHandler *handler)
{
gtk_init (argc, argv);
gtk_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_icon_name (GTK_WINDOW (gtk_window), "multimedia-player");
g_signal_connect (G_OBJECT (gtk_window), "key-press-event", G_CALLBACK (key_press_event_cb), this);
+ g_signal_connect (G_OBJECT (gtk_window), "button-press-event", G_CALLBACK (button_press_event_cb), this);
g_signal_connect (G_OBJECT (gtk_window), "motion-notify-event", G_CALLBACK (motion_notify_event_cb), this);
g_signal_connect (G_OBJECT (gtk_window), "delete-event", G_CALLBACK (close_cb), this);
g_signal_connect (G_OBJECT (gtk_window), "window-state-event", G_CALLBACK (window_state_event_cb), this);
@@ -119,12 +129,20 @@ GtkInterface::init (int *argc, char ***argv, KeyHandler *handler)
video_fullscreen = Options::the().fullscreen; // initially fullscreen?
// make background black
- GdkColor color;
- gdk_color_parse ("black", &color);
- gtk_widget_modify_bg (gtk_window, GTK_STATE_NORMAL, &color);
+ GtkCssProvider* provider = gtk_css_provider_new();
+ GdkDisplay* display = gdk_display_get_default();
+ GdkScreen* screen = gdk_display_get_default_screen(display);
+
+ gtk_style_context_add_provider_for_screen(screen,
+ GTK_STYLE_PROVIDER (provider),
+ GTK_STYLE_PROVIDER_PRIORITY_USER);
+
+ gtk_css_provider_load_from_data(GTK_CSS_PROVIDER(provider),
+ "GtkWindow {background-color: black;}\n", -1, NULL);
+ g_object_unref(provider);
visible_cursor = NULL;
- invisible_cursor = gdk_cursor_new (GDK_BLANK_CURSOR);
+ invisible_cursor = gdk_cursor_new_for_display (gdk_display_get_default (), GDK_BLANK_CURSOR);
cursor_timeout = 3;
g_timeout_add (500, (GSourceFunc) timeout_cb, this);
@@ -136,15 +154,15 @@ GtkInterface::init (int *argc, char ***argv, KeyHandler *handler)
gtk_window_visible = false;
/* initialize map from Gdk keysyms to KeyHandler codes */
- key_map[GDK_Page_Up] = KEY_HANDLER_PAGE_UP;
- key_map[GDK_Page_Down] = KEY_HANDLER_PAGE_DOWN;
- key_map[GDK_Left] = KEY_HANDLER_LEFT;
- key_map[GDK_Right] = KEY_HANDLER_RIGHT;
- key_map[GDK_Up] = KEY_HANDLER_UP;
- key_map[GDK_Down] = KEY_HANDLER_DOWN;
- key_map[GDK_BackSpace] = KEY_HANDLER_BACKSPACE;
- key_map[GDK_KP_Add] = '+';
- key_map[GDK_KP_Subtract] = '-';
+ key_map[GDK_KEY_Page_Up] = KEY_HANDLER_PAGE_UP;
+ key_map[GDK_KEY_Page_Down] = KEY_HANDLER_PAGE_DOWN;
+ key_map[GDK_KEY_Left] = KEY_HANDLER_LEFT;
+ key_map[GDK_KEY_Right] = KEY_HANDLER_RIGHT;
+ key_map[GDK_KEY_Up] = KEY_HANDLER_UP;
+ key_map[GDK_KEY_Down] = KEY_HANDLER_DOWN;
+ key_map[GDK_KEY_BackSpace] = KEY_HANDLER_BACKSPACE;
+ key_map[GDK_KEY_KP_Add] = '+';
+ key_map[GDK_KEY_KP_Subtract] = '-';
}
bool
@@ -152,7 +170,7 @@ GtkInterface::is_fullscreen()
{
g_return_val_if_fail (gtk_window != NULL && gtk_window_visible, false);
- GdkWindowState state = gdk_window_get_state (GDK_WINDOW (gtk_window->window));
+ GdkWindowState state = gdk_window_get_state (gtk_widget_get_window (gtk_window));
return (state & GDK_WINDOW_STATE_FULLSCREEN);
}
@@ -161,7 +179,7 @@ GtkInterface::is_maximized()
{
g_return_val_if_fail (gtk_window != NULL && gtk_window_visible, false);
- GdkWindowState state = gdk_window_get_state (GDK_WINDOW (gtk_window->window));
+ GdkWindowState state = gdk_window_get_state (gtk_widget_get_window (gtk_window));
return (state & GDK_WINDOW_STATE_MAXIMIZED);
}
@@ -209,7 +227,7 @@ GtkInterface::show()
// get cursor, so we can restore it after hiding it
if (!visible_cursor)
- visible_cursor = gdk_window_get_cursor (GDK_WINDOW (gtk_window->window));
+ visible_cursor = gdk_window_get_cursor (gtk_widget_get_window (gtk_window));
// sync, to make the window really visible before we return
gdk_display_sync (gdk_display_get_default());
@@ -270,7 +288,7 @@ GtkInterface::hide()
if (video_maximized)
gtk_window_unmaximize (GTK_WINDOW (gtk_window));
- gtk_widget_hide_all (gtk_window);
+ gtk_widget_hide (gtk_window);
screen_saver (RESUME);
gtk_window_visible = false;
@@ -341,10 +359,10 @@ GtkInterface::set_opacity (double alpha_change)
{
double alpha;
- alpha = gtk_window_get_opacity (GTK_WINDOW (gtk_window));
+ alpha = gtk_widget_get_opacity (gtk_window);
alpha = CLAMP (alpha + alpha_change, 0.0, 1.0);
Msg::update_status ("Opacity: %3.1f%%", alpha * 100);
- gtk_window_set_opacity (GTK_WINDOW (gtk_window), alpha);
+ gtk_widget_set_opacity (gtk_window, alpha);
}
}
@@ -366,6 +384,17 @@ GtkInterface::handle_keypress_event (GdkEventKey *event)
return false;
}
+bool
+GtkInterface::handle_buttonpress_event (GdkEventButton *event)
+{
+ if (event->button == 1 && event->state == 0)
+ {
+ key_handler->process_input (' ');
+ return true;
+ }
+ return false;
+}
+
void
GtkInterface::set_title (const string& title)
{
@@ -380,7 +409,7 @@ GtkInterface::handle_timeout()
{
if (cursor_timeout == 0)
{
- gdk_window_set_cursor (GDK_WINDOW (gtk_window->window), invisible_cursor);
+ gdk_window_set_cursor (gtk_widget_get_window (gtk_window), invisible_cursor);
cursor_timeout = -1;
}
else if (cursor_timeout > 0)
@@ -396,7 +425,7 @@ GtkInterface::handle_motion_notify_event (GdkEventMotion *event)
{
if (gtk_window != NULL && gtk_window_visible)
{
- gdk_window_set_cursor (GDK_WINDOW (gtk_window->window), visible_cursor);
+ gdk_window_set_cursor (gtk_widget_get_window (gtk_window), visible_cursor);
cursor_timeout = 3;
}
return true;
@@ -438,10 +467,10 @@ GtkInterface::handle_close()
void
GtkInterface::screen_saver (ScreenSaverSetting setting)
{
- GdkWindow *window = GTK_WIDGET (gtk_window)->window;
+ GdkWindow *window = gtk_widget_get_window (gtk_window);
if (gtk_window != NULL && window)
{
- guint64 wid = GDK_WINDOW_XWINDOW (window);
+ guint64 wid = GDK_WINDOW_XID (window);
const char *setting_str = (setting == SUSPEND) ? "suspend" : "resume";
diff --git a/src/gtkinterface.h b/src/gtkinterface.h
index 924f467..549ed95 100644
--- a/src/gtkinterface.h
+++ b/src/gtkinterface.h
@@ -60,6 +60,7 @@ class GtkInterface
gulong window_xid_nolock() const;
void toggle_fullscreen();
bool handle_keypress_event (GdkEventKey *event);
+ bool handle_buttonpress_event (GdkEventButton *event);
bool handle_motion_notify_event (GdkEventMotion *event);
bool handle_window_state_event (GdkEventWindowState *event);
bool handle_timeout();