summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.am9
-rw-r--r--configure.ac15
-rw-r--r--deadbeef.h7
-rw-r--r--main.c309
-rw-r--r--plugins/gtkui/Makefile.am15
-rw-r--r--plugins/gtkui/callbacks.c (renamed from callbacks.c)0
-rw-r--r--plugins/gtkui/callbacks.h (renamed from callbacks.h)0
-rw-r--r--plugins/gtkui/deadbeef.glade (renamed from deadbeef.glade)0
-rw-r--r--plugins/gtkui/deadbeef.gladep (renamed from deadbeef.gladep)0
-rw-r--r--plugins/gtkui/drawing.h (renamed from drawing.h)0
-rw-r--r--plugins/gtkui/gdkdrawing.c (renamed from gdkdrawing.c)0
-rw-r--r--plugins/gtkui/gtkplaylist.c (renamed from gtkplaylist.c)0
-rw-r--r--plugins/gtkui/gtkplaylist.h (renamed from gtkplaylist.h)0
-rw-r--r--plugins/gtkui/gtksession.c (renamed from gtksession.c)0
-rw-r--r--plugins/gtkui/gtkui.c343
-rw-r--r--plugins/gtkui/interface.c (renamed from interface.c)0
-rw-r--r--plugins/gtkui/interface.h (renamed from interface.h)0
17 files changed, 438 insertions, 260 deletions
diff --git a/Makefile.am b/Makefile.am
index 0bf99b0e..b1e67241 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -16,7 +16,8 @@ SUBDIRS = gme/Game_Music_Emu-0.5.2\
${WAVPACK_DIR}\
${SNDFILE_DIR}\
${VFS_CURL_DIR}\
- ${CDDA_DIR}
+ ${CDDA_DIR}\
+ ${GTKUI_DIR}
dumbpath=@top_srcdir@/dumb
sidpath=@top_srcdir@/sid/sidplay-libs-2.1.0
@@ -27,8 +28,7 @@ bin_PROGRAMS = deadbeef
deadbeef_SOURCES =\
main.c common.h deadbeef.h\
plugins.c plugins.h moduleconf.h\
- callbacks.c interface.c support.c callbacks.h interface.h support.h\
- playlist.c playlist.h gtkplaylist.c gtkplaylist.h\
+ playlist.c playlist.h \
streamer.c streamer.h\
progress.c progress.h\
codec.c codec.h\
@@ -40,8 +40,7 @@ deadbeef_SOURCES =\
threading_pthread.c threading.h\
md5/md5.c md5/md5.h md5/md5_loc.h\
volume.c volume.h\
- drawing.h gdkdrawing.c\
- session.h session.c gtksession.c\
+ session.h session.c \
junklib.h junklib.c utf8.c utf8.h\
optmath.h\
vfs.c vfs.h vfs_stdio.c\
diff --git a/configure.ac b/configure.ac
index 9613e33c..b55e861e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -39,7 +39,8 @@ test "x$prefix" = xNONE && prefix=$ac_default_prefix
CFLAGS="$CFLAGS -D_GNU_SOURCE -DLIBDIR=\\\"$libdir\\\" -DPREFIX=\\\"$prefix\\\""
CPPFLAGS="$CFLAGS"
-PKG_CHECK_MODULES(DEPS, gtk+-2.0 >= 2.12 gthread-2.0 glib-2.0 samplerate alsa)
+PKG_CHECK_MODULES(DEPS, samplerate alsa)
+PKG_CHECK_MODULES(GTKUI_DEPS, gtk+-2.0 >= 2.12 gthread-2.0 glib-2.0, HAVE_GTK=1)
AX_CHECK_COMPILER_FLAGS(-msse2, SIMD_FLAGS="$SIMD_FLAGS -msse2";HAVE_SSE2=1, [])
if test ${HAVE_SSE2}; then
@@ -143,6 +144,16 @@ if test ${HAVE_CDIO} && test ${HAVE_CDDB}; then
AC_SUBST(CDDA_DIR)
fi
+dnl gtkui plugin
+AM_CONDITIONAL(HAVE_GTK, test $HAVE_GTK)
+if test ${HAVE_GTK}; then
+ GTKUI_DIR="plugins/gtkui"
+ AC_SUBST(GTKUI_DEPS_CFLAGS)
+ AC_SUBST(GTKUI_DEPS_LIBS)
+ AC_SUBST(GTKUI_DIR)
+fi
+
+
dnl print summary
echo
echo "plugin summary:"
@@ -172,6 +183,7 @@ PRINT_PLUGIN_INFO([sndfile],[PCM (wav,aiff,etc) player based on libsndfile],[tes
PRINT_PLUGIN_INFO([vfs_curl],[http/ftp streaming support],[test $HAVE_CURL])
dnl PRINT_PLUGIN_INFO([faad2],[aac/mp4 player],[test $HAVE_FAAD && test $HAVE_MP4FF])
PRINT_PLUGIN_INFO([cdda],[cd audio player],[test $HAVE_CDIO && test $HAVE_CDDB])
+PRINT_PLUGIN_INFO([gtkui],[GTK user interface],[test $HAVE_GTK])
echo
AC_OUTPUT([
@@ -192,6 +204,7 @@ plugins/wavpack/Makefile
plugins/sndfile/Makefile
plugins/vfs_curl/Makefile
plugins/cdda/Makefile
+plugins/gtkui/Makefile
deadbeef.desktop
])
diff --git a/deadbeef.h b/deadbeef.h
index 8dfa1296..4c4c0fd1 100644
--- a/deadbeef.h
+++ b/deadbeef.h
@@ -412,6 +412,13 @@ typedef struct DB_vfs_s {
unsigned streaming : 1;
} DB_vfs_t;
+// gui plugin
+// implements pretty much anything it wants
+// works mostly like misc plugin, except we need separate type for that
+typedef struct DB_gui_s {
+ DB_plugin_t plugin;
+} DB_gui_t;
+
#ifdef __cplusplus
}
#endif
diff --git a/main.c b/main.c
index fc079dae..8b0d0ce7 100644
--- a/main.c
+++ b/main.c
@@ -15,7 +15,6 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <gtk/gtk.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
@@ -33,19 +32,13 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
-#include "interface.h"
-#include "callbacks.h"
-#include "support.h"
#include "playlist.h"
#include "playback.h"
#include "unistd.h"
#include "threading.h"
#include "messagepump.h"
-#include "gtkplaylist.h"
#include "codec.h"
#include "streamer.h"
-#include "search.h"
-#include "progress.h"
#include "conf.h"
#include "volume.h"
#include "session.h"
@@ -61,116 +54,6 @@ char dbconfdir[1024]; // $HOME/.config/deadbeef
char defpl[1024]; // $HOME/.config/deadbeef/default.dbpl
char sessfile[1024]; // $HOME/.config/deadbeef/session
-// main widgets
-GtkWidget *mainwin;
-GtkWidget *searchwin;
-GtkStatusIcon *trayicon;
-GtkWidget *traymenu;
-
-// playlist configuration structures
-gtkplaylist_t main_playlist;
-gtkplaylist_t search_playlist;
-
-// update status bar and window title
-static int sb_context_id = -1;
-static char sb_text[512];
-static float last_songpos = -1;
-
-void
-update_songinfo (void) {
- char sbtext_new[512] = "-";
- float songpos = last_songpos;
-
- int daystotal = (int)pl_totaltime / (3600*24);
- int hourtotal = ((int)pl_totaltime / 3600) % 24;
- int mintotal = ((int)pl_totaltime/60) % 60;
- int sectotal = ((int)pl_totaltime) % 60;
-
- char totaltime_str[512] = "";
- if (daystotal == 0)
- snprintf (totaltime_str, sizeof (totaltime_str), "%d:%02d:%02d", hourtotal, mintotal, sectotal);
-
- else if (daystotal == 1)
- snprintf (totaltime_str, sizeof (totaltime_str), "1 day %d:%02d:%02d", hourtotal, mintotal, sectotal);
-
- else
- snprintf (totaltime_str, sizeof (totaltime_str), "%d days %d:%02d:%02d", daystotal, hourtotal, mintotal, sectotal);
-
- if (p_isstopped ()) {
- snprintf (sbtext_new, sizeof (sbtext_new), "Stopped | %s total playtime", totaltime_str);
- songpos = 0;
- }
- else if (str_playing_song.decoder) {
-// codec_lock ();
- DB_decoder_t *c = str_playing_song.decoder;
- float playpos = streamer_get_playpos ();
- int minpos = playpos / 60;
- int secpos = playpos - minpos * 60;
- int mindur = str_playing_song._duration / 60;
- int secdur = str_playing_song._duration - mindur * 60;
-
- const char *mode = c->info.channels == 1 ? "Mono" : "Stereo";
- int samplerate = c->info.samplerate;
- int bitspersample = c->info.bps;
- songpos = playpos;
-// codec_unlock ();
-
- char t[100];
- if (str_playing_song._duration >= 0) {
- snprintf (t, sizeof (t), "%d:%02d", mindur, secdur);
- }
- else {
- strcpy (t, "-:--");
- }
-
- char sbitrate[20] = "";
-#if 0 // NOTE: do not enable that for stable branch yet
- int bitrate = streamer_get_bitrate ();
- if (bitrate > 0) {
- snprintf (sbitrate, sizeof (sbitrate), "%d kbps ", bitrate);
- }
-#endif
- const char *spaused = p_ispaused () ? "Paused | " : "";
- snprintf (sbtext_new, sizeof (sbtext_new), "%s%s %s| %dHz | %d bit | %s | %d:%02d / %s | %d songs | %s total playtime", spaused, str_playing_song.filetype ? str_playing_song.filetype:"-", sbitrate, samplerate, bitspersample, mode, minpos, secpos, t, pl_getcount (), totaltime_str);
- }
-
- if (strcmp (sbtext_new, sb_text)) {
- strcpy (sb_text, sbtext_new);
-
- // form statusline
- GDK_THREADS_ENTER();
- // FIXME: don't update if window is not visible
- GtkStatusbar *sb = GTK_STATUSBAR (lookup_widget (mainwin, "statusbar"));
- if (sb_context_id == -1) {
- sb_context_id = gtk_statusbar_get_context_id (sb, "msg");
- }
-
- gtk_statusbar_pop (sb, sb_context_id);
- gtk_statusbar_push (sb, sb_context_id, sb_text);
-
- GDK_THREADS_LEAVE();
- }
-
- if (songpos != last_songpos) {
- void seekbar_draw (GtkWidget *widget);
- void seekbar_expose (GtkWidget *widget, int x, int y, int w, int h);
- if (mainwin) {
- GtkWidget *widget = lookup_widget (mainwin, "seekbar");
- // translate volume to seekbar pixels
- songpos /= str_playing_song._duration;
- songpos *= widget->allocation.width;
- if ((int)(songpos*2) != (int)(last_songpos*2)) {
- GDK_THREADS_ENTER();
- seekbar_draw (widget);
- seekbar_expose (widget, 0, 0, widget->allocation.width, widget->allocation.height);
- GDK_THREADS_LEAVE();
- last_songpos = songpos;
- }
- }
- }
-}
-
-
// -1 error, program must exit with error code -1
// 0 proceed normally as nothing happened
// 1 no error, but program must exit with error code 0
@@ -236,7 +119,9 @@ exec_command_line (const char *cmdline, int len, int filter) {
// add files
if (!queue) {
pl_free ();
- main_playlist.row = -1;
+ // <placeholder>
+ // reset selection in playlist
+ guiplug_reset_selection ();
}
while (parg < pend) {
char resolved[PATH_MAX];
@@ -316,17 +201,17 @@ server_update (void) {
int size;
if ((size = recv (s2, str, 2048, 0)) >= 0) {
if (size == 1 && str[0] == 0) {
- GDK_THREADS_ENTER();
- gtk_widget_show (mainwin);
- gtk_window_present (GTK_WINDOW (mainwin));
- GDK_THREADS_LEAVE();
+ // <placeholder>
+ // should notify gui plugin that user tried to run
+ // application while already running
+ guiplug_showwindow ();
}
else {
int res = exec_command_line (str, size, 0);
if (res == 2) {
- GDK_THREADS_ENTER();
- gtkpl_playsong (&main_playlist);
- GDK_THREADS_LEAVE();
+ // <placeholder>
+ // play a song, notify gui plugin
+ guiplug_play_current_song ();
}
}
}
@@ -369,60 +254,47 @@ player_thread (uintptr_t ctx) {
}
break;
case M_TERMINATE:
- GDK_THREADS_ENTER();
- gtk_widget_hide (mainwin);
- gtk_main_quit ();
- GDK_THREADS_LEAVE();
+ // <placeholder>
+ // tell gui plugin to shut down
+ // FIXME: cleanup properly on main thread
+ guiplug_shutdown ();
return;
case M_SONGCHANGED:
{
int from = p1;
int to = p2;
- gtkpl_songchanged_wrapper (from, to);
+ // <placeholder>
+ // notify gui that song was changed
+ // probably using DB_EV_SONGCHANGED
+ guiplug_songchanged (from, to);
plug_trigger_event (DB_EV_SONGCHANGED, 0);
}
break;
case M_PLAYSONG:
- gtkpl_playsong (&main_playlist);
- if (playlist_current_ptr) {
- GDK_THREADS_ENTER();
- gtkpl_redraw_pl_row (&main_playlist, pl_get_idx_of (playlist_current_ptr), playlist_current_ptr);
- GDK_THREADS_LEAVE();
- }
+ // <placeholder>
+ // start a track
+ guiplug_start_current_track ();
break;
case M_TRACKCHANGED:
- {
- playItem_t *it = pl_get_for_idx (p1);
- if (it) {
- GDK_THREADS_ENTER();
- gtkpl_redraw_pl_row (&main_playlist, p1, it);
- if (it == playlist_current_ptr) {
- gtkpl_current_track_changed (it);
- }
- GDK_THREADS_LEAVE();
- }
- }
+ // <placeholder>
+ // notify gui that track information was changed
+ guiplug_track_changed (p1);
break;
case M_PLAYSONGNUM:
- GDK_THREADS_ENTER();
- gtkpl_playsongnum (p1);
- GDK_THREADS_LEAVE();
+ // <placeholder>
+ // start track by number in p1
+ guiplug_start_track (p1);
break;
case M_STOPSONG:
- //p_stop ();
streamer_set_nextsong (-2, 0);
break;
case M_NEXTSONG:
- GDK_THREADS_ENTER();
p_stop ();
pl_nextsong (1);
- GDK_THREADS_LEAVE();
break;
case M_PREVSONG:
- GDK_THREADS_ENTER();
p_stop ();
pl_prevsong ();
- GDK_THREADS_LEAVE();
break;
case M_PAUSESONG:
if (p_ispaused ()) {
@@ -431,52 +303,50 @@ player_thread (uintptr_t ctx) {
else {
p_pause ();
}
-
- GDK_THREADS_ENTER();
+ // <placeholder>
+ // notify that current track was paused
if (playlist_current_ptr) {
- gtkpl_redraw_pl_row (&main_playlist, pl_get_idx_of (playlist_current_ptr), playlist_current_ptr);
+ guiplug_track_paused (pl_get_idx_of (playlist_current_ptr));
}
- GDK_THREADS_LEAVE();
break;
case M_PLAYRANDOM:
- GDK_THREADS_ENTER();
- gtkpl_randomsong ();
- GDK_THREADS_LEAVE();
+ // <placeholder>
+ // play random song
+ guiplug_start_random ();
break;
case M_ADDDIR:
- {
- // long time processing
-// float t1 = (float)clock () / CLOCKS_PER_SEC;
- gtkpl_add_dir (&main_playlist, (char *)ctx);
-// float t2 = (float)clock () / CLOCKS_PER_SEC;
-// printf ("time: %f\n", t2-t1);
- }
+ // <placeholder>
+ // * let guiplug know that addition is in progress
+ // * call it back on every file
+ // * let guiplug know that addition is done
+ guiplug_add_dir ((char *)ctx);
break;
case M_ADDDIRS:
- {
- // long time processing
-// float t1 = (float)clock () / CLOCKS_PER_SEC;
- gtkpl_add_dirs (&main_playlist, (GSList *)ctx);
-// float t2 = (float)clock () / CLOCKS_PER_SEC;
-// printf ("time: %f\n", t2-t1);
- }
+ // <placeholder>
+ // same as above, but for many folders
+ guiplug_add_dirs ((GSList *)ctx);
break;
case M_ADDFILES:
- gtkpl_add_files (&main_playlist, (GSList *)ctx);
+ // <placeholder>
+ // same as above but for many files
+ guiplug_add_files ((GSList *)ctx);
break;
case M_OPENFILES:
p_stop ();
- gtkpl_add_files (&main_playlist, (GSList *)ctx);
- gtkpl_playsong (&main_playlist);
+ // <placeholder>
+ // open many files and start 1st of them
+ guiplug_open_files ((GSList *)ctx);
break;
case M_FMDRAGDROP:
- gtkpl_add_fm_dropped_files (&main_playlist, (char *)ctx, p1, p2);
+ // <placeholder>
+ // handle drag-n-drop from filemanager
+ // that should be handled internally in ui plugin
+ guiplug_add_fm_dropped_files ((char *)ctx, p1, p2)
break;
case M_PLAYLISTREFRESH:
- GDK_THREADS_ENTER();
- playlist_refresh ();
- search_refresh ();
- GDK_THREADS_LEAVE();
+ // <placeholder>
+ // refresh all playlist windows
+ guiplug_refresh_playlist ();
break;
case M_CONFIGCHANGED:
palsa_configchanged ();
@@ -486,77 +356,8 @@ player_thread (uintptr_t ctx) {
}
}
usleep(50000);
- update_songinfo ();
- }
-}
-
-gboolean
-on_trayicon_scroll_event (GtkWidget *widget,
- GdkEventScroll *event,
- gpointer user_data)
-{
- float vol = volume_get_db ();
- if (event->direction == GDK_SCROLL_UP || event->direction == GDK_SCROLL_RIGHT) {
- vol += 1;
- }
- else if (event->direction == GDK_SCROLL_DOWN || event->direction == GDK_SCROLL_LEFT) {
- vol -= 1;
+ guiplug_frameupdate ();
}
- if (vol > 0) {
- vol = 0;
- }
- else if (vol < -60) {
- vol = -60;
- }
- volume_set_db (vol);
- GtkWidget *volumebar = lookup_widget (mainwin, "volumebar");
- volumebar_draw (volumebar);
- volumebar_expose (volumebar, 0, 0, volumebar->allocation.width, volumebar->allocation.height);
- return FALSE;
-}
-
-#if GTK_MINOR_VERSION<=14
-gboolean
-on_trayicon_activate (GtkWidget *widget,
- GdkEvent *event,
- gpointer user_data)
-{
- if (GTK_WIDGET_VISIBLE (mainwin)) {
- gtk_widget_hide (mainwin);
- }
- else {
- gtk_widget_show (mainwin);
- gtk_window_present (GTK_WINDOW (mainwin));
- }
- return FALSE;
-}
-#endif
-
-gboolean
-on_trayicon_button_press_event (GtkWidget *widget,
- GdkEventButton *event,
- gpointer user_data)
-{
- if (event->button == 1) {
- if (GTK_WIDGET_VISIBLE (mainwin)) {
- gtk_widget_hide (mainwin);
- }
- else {
- gtk_widget_show (mainwin);
- gtk_window_present (GTK_WINDOW (mainwin));
- }
- }
- return FALSE;
-}
-
-gboolean
-on_trayicon_popup_menu (GtkWidget *widget,
- guint button,
- guint time,
- gpointer user_data)
-{
- gtk_menu_popup (GTK_MENU (traymenu), NULL, NULL, gtk_status_icon_position_menu, trayicon, button, time);
- return FALSE;
}
void
diff --git a/plugins/gtkui/Makefile.am b/plugins/gtkui/Makefile.am
new file mode 100644
index 00000000..13ace983
--- /dev/null
+++ b/plugins/gtkui/Makefile.am
@@ -0,0 +1,15 @@
+#if HAVE_GTK
+#gtkuidir = $(libdir)/$(PACKAGE)
+#pkglib_LTLIBRARIES = gtkui.la
+#gtkui_la_SOURCES = gtkui.c\
+# callbacks.c interface.c support.c callbacks.h interface.h support.h\
+# gtkplaylist.c gtkplaylist.h\
+# drawing.h gdkdrawing.c\
+# gtksession.c
+#
+#
+#gtkui_la_LDFLAGS = -module
+#
+#gtkui_la_LIBADD = $(LDADD) $(GTKUI_DEPS_LIBS)
+#AM_CFLAGS = -std=c99 $(GTKUI_DEPS_CFLAGS)
+#endif
diff --git a/callbacks.c b/plugins/gtkui/callbacks.c
index 8d6d9bbf..8d6d9bbf 100644
--- a/callbacks.c
+++ b/plugins/gtkui/callbacks.c
diff --git a/callbacks.h b/plugins/gtkui/callbacks.h
index d2e3f61a..d2e3f61a 100644
--- a/callbacks.h
+++ b/plugins/gtkui/callbacks.h
diff --git a/deadbeef.glade b/plugins/gtkui/deadbeef.glade
index c71e3a65..c71e3a65 100644
--- a/deadbeef.glade
+++ b/plugins/gtkui/deadbeef.glade
diff --git a/deadbeef.gladep b/plugins/gtkui/deadbeef.gladep
index 22ea860c..22ea860c 100644
--- a/deadbeef.gladep
+++ b/plugins/gtkui/deadbeef.gladep
diff --git a/drawing.h b/plugins/gtkui/drawing.h
index 23c350b6..23c350b6 100644
--- a/drawing.h
+++ b/plugins/gtkui/drawing.h
diff --git a/gdkdrawing.c b/plugins/gtkui/gdkdrawing.c
index 621ee92e..621ee92e 100644
--- a/gdkdrawing.c
+++ b/plugins/gtkui/gdkdrawing.c
diff --git a/gtkplaylist.c b/plugins/gtkui/gtkplaylist.c
index cef45ea4..cef45ea4 100644
--- a/gtkplaylist.c
+++ b/plugins/gtkui/gtkplaylist.c
diff --git a/gtkplaylist.h b/plugins/gtkui/gtkplaylist.h
index 2e827839..2e827839 100644
--- a/gtkplaylist.h
+++ b/plugins/gtkui/gtkplaylist.h
diff --git a/gtksession.c b/plugins/gtkui/gtksession.c
index e24706b6..e24706b6 100644
--- a/gtksession.c
+++ b/plugins/gtkui/gtksession.c
diff --git a/plugins/gtkui/gtkui.c b/plugins/gtkui/gtkui.c
new file mode 100644
index 00000000..c5a87056
--- /dev/null
+++ b/plugins/gtkui/gtkui.c
@@ -0,0 +1,343 @@
+/*
+ DeaDBeeF - ultimate music player for GNU/Linux systems with X11
+ Copyright (C) 2009 Alexey Yakovenko
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+#include "../../deadbeef.h"
+#include <gtk/gtk.h>
+#include "gtkplaylist.h"
+#include "search.h"
+#include "progress.h"
+#include "interface.h"
+#include "callbacks.h"
+#include "support.h"
+
+// main widgets
+GtkWidget *mainwin;
+GtkWidget *searchwin;
+GtkStatusIcon *trayicon;
+GtkWidget *traymenu;
+
+// playlist configuration structures
+gtkplaylist_t main_playlist;
+gtkplaylist_t search_playlist;
+
+// update status bar and window title
+static int sb_context_id = -1;
+static char sb_text[512];
+static float last_songpos = -1;
+
+static void
+update_songinfo (void) {
+ char sbtext_new[512] = "-";
+ float songpos = last_songpos;
+
+ int daystotal = (int)pl_totaltime / (3600*24);
+ int hourtotal = ((int)pl_totaltime / 3600) % 24;
+ int mintotal = ((int)pl_totaltime/60) % 60;
+ int sectotal = ((int)pl_totaltime) % 60;
+
+ char totaltime_str[512] = "";
+ if (daystotal == 0)
+ snprintf (totaltime_str, sizeof (totaltime_str), "%d:%02d:%02d", hourtotal, mintotal, sectotal);
+
+ else if (daystotal == 1)
+ snprintf (totaltime_str, sizeof (totaltime_str), "1 day %d:%02d:%02d", hourtotal, mintotal, sectotal);
+
+ else
+ snprintf (totaltime_str, sizeof (totaltime_str), "%d days %d:%02d:%02d", daystotal, hourtotal, mintotal, sectotal);
+
+ if (p_isstopped ()) {
+ snprintf (sbtext_new, sizeof (sbtext_new), "Stopped | %s total playtime", totaltime_str);
+ songpos = 0;
+ }
+ else if (str_playing_song.decoder) {
+// codec_lock ();
+ DB_decoder_t *c = str_playing_song.decoder;
+ float playpos = streamer_get_playpos ();
+ int minpos = playpos / 60;
+ int secpos = playpos - minpos * 60;
+ int mindur = str_playing_song._duration / 60;
+ int secdur = str_playing_song._duration - mindur * 60;
+
+ const char *mode = c->info.channels == 1 ? "Mono" : "Stereo";
+ int samplerate = c->info.samplerate;
+ int bitspersample = c->info.bps;
+ songpos = playpos;
+// codec_unlock ();
+
+ char t[100];
+ if (str_playing_song._duration >= 0) {
+ snprintf (t, sizeof (t), "%d:%02d", mindur, secdur);
+ }
+ else {
+ strcpy (t, "-:--");
+ }
+
+ char sbitrate[20] = "";
+#if 0 // NOTE: do not enable that for stable branch yet
+ int bitrate = streamer_get_bitrate ();
+ if (bitrate > 0) {
+ snprintf (sbitrate, sizeof (sbitrate), "%d kbps ", bitrate);
+ }
+#endif
+ const char *spaused = p_ispaused () ? "Paused | " : "";
+ snprintf (sbtext_new, sizeof (sbtext_new), "%s%s %s| %dHz | %d bit | %s | %d:%02d / %s | %d songs | %s total playtime", spaused, str_playing_song.filetype ? str_playing_song.filetype:"-", sbitrate, samplerate, bitspersample, mode, minpos, secpos, t, pl_getcount (), totaltime_str);
+ }
+
+ if (strcmp (sbtext_new, sb_text)) {
+ strcpy (sb_text, sbtext_new);
+
+ // form statusline
+ GDK_THREADS_ENTER();
+ // FIXME: don't update if window is not visible
+ GtkStatusbar *sb = GTK_STATUSBAR (lookup_widget (mainwin, "statusbar"));
+ if (sb_context_id == -1) {
+ sb_context_id = gtk_statusbar_get_context_id (sb, "msg");
+ }
+
+ gtk_statusbar_pop (sb, sb_context_id);
+ gtk_statusbar_push (sb, sb_context_id, sb_text);
+
+ GDK_THREADS_LEAVE();
+ }
+
+ if (songpos != last_songpos) {
+ void seekbar_draw (GtkWidget *widget);
+ void seekbar_expose (GtkWidget *widget, int x, int y, int w, int h);
+ if (mainwin) {
+ GtkWidget *widget = lookup_widget (mainwin, "seekbar");
+ // translate volume to seekbar pixels
+ songpos /= str_playing_song._duration;
+ songpos *= widget->allocation.width;
+ if ((int)(songpos*2) != (int)(last_songpos*2)) {
+ GDK_THREADS_ENTER();
+ seekbar_draw (widget);
+ seekbar_expose (widget, 0, 0, widget->allocation.width, widget->allocation.height);
+ GDK_THREADS_LEAVE();
+ last_songpos = songpos;
+ }
+ }
+ }
+}
+
+gboolean
+on_trayicon_scroll_event (GtkWidget *widget,
+ GdkEventScroll *event,
+ gpointer user_data)
+{
+ float vol = volume_get_db ();
+ if (event->direction == GDK_SCROLL_UP || event->direction == GDK_SCROLL_RIGHT) {
+ vol += 1;
+ }
+ else if (event->direction == GDK_SCROLL_DOWN || event->direction == GDK_SCROLL_LEFT) {
+ vol -= 1;
+ }
+ if (vol > 0) {
+ vol = 0;
+ }
+ else if (vol < -60) {
+ vol = -60;
+ }
+ volume_set_db (vol);
+ GtkWidget *volumebar = lookup_widget (mainwin, "volumebar");
+ volumebar_draw (volumebar);
+ volumebar_expose (volumebar, 0, 0, volumebar->allocation.width, volumebar->allocation.height);
+ return FALSE;
+}
+
+#if GTK_MINOR_VERSION<=14
+gboolean
+on_trayicon_activate (GtkWidget *widget,
+ GdkEvent *event,
+ gpointer user_data)
+{
+ if (GTK_WIDGET_VISIBLE (mainwin)) {
+ gtk_widget_hide (mainwin);
+ }
+ else {
+ gtk_widget_show (mainwin);
+ gtk_window_present (GTK_WINDOW (mainwin));
+ }
+ return FALSE;
+}
+#endif
+
+gboolean
+on_trayicon_button_press_event (GtkWidget *widget,
+ GdkEventButton *event,
+ gpointer user_data)
+{
+ if (event->button == 1) {
+ if (GTK_WIDGET_VISIBLE (mainwin)) {
+ gtk_widget_hide (mainwin);
+ }
+ else {
+ gtk_widget_show (mainwin);
+ gtk_window_present (GTK_WINDOW (mainwin));
+ }
+ }
+ return FALSE;
+}
+
+gboolean
+on_trayicon_popup_menu (GtkWidget *widget,
+ guint button,
+ guint time,
+ gpointer user_data)
+{
+ gtk_menu_popup (GTK_MENU (traymenu), NULL, NULL, gtk_status_icon_position_menu, trayicon, button, time);
+ return FALSE;
+}
+
+void
+guiplug_showwindow (void) {
+ GDK_THREADS_ENTER();
+ gtk_widget_show (mainwin);
+ gtk_window_present (GTK_WINDOW (mainwin));
+ GDK_THREADS_LEAVE();
+}
+
+void
+guiplug_play_current_song (void) {
+ GDK_THREADS_ENTER();
+ gtkpl_playsong (&main_playlist);
+ GDK_THREADS_LEAVE();
+}
+
+void
+guiplug_shutdown (void) {
+ GDK_THREADS_ENTER();
+ gtk_widget_hide (mainwin);
+ gtk_main_quit ();
+ GDK_THREADS_LEAVE();
+}
+
+void
+guiplug_songchanged (int from, int to) {
+ gtkpl_songchanged_wrapper (from, to);
+}
+
+void
+guiplug_start_current_track (void) {
+ gtkpl_playsong (&main_playlist);
+ if (playlist_current_ptr) {
+ GDK_THREADS_ENTER();
+ gtkpl_redraw_pl_row (&main_playlist, pl_get_idx_of (playlist_current_ptr), playlist_current_ptr);
+ GDK_THREADS_LEAVE();
+ }
+}
+void
+guiplug_track_changed (int idx) {
+ playItem_t *it = pl_get_for_idx (idx);
+ if (it) {
+ GDK_THREADS_ENTER();
+ gtkpl_redraw_pl_row (&main_playlist, idx, it);
+ if (it == playlist_current_ptr) {
+ gtkpl_current_track_changed (it);
+ }
+ GDK_THREADS_LEAVE();
+ }
+}
+
+void
+guiplug_start_track (int idx) {
+ GDK_THREADS_ENTER();
+ gtkpl_playsongnum (idx);
+ GDK_THREADS_LEAVE();
+}
+
+void
+guiplug_track_paused (int idx) {
+ GDK_THREADS_ENTER();
+ gtkpl_redraw_pl_row (&main_playlist, idx, pl_get_for_idx (idx));
+ GDK_THREADS_LEAVE();
+}
+
+void
+guiplug_start_random (void) {
+ GDK_THREADS_ENTER();
+ gtkpl_randomsong ();
+ GDK_THREADS_LEAVE();
+}
+
+void
+guiplug_add_dir (const char *dir) {
+ // long time processing
+ // float t1 = (float)clock () / CLOCKS_PER_SEC;
+ gtkpl_add_dir (&main_playlist, dir);
+ // float t2 = (float)clock () / CLOCKS_PER_SEC;
+ // printf ("time: %f\n", t2-t1);
+}
+
+void
+guiplug_add_dirs (GSList *dirs) {
+ // long time processing
+ // float t1 = (float)clock () / CLOCKS_PER_SEC;
+ gtkpl_add_dirs (&main_playlist, dirs);
+ // float t2 = (float)clock () / CLOCKS_PER_SEC;
+ // printf ("time: %f\n", t2-t1);
+}
+
+void
+guiplug_add_files (GSList *files) {
+ gtkpl_add_files (&main_playlist, files);
+}
+
+void
+guiplug_open_files (GSList *files) {
+ gtkpl_add_files (&main_playlist, files);
+ gtkpl_playsong (&main_playlist);
+}
+
+void
+guiplug_refresh_playlist (void) {
+ GDK_THREADS_ENTER();
+ playlist_refresh ();
+ search_refresh ();
+ GDK_THREADS_LEAVE();
+}
+
+void
+guiplug_add_fm_dropped_files (char *files, int p1, int p2) {
+ gtkpl_add_fm_dropped_files (&main_playlist, (char *)ctx, p1, p2);
+}
+
+void
+guiplug_frameupdate (void) {
+ update_songinfo ();
+}
+
+void
+guiplug_reset_selection (void) {
+ search_playlist.row = -1;
+ main_playlist.row = -1;
+}
+
+// define plugin interface
+static DB_gui_t plugin = {
+ DB_PLUGIN_SET_API_VERSION
+ .plugin.version_major = 0,
+ .plugin.version_minor = 1,
+ .plugin.type = DB_PLUGIN_MISC,
+ .plugin.name = "Standard GTK2 user interface",
+ .plugin.descr = "",
+ .plugin.author = "Alexey Yakovenko",
+ .plugin.email = "waker@users.sourceforge.net",
+ .plugin.website = "http://deadbeef.sf.net",
+ .plugin.start = gtkui_start,
+ .plugin.stop = gtkui_stop
+};
diff --git a/interface.c b/plugins/gtkui/interface.c
index 88acb8d0..88acb8d0 100644
--- a/interface.c
+++ b/plugins/gtkui/interface.c
diff --git a/interface.h b/plugins/gtkui/interface.h
index f9b470ff..f9b470ff 100644
--- a/interface.h
+++ b/plugins/gtkui/interface.h