fi
dnl
+dnl libcurl, see below for more (this has to be above the other uses of want_curl)
+dnl
+
+AC_ARG_ENABLE([curl],
+ AC_HELP_STRING([--enable-curl], [enable if you want curl support @<:@default=no@:>@]),
+ [want_curl="$enableval"], [want_curl=no])
+
+dnl
dnl EVE Skill Monitor
dnl
AM_CONDITIONAL(BUILD_EVE, test x$want_eve = xyes)
if test x$want_eve = xyes; then
- PKG_CHECK_MODULES([libxml2], libxml-2.0)
- PKG_CHECK_MODULES([libcurl], libcurl)
- conky_CFLAGS="$conky_CFLAGS $libxml2_CFLAGS $libcurl_CFLAGS"
- conky_LIBS="$conky_LIBS $libxml2_LIBS $libcurl_LIBS"
+ want_curl=yes
+ want_libxml2=yes
AC_DEFINE(EVE, 1, [Define if you want Eve-Online Skill monitor support])
AC_DEFINE(EVEURL_TRAINING, "http://api.eve-online.com/char/SkillInTraining.xml.aspx", [Eve training URL])
AC_DEFINE(EVEURL_SKILLTREE, "http://api.eve-online.com/eve/Skilltree.xml.aspx", [Eve skilltree URL])
AM_CONDITIONAL(BUILD_RSS, test x$want_rss = xyes)
if test x$want_rss = xyes; then
WANT_GLIB=yes
- PKG_CHECK_MODULES([libxml2], libxml-2.0)
- PKG_CHECK_MODULES([libcurl], libcurl)
- conky_CFLAGS="$conky_CFLAGS $libxml2_CFLAGS $libcurl_CFLAGS"
- conky_LIBS="$conky_LIBS $libxml2_LIBS $libcurl_LIBS"
- AC_DEFINE(RSS, 1, [Define if you want rss support])
+ want_curl=yes
+ want_libxml2=yes
+ AC_DEFINE(RSS, 1, [Define if you want Curl support])
fi
dnl
#
AM_CONDITIONAL(BUILD_WEATHER, test x$want_weather = xyes)
if test x$want_weather = xyes; then
- AM_CONDITIONAL(BUILD_XOAP, test x$want_xoap = xyes)
- if test x$want_xoap = xyes; then
- PKG_CHECK_MODULES([libxml2], libxml-2.0)
- conky_CFLAGS="$conky_CFLAGS $libxml2_CFLAGS"
- conky_LIBS="$conky_LIBS $libxml2_LIBS"
- AC_DEFINE(XOAP, 1, [Define if you want weather xoap support])
- AC_DEFINE(XOAP_FILE, "$HOME/.xoaprc", [User xoap keys file])
+ AM_CONDITIONAL(BUILD_XOAP, test x$want_xoap = xyes)
+ if test x$want_xoap = xyes; then
+ want_libxml2=yes
+ AC_DEFINE(XOAP, 1, [Define if you want weather xoap support])
+ AC_DEFINE(XOAP_FILE, "$HOME/.xoaprc", [User xoap keys file])
fi
- PKG_CHECK_MODULES([libcurl], libcurl)
- conky_CFLAGS="$conky_CFLAGS $libcurl_CFLAGS"
- conky_LIBS="$conky_LIBS $libcurl_LIBS"
+ want_curl=yes
AC_DEFINE(WEATHER, 1, [Define if you want weather support])
fi
fi
dnl
+dnl libcurl
+dnl
+
+if test x$want_curl = xyes; then
+ PKG_CHECK_MODULES([libcurl], libcurl)
+ conky_CFLAGS="$conky_CFLAGS $libcurl_CFLAGS"
+ conky_LIBS="$conky_LIBS $libcurl_LIBS"
+ AC_DEFINE(HAVE_CURL, 1, [Define if you want Curl support])
+fi
+AM_CONDITIONAL(BUILD_CURL, test x$want_curl = xyes)
+
+dnl
+dnl libx
+dnl
+
+if test x$want_libxml2 = xyes; then
+ PKG_CHECK_MODULES([libxml2], libxml-2.0)
+ conky_CFLAGS="$conky_CFLAGS $libxml2_CFLAGS"
+ conky_LIBS="$conky_LIBS $libxml2_LIBS"
+fi
+
+dnl
dnl KVM
dnl
hddtemp: $want_hddtemp
portmon: $want_portmon
RSS: $want_rss
- Weather (METAR)
- NOAA: $want_weather
- XOAP: $want_xoap
+ Curl: $want_curl
+ Weather
+ NOAA: $want_weather
+ XOAP: $want_xoap
wireless: $want_wlan
IBM: $want_ibm
nvidia: $want_nvidia
Colour can be also in
#rrggbb format (hex).
</para>
+ <para>
+ Some objects may create threads, and sometimes these threads will
+ not be destroyed until Conky terminates. There is no way to
+ destroy or clean up threads while Conky is running. For example,
+ if you use an MPD variable, the MPD thread will keep running until
+ Conky dies. Some threaded objects will use one of the parameters
+ as a 'key', so that you only have 1 relevant thread running (for
+ example, the $curl, $rss and $weather objects launch one thread per
+ URI).
+ </para>
&variables;
</refsect1>
<refsect1>
hooks.
</para>
<para>
+ Be careful when creating threaded objects through the Lua API. You
+ could wind up with a whole bunch of threads running if a thread is
+ created with each iteration.
+ </para>
+ <para>
At this time, the Lua API should not be considered stable and may
change drastically from one release to another as it matures.
</para>
<varlistentry>
<term>
<command>
+ <option>curl</option>
+ </command>
+ <option>url interval_in_minutes</option>
+ </term>
+ <listitem>
+ <para>
+ Download data from URI using Curl at the specified interval.
+ The interval may be a floating point value greater than 0,
+ otherwise defaults to 15 minutes. Most useful when used in
+ conjunction with Lua and the Lua API. This object is threaded,
+ and once a thread is created it can't be explicitely destroyed.
+ One thread will run for each URI specified. You can use any
+ protocol that Curl supports.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>
+ <command>
<option>rss</option>
</command>
- <option>url delay_in_minutes action (num_par
+ <option>uri interval_in_minutes action (num_par
(spaces_in_front))</option>
</term>
- <listitem>Download and parse RSS feeds. Action may be one
- of the following: feed_title, item_title (with num par),
- item_desc (with num par) and item_titles (when using this
- action and spaces_in_front is given conky places that many
- spaces in front of each item).
- <para /></listitem>
- </varlistentry>
- <varlistentry>
+ <listitem>
+ <para>
+ Download and parse RSS feeds. The interval may be a floating
+ point value greater than 0, otherwise defaults to 15 minutes.
+ Action may be one of the following: feed_title, item_title
+ (with num par), item_desc (with num par) and item_titles (when
+ using this action and spaces_in_front is given conky places
+ that many spaces in front of each item). This object is
+ threaded, and once a thread is created it can't be explicitely
+ destroyed. One thread will run for each URI specified. You
+ can use any protocol that Curl supports.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
<term>
<command>
<option>running_processes</option>
longer then the time it takes your script to execute. For
example, if you have a script that take 5 seconds to
execute, you should make the interval at least 6 seconds.
- See also $execi.
+ See also $execi. This object will clean up the thread when it is
+ destroyed, so it can safely be used in a nested fashion, though it may
+ not produce the desired behaviour if used this way.
<para /></listitem>
</varlistentry>
<varlistentry>
<command>
<option>weather</option>
</command>
- <option>URI locID data_type (delay_in_minutes)</option>
+ <option>URI locID data_type (interval_in_minutes)</option>
</term>
<listitem>
<para>Download, parse and display METAR data.</para>
</simplelist>
<para>'delay_in_minutes' (optional, default 30) cannot
be lower than 30 min.</para>
+ <para>
+ This object is threaded, and once a thread is created it can't be
+ explicitely destroyed. One thread will run for each URI specified.
+ You can use any protocol that Curl supports.
+ </para>
<para>Note that these variables are still EXPERIMENTAL
and can be subject to many future changes.</para>
</listitem>
eve = eve.c eve.h
endif
+if BUILD_CURL
+ccurl_thread = ccurl_thread.c ccurl_thread.h
+endif
+
if BUILD_RSS
rss = rss.c prss.c prss.h
endif
$(eve) \
$(rss) \
$(weather) \
- $(lua) \
+ $(lua) \
$(solaris) \
timed_thread.c \
timed_thread.h \
text_object.h \
text_object.c \
algebra.h \
- algebra.c \
- $(imlib2)
+ algebra.c \
+ $(imlib2) \
+ $(ccurl_thread)
conky_LDFLAGS = \
$(PTHREAD_LIBS) \
libtcp-portmon.c \
libtcp-portmon.h \
rss.h \
- weather.h \
- llua.h \
+ prss.h \
+ weather.h \
+ llua.h \
mail.h \
mixer.h \
moc.h \
ibm.c \
ibm.h \
sony.h \
- users.c \
- imlib2.c \
- imlib2.h
+ users.c \
+ imlib2.c \
+ imlib2.h \
+ ccurl_thread.h
# vi:set ts=4 sw=4 noet ai nocindent syntax=automake:
}
}
-/* utility function used by RSS and Weather stuff for a curl callback.
- */
-size_t WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data)
-{
- size_t realsize = size * nmemb;
- struct MemoryStruct *mem = (struct MemoryStruct *) data;
-
- mem->memory = (char *) realloc(mem->memory, mem->size + realsize + 1);
- if (mem->memory) {
- memcpy(&(mem->memory[mem->size]), ptr, realsize);
- mem->size += realsize;
- mem->memory[mem->size] = 0;
- }
- return realsize;
-}
-
-
int get_battery_perct_bar(const char *bat);
void get_battery_short_status(char *buf, unsigned int n, const char *bat);
-/*
- * used by RSS and Weather
- */
-struct MemoryStruct {
- char *memory;
- size_t size;
-};
-
-size_t WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data);
-
#endif /* _COMMON_H */
static void generate_text_internal(char *, int, struct text_object,
struct information *);
static int extract_variable_text_internal(struct text_object *,
- const char *, char);
+ const char *);
static void print_version(void)
{
#ifdef TCP_PORT_MONITOR
" * portmon\n"
#endif /* TCP_PORT_MONITOR */
+#ifdef HAVE_CURL
+ " * Curl\n"
+#endif /* HAVE_CURL */
#ifdef RSS
" * RSS\n"
#endif /* RSS */
case OBJ_eve:
break;
#endif
+#ifdef HAVE_CURL
+ case OBJ_curl:
+ free(data.curl.uri);
+ break;
+#endif
#ifdef RSS
case OBJ_rss:
free(data.rss.uri);
free(data.execi.buffer);
break;
case OBJ_texeci:
+ if (data.texeci.p_timed_thread) timed_thread_destroy(data.texeci.p_timed_thread, &data.texeci.p_timed_thread);
free(data.texeci.cmd);
free(data.texeci.buffer);
break;
/* construct_text_object() creates a new text_object */
static struct text_object *construct_text_object(const char *s,
- const char *arg, long line, char allow_threaded, void **ifblock_opaque, void *free_at_crash)
+ const char *arg, long line, void **ifblock_opaque, void *free_at_crash)
{
// struct text_object *obj = new_text_object();
struct text_object *obj = new_text_object_internal();
#define OBJ_IF(a, n) if (strcmp(s, #a) == 0) { \
obj->type = OBJ_##a; need_mask |= (1ULL << n); \
obj_be_ifblock_if(ifblock_opaque, obj); {
-#define OBJ_THREAD(a, n) if (strcmp(s, #a) == 0 && allow_threaded) { \
- obj->type = OBJ_##a; need_mask |= (1ULL << n); {
#define END } } else
#define SIZE_DEFAULTS(arg) { \
obj->data.execi.cmd = strndup(arg + n, text_buffer_size);
obj->data.execi.buffer = malloc(text_buffer_size);
}
- END OBJ_THREAD(texeci, 0)
+ END OBJ(texeci, 0)
int n;
if (!arg || sscanf(arg, "%f %n", &obj->data.texeci.interval, &n) <= 0) {
obj->data.ifblock.s = strndup(arg, text_buffer_size);
obj->sub = malloc(sizeof(struct text_object));
extract_variable_text_internal(obj->sub,
- obj->data.ifblock.s, 0);
+ obj->data.ifblock.s);
}
END OBJ_IF(if_match, 0)
if (!arg) {
obj->data.ifblock.s = strndup(arg, text_buffer_size);
obj->sub = malloc(sizeof(struct text_object));
extract_variable_text_internal(obj->sub,
- obj->data.ifblock.s, 0);
+ obj->data.ifblock.s);
}
END OBJ_IF(if_existing, 0)
if (!arg) {
END OBJ(apm_battery_life, 0)
END OBJ(apm_battery_time, 0)
#endif /* __FreeBSD__ */
- END OBJ_THREAD(imap_unseen, 0)
+ END OBJ(imap_unseen, 0)
if (arg) {
// proccss
obj->data.mail = parse_mail_args(IMAP_TYPE, arg);
} else {
obj->char_b = 1;
}
- END OBJ_THREAD(imap_messages, 0)
+ END OBJ(imap_messages, 0)
if (arg) {
// proccss
obj->data.mail = parse_mail_args(IMAP_TYPE, arg);
} else {
obj->char_b = 1;
}
- END OBJ_THREAD(pop3_unseen, 0)
+ END OBJ(pop3_unseen, 0)
if (arg) {
// proccss
obj->data.mail = parse_mail_args(POP3_TYPE, arg);
} else {
obj->char_b = 1;
}
- END OBJ_THREAD(pop3_used, 0)
+ END OBJ(pop3_used, 0)
if (arg) {
// proccss
obj->data.mail = parse_mail_args(POP3_TYPE, arg);
CRIT_ERR(obj, free_at_crash, "eve needs arguments: <userid> <apikey> <characterid>");
}
#endif
+#ifdef HAVE_CURL
+ END OBJ(curl, 0)
+ if (arg) {
+ int argc;
+ float interval;
+ char *uri = (char *) malloc(128 * sizeof(char));
+
+ argc = sscanf(arg, "%127s %f", uri, &interval);
+ obj->data.curl.uri = uri;
+ obj->data.curl.interval = interval > 0 ? interval * 60 : 15*60;
+ } else {
+ CRIT_ERR(obj, free_at_crash, "curl needs arguments: <uri> <interval in minutes>");
+ }
+#endif
#ifdef RSS
END OBJ(rss, 0)
if (arg) {
- int argc, delay, act_par;
+ float interval;
+ int argc, act_par;
unsigned int nrspaces = 0;
char *uri = (char *) malloc(128 * sizeof(char));
char *action = (char *) malloc(64 * sizeof(char));
- argc = sscanf(arg, "%127s %d %63s %d %u", uri, &delay, action,
+ argc = sscanf(arg, "%127s %f %63s %d %u", uri, &interval, action,
&act_par, &nrspaces);
obj->data.rss.uri = uri;
- obj->data.rss.delay = delay;
+ obj->data.rss.interval = interval > 0 ? interval * 60 : 15*60;
obj->data.rss.action = action;
obj->data.rss.act_par = act_par;
obj->data.rss.nrspaces = nrspaces;
-
- init_rss_info();
} else {
- CRIT_ERR(obj, free_at_crash, "rss needs arguments: <uri> <delay in minutes> <action> "
+ CRIT_ERR(obj, free_at_crash, "rss needs arguments: <uri> <interval in minutes> <action> "
"[act_par] [spaces in front]");
}
#endif
#ifdef WEATHER
- END OBJ_THREAD(weather, 0)
+ END OBJ(weather, 0)
if (arg) {
int argc, interval;
char *locID = (char *) malloc(9 * sizeof(char));
argc = sscanf(arg, "%119s %8s %31s %d", uri, locID, data_type, &interval);
- //locID MUST BE upper-case
+ /* locID MUST BE upper-case */
tmp_p = locID;
while (*tmp_p) {
*tmp_p = toupper(*tmp_p);
tmp_p++;
}
- //Construct complete uri
+ /* Construct complete uri */
if (strstr(uri, "xoap.weather.com")) {
if(xoap != NULL) {
strcat(uri, locID);
obj->data.weather.uri = uri;
obj->data.weather.data_type = data_type;
- //Limit the data retrieval interval to half hour min
+ /* Limit the data retrieval interval to half hour min */
if (interval < 30) {
interval = 30;
}
- //Convert to seconds
+ /* Convert to seconds */
obj->data.weather.interval = interval * 60;
free(locID);
END OBJ(blink, 0)
if(arg) {
obj->sub = malloc(sizeof(struct text_object));
- extract_variable_text_internal(obj->sub, arg, 0);
+ extract_variable_text_internal(obj->sub, arg);
}else{
CRIT_ERR(obj, free_at_crash, "blink needs a argument");
}
END OBJ(to_bytes, 0)
if(arg) {
obj->sub = malloc(sizeof(struct text_object));
- extract_variable_text_internal(obj->sub, arg, 0);
+ extract_variable_text_internal(obj->sub, arg);
}else{
CRIT_ERR(obj, free_at_crash, "to_bytes needs a argument");
}
obj->data.scroll.start = 0;
obj->sub = malloc(sizeof(struct text_object));
extract_variable_text_internal(obj->sub,
- obj->data.scroll.text, 0);
+ obj->data.scroll.text);
} else {
CRIT_ERR(obj, free_at_crash, "scroll needs arguments: <length> [<step>] <text>");
}
obj->data.combine.right[endvar[1] - startvar[1]] = 0;
obj->sub = malloc(sizeof(struct text_object));
- extract_variable_text_internal(obj->sub, obj->data.combine.left, 0);
+ extract_variable_text_internal(obj->sub, obj->data.combine.left);
obj->sub->sub = malloc(sizeof(struct text_object));
- extract_variable_text_internal(obj->sub->sub, obj->data.combine.right, 0);
+ extract_variable_text_internal(obj->sub->sub, obj->data.combine.right);
} else {
CRIT_ERR(obj, free_at_crash, "combine needs arguments: <text1> <text2>");
}
return folded;
}
-static int extract_variable_text_internal(struct text_object *retval, const char *const_p, char allow_threaded)
+static int extract_variable_text_internal(struct text_object *retval, const char *const_p)
{
struct text_object *obj;
char *p, *s, *orig_p;
}
obj = construct_text_object(buf, arg,
- line, allow_threaded,
- &ifblock_opaque, orig_p);
+ line, &ifblock_opaque, orig_p);
if (obj != NULL) {
append_object(retval, obj);
}
text_buffer = 0;
}
- extract_variable_text_internal(&global_root_object, p, 1);
+ extract_variable_text_internal(&global_root_object, p);
}
void parse_conky_vars(struct text_object *root, char *txt, char *p, struct information *cur)
{
- extract_variable_text_internal(root, txt, 0);
+ extract_variable_text_internal(root, txt);
generate_text_internal(p, max_user_text, *root, cur);
return;
}
if (!obj->data.texeci.p_timed_thread) {
ERR("Error creating texeci timed thread");
}
- timed_thread_register(obj->data.texeci.p_timed_thread,
- &obj->data.texeci.p_timed_thread);
+ /*
+ * note that we don't register this thread with the
+ * timed_thread list, because we destroy it manually
+ */
if (timed_thread_run(obj->data.texeci.p_timed_thread)) {
ERR("Error running texeci timed thread");
}
snprintf(p, p_max_size, "%s", skill);
}
#endif
+#ifdef HAVE_CURL
+ OBJ(curl) {
+ if (obj->data.curl.uri != NULL) {
+ ccurl_process_info(p, p_max_size, obj->data.curl.uri, obj->data.curl.interval);
+ } else {
+ ERR("error processing Curl data");
+ }
+ }
+#endif
#ifdef RSS
OBJ(rss) {
- PRSS *data = get_rss_info(obj->data.rss.uri,
- obj->data.rss.delay);
- char *str;
-
- if (data == NULL) {
- snprintf(p, p_max_size, "prss: Error reading RSS data\n");
+ if (obj->data.rss.uri != NULL) {
+ rss_process_info(p, p_max_size, obj->data.rss.uri, obj->data.rss.action, obj->data.rss.act_par, obj->data.rss.interval, obj->data.rss.nrspaces);
} else {
- if (strcmp(obj->data.rss.action, "feed_title") == EQUAL) {
- str = data->title;
- // remove trailing new line if one exists
- if (str[strlen(str) - 1] == '\n') {
- str[strlen(str) - 1] = 0;
- }
- snprintf(p, p_max_size, "%s", str);
- } else if (strcmp(obj->data.rss.action, "item_title") == EQUAL) {
- if (obj->data.rss.act_par < data->item_count) {
- str = data->items[obj->data.rss.act_par].title;
- // remove trailing new line if one exists
- if (str[strlen(str) - 1] == '\n') {
- str[strlen(str) - 1] = 0;
- }
- snprintf(p, p_max_size, "%s", str);
- }
- } else if (strcmp(obj->data.rss.action, "item_desc") == EQUAL) {
- if (obj->data.rss.act_par < data->item_count) {
- str =
- data->items[obj->data.rss.act_par].description;
- // remove trailing new line if one exists
- if (str[strlen(str) - 1] == '\n') {
- str[strlen(str) - 1] = 0;
- }
- snprintf(p, p_max_size, "%s", str);
- }
- } else if (strcmp(obj->data.rss.action, "item_titles") == EQUAL) {
- if (data->item_count > 0) {
- int itmp;
- int show;
- //'tmpspaces' is a string with spaces too be placed in front of each title
- char *tmpspaces = malloc(obj->data.rss.nrspaces + 1);
- memset(tmpspaces, ' ', obj->data.rss.nrspaces);
- tmpspaces[obj->data.rss.nrspaces]=0;
-
- p[0] = 0;
-
- if (obj->data.rss.act_par > data->item_count) {
- show = data->item_count;
- } else {
- show = obj->data.rss.act_par;
- }
- for (itmp = 0; itmp < show; itmp++) {
- PRSS_Item *item = &data->items[itmp];
-
- str = item->title;
- if (str) {
- // don't add new line before first item
- if (itmp > 0) {
- strncat(p, "\n", p_max_size);
- }
- /* remove trailing new line if one exists,
- * we have our own */
- if (str[strlen(str) - 1] == '\n') {
- str[strlen(str) - 1] = 0;
- }
- strncat(p, tmpspaces, p_max_size);
- strncat(p, str, p_max_size);
- }
- }
- free(tmpspaces);
- }
- }
+ ERR("error processing RSS data");
}
}
#endif
#ifdef WEATHER
OBJ(weather) {
- if( obj->data.weather.uri != NULL ) {
- process_weather_info(p, p_max_size, obj->data.weather.uri, obj->data.weather.data_type, obj->data.weather.interval);
- } else {
- strncpy(p, "either invalid xoap keys file or compiled without xoap support", p_max_size);
+ if (obj->data.weather.uri != NULL) {
+ weather_process_info(p, p_max_size, obj->data.weather.uri, obj->data.weather.data_type, obj->data.weather.interval);
+ } else {
+ ERR("error processing weather data, check that you have a valid XOAP key if using XOAP.");
}
}
#endif
#ifdef TCP_PORT_MONITOR
tcp_portmon_clear();
#endif
+#ifdef HAVE_CURL
+ ccurl_free_info();
+#endif
#ifdef RSS
- free_rss_info();
+ rss_free_info();
#endif
#ifdef WEATHER
- free_weather_info();
+ weather_free_info();
#endif
#ifdef HAVE_LUA
llua_close();
#include "nvidia.h"
#endif
+#ifdef HAVE_CURL
+#include "ccurl_thread.h"
+#endif /* HAVE_CURL */
+
#ifdef RSS
#include "rss.h"
-#endif
+#endif /* RSS */
#ifdef WEATHER
#include "weather.h"
-#endif
+#endif /* WEATHER */
#ifdef HAVE_LUA
#include "llua.h"
-#endif
+#endif /* HAVE_LUA */
#ifdef TCP_PORT_MONITOR
#include "tcp-portmon.h"
INFO_XMMS2 = 22,
#endif
INFO_ENTROPY = 23,
-#ifdef RSS
- INFO_RSS = 24,
-#endif
#ifdef IBM
INFO_SMAPI = 25,
#endif
#define PARSE_OPTIONS 0
#endif
-PRSS *prss_parse_doc(xmlDocPtr doc);
+void prss_parse_doc(PRSS *result, xmlDocPtr doc);
-PRSS *prss_parse_data(const char *xml_data)
+void prss_parse_data(void *result, const char *xml_data)
{
+ PRSS *data = (PRSS*)result;
xmlDocPtr doc = xmlReadMemory(xml_data, strlen(xml_data), "", NULL,
PARSE_OPTIONS);
if (!doc) {
- return NULL;
- }
-
- return prss_parse_doc(doc);
-}
-
-PRSS *prss_parse_file(const char *xml_file)
-{
- xmlDocPtr doc = xmlReadFile(xml_file, NULL, PARSE_OPTIONS);
-
- if (!doc) {
- return NULL;
+ return;
}
- return prss_parse_doc(doc);
+ prss_parse_doc(data, doc);
}
void prss_free(PRSS *data)
xmlFreeDoc(data->_data);
free(data->version);
free(data->items);
- free(data);
}
static inline void prss_null(PRSS *p)
}
res->version = strndup("2.0", text_buffer_size);
+ if (res->items) free(res->items);
res->items = malloc(items * sizeof(PRSS_Item));
res->item_count = 0;
}
res->version = strndup("1.0", text_buffer_size);
+ if (res->items) free(res->items);
res->items = malloc(items * sizeof(PRSS_Item));
res->item_count = 0;
return parse_rss_2_0(res, root);
}
-PRSS *prss_parse_doc(xmlDocPtr doc)
+void prss_parse_doc(PRSS *result, xmlDocPtr doc)
{
/* FIXME: doc shouldn't be freed after failure when called explicitly from
* program! */
xmlNodePtr root = xmlDocGetRootElement(doc);
- PRSS *result = malloc(sizeof(PRSS));
prss_null(result);
result->_data = doc;
if (root->type == XML_ELEMENT_NODE) {
if (!strcmp((const char *) root->name, "RDF")) {
// RSS 1.0 document
- if (!parse_rss_1_0(result, root)) {
- free(result);
- xmlFreeDoc(doc);
- return NULL;
- }
- return result;
+ parse_rss_1_0(result, root);
+ return;
} else if (!strcmp((const char *) root->name, "rss")) {
// RSS 2.0 or <1.0 document
- if (!parse_rss_2_0(result, root)) {
- free(result);
- xmlFreeDoc(doc);
- return NULL;
- }
- return result;
+ parse_rss_2_0(result, root);
+ return;
}
}
root = root->next;
} while (root);
- free(result);
- return NULL;
+ return;
}
} PRSS;
/* Functions for parsing RSS-data */
-PRSS *prss_parse_data(const char *xml_data);
-PRSS *prss_parse_file(const char *xml_file);
+void prss_parse_data(void *result, const char *xml_data);
/* // Works wrong currently when called from application!
PRSS *prss_parse_doc(xmlDocPtr doc); */
#include "conky.h"
#include "logging.h"
#include "prss.h"
+#include "ccurl_thread.h"
#include <time.h>
#include <assert.h>
-#include <curl/curl.h>
-#include <curl/types.h>
-#include <curl/easy.h>
-#define MAX_FEEDS 16
+static ccurl_location_t *locations_head = 0;
-typedef struct feed_ {
- char *uri;
- int last_update;
- PRSS *data;
-} feed;
-
-int num_feeds = 0;
-feed feeds[MAX_FEEDS];
-
-int rss_delay(int *wait_time, int delay)
+void rss_free_info(void)
{
- time_t now = time(NULL);
+ ccurl_location_t *tail = locations_head;
- // make it minutes
- if (delay < 1) {
- delay = 1;
+ while (tail) {
+ if (tail->result) prss_free((PRSS*)tail->result); /* clean up old data */
+ tail = tail->next;
}
- delay *= 60;
-
- if (!*wait_time) {
- *wait_time = now + delay;
- return 1;
- }
-
- if (now >= *wait_time + delay) {
- *wait_time = now + delay;
- return 1;
- }
-
- return 0;
+ ccurl_free_locations(&locations_head);
}
-void init_rss_info(void)
+void rss_process_info(char *p, int p_max_size, char *uri, char *action, int
+ act_par, int interval, unsigned int nrspaces)
{
- int i;
-
- for (i = 0; i < MAX_FEEDS; i++) {
- feeds[i].uri = NULL;
- feeds[i].data = NULL;
- feeds[i].last_update = 0;
- }
-}
-
-void free_rss_info(void)
-{
- int i;
-
- for (i = 0; i < num_feeds; i++) {
- if (feeds[i].uri != NULL) {
- free(feeds[i].uri);
+ PRSS *data;
+ char *str;
+
+ ccurl_location_t *curloc = ccurl_find_location(&locations_head, uri);
+ if (!curloc->p_timed_thread) {
+ curloc->result = malloc(sizeof(PRSS));
+ memset(curloc->result, 0, sizeof(PRSS));
+ curloc->process_function = &prss_parse_data;
+ ccurl_init_thread(curloc, interval);
+ if (!curloc->p_timed_thread) {
+ ERR("error setting up weather thread");
}
}
-}
-
-PRSS *get_rss_info(char *uri, int delay)
-{
- CURL *curl = NULL;
- CURLcode res;
-
- // pointers to struct
- feed *curfeed = NULL;
- PRSS *curdata = NULL;
- int *last_update = 0;
-
- int i;
-
- // curl temps
- struct MemoryStruct chunk;
- chunk.memory = NULL;
- chunk.size = 0;
-
- // first seek for the uri in list
- for (i = 0; i < num_feeds; i++) {
- if (feeds[i].uri != NULL) {
- if (!strcmp(feeds[i].uri, uri)) {
- curfeed = &feeds[i];
- break;
+ timed_thread_lock(curloc->p_timed_thread);
+ data = (PRSS*)curloc->result;
+
+ if (data == NULL) {
+ snprintf(p, p_max_size, "prss: Error reading RSS data\n");
+ } else {
+ if (strcmp(action, "feed_title") == EQUAL) {
+ str = data->title;
+ // remove trailing new line if one exists
+ if (str[strlen(str) - 1] == '\n') {
+ str[strlen(str) - 1] = 0;
+ }
+ snprintf(p, p_max_size, "%s", str);
+ } else if (strcmp(action, "item_title") == EQUAL) {
+ if (act_par < data->item_count) {
+ str = data->items[act_par].title;
+ // remove trailing new line if one exists
+ if (str[strlen(str) - 1] == '\n') {
+ str[strlen(str) - 1] = 0;
+ }
+ snprintf(p, p_max_size, "%s", str);
+ }
+ } else if (strcmp(action, "item_desc") == EQUAL) {
+ if (act_par < data->item_count) {
+ str =
+ data->items[act_par].description;
+ // remove trailing new line if one exists
+ if (str[strlen(str) - 1] == '\n') {
+ str[strlen(str) - 1] = 0;
+ }
+ snprintf(p, p_max_size, "%s", str);
+ }
+ } else if (strcmp(action, "item_titles") == EQUAL) {
+ if (data->item_count > 0) {
+ int itmp;
+ int show;
+ //'tmpspaces' is a string with spaces too be placed in front of each title
+ char *tmpspaces = malloc(nrspaces + 1);
+ memset(tmpspaces, ' ', nrspaces);
+ tmpspaces[nrspaces]=0;
+
+ p[0] = 0;
+
+ if (act_par > data->item_count) {
+ show = data->item_count;
+ } else {
+ show = act_par;
+ }
+ for (itmp = 0; itmp < show; itmp++) {
+ PRSS_Item *item = &data->items[itmp];
+
+ str = item->title;
+ if (str) {
+ // don't add new line before first item
+ if (itmp > 0) {
+ strncat(p, "\n", p_max_size);
+ }
+ /* remove trailing new line if one exists,
+ * we have our own */
+ if (str[strlen(str) - 1] == '\n') {
+ str[strlen(str) - 1] = 0;
+ }
+ strncat(p, tmpspaces, p_max_size);
+ strncat(p, str, p_max_size);
+ }
+ }
+ free(tmpspaces);
}
}
}
-
- if (!curfeed) { // new feed
- if (num_feeds == MAX_FEEDS - 1) {
- return NULL;
- }
- curfeed = &feeds[num_feeds];
- curfeed->uri = strndup(uri, text_buffer_size);
- num_feeds++;
- }
-
- last_update = &curfeed->last_update;
- curdata = curfeed->data;
-
- if (!rss_delay(last_update, delay)) {
- return curdata; // wait for delay to pass
- }
-
- if (curdata != NULL) {
- prss_free(curdata); // clean up old data
- curdata = NULL;
- }
-
- curl = curl_easy_init();
- if (curl) {
- curl_easy_setopt(curl, CURLOPT_URL, uri);
- curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1);
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
- curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *) &chunk);
- curl_easy_setopt(curl, CURLOPT_USERAGENT, "conky-rss/1.0");
-
- res = curl_easy_perform(curl);
- if (res == CURLE_OK && chunk.size) {
- curdata = prss_parse_data(chunk.memory);
- free(chunk.memory);
- } else {
- ERR("No data from server");
- }
-
- curl_easy_cleanup(curl);
- }
-
- curfeed->data = curdata;
-
- return curdata;
+ timed_thread_unlock(curloc->p_timed_thread);
}
+
#include "prss.h"
-PRSS *get_rss_info(char *uri, int delay);
-void init_rss_info(void);
-void free_rss_info(void);
+void rss_free_info(void);
+void rss_process_info(char *p, int p_max_size, char *uri, char *action, int
+ act_par, int interval, unsigned int nrspaces);
#endif /*RSS_H_*/
#ifdef EVE
OBJ_eve,
#endif /* EVE */
+#ifdef HAVE_CURL
+ OBJ_curl,
+#endif /* HAVE_CURL */
#ifdef RSS
OBJ_rss,
#endif /* RSS */
char *userid;
} eve;
#endif
+#ifdef HAVE_CURL
+ struct {
+ char *uri;
+ float interval;
+ } curl;
+#endif
#ifdef RSS
struct {
char *uri;
char *action;
int act_par;
- int delay;
+ float interval;
unsigned int nrspaces;
- timed_thread *p_timed_thread;
} rss;
#endif
#ifdef WEATHER
struct {
char *uri;
- char *data_type;
- int interval;
- timed_thread *p_timed_thread;
+ char *data_type;
+ int interval;
} weather;
#endif
struct {
#include "logging.h"
#include "weather.h"
#include "temphelper.h"
+#include "ccurl_thread.h"
#include <time.h>
#include <ctype.h>
#ifdef MATH
#include <math.h>
#endif /* MATH */
-#include <curl/curl.h>
-#include <curl/types.h>
-#include <curl/easy.h>
#ifdef XOAP
#include <libxml/parser.h>
#endif /* XOAP */
"FC", "PO", "SQ", "SS", "DS"
};
-typedef struct location_ {
- char *uri;
- int last_update;
- PWEATHER data;
- timed_thread *p_timed_thread;
- struct location_ *next;
-} location;
+static ccurl_location_t *locations_head = 0;
-static location *locations_head = 0;
-
-location *find_location(char *uri)
-{
- location *tail = locations_head;
- location *new = 0;
- while (tail) {
- if (tail->uri &&
- strcmp(tail->uri, uri) == EQUAL) {
- return tail;
- }
- tail = tail->next;
- }
- if (!tail) { // new location!!!!!!!
- new = malloc(sizeof(location));
- memset(new, 0, sizeof(location));
- new->uri = strndup(uri, text_buffer_size);
- tail = locations_head;
- while (tail && tail->next) {
- tail = tail->next;
- }
- if (!tail) {
- // omg the first one!!!!!!!
- locations_head = new;
- } else {
- tail->next = new;
- }
- }
- return new;
-}
-
-void free_weather_info(void)
+void weather_free_info(void)
{
- location *tail = locations_head;
- location *last = 0;
-
- while (tail) {
- if (tail->uri) free(tail->uri);
- last = tail;
- tail = tail->next;
- free(last);
- }
- locations_head = 0;
+ ccurl_free_locations(&locations_head);
}
int rel_humidity(int dew_point, int air) {
}
}
-static void parse_weather(PWEATHER *res, const char *data)
+void parse_weather(void *result, const char *data)
{
- //Reset results
+ PWEATHER *res = (PWEATHER*)result;
+ /* Reset results */
memset(res, 0, sizeof(PWEATHER));
#ifdef XOAP
}
}
-void fetch_weather_info(location *curloc)
-{
- CURL *curl = NULL;
- CURLcode res;
-
- // curl temps
- struct MemoryStruct chunk;
-
- chunk.memory = NULL;
- chunk.size = 0;
-
- curl = curl_easy_init();
- if (curl) {
- curl_easy_setopt(curl, CURLOPT_URL, curloc->uri);
- curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1);
- curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
- curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *) &chunk);
- curl_easy_setopt(curl, CURLOPT_USERAGENT, "conky-weather/1.0");
-
- res = curl_easy_perform(curl);
- if (res == CURLE_OK && chunk.size) {
- timed_thread_lock(curloc->p_timed_thread);
- parse_weather(&curloc->data, chunk.memory);
- timed_thread_unlock(curloc->p_timed_thread);
- free(chunk.memory);
- } else {
- ERR("weather: no data from server");
- }
-
- curl_easy_cleanup(curl);
- }
-
- return;
-}
-
-void *weather_thread(void *) __attribute__((noreturn));
-
-void init_thread(location *curloc, int interval)
-{
- curloc->p_timed_thread =
- timed_thread_create(&weather_thread,
- (void *)curloc, interval * 1000000);
- if (!curloc->p_timed_thread) {
- ERR("weather: error creating timed thread");
- }
- timed_thread_register(curloc->p_timed_thread,
- &curloc->p_timed_thread);
- if (timed_thread_run(curloc->p_timed_thread)) {
- ERR("weather: error running timed thread");
- }
-}
-
-
-void process_weather_info(char *p, int p_max_size, char *uri, char *data_type, int interval)
+void weather_process_info(char *p, int p_max_size, char *uri, char *data_type, int interval)
{
static const char *wc[] = {
"", "drizzle", "rain", "hail", "soft hail",
"mist", "dust", "sand", "funnel cloud tornado",
"dust/sand", "squall", "sand storm", "dust storm"
};
+ PWEATHER *data;
- location *curloc = find_location(uri);
- if (!curloc->p_timed_thread) init_thread(curloc, interval);
+ ccurl_location_t *curloc = ccurl_find_location(&locations_head, uri);
+ if (!curloc->p_timed_thread) {
+ curloc->result = malloc(sizeof(PWEATHER));
+ memset(curloc->result, 0, sizeof(PWEATHER));
+ curloc->process_function = &parse_weather;
+ ccurl_init_thread(curloc, interval);
+ if (!curloc->p_timed_thread) {
+ ERR("error setting up weather thread");
+ }
+ }
timed_thread_lock(curloc->p_timed_thread);
+ data = (PWEATHER*)curloc->result;
if (strcmp(data_type, "last_update") == EQUAL) {
- strncpy(p, curloc->data.lastupd, p_max_size);
+ strncpy(p, data->lastupd, p_max_size);
} else if (strcmp(data_type, "temperature") == EQUAL) {
- temp_print(p, p_max_size, curloc->data.temp, TEMP_CELSIUS);
+ temp_print(p, p_max_size, data->temp, TEMP_CELSIUS);
} else if (strcmp(data_type, "cloud_cover") == EQUAL) {
#ifdef XOAP
- if (curloc->data.xoap_t[0] != '\0') {
- strncpy(p, curloc->data.xoap_t, p_max_size);
+ if (data->xoap_t[0] != '\0') {
+ strncpy(p, data->xoap_t, p_max_size);
} else
#endif /* XOAP */
- if (curloc->data.cc == 0) {
+ if (data->cc == 0) {
strncpy(p, "", p_max_size);
- } else if (curloc->data.cc < 3) {
+ } else if (data->cc < 3) {
strncpy(p, "clear", p_max_size);
- } else if (curloc->data.cc < 5) {
+ } else if (data->cc < 5) {
strncpy(p, "partly cloudy", p_max_size);
- } else if (curloc->data.cc == 5) {
+ } else if (data->cc == 5) {
strncpy(p, "cloudy", p_max_size);
- } else if (curloc->data.cc == 6) {
+ } else if (data->cc == 6) {
strncpy(p, "overcast", p_max_size);
- } else if (curloc->data.cc == 7) {
+ } else if (data->cc == 7) {
strncpy(p, "towering cumulus", p_max_size);
} else {
strncpy(p, "cumulonimbus", p_max_size);
}
} else if (strcmp(data_type, "pressure") == EQUAL) {
- snprintf(p, p_max_size, "%d", curloc->data.bar);
+ snprintf(p, p_max_size, "%d", data->bar);
} else if (strcmp(data_type, "wind_speed") == EQUAL) {
- snprintf(p, p_max_size, "%d", curloc->data.wind_s);
+ snprintf(p, p_max_size, "%d", data->wind_s);
} else if (strcmp(data_type, "wind_dir") == EQUAL) {
- if ((curloc->data.wind_d >= 349) || (curloc->data.wind_d < 12)) {
+ if ((data->wind_d >= 349) || (data->wind_d < 12)) {
strncpy(p, "N", p_max_size);
- } else if (curloc->data.wind_d < 33) {
+ } else if (data->wind_d < 33) {
strncpy(p, "NNE", p_max_size);
- } else if (curloc->data.wind_d < 57) {
+ } else if (data->wind_d < 57) {
strncpy(p, "NE", p_max_size);
- } else if (curloc->data.wind_d < 79) {
+ } else if (data->wind_d < 79) {
strncpy(p, "ENE", p_max_size);
- } else if (curloc->data.wind_d < 102) {
+ } else if (data->wind_d < 102) {
strncpy(p, "E", p_max_size);
- } else if (curloc->data.wind_d < 124) {
+ } else if (data->wind_d < 124) {
strncpy(p, "ESE", p_max_size);
- } else if (curloc->data.wind_d < 147) {
+ } else if (data->wind_d < 147) {
strncpy(p, "SE", p_max_size);
- } else if (curloc->data.wind_d < 169) {
+ } else if (data->wind_d < 169) {
strncpy(p, "SSE", p_max_size);
- } else if (curloc->data.wind_d < 192) {
+ } else if (data->wind_d < 192) {
strncpy(p, "S", p_max_size);
- } else if (curloc->data.wind_d < 214) {
+ } else if (data->wind_d < 214) {
strncpy(p, "SSW", p_max_size);
- } else if (curloc->data.wind_d < 237) {
+ } else if (data->wind_d < 237) {
strncpy(p, "SW", p_max_size);
- } else if (curloc->data.wind_d < 259) {
+ } else if (data->wind_d < 259) {
strncpy(p, "WSW", p_max_size);
- } else if (curloc->data.wind_d < 282) {
+ } else if (data->wind_d < 282) {
strncpy(p, "W", p_max_size);
- } else if (curloc->data.wind_d < 304) {
+ } else if (data->wind_d < 304) {
strncpy(p, "WNW", p_max_size);
- } else if (curloc->data.wind_d < 327) {
+ } else if (data->wind_d < 327) {
strncpy(p, "NW", p_max_size);
- } else if (curloc->data.wind_d < 349) {
+ } else if (data->wind_d < 349) {
strncpy(p, "NNW", p_max_size);
};
} else if (strcmp(data_type, "wind_dir_DEG") == EQUAL) {
- snprintf(p, p_max_size, "%d", curloc->data.wind_d);
+ snprintf(p, p_max_size, "%d", data->wind_d);
} else if (strcmp(data_type, "humidity") == EQUAL) {
- snprintf(p, p_max_size, "%d", curloc->data.hmid);
+ snprintf(p, p_max_size, "%d", data->hmid);
} else if (strcmp(data_type, "weather") == EQUAL) {
- strncpy(p, wc[curloc->data.wc], p_max_size);
+ strncpy(p, wc[data->wc], p_max_size);
}
timed_thread_unlock(curloc->p_timed_thread);
}
-void *weather_thread(void *arg)
-{
- location *curloc = (location*)arg;
-
- while (1) {
- fetch_weather_info(curloc);
- if (timed_thread_test(curloc->p_timed_thread, 0)) {
- timed_thread_exit(curloc->p_timed_thread);
- }
- }
- /* never reached */
-}
-
} PWEATHER;
/* Prototypes */
-void init_weather_info(void);
-void free_weather_info(void);
-void process_weather_info(char *p, int p_max_size, char *uri, char *data_type, int interval);
+void weather_free_info(void);
+void weather_process_info(char *p, int p_max_size, char *uri, char *data_type, int interval);
#endif /*WEATHER_H_*/