Make sure audacious-code compiles
[monky] / src / audacious.c
index ee28fe9..49342e8 100644 (file)
@@ -1,9 +1,9 @@
-/* -------------------------------------------------------------------------
+/* -*- mode: c; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*-
+ * vim: ts=4 sw=4 noet ai cindent syntax=c
+ *
  * audacious.c:  conky support for audacious music player
  *
- * Copyright (C) 2005  Philip Kovacs kovacsp3@comcast.net
- * 
- * $Id$
+ * Copyright (C) 2005-2007 Philip Kovacs pkovacs@users.sourceforge.net
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  *
  * You should have received a copy of the GNU Lesser 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
- * --------------------------------------------------------------------------- */
-
-#include <pthread.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <glib.h>
-#include <audacious/beepctrl.h>
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
+ * USA.
+ *
+ */
 
 #include "config.h"
 #include "conky.h"
+#include "logging.h"
 #include "audacious.h"
 
+#include <glib.h>
+#ifndef AUDACIOUS_LEGACY
+#include <glib-object.h>
+#include <audacious/audctrl.h>
+#include <audacious/dbus.h>
+#else
+#include <audacious/beepctrl.h>
+#define audacious_remote_is_running(x)                         \
+       xmms_remote_is_running(x)
+#define audacious_remote_is_paused(x)                          \
+       xmms_remote_is_paused(x)
+#define audacious_remote_is_playing(x)                         \
+       xmms_remote_is_playing(x)
+#define audacious_remote_get_playlist_pos(x)           \
+       xmms_remote_get_playlist_pos(x)
+#define audacious_remote_get_playlist_title(x, y)      \
+       xmms_remote_get_playlist_title(x, y)
+#define audacious_remote_get_playlist_time(x, y)       \
+       xmms_remote_get_playlist_time(x, y)
+#define audacious_remote_get_output_time(x)                    \
+       xmms_remote_get_output_time(x)
+#define audacious_remote_get_info(w, x, y, z)          \
+       xmms_remote_get_info(w, x, y, z)
+#define audacious_remote_get_playlist_file(x, y)       \
+       xmms_remote_get_playlist_file(x, y)
+#define audacious_remote_get_playlist_length(x)                \
+       xmms_remote_get_playlist_length(x)
+#endif
+
 /* access to this item array is synchronized */
 static audacious_t audacious_items;
 
 /* -----------------------------------------
  * Conky update function for audacious data.
  * ----------------------------------------- */
-void update_audacious(void)
+int update_audacious(void)
 {
-    /* 
-      The worker thread is updating audacious_items array asynchronously to the main 
-      conky thread.  We merely copy the audacious_items array into the main thread's 
-      info structure when the main thread's update cycle fires. 
-    */
-    pthread_mutex_lock(&info.audacious.item_mutex);
-    memcpy(&info.audacious.items,audacious_items,sizeof(audacious_items));
-    pthread_mutex_unlock(&info.audacious.item_mutex);
+       /* The worker thread is updating audacious_items array asynchronously
+        * to the main conky thread.
+        * We merely copy the audacious_items array into the main thread's info
+        * structure when the main thread's update cycle fires. */
+       if (!info.audacious.p_timed_thread) {
+               if (create_audacious_thread() != 0) {
+                       CRIT_ERR(NULL, NULL, "unable to create audacious thread!");
+               }
+               timed_thread_register(info.audacious.p_timed_thread,
+                       &info.audacious.p_timed_thread);
+       }
+
+       timed_thread_lock(info.audacious.p_timed_thread);
+       memcpy(&info.audacious.items, audacious_items, sizeof(audacious_items));
+       timed_thread_unlock(info.audacious.p_timed_thread);
+       return 0;
 }
 
-
-/* ------------------------------------------------------------
+/* ---------------------------------------------------------
  * Create a worker thread for audacious media player status.
  *
- * Returns 0 on success, -1 on error. 
- * ------------------------------------------------------------*/
+ * Returns 0 on success, -1 on error.
+ * --------------------------------------------------------- */
 int create_audacious_thread(void)
 {
-    /* Is a worker is thread already running? */
-    if (info.audacious.thread)
-       return(-1);
-
-    /* Joinable thread for audacious activity */
-    pthread_attr_init(&info.audacious.thread_attr);
-    pthread_attr_setdetachstate(&info.audacious.thread_attr, PTHREAD_CREATE_JOINABLE);
-    /* Init mutexes */
-    pthread_mutex_init(&info.audacious.item_mutex, NULL);
-    pthread_mutex_init(&info.audacious.runnable_mutex, NULL);
-    /* Init runnable condition for worker thread */
-    pthread_mutex_lock(&info.audacious.runnable_mutex);
-    info.audacious.runnable=1;
-    pthread_mutex_unlock(&info.audacious.runnable_mutex);
-    if (pthread_create(&info.audacious.thread, &info.audacious.thread_attr, audacious_thread_func, NULL))
-        return(-1);
-
-    return 0;
+       if (!info.audacious.p_timed_thread) {
+               info.audacious.p_timed_thread =
+                       timed_thread_create(audacious_thread_func, NULL,
+                       info.music_player_interval * 1000000);
+       }
+
+       if (!info.audacious.p_timed_thread
+                       || timed_thread_run(info.audacious.p_timed_thread)) {
+               return -1;
+       }
+
+       return 0;
 }
 
-/* ------------------------------------------------
- * Destroy audacious player status thread. 
+/* ---------------------------------------
+ * Destroy audacious player status thread.
  *
  * Returns 0 on success, -1 on error.
- * ------------------------------------------------ */
+ * --------------------------------------- */
 int destroy_audacious_thread(void)
 {
-    /* Is a worker is thread running? If not, no error. */
-    if (!info.audacious.thread)
-        return(0);
-
-    /* Signal audacious thread to terminate */
-    pthread_mutex_lock(&info.audacious.runnable_mutex);
-    info.audacious.runnable=0;
-    pthread_mutex_unlock(&info.audacious.runnable_mutex);
-    /* Destroy thread attribute and wait for thread */
-    pthread_attr_destroy(&info.audacious.thread_attr);
-    if (pthread_join(info.audacious.thread, NULL))
-        return(-1);
-    /* Destroy mutexes */
-    pthread_mutex_destroy(&info.audacious.item_mutex);
-    pthread_mutex_destroy(&info.audacious.runnable_mutex);
-
-    info.audacious.thread=(pthread_t)0;
-    return 0;
+       /* Is a worker is thread running? If not, no error. */
+       if (info.audacious.p_timed_thread) {
+               timed_thread_destroy(info.audacious.p_timed_thread,
+                       &info.audacious.p_timed_thread);
+       }
+
+       return 0;
 }
 
 /* ---------------------------------------------------
  * Worker thread function for audacious data sampling.
- * --------------------------------------------------- */ 
+ * --------------------------------------------------- */
+__attribute((noreturn))
 void *audacious_thread_func(void *pvoid)
 {
-    int runnable;
-    static audacious_t items;
-    gint session,playpos,frames,length;
-    gint rate,freq,chans;
-    gchar *psong,*pfilename;
-
-    pvoid=(void *)pvoid;  /* avoid warning */
-    session=0;
-    psong=NULL;
-    pfilename=NULL;
-
-    /* Grab the runnable signal.  Should be non-zero here or we do nothing. */
-    pthread_mutex_lock(&info.audacious.runnable_mutex);
-    runnable=info.audacious.runnable;
-    pthread_mutex_unlock(&info.audacious.runnable_mutex );
-
-    /* Loop until the main thread sets the runnable signal to 0. */
-    while(runnable) {
-
-        for (;;) {  /* convenience loop so we can break below */
-
-            if (!xmms_remote_is_running (session)) {
-                memset(&items,0,sizeof(items));
-                strcpy(items[AUDACIOUS_STATUS],"Not running");
-                break;
-            }
-
-            /* Player status */
-            if (xmms_remote_is_paused (session))
-                strcpy(items[AUDACIOUS_STATUS],"Paused");
-            else if (xmms_remote_is_playing (session))
-                 strcpy(items[AUDACIOUS_STATUS],"Playing");
-            else
-                 strcpy(items[AUDACIOUS_STATUS],"Stopped");
-
-            /* Current song title */
-            playpos = xmms_remote_get_playlist_pos (session);
-            psong = xmms_remote_get_playlist_title (session, playpos);
-            if (psong) {
-                strncpy(items[AUDACIOUS_TITLE],psong,sizeof(items[AUDACIOUS_TITLE])-1);
-                g_free (psong);
-                psong=NULL;
-            }
-
-            /* Current song length as MM:SS */
-            frames = xmms_remote_get_playlist_time (session,playpos);
-            length = frames / 1000;
-            snprintf(items[AUDACIOUS_LENGTH],sizeof(items[AUDACIOUS_LENGTH])-1,
-                     "%d:%.2d", length / 60, length % 60);
-
-            /* Current song length in seconds */
-            snprintf(items[AUDACIOUS_LENGTH_SECONDS],sizeof(items[AUDACIOUS_LENGTH_SECONDS])-1,
-                     "%d", length);
-
-            /* Current song position as MM:SS */
-            frames = xmms_remote_get_output_time (session);
-            length = frames / 1000;
-            snprintf(items[AUDACIOUS_POSITION],sizeof(items[AUDACIOUS_POSITION])-1,
-                     "%d:%.2d", length / 60, length % 60);
-
-            /* Current song position in seconds */
-            snprintf(items[AUDACIOUS_POSITION_SECONDS],sizeof(items[AUDACIOUS_POSITION_SECONDS])-1,
-                     "%d", length);
-
-            /* Current song bitrate */
-            xmms_remote_get_info (session, &rate, &freq, &chans);
-            snprintf(items[AUDACIOUS_BITRATE],sizeof(items[AUDACIOUS_BITRATE])-1, "%d", rate);
-
-            /* Current song frequency */
-            snprintf(items[AUDACIOUS_FREQUENCY],sizeof(items[AUDACIOUS_FREQUENCY])-1, "%d", freq);
-
-            /* Current song channels */
-            snprintf(items[AUDACIOUS_CHANNELS],sizeof(items[AUDACIOUS_CHANNELS])-1, "%d", chans);
-
-            /* Current song filename */
-            pfilename = xmms_remote_get_playlist_file (session,playpos);
-            if (pfilename) {
-                strncpy(items[AUDACIOUS_FILENAME],pfilename,sizeof(items[AUDACIOUS_FILENAME])-1);
-                g_free (pfilename);
-                pfilename=NULL;
-            }
-
-            /* Length of the Playlist (number of songs) */
-            length = xmms_remote_get_playlist_length (session);
-            snprintf(items[AUDACIOUS_PLAYLIST_LENGTH],sizeof(items[AUDACIOUS_PLAYLIST_LENGTH])-1, "%d", length);
-
-            /* Playlist position (index of song) */
-            snprintf(items[AUDACIOUS_PLAYLIST_POSITION],sizeof(items[AUDACIOUS_PLAYLIST_POSITION])-1, "%d", playpos+1);
-
-            break;
-        }
-
-        /* Deliver the refreshed items array to audacious_items. */
-        pthread_mutex_lock(&info.audacious.item_mutex);
-        memcpy(&audacious_items,items,sizeof(items));
-        pthread_mutex_unlock(&info.audacious.item_mutex);
-
-        /* Grab the runnable signal for next loop. */
-        pthread_mutex_lock(&info.audacious.runnable_mutex);
-        runnable=info.audacious.runnable;
-        pthread_mutex_unlock(&info.audacious.runnable_mutex);
-
-        sleep(1);
-    }
-
-    pthread_exit(NULL);
+       static audacious_t items;
+       gint playpos, frames, length;
+       gint rate, freq, chans, vol;
+       gchar *psong, *pfilename;
+
+#ifndef AUDACIOUS_LEGACY
+       DBusGProxy *session = NULL;
+       DBusGConnection *connection = NULL;
+#else
+       gint session;
+#endif
+
+       pvoid = (void *) pvoid; /* avoid warning */
+       session = 0;
+       psong = NULL;
+       pfilename = NULL;
+
+#ifndef AUDACIOUS_LEGACY
+       g_type_init();
+       connection = dbus_g_bus_get(DBUS_BUS_SESSION, NULL);
+       if (!connection) {
+               CRIT_ERR(NULL, NULL, "unable to establish dbus connection");
+       }
+       session = dbus_g_proxy_new_for_name(connection, AUDACIOUS_DBUS_SERVICE,
+                       AUDACIOUS_DBUS_PATH, AUDACIOUS_DBUS_INTERFACE);
+       if (!session) {
+               CRIT_ERR(NULL, NULL, "unable to create dbus proxy");
+       }
+#endif /* AUDACIOUS_LEGACY */
+
+       /* Loop until the main thread resets the runnable signal. */
+       while (1) {
+
+               do {
+                       if (!audacious_remote_is_running(session)) {
+                               memset(&items, 0, sizeof(items));
+                               strcpy(items[AUDACIOUS_STATUS], "Not running");
+                               break;
+                       }
+
+                       /* Player status */
+                       if (audacious_remote_is_paused(session)) {
+                               strcpy(items[AUDACIOUS_STATUS], "Paused");
+                       } else if (audacious_remote_is_playing(session)) {
+                               strcpy(items[AUDACIOUS_STATUS], "Playing");
+                       } else {
+                               strcpy(items[AUDACIOUS_STATUS], "Stopped");
+                       }
+
+                       /* Current song title */
+                       playpos = audacious_remote_get_playlist_pos(session);
+                       psong = audacious_remote_get_playlist_title(session, playpos);
+                       if (psong) {
+                               strncpy(items[AUDACIOUS_TITLE], psong,
+                                               sizeof(items[AUDACIOUS_TITLE]) - 1);
+                               g_free(psong);
+                               psong = NULL;
+                       }
+
+                       /* Current song length as MM:SS */
+                       frames = audacious_remote_get_playlist_time(session, playpos);
+                       length = frames / 1000;
+                       snprintf(items[AUDACIOUS_LENGTH], sizeof(items[AUDACIOUS_LENGTH]) - 1,
+                                       "%d:%.2d", length / 60, length % 60);
+
+                       /* Current song length in seconds */
+                       snprintf(items[AUDACIOUS_LENGTH_SECONDS],
+                                       sizeof(items[AUDACIOUS_LENGTH_SECONDS]) - 1, "%d", length);
+
+                       /* Current song position as MM:SS */
+                       frames = audacious_remote_get_output_time(session);
+                       length = frames / 1000;
+                       snprintf(items[AUDACIOUS_POSITION],
+                                       sizeof(items[AUDACIOUS_POSITION]) - 1, "%d:%.2d", length / 60,
+                                       length % 60);
+
+                       /* Current song position in seconds */
+                       snprintf(items[AUDACIOUS_POSITION_SECONDS],
+                                       sizeof(items[AUDACIOUS_POSITION_SECONDS]) - 1, "%d", length);
+
+                       /* Current song bitrate */
+                       audacious_remote_get_info(session, &rate, &freq, &chans);
+                       snprintf(items[AUDACIOUS_BITRATE], sizeof(items[AUDACIOUS_BITRATE]) - 1,
+                                       "%d", rate);
+
+                       /* Current song frequency */
+                       snprintf(items[AUDACIOUS_FREQUENCY],
+                                       sizeof(items[AUDACIOUS_FREQUENCY]) - 1, "%d", freq);
+
+                       /* Current song channels */
+                       snprintf(items[AUDACIOUS_CHANNELS],
+                                       sizeof(items[AUDACIOUS_CHANNELS]) - 1, "%d", chans);
+
+                       /* Current song filename */
+                       pfilename = audacious_remote_get_playlist_file(session, playpos);
+                       if (pfilename) {
+                               strncpy(items[AUDACIOUS_FILENAME], pfilename,
+                                               sizeof(items[AUDACIOUS_FILENAME]) - 1);
+                               g_free(pfilename);
+                               pfilename = NULL;
+                       }
+
+                       /* Length of the Playlist (number of songs) */
+                       length = audacious_remote_get_playlist_length(session);
+                       snprintf(items[AUDACIOUS_PLAYLIST_LENGTH],
+                                       sizeof(items[AUDACIOUS_PLAYLIST_LENGTH]) - 1, "%d", length);
+
+                       /* Playlist position (index of song) */
+                       snprintf(items[AUDACIOUS_PLAYLIST_POSITION],
+                                       sizeof(items[AUDACIOUS_PLAYLIST_POSITION]) - 1, "%d", playpos + 1);
+                       /* Main volume */
+                       vol = audacious_remote_get_main_volume(session);
+                       snprintf(items[AUDACIOUS_MAIN_VOLUME],
+                                       sizeof(items[AUDACIOUS_MAIN_VOLUME]) - 1, "%d", vol);
+
+               } while (0);
+               /* Deliver the refreshed items array to audacious_items. */
+               timed_thread_lock(info.audacious.p_timed_thread);
+               memcpy(&audacious_items, items, sizeof(items));
+               timed_thread_unlock(info.audacious.p_timed_thread);
+
+               if (timed_thread_test(info.audacious.p_timed_thread, 0)) {
+#ifndef AUDACIOUS_LEGACY
+                       /* release reference to dbus proxy */
+                       g_object_unref(session);
+#endif
+                       timed_thread_exit(info.audacious.p_timed_thread);
+               }
+       }
 }