2010-01-07 03:45:19 +00:00
|
|
|
/* -*- mode: c++; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*-
|
|
|
|
* vim: ts=4 sw=4 noet ai cindent syntax=cpp
|
2009-07-28 21:44:22 +00:00
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
*/
|
2006-11-03 20:54:52 +00:00
|
|
|
|
2010-01-04 17:06:14 +00:00
|
|
|
#include <config.h>
|
2008-12-15 21:40:24 +00:00
|
|
|
#include "conky.h"
|
|
|
|
#include "logging.h"
|
|
|
|
#include "audacious.h"
|
2010-01-04 17:06:14 +00:00
|
|
|
#include <mutex>
|
2007-11-17 04:13:20 +00:00
|
|
|
|
2006-11-03 20:54:52 +00:00
|
|
|
#include <glib.h>
|
2010-01-07 02:38:12 +00:00
|
|
|
#ifndef BUILD_AUDACIOUS_LEGACY
|
2007-11-17 03:43:21 +00:00
|
|
|
#include <glib-object.h>
|
|
|
|
#include <audacious/audctrl.h>
|
|
|
|
#include <audacious/dbus.h>
|
2010-01-07 02:38:12 +00:00
|
|
|
#else /* BUILD_AUDACIOUS_LEGACY */
|
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)
|
2010-01-07 02:38:12 +00:00
|
|
|
#endif /* BUILD_AUDACIOUS_LEGACY */
|
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.
|
|
|
|
* ----------------------------------------- */
|
2010-05-09 20:07:12 +00:00
|
|
|
int update_audacious(void)
|
2006-11-03 20:54:52 +00:00
|
|
|
{
|
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
|
|
|
}
|
2008-02-20 20:30:45 +00:00
|
|
|
}
|
|
|
|
|
2010-02-24 19:10:26 +00:00
|
|
|
std::lock_guard<std::mutex> lock(info.audacious.p_timed_thread->mutex());
|
2008-02-20 20:30:45 +00:00
|
|
|
memcpy(&info.audacious.items, audacious_items, sizeof(audacious_items));
|
2010-05-09 20:07:12 +00:00
|
|
|
return 0;
|
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 =
|
2010-06-10 17:13:15 +00:00
|
|
|
timed_thread::create(std::bind(audacious_thread_func, std::placeholders::_1),
|
|
|
|
std::chrono::microseconds(long(info.music_player_interval * 1000000)));
|
2008-02-20 20:30:45 +00:00
|
|
|
}
|
|
|
|
|
2010-01-04 17:06:14 +00:00
|
|
|
if (!info.audacious.p_timed_thread) {
|
2008-02-20 20:30:45 +00:00
|
|
|
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) {
|
2010-01-04 17:06:14 +00:00
|
|
|
info.audacious.p_timed_thread.reset();
|
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
|
|
|
* --------------------------------------------------- */
|
2010-01-04 17:06:14 +00:00
|
|
|
void audacious_thread_func(thread_handle &handle)
|
2006-11-03 20:54:52 +00:00
|
|
|
{
|
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
|
|
|
|
2010-01-07 02:38:12 +00:00
|
|
|
#ifndef BUILD_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
|
|
|
session = 0;
|
|
|
|
psong = NULL;
|
|
|
|
pfilename = NULL;
|
2006-12-23 06:01:16 +00:00
|
|
|
|
2010-01-07 02:38:12 +00:00
|
|
|
#ifndef BUILD_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
|
|
|
}
|
2010-01-07 02:38:12 +00:00
|
|
|
#endif /* BUILD_AUDACIOUS_LEGACY */
|
2007-11-17 03:43:21 +00:00
|
|
|
|
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);
|
2010-01-04 17:06:14 +00:00
|
|
|
{
|
|
|
|
/* Deliver the refreshed items array to audacious_items. */
|
2010-02-24 19:10:26 +00:00
|
|
|
std::lock_guard<std::mutex> lock(handle.mutex());
|
2010-01-04 17:06:14 +00:00
|
|
|
memcpy(&audacious_items, items, sizeof(items));
|
|
|
|
}
|
2006-12-23 06:01:16 +00:00
|
|
|
|
2010-01-04 17:06:14 +00:00
|
|
|
if (handle.test(0)) {
|
2010-01-07 02:38:12 +00:00
|
|
|
#ifndef BUILD_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
|
2010-01-04 17:06:14 +00:00
|
|
|
return;
|
2008-02-20 20:30:45 +00:00
|
|
|
}
|
|
|
|
}
|
2006-11-03 20:54:52 +00:00
|
|
|
}
|
2009-11-08 18:19:42 +00:00
|
|
|
|
2010-01-04 17:06:14 +00:00
|
|
|
void print_audacious_title(struct text_object *, char *p, int p_max_size)
|
2009-11-08 18:19:42 +00:00
|
|
|
{
|
|
|
|
snprintf(p, info.audacious.max_title_len > 0
|
|
|
|
? info.audacious.max_title_len : p_max_size, "%s",
|
|
|
|
info.audacious.items[AUDACIOUS_TITLE]);
|
|
|
|
}
|
|
|
|
|
2010-01-04 17:06:14 +00:00
|
|
|
double audacious_barval(struct text_object *)
|
2009-11-08 18:19:42 +00:00
|
|
|
{
|
|
|
|
|
2009-12-04 00:32:49 +00:00
|
|
|
return atof(info.audacious.items[AUDACIOUS_POSITION_SECONDS]) /
|
|
|
|
atof(info.audacious.items[AUDACIOUS_LENGTH_SECONDS]);
|
2009-11-08 18:19:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#define AUDACIOUS_PRINT_GENERATOR(name, idx) \
|
2010-01-04 17:06:14 +00:00
|
|
|
void print_audacious_##name(struct text_object *, char *p, int p_max_size) \
|
2009-11-08 18:19:42 +00:00
|
|
|
{ \
|
|
|
|
snprintf(p, p_max_size, "%s", info.audacious.items[AUDACIOUS_##idx]); \
|
|
|
|
}
|
|
|
|
|
|
|
|
AUDACIOUS_PRINT_GENERATOR(status, STATUS)
|
|
|
|
AUDACIOUS_PRINT_GENERATOR(length, LENGTH)
|
|
|
|
AUDACIOUS_PRINT_GENERATOR(length_seconds, LENGTH_SECONDS)
|
|
|
|
AUDACIOUS_PRINT_GENERATOR(position, POSITION)
|
|
|
|
AUDACIOUS_PRINT_GENERATOR(position_seconds, POSITION_SECONDS)
|
|
|
|
AUDACIOUS_PRINT_GENERATOR(bitrate, BITRATE)
|
|
|
|
AUDACIOUS_PRINT_GENERATOR(frequency, FREQUENCY)
|
|
|
|
AUDACIOUS_PRINT_GENERATOR(channels, CHANNELS)
|
|
|
|
AUDACIOUS_PRINT_GENERATOR(filename, FILENAME)
|
|
|
|
AUDACIOUS_PRINT_GENERATOR(playlist_length, PLAYLIST_LENGTH)
|
|
|
|
AUDACIOUS_PRINT_GENERATOR(playlist_position, PLAYLIST_POSITION)
|
|
|
|
AUDACIOUS_PRINT_GENERATOR(main_volume, MAIN_VOLUME)
|
|
|
|
|
|
|
|
#undef AUDACIOUS_PRINT_GENERATOR
|