diff --git a/configure.in b/configure.in index b8b22a88..1222b67c 100644 --- a/configure.in +++ b/configure.in @@ -1,6 +1,6 @@ -AC_INIT([Conky],[1.3.5],[brenden1@users.sourceforge.net]) +AC_INIT([Conky],[1.3.6_CVS_20060105],[brenden1@users.sourceforge.net]) -AM_INIT_AUTOMAKE(conky, 1.3.5) +AM_INIT_AUTOMAKE(conky, 1.3.6_CVS_20060105) AM_CONFIG_HEADER(src/config.h) AC_PROG_LIBTOOL @@ -127,6 +127,20 @@ if test x$want_mpd = xyes; then AC_DEFINE(MPD, 1, [Define if you want MPD support]) fi +dnl +dnl INFOPIPE +dnl + +want_infopipe=yes +AC_ARG_ENABLE(infopipe, +[ --enable-infopipe enable if you want XMMS/BMP InfoPipe support [[default=no]]], + [want_infopipe="$enableval"]) + +AM_CONDITIONAL(BUILD_INFOPIPE, test x$want_infopipe = xyes) +if test x$want_infopipe = xyes; then + AC_DEFINE(INFOPIPE, 1, [Define if you want XMMS/BMP InfoPipe support]) +fi + dnl dnl PORT_MONITORS dnl diff --git a/src/Makefile.am b/src/Makefile.am index f623dc68..8a855c45 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -4,6 +4,10 @@ if BUILD_BMPX bmpx = bmpx.c endif +if BUILD_INFOPIPE +infopipe = infopipe.c +endif + if BUILD_SETI seti = seti.c endif @@ -42,7 +46,7 @@ if BUILD_X11 x11 = x11.c endif -conky_SOURCES = common.c fs.c $(linux) mail.c mixer.c $(seti) $(mpd) $(solaris) $(freebsd) $(netbsd) $(port_monitors) conky.c conky.h $(x11) $(mldonkey) remoted.c remoted.h remotec.c remotec.h $(bmpx) +conky_SOURCES = common.c fs.c $(linux) mail.c mixer.c $(seti) $(mpd) $(solaris) $(freebsd) $(netbsd) $(port_monitors) conky.c conky.h $(x11) $(mldonkey) remoted.c remoted.h remotec.c remotec.h $(bmpx) $(infopipe) AM_LDFLAGS = $(X11_LIBS) $(XFT_LIBS) $(CAIRO_LIBS) $(PTHREAD_LIBS) -lm diff --git a/src/common.c b/src/common.c index a1e18c26..46d9d62f 100644 --- a/src/common.c +++ b/src/common.c @@ -230,7 +230,10 @@ void update_stuff() if (NEED(INFO_BMPX)) update_bmpx(); #endif - +#ifdef INFOPIPE + if (NEED(INFO_INFOPIPE)) + update_infopipe(); +#endif if (NEED(INFO_LOADAVG)) update_load_average(); diff --git a/src/conky.c b/src/conky.c index 16add90d..66bc1edb 100644 --- a/src/conky.c +++ b/src/conky.c @@ -899,6 +899,22 @@ enum text_object_type { OBJ_bmpx_uri, OBJ_bmpx_bitrate, #endif +#ifdef INFOPIPE + OBJ_infopipe_protocol, + OBJ_infopipe_version, + OBJ_infopipe_status, + OBJ_infopipe_playlist_tunes, + OBJ_infopipe_playlist_currtune, + OBJ_infopipe_usec_position, + OBJ_infopipe_position, + OBJ_infopipe_usec_time, + OBJ_infopipe_time, + OBJ_infopipe_bitrate, + OBJ_infopipe_frequency, + OBJ_infopipe_channels, + OBJ_infopipe_title, + OBJ_infopipe_file, +#endif #ifdef TCP_PORT_MONITOR OBJ_tcp_portmon, #endif @@ -1807,6 +1823,22 @@ int a = stippled_borders, b = 1; OBJ(bmpx_bitrate, INFO_BMPX) END #endif +#ifdef INFOPIPE + OBJ(infopipe_protocol, INFO_INFOPIPE) END + OBJ(infopipe_version, INFO_INFOPIPE) END + OBJ(infopipe_status, INFO_INFOPIPE) END + OBJ(infopipe_playlist_tunes, INFO_INFOPIPE) END + OBJ(infopipe_playlist_currtune, INFO_INFOPIPE) END + OBJ(infopipe_usec_position, INFO_INFOPIPE) END + OBJ(infopipe_position, INFO_INFOPIPE) END + OBJ(infopipe_usec_time, INFO_INFOPIPE) END + OBJ(infopipe_time, INFO_INFOPIPE) END + OBJ(infopipe_bitrate, INFO_INFOPIPE) END + OBJ(infopipe_frequency, INFO_INFOPIPE) END + OBJ(infopipe_channels, INFO_INFOPIPE) END + OBJ(infopipe_title, INFO_INFOPIPE) END + OBJ(infopipe_file, INFO_INFOPIPE) END +#endif #ifdef TCP_PORT_MONITOR OBJ(tcp_portmon, INFO_TCP_PORT_MONITOR) int argc, port_begin, port_end, item, connection_index; @@ -3081,6 +3113,50 @@ static void generate_text_internal(char *p, int p_max_size, struct text_object * OBJ(bmpx_bitrate) { snprintf(p, p_max_size, "%i", cur->bmpx.bitrate); } +#endif +#ifdef INFOPIPE + OBJ(infopipe_protocol) { + snprintf(p, p_max_size, "%s", cur->infopipe.item[INFOPIPE_PROTOCOL]); + } + OBJ(infopipe_version) { + snprintf(p, p_max_size, "%s", cur->infopipe.item[INFOPIPE_VERSION]); + } + OBJ(infopipe_status) { + snprintf(p, p_max_size, "%s", cur->infopipe.item[INFOPIPE_STATUS]); + } + OBJ(infopipe_playlist_tunes) { + snprintf(p, p_max_size, "%s", cur->infopipe.item[INFOPIPE_PLAYLIST_TUNES]); + } + OBJ(infopipe_playlist_currtune) { + snprintf(p, p_max_size, "%s", cur->infopipe.item[INFOPIPE_PLAYLIST_CURRTUNE]); + } + OBJ(infopipe_usec_position) { + snprintf(p, p_max_size, "%s", cur->infopipe.item[INFOPIPE_USEC_POSITION]); + } + OBJ(infopipe_position) { + snprintf(p, p_max_size, "%s", cur->infopipe.item[INFOPIPE_POSITION]); + } + OBJ(infopipe_usec_time) { + snprintf(p, p_max_size, "%s", cur->infopipe.item[INFOPIPE_USEC_TIME]); + } + OBJ(infopipe_time) { + snprintf(p, p_max_size, "%s", cur->infopipe.item[INFOPIPE_TIME]); + } + OBJ(infopipe_bitrate) { + snprintf(p, p_max_size, "%s", cur->infopipe.item[INFOPIPE_BITRATE]); + } + OBJ(infopipe_frequency) { + snprintf(p, p_max_size, "%s", cur->infopipe.item[INFOPIPE_FREQUENCY]); + } + OBJ(infopipe_channels) { + snprintf(p, p_max_size, "%s", cur->infopipe.item[INFOPIPE_CHANNELS]); + } + OBJ(infopipe_title) { + snprintf(p, p_max_size, "%s", cur->infopipe.item[INFOPIPE_TITLE]); + } + OBJ(infopipe_file) { + snprintf(p, p_max_size, "%s", cur->infopipe.item[INFOPIPE_FILE]); + } #endif OBJ(top) { if (obj->data.top.type == TOP_NAME @@ -5393,7 +5469,40 @@ int main(int argc, char **argv) ERR("error setting signal handler: %s", strerror(errno) ); } +#ifdef INFOPIPE + /* joinable thread for infopipe activity */ + pthread_attr_init(&info.infopipe.thread_attr); + pthread_attr_setdetachstate(&info.infopipe.thread_attr, PTHREAD_CREATE_JOINABLE); + /* init mutexex */ + pthread_mutex_init(&info.infopipe.item_mutex, NULL); + pthread_mutex_init(&info.infopipe.runnable_mutex, NULL); + /* init runnable condition for worker thread */ + pthread_mutex_lock(&info.infopipe.runnable_mutex); + info.infopipe.runnable=1; + pthread_mutex_unlock(&info.infopipe.runnable_mutex); + if (pthread_create(&info.infopipe.thread, &info.infopipe.thread_attr, infopipe_service, NULL)) + { + CRIT_ERR("unable to create infopipe thread!"); + } +#endif + main_loop(); + +#ifdef INFOPIPE + /* signal infopipe worker thread to terminate */ + pthread_mutex_lock(&info.infopipe.runnable_mutex); + info.infopipe.runnable=0; + pthread_mutex_unlock(&info.infopipe.runnable_mutex); + /* destroy thread attribute and wait for thread */ + pthread_attr_destroy(&info.infopipe.thread_attr); + if (pthread_join(info.infopipe.thread, NULL)) + { + ERR("error joining infopipe thread"); + } + /* destroy mutexes */ + pthread_mutex_destroy(&info.infopipe.item_mutex); + pthread_mutex_destroy(&info.infopipe.runnable_mutex); +#endif return 0; } diff --git a/src/conky.h b/src/conky.h index bb0ce079..91d6ccfc 100644 --- a/src/conky.h +++ b/src/conky.h @@ -9,6 +9,9 @@ #ifndef _conky_h_ #define _conky_h_ +#ifdef INFOPIPE +#include +#endif #if defined(HAS_MCHECK_H) #include #endif /* HAS_MCHECK_H */ @@ -136,6 +139,34 @@ struct bmpx_s { }; #endif +#ifdef INFOPIPE +#include "infopipe.h" +enum _infopipe_keys { + INFOPIPE_PROTOCOL, + INFOPIPE_VERSION, + INFOPIPE_STATUS, + INFOPIPE_PLAYLIST_TUNES, + INFOPIPE_PLAYLIST_CURRTUNE, + INFOPIPE_USEC_POSITION, + INFOPIPE_POSITION, + INFOPIPE_USEC_TIME, + INFOPIPE_TIME, + INFOPIPE_BITRATE, + INFOPIPE_FREQUENCY, + INFOPIPE_CHANNELS, + INFOPIPE_TITLE, + INFOPIPE_FILE +}; +struct infopipe_s { + char item[14][256]; /* use enum as first array index, e.g. item[INFOPIPE_STATUS] */ + int runnable; /* used to signal infopipe thread to stop */ + pthread_t thread; /* worker thread for infopipe updating */ + pthread_attr_t thread_attr; /* thread attributes */ + pthread_mutex_t item_mutex; /* mutex for item array */ + pthread_mutex_t runnable_mutex; /* mutex for runnable flag */ +}; +#endif + #ifdef TCP_PORT_MONITOR #include "libtcp-portmon.h" #define MIN_PORT_MONITORS_DEFAULT 16 @@ -176,6 +207,9 @@ enum { #ifdef BMPX INFO_BMPX = 23, #endif +#ifdef INFOPIPE + INFO_INFOPIPE = 24, +#endif }; @@ -221,6 +255,9 @@ struct information { #endif #ifdef BMPX struct bmpx_s bmpx; +#endif +#ifdef INFOPIPE + struct infopipe_s infopipe; #endif struct process *cpu[10]; struct process *memu[10]; diff --git a/src/infopipe.c b/src/infopipe.c new file mode 100644 index 00000000..34978b15 --- /dev/null +++ b/src/infopipe.c @@ -0,0 +1,132 @@ +/* ------------------------------------------------------------------------- + * infopipe.c: conky support for XMMS/BMP InfoPipe plugin + * + * http://www.beastwithin.org/users/wwwwolf/code/xmms/infopipe.html + * + * Copyright (C) 2005 Philip Kovacs kovacsp3@comcast.net + * + * Based on original ideas and code graciously presented by: + * Ulrich Jansen - ulrich( dot )jansen( at )rwth-aachen.de + * + * $Id$ + * + * 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 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * --------------------------------------------------------------------------- */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "conky.h" + +static char g_item[14][256]; + +/* ---------------------------------------- + * Conky update function for InfoPipe data. + * ---------------------------------------- */ +void update_infopipe(void) +{ + /* + The worker thread is updating ihe g_item array asynchronously to the main + conky thread. We merely copy the g_item array into the main thread's info + structure when the main thread's update cycle fires. Note that using the + mutexes here makes it easier since we won't have to do any sync in conky.c. + */ + pthread_mutex_lock(&info.infopipe.item_mutex); + memcpy(&info.infopipe.item,g_item,sizeof(g_item)); + pthread_mutex_unlock(&info.infopipe.item_mutex); +} + + +/* -------------------------------------------------- + * Worker thread function for InfoPipe data sampling. + * -------------------------------------------------- */ +void *infopipe_service(void *pvoid) +{ + int i,fd,runnable; + fd_set readset; + struct timeval tm; + char buf[2048],*pbuf; + + pvoid=(void*)pvoid; /* useless cast to avoid unused var warning */ + + /* I/O multiplexing timer is set for one second select() */ + tm.tv_sec=1; + tm.tv_usec=0; + + /* Grab the runnable signal. Should be non-zero here or we do nothing. */ + pthread_mutex_lock(&info.infopipe.runnable_mutex); + runnable=info.infopipe.runnable; + pthread_mutex_unlock(&info.infopipe.runnable_mutex ); + + /* Loop until the main thread sets the runnable signal to 0. */ + while(runnable) { + + for (;;) { /* convenience loop so we can break below */ + + memset(buf,0,sizeof(buf)); + memset(g_item,0,sizeof(g_item)); + + if ((fd=open(INFOPIPE_NAMED_PIPE, O_RDONLY | O_NONBLOCK)) < 0) + break; + + FD_ZERO(&readset); + FD_SET(fd,&readset); + + /* This select() can block for a brief while (tm time value) and is + ideally suited for a worker thread such as this. We don't want to + slow down ui updates in the main thread as there is already excess + latency there. */ + if (select(fd+1,&readset,NULL,NULL,&tm) != 1) /* nothing to read yet */ + break; + + if (read(fd,buf,sizeof(buf))>0) { + + pbuf=buf; + for (i=0;i<14;i++) { + sscanf(pbuf,"%*[^:]: %[^\n]",g_item[i]); + while(*pbuf++ != '\n'); + } + + pthread_mutex_lock(&info.infopipe.item_mutex); + memcpy(&info.infopipe.item,g_item,sizeof(g_item)); + pthread_mutex_unlock(&info.infopipe.item_mutex); + /* + for(i=0;i<14;i++) + printf("%s\n",g_item[i]); + */ + + } + + if (close(fd)<0) + break; + + break; + } + + sleep(2); /* need a var here */ + + /* Grab the runnable signal for next loop. */ + pthread_mutex_lock(&info.infopipe.runnable_mutex); + runnable=info.infopipe.runnable; + pthread_mutex_unlock(&info.infopipe.runnable_mutex); + } + + pthread_exit(NULL); +} diff --git a/src/infopipe.h b/src/infopipe.h new file mode 100644 index 00000000..87c6728a --- /dev/null +++ b/src/infopipe.h @@ -0,0 +1,36 @@ +/* ------------------------------------------------------------------------- + * infopipe.h: conky support for XMMS/BMP InfoPipe plugin + * + * InfoPipe: http://www.beastwithin.org/users/wwwwolf/code/xmms/infopipe.html + * + * Copyright (C) 2005 Philip Kovacs kovacsp3@comcast.net + * + * Based on original ideas and code graciously presented by: + * Ulrich Jansen - ulrich( dot )jansen( at )rwth-aachen.de + * + * $Id$ + * + * 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 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * --------------------------------------------------------------------------- */ + +#ifndef INFOPIPE_H +#define INFOPIPE_H + +#define INFOPIPE_NAMED_PIPE "/tmp/xmms-info" + +void update_infopipe(void); +void *infopipe_service(void *); + +#endif