/* 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 3 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, see . */ #include #include #include #include #include #include #include #include "interface.h" #include "support.h" #include "playlist.h" #include "playback.h" #include "unistd.h" #include "threading.h" #include "messagepump.h" #include "messages.h" #include "gtkplaylist.h" #include "codec.h" #include "streamer.h" GtkWidget *mainwin; gtkplaylist_t main_playlist; gtkplaylist_t search_playlist; int psdl_terminate = 0; // update status bar and window title static int sb_context_id = -1; static char sb_text[512]; static int last_songpos = -1; void update_songinfo (void) { if (!mainwin) { return; } char sbtext_new[512] = "-"; int songpos = 0; if (p_ispaused ()) { strcpy (sbtext_new, "Paused"); songpos = 0; } else if (p_isstopped ()) { strcpy (sbtext_new, "Stopped"); } else if (playlist_current.codec) { codec_lock (); codec_t *c = playlist_current.codec; int minpos = c->info.position / 60; int secpos = c->info.position - minpos * 60; int mindur = playlist_current.duration / 60; int secdur = playlist_current.duration - mindur * 60; const char *mode = c->info.channels == 1 ? "Mono" : "Stereo"; int samplerate = c->info.samplesPerSecond; int bitspersample = c->info.bitsPerSample; float pos = c->info.position; int dur = playlist_current.duration; songpos = pos * 1000 / dur; codec_unlock (); snprintf (sbtext_new, 512, "[%s] %dHz | %d bit | %s | %d:%02d / %d:%02d | %d songs total", playlist_current.filetype ? playlist_current.filetype:"-", samplerate, bitspersample, mode, minpos, secpos, mindur, secdur, pl_getcount ()); } 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) { last_songpos = songpos; extern int g_disable_seekbar_handler; g_disable_seekbar_handler = 1; GtkRange *seekbar = GTK_RANGE (lookup_widget (mainwin, "playpos")); gtk_range_set_value (seekbar, songpos); g_disable_seekbar_handler = 0; } } void psdl_thread (uintptr_t ctx) { p_play (); while (!psdl_terminate) { uint32_t msg; uintptr_t ctx; uint32_t p1; uint32_t p2; while (messagepump_pop(&msg, &ctx, &p1, &p2) != -1) { switch (msg) { case M_SONGCHANGED: GDK_THREADS_ENTER(); // update window title int from = p1; int to = p2; if (from >= 0 || to >= 0) { if (to >= 0) { playItem_t *it = pl_get_for_idx (to); char str[600]; char dname[512]; pl_format_item_display_name (it, dname, 512); snprintf (str, 600, "DeaDBeeF - %s", dname); gtk_window_set_title (GTK_WINDOW (mainwin), str); } else { gtk_window_set_title (GTK_WINDOW (mainwin), "DeaDBeeF"); } } // update playlist view gtkpl_songchanged (&main_playlist, p1, p2); GDK_THREADS_LEAVE(); break; case M_PLAYSONG: GDK_THREADS_ENTER(); gtkpl_playsong (&main_playlist); GDK_THREADS_LEAVE(); break; case M_PLAYSONGNUM: GDK_THREADS_ENTER(); gtkpl_playsongnum (p1); GDK_THREADS_LEAVE(); break; case M_STOPSONG: p_stop (); GDK_THREADS_ENTER(); gtkpl_redraw_pl_row (&main_playlist, main_playlist.row); GDK_THREADS_LEAVE(); 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 ()) { p_unpause (); } else { p_pause (); } GDK_THREADS_ENTER(); gtkpl_redraw_pl_row (&main_playlist, main_playlist.row); GDK_THREADS_LEAVE(); break; case M_PLAYRANDOM: GDK_THREADS_ENTER(); gtkpl_randomsong (); GDK_THREADS_LEAVE(); break; case M_SONGSEEK: if (playlist_current.codec) { p_pause (); codec_lock (); playlist_current.codec->seek (p1 / 1000.f); codec_unlock (); p_unpause (); } break; case M_ADDDIR: // long time processing gtkpl_add_dir (&main_playlist, (char *)ctx); break; case M_ADDFILES: gtkpl_add_files (&main_playlist, (GSList *)ctx); break; case M_FMDRAGDROP: gtkpl_add_fm_dropped_files (&main_playlist, (char *)ctx, p1, p2); break; } } usleep(10000); update_songinfo (); } } int main (int argc, char *argv[]) { char *homedir = getenv ("HOME"); if (!homedir) { fprintf (stderr, "unable to find home directory. stopping.\n"); return -1; } char defpl[1024]; snprintf (defpl, 1024, "%s/.config/deadbeef/default.dbpl", homedir); char confdir[1024]; snprintf (confdir, 1024, "%s/.config", homedir); mkdir (confdir, 0755); char dbconfdir[1024]; snprintf (dbconfdir, 1024, "%s/.config/deadbeef", homedir); mkdir (dbconfdir, 0755); messagepump_init (); codec_init_locking (); streamer_init (); p_init (); thread_start (psdl_thread, 0); g_thread_init (NULL); add_pixmap_directory ("/usr/share/deadbeef/images"); gdk_threads_init (); gdk_threads_enter (); gtk_set_locale (); gtk_init (&argc, &argv); pl_load (defpl); mainwin = create_mainwin (); gtk_widget_show (mainwin); gtk_main (); gdk_threads_leave (); messagepump_free (); psdl_terminate = 1; p_free (); streamer_free (); codec_free_locking (); pl_save (defpl); pl_free (); return 0; }