2009-07-28 21:44:22 +00:00
|
|
|
/* -*- mode: c; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*-
|
|
|
|
*
|
|
|
|
* audacious.c: conky support for audacious music player
|
2006-11-03 20:54:52 +00:00
|
|
|
*
|
2007-08-10 20:09:43 +00:00
|
|
|
* Copyright (C) 2005-2007 Philip Kovacs pkovacs@users.sourceforge.net
|
2008-02-20 20:30:45 +00:00
|
|
|
*
|
2006-11-03 20:54:52 +00:00
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 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
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
2006-12-13 16:54:59 +00:00
|
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
2009-07-27 20:47:19 +00:00
|
|
|
* USA.
|
|
|
|
*
|
|
|
|
* vim: ts=4 sw=4 noet ai cindent syntax=c
|
|
|
|
*
|
|
|
|
*/
|
2006-11-03 20:54:52 +00:00
|
|
|
|
2008-12-15 21:40:24 +00:00
|
|
|
#include "config.h"
|
|
|
|
#include "conky.h"
|
|
|
|
#include "logging.h"
|
|
|
|
#include "audacious.h"
|
2007-11-17 04:13:20 +00:00
|
|
|
|
2006-11-03 20:54:52 +00:00
|
|
|
#include <glib.h>
|
2007-11-17 03:43:21 +00:00
|
|
|
#ifndef AUDACIOUS_LEGACY
|
|
|
|
#include <glib-object.h>
|
|
|
|
#include <audacious/audctrl.h>
|
|
|
|
#include <audacious/dbus.h>
|
|
|
|
#else
|
2006-11-03 20:54:52 +00:00
|
|
|
#include <audacious/beepctrl.h>
|
2008-02-20 20:30:45 +00:00
|
|
|
#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)
|
2007-11-17 03:43:21 +00:00
|
|
|
#endif
|
2006-11-03 20:54:52 +00:00
|
|
|
|
|
|
|
/* access to this item array is synchronized */
|
|
|
|
static audacious_t audacious_items;
|
|
|
|
|
|
|
|
/* -----------------------------------------
|
|
|
|
* Conky update function for audacious data.
|
|
|
|
* ----------------------------------------- */
|
|
|
|
void update_audacious(void)
|
|
|
|
{
|
2008-02-20 20:30:45 +00:00
|
|
|
/* 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) {
|
2008-03-17 22:27:20 +00:00
|
|
|
if (create_audacious_thread() != 0) {
|
2009-07-23 18:30:53 +00:00
|
|
|
CRIT_ERR(NULL, NULL, "unable to create audacious thread!");
|
2008-03-17 22:27:20 +00:00
|
|
|
}
|
|
|
|
timed_thread_register(info.audacious.p_timed_thread,
|
|
|
|
&info.audacious.p_timed_thread);
|
2008-02-20 20:30:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
2006-11-03 20:54:52 +00:00
|
|
|
}
|
|
|
|
|
2008-02-20 20:30:45 +00:00
|
|
|
/* ---------------------------------------------------------
|
2006-11-03 20:54:52 +00:00
|
|
|
* Create a worker thread for audacious media player status.
|
|
|
|
*
|
2008-02-20 20:30:45 +00:00
|
|
|
* Returns 0 on success, -1 on error.
|
|
|
|
* --------------------------------------------------------- */
|
2006-11-03 20:54:52 +00:00
|
|
|
int create_audacious_thread(void)
|
|
|
|
{
|
2008-02-20 20:30:45 +00:00
|
|
|
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;
|
2006-11-03 20:54:52 +00:00
|
|
|
}
|
|
|
|
|
2008-02-20 20:30:45 +00:00
|
|
|
/* ---------------------------------------
|
|
|
|
* Destroy audacious player status thread.
|
2006-11-03 20:54:52 +00:00
|
|
|
*
|
|
|
|
* Returns 0 on success, -1 on error.
|
2008-02-20 20:30:45 +00:00
|
|
|
* --------------------------------------- */
|
2006-11-03 20:54:52 +00:00
|
|
|
int destroy_audacious_thread(void)
|
|
|
|
{
|
2008-02-20 20:30:45 +00:00
|
|
|
/* Is a worker is thread running? If not, no error. */
|
2008-06-21 09:25:37 +00:00
|
|
|
if (info.audacious.p_timed_thread) {
|
|
|
|
timed_thread_destroy(info.audacious.p_timed_thread,
|
|
|
|
&info.audacious.p_timed_thread);
|
2008-02-20 20:30:45 +00:00
|
|
|
}
|
2006-11-03 20:54:52 +00:00
|
|
|
|
2008-02-20 20:30:45 +00:00
|
|
|
return 0;
|
2006-11-03 20:54:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ---------------------------------------------------
|
|
|
|
* Worker thread function for audacious data sampling.
|
2008-02-20 20:30:45 +00:00
|
|
|
* --------------------------------------------------- */
|
2008-06-19 06:17:53 +00:00
|
|
|
__attribute((noreturn))
|
2006-11-03 20:54:52 +00:00
|
|
|
void *audacious_thread_func(void *pvoid)
|
|
|
|
{
|
2008-02-20 20:30:45 +00:00
|
|
|
static audacious_t items;
|
|
|
|
gint playpos, frames, length;
|
2008-12-07 07:38:06 +00:00
|
|
|
gint rate, freq, chans, vol;
|
2008-02-20 20:30:45 +00:00
|
|
|
gchar *psong, *pfilename;
|
2006-12-23 06:01:16 +00:00
|
|
|
|
2007-11-17 03:43:21 +00:00
|
|
|
#ifndef AUDACIOUS_LEGACY
|
2008-02-20 20:30:45 +00:00
|
|
|
DBusGProxy *session = NULL;
|
|
|
|
DBusGConnection *connection = NULL;
|
2007-11-17 03:43:21 +00:00
|
|
|
#else
|
2008-02-20 20:30:45 +00:00
|
|
|
gint session;
|
2007-11-17 03:43:21 +00:00
|
|
|
#endif
|
|
|
|
|
2008-02-20 20:30:45 +00:00
|
|
|
pvoid = (void *) pvoid; /* avoid warning */
|
|
|
|
session = 0;
|
|
|
|
psong = NULL;
|
|
|
|
pfilename = NULL;
|
2006-12-23 06:01:16 +00:00
|
|
|
|
2007-11-17 03:43:21 +00:00
|
|
|
#ifndef AUDACIOUS_LEGACY
|
2008-02-20 20:30:45 +00:00
|
|
|
g_type_init();
|
|
|
|
connection = dbus_g_bus_get(DBUS_BUS_SESSION, NULL);
|
|
|
|
if (!connection) {
|
2009-07-23 18:30:53 +00:00
|
|
|
CRIT_ERR(NULL, NULL, "unable to establish dbus connection");
|
2008-02-20 20:30:45 +00:00
|
|
|
}
|
|
|
|
session = dbus_g_proxy_new_for_name(connection, AUDACIOUS_DBUS_SERVICE,
|
2008-04-10 22:45:45 +00:00
|
|
|
AUDACIOUS_DBUS_PATH, AUDACIOUS_DBUS_INTERFACE);
|
2008-02-20 20:30:45 +00:00
|
|
|
if (!session) {
|
2009-07-23 18:30:53 +00:00
|
|
|
CRIT_ERR(NULL, NULL, "unable to create dbus proxy");
|
2008-02-20 20:30:45 +00:00
|
|
|
}
|
2007-11-17 03:43:21 +00:00
|
|
|
#endif /* AUDACIOUS_LEGACY */
|
|
|
|
|
2008-02-20 20:30:45 +00:00
|
|
|
/* Loop until the main thread resets the runnable signal. */
|
|
|
|
while (1) {
|
|
|
|
|
2008-04-10 22:45:45 +00:00
|
|
|
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);
|
2008-12-07 07:38:06 +00:00
|
|
|
/* Main volume */
|
|
|
|
vol = audacious_remote_get_main_volume(session);
|
|
|
|
snprintf(items[AUDACIOUS_MAIN_VOLUME],
|
2009-02-22 17:35:47 +00:00
|
|
|
sizeof(items[AUDACIOUS_MAIN_VOLUME]) - 1, "%d", vol);
|
2008-12-07 07:38:06 +00:00
|
|
|
|
2008-04-10 22:45:45 +00:00
|
|
|
} while (0);
|
2008-02-20 20:30:45 +00:00
|
|
|
/* 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);
|
2006-12-23 06:01:16 +00:00
|
|
|
|
2008-12-09 23:37:24 +00:00
|
|
|
if (timed_thread_test(info.audacious.p_timed_thread, 0)) {
|
2007-11-22 19:38:17 +00:00
|
|
|
#ifndef AUDACIOUS_LEGACY
|
2008-02-20 20:30:45 +00:00
|
|
|
/* release reference to dbus proxy */
|
|
|
|
g_object_unref(session);
|
2007-11-22 19:38:17 +00:00
|
|
|
#endif
|
2008-02-20 20:30:45 +00:00
|
|
|
timed_thread_exit(info.audacious.p_timed_thread);
|
|
|
|
}
|
|
|
|
}
|
2006-11-03 20:54:52 +00:00
|
|
|
}
|