From 354e577b1565326d69391d986d9a32ec4e617f65 Mon Sep 17 00:00:00 2001 From: Christian Brabandt Date: Tue, 10 May 2011 22:40:53 +0200 Subject: [PATCH] Cmus support added to conky --- cmake/ConkyBuildOptions.cmake | 2 + cmake/config.h.in | 2 + doc/variables.xml | 145 +++++++++++++++++++++++ src/CMakeLists.txt | 5 + src/cmus.cc | 215 ++++++++++++++++++++++++++++++++++ src/cmus.h | 46 ++++++++ src/conky.cc | 5 +- src/core.cc | 56 +++++++++ 8 files changed, 475 insertions(+), 1 deletion(-) create mode 100644 src/cmus.cc create mode 100644 src/cmus.h diff --git a/cmake/ConkyBuildOptions.cmake b/cmake/ConkyBuildOptions.cmake index 580a9a24..175d2012 100644 --- a/cmake/ConkyBuildOptions.cmake +++ b/cmake/ConkyBuildOptions.cmake @@ -164,3 +164,5 @@ if(BUILD_HTTP) endif(BUILD_HTTP) option(BUILD_ICONV "Enable iconv support" false) + +option(BUILD_CMUS "Enable support for cmus music player" false) diff --git a/cmake/config.h.in b/cmake/config.h.in index 9a91a860..531a4b9c 100644 --- a/cmake/config.h.in +++ b/cmake/config.h.in @@ -116,4 +116,6 @@ #cmakedefine BUILD_RSS 1 +#cmakedefine BUILD_CMUS 1 + #endif /* _conky_config_h_ */ diff --git a/doc/variables.xml b/doc/variables.xml index d0f147a0..5775fd93 100644 --- a/doc/variables.xml +++ b/doc/variables.xml @@ -547,6 +547,151 @@ commandline + + + + + + + Print aaa status of cmus (all/artist/album). + + + + + + + + + Prints the album of the current cmus song. + + + + + + + + + Prints the artist of the current cmus song. + + + + + + + + + Current time of the current cmus song. + + + + + + + + + Print the file name of the current cmus song + + + + + + + + + Print the date of the current cmus song + + + + + + + + + Print the genre name of the current cmus song + + + + + + + + + Percent of song's progress. + + + + + + + + + + cmus' progress bar. + + + + + + + + + Random status of cmus (on/off). + + + + + + + + + Repeat status of cmus (song/all/off). + + + + + + + + + Current state of cmus (playing, paused, stopped etc). + + + + + + + + + Time left of the current cmus song. + + + + + + + + + Prints the title of the current cmus song. + + + + + + + + + Total length of the current cmus song. + + + + + + + + + Print track number of current cmus song. + + diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2bc6a6d6..067bfaf6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -99,6 +99,11 @@ if(BUILD_MOC) set(optional_sources ${optional_sources} ${moc}) endif(BUILD_MOC) +if(BUILD_CMUS) + set(cmus cmus.cc) + set(optional_sources ${optional_sources} ${cmus}) +endif(BUILD_CMUS) + if(BUILD_XMMS2) set(xmms2 xmms2.cc) set(optional_sources ${optional_sources} ${xmms2}) diff --git a/src/cmus.cc b/src/cmus.cc new file mode 100644 index 00000000..61e72ed6 --- /dev/null +++ b/src/cmus.cc @@ -0,0 +1,215 @@ +/* -*- mode: c++; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*- + * vim: ts=4 sw=4 noet ai cindent syntax=cpp + * + * CMUS Conky integration + * + * Please see COPYING for details + * + * Copyright (c) 2008, Henri Häkkinen + * + * 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 "conky.h" +#include "logging.h" +#include "text_object.h" + +#include +#include +#include +#include +#include +#include + +#include "update-cb.hh" + +namespace { + struct cmus_result { + std::string state; + std::string file; + std::string title; + std::string artist; + std::string album; + std::string totaltime; + std::string curtime; + std::string random; + std::string repeat; + std::string aaa; + std::string track; + std::string genre; + std::string date; + float progress; + float timeleft; + }; + + class cmus_cb: public conky::callback { + typedef conky::callback Base; + + protected: + virtual void work(); + + public: + cmus_cb(uint32_t period) + : Base(period, false, Tuple()) + {} + }; + + void cmus_cb::work() + { + cmus_result cmus; + FILE *fp; + + fp = popen("cmus-remote -Q 2>/dev/null", "r"); + if (!fp) { + cmus.state = "Can't run 'cmus-remote -Q'"; + } else { + while (1) { + char line[255]; + char *p; + + /* Read a line from the pipe and strip the possible '\n'. */ + if (!fgets(line, 255, fp)) + break; + if ((p = strrchr(line, '\n'))) + *p = '\0'; + + /* Parse infos. */ + if (strncmp(line, "status ", 7) == 0) + cmus.state = line + 7; + + else if (strncmp(line, "file ", 5) == 0) + cmus.file = line + 5; + + else if (strncmp(line, "tag artist ", 11) == 0) + cmus.artist = line + 11; + + else if (strncmp(line, "tag title ", 10) == 0) + cmus.title = line + 10; + + else if (strncmp(line, "tag album ", 10) == 0) + cmus.album = line + 10; + + else if (strncmp(line, "duration ", 9) == 0) + cmus.totaltime = line + 9; + + else if (strncmp(line, "position ", 9) == 0) + { + cmus.curtime = line + 9; + cmus.timeleft = atoi(cmus.totaltime.c_str()) - atoi(cmus.curtime.c_str()); + if (cmus.curtime.size() > 0) + cmus.progress = (float) atoi(cmus.curtime.c_str()) / atoi(cmus.totaltime.c_str()); + else + cmus.progress = 0; + } + + else if (strncmp(line, "set shuffle ", 12) == 0) + cmus.random = (strncmp(line+12, "true", 4) == 0 ? + "on" : "off" ); + + else if (strncmp(line, "set repeat ", 11) == 0) + cmus.repeat = (strncmp((line+11), "true", 4) == 0 ? + "all" : "off" ); + + else if (strncmp(line, "set repeat_current ", 19) == 0) + cmus.repeat = (strncmp((line + 19), "true", 4) == 0 ? + "song" : cmus.repeat ); + else if (strncmp(line, "set aaa_mode ", 13) == 0) + cmus.aaa = line + 13; + + else if (strncmp(line, "tag tracknumber ", 16) == 0) + cmus.track = line + 16; + else if (strncmp(line, "tag genre ", 10) == 0) + cmus.genre = line + 10; + else if (strncmp(line, "tag date ", 9) == 0) + cmus.date = line + 9; + } + } + + pclose(fp); + + std::lock_guard l(result_mutex); + result = cmus; + } +} + +#define CMUS_PRINT_GENERATOR(type, alt) \ +void print_cmus_##type(struct text_object *obj, char *p, int p_max_size) \ +{ \ + (void)obj; \ + uint32_t period = std::max( \ + std::lround(music_player_interval.get(*state)/active_update_interval()), 1l \ + ); \ + const cmus_result &cmus = conky::register_cb(period)->get_result_copy(); \ + snprintf(p, p_max_size, "%s", (cmus.type.length() ? cmus.type.c_str() : alt)); \ +} + +CMUS_PRINT_GENERATOR(state, "Off") +CMUS_PRINT_GENERATOR(file, "no file") +CMUS_PRINT_GENERATOR(title, "no title") +CMUS_PRINT_GENERATOR(artist, "no artist") +CMUS_PRINT_GENERATOR(album, "no album") +CMUS_PRINT_GENERATOR(random, "") +CMUS_PRINT_GENERATOR(repeat, "") +CMUS_PRINT_GENERATOR(aaa, "all") +CMUS_PRINT_GENERATOR(track, "no track") +CMUS_PRINT_GENERATOR(genre, "") +CMUS_PRINT_GENERATOR(date, "") + +uint8_t cmus_percent(struct text_object *obj) +{ + (void)obj; + uint32_t period = std::max( + std::lround(music_player_interval.get(*state)/active_update_interval()), 1l); + const cmus_result &cmus = conky::register_cb(period)->get_result_copy(); + return (uint8_t) round(cmus.progress * 100.0f); +} + +double cmus_progress(struct text_object *obj) +{ + (void)obj; + uint32_t period = std::max( + std::lround(music_player_interval.get(*state)/active_update_interval()), 1l); + const cmus_result &cmus = conky::register_cb(period)->get_result_copy(); + return (double) cmus.progress; +} + +void print_cmus_totaltime(struct text_object *obj, char *p, int p_max_size) +{ + (void)obj; + uint32_t period = std::max( + std::lround(music_player_interval.get(*state)/active_update_interval()), 1l); + const cmus_result &cmus = conky::register_cb(period)->get_result_copy(); + format_seconds_short(p, p_max_size, atol(cmus.totaltime.c_str())); +} + +void print_cmus_timeleft(struct text_object *obj, char *p, int p_max_size) +{ + (void)obj; + uint32_t period = std::max( + std::lround(music_player_interval.get(*state)/active_update_interval()), 1l); + const cmus_result &cmus = conky::register_cb(period)->get_result_copy(); + //format_seconds_short(p, p_max_size, atol(cmus.timeleft.c_str())); + format_seconds_short(p, p_max_size, (long)cmus.timeleft); +} + +void print_cmus_curtime(struct text_object *obj, char *p, int p_max_size) +{ + (void)obj; + uint32_t period = std::max( + std::lround(music_player_interval.get(*state)/active_update_interval()), 1l); + const cmus_result &cmus = conky::register_cb(period)->get_result_copy(); + format_seconds_short(p, p_max_size, atol(cmus.curtime.c_str())); +} + +#undef CMUS_PRINT_GENERATOR diff --git a/src/cmus.h b/src/cmus.h new file mode 100644 index 00000000..7c518f99 --- /dev/null +++ b/src/cmus.h @@ -0,0 +1,46 @@ +/* -*- mode: c++; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*- + * vim: ts=4 sw=4 noet ai cindent syntax=cpp + * + * CMUS Conky integration + * + * Please see COPYING for details + * + * Copyright (c) 2011, Christian Brabandt + * + * 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 . + * + */ + +#ifndef CMUS_H_ +#define CMUS_H_ + +void print_cmus_state(struct text_object *, char *, int); +void print_cmus_file(struct text_object *, char *, int); +void print_cmus_title(struct text_object *, char *, int); +void print_cmus_artist(struct text_object *, char *, int); +void print_cmus_album(struct text_object *, char *, int); +void print_cmus_totaltime(struct text_object *, char *, int); +void print_cmus_timeleft(struct text_object *, char *, int); +void print_cmus_curtime(struct text_object *, char *, int); +void print_cmus_random(struct text_object *, char *, int); +void print_cmus_repeat(struct text_object *, char *, int); +void print_cmus_aaa(struct text_object *, char *, int); +void print_cmus_track(struct text_object *, char *, int); +void print_cmus_genre(struct text_object *, char *, int); +void print_cmus_date(struct text_object *, char *, int); +void print_cmus_bar(struct text_object *, char *, int); +double cmus_progress(struct text_object *obj); +uint8_t cmus_percent(struct text_object *obj); + +#endif /* CMUS_H_ */ + diff --git a/src/conky.cc b/src/conky.cc index 144d250c..1f2e5920 100644 --- a/src/conky.cc +++ b/src/conky.cc @@ -340,7 +340,7 @@ static void print_version(void) << _(" * Own window\n") #endif #endif /* BUILD_X11 */ -#if defined BUILD_AUDACIOUS || defined BUILD_BMPX || defined BUILD_MPD || defined BUILD_MOC || defined BUILD_XMMS2 +#if defined BUILD_AUDACIOUS || defined BUILD_BMPX || defined BUILD_CMUS || defined BUILD_MPD || defined BUILD_MOC || defined BUILD_XMMS2 << _("\n Music detection:\n") #endif #ifdef BUILD_AUDACIOUS @@ -349,6 +349,9 @@ static void print_version(void) #ifdef BUILD_BMPX << _(" * BMPx\n") #endif /* BUILD_BMPX */ +#ifdef BUILD_CMUS + << _(" * CMUS\n") +#endif /* BUILD_CMUS */ #ifdef BUILD_MPD << _(" * MPD\n") #endif /* BUILD_MPD */ diff --git a/src/core.cc b/src/core.cc index dd9cf0bd..bae6ad7e 100644 --- a/src/core.cc +++ b/src/core.cc @@ -96,6 +96,9 @@ #ifdef BUILD_AUDACIOUS #include "audacious.h" #endif +#ifdef BUILD_CMUS +#include "cmus.h" +#endif /* check for OS and include appropriate headers */ #if defined(__linux__) @@ -1467,6 +1470,59 @@ struct text_object *construct_text_object(char *s, const char *arg, long END OBJ(moc_rate, 0) obj->callbacks.print = &print_moc_rate; #endif /* BUILD_MOC */ +#ifdef BUILD_CMUS + END OBJ(cmus_state, 0) + obj->callbacks.print = &print_cmus_state; + END OBJ(cmus_file, 0) + obj->callbacks.print = &print_cmus_file; + END OBJ(cmus_title, 0) + obj->callbacks.print = &print_cmus_title; + END OBJ(cmus_artist, 0) + obj->callbacks.print = &print_cmus_artist; + END OBJ(cmus_album, 0) + obj->callbacks.print = &print_cmus_album; + END OBJ(cmus_totaltime, 0) + obj->callbacks.print = &print_cmus_totaltime; + END OBJ(cmus_timeleft, 0) + obj->callbacks.print = &print_cmus_timeleft; + END OBJ(cmus_curtime, 0) + obj->callbacks.print = &print_cmus_curtime; + END OBJ(cmus_random, 0) + obj->callbacks.print = &print_cmus_random; + END OBJ(cmus_state, 0) + obj->callbacks.print = &print_cmus_state; + END OBJ(cmus_file, 0) + obj->callbacks.print = &print_cmus_file; + END OBJ(cmus_title, 0) + obj->callbacks.print = &print_cmus_title; + END OBJ(cmus_artist, 0) + obj->callbacks.print = &print_cmus_artist; + END OBJ(cmus_album, 0) + obj->callbacks.print = &print_cmus_album; + END OBJ(cmus_totaltime, 0) + obj->callbacks.print = &print_cmus_totaltime; + END OBJ(cmus_timeleft, 0) + obj->callbacks.print = &print_cmus_timeleft; + END OBJ(cmus_curtime, 0) + obj->callbacks.print = &print_cmus_curtime; + END OBJ(cmus_random, 0) + obj->callbacks.print = &print_cmus_random; + END OBJ(cmus_repeat, 0) + obj->callbacks.print = &print_cmus_repeat; + END OBJ(cmus_aaa, 0) + obj->callbacks.print = &print_cmus_aaa; + END OBJ(cmus_track, 0) + obj->callbacks.print = &print_cmus_track; + END OBJ(cmus_genre, 0) + obj->callbacks.print = &print_cmus_genre; + END OBJ(cmus_date, 0) + obj->callbacks.print = &print_cmus_date; + END OBJ(cmus_progress, 0) + scan_bar(obj, arg, 1); + obj->callbacks.barval = &cmus_progress; + END OBJ(cmus_percent, 0) + obj->callbacks.percentage = &cmus_percent; +#endif /* BUILD_CMUS */ #ifdef BUILD_XMMS2 END OBJ(xmms2_artist, &update_xmms2) obj->callbacks.print = &print_xmms2_artist;