1
0
mirror of https://github.com/Llewellynvdm/conky.git synced 2024-12-26 04:17:33 +00:00

Overhauled RSS and weather, added $curl.

I've taken the curl stuff out of weather and RSS and moved it into it's
own entity.  It should be easier to create curl-based objects if needed
now.
This commit is contained in:
Brenden Matthews 2009-07-19 23:43:36 -06:00
parent 80a71ea8bd
commit c05c157ead
15 changed files with 374 additions and 499 deletions

View File

@ -307,6 +307,14 @@ if test x$want_xmms2 = xyes; then
AC_DEFINE(XMMS2, 1, [Define if you want XMMS2 support])
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
@ -317,10 +325,8 @@ AC_ARG_ENABLE([eve],
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])
@ -339,11 +345,9 @@ AC_ARG_ENABLE([rss],
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
@ -362,15 +366,11 @@ 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"
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
@ -648,6 +648,28 @@ if test x$WANT_GLIB = xyes; then
conky_LIBS="$conky_LIBS $GLib2_LIBS"
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
@ -907,7 +929,8 @@ $PACKAGE $VERSION configured successfully:
hddtemp: $want_hddtemp
portmon: $want_portmon
RSS: $want_rss
Weather (METAR)
Curl: $want_curl
Weather
NOAA: $want_weather
XOAP: $want_xoap
wireless: $want_wlan

View File

@ -194,6 +194,16 @@
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>
@ -209,6 +219,11 @@
then call functions in Lua via Conky's $lua, $lua_read, and Lua
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.

View File

@ -2546,20 +2546,46 @@
mailboxes are supported, mbox type will return -1.
<para /></listitem>
</varlistentry>
<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>
<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>
@ -2963,7 +2989,9 @@
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>
@ -3288,7 +3316,7 @@
<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>
@ -3363,6 +3391,11 @@
</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>

View File

@ -110,6 +110,10 @@ if BUILD_EVE
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
@ -180,7 +184,8 @@ conky_SOURCES = \
text_object.c \
algebra.h \
algebra.c \
$(imlib2)
$(imlib2) \
$(ccurl_thread)
conky_LDFLAGS = \
$(PTHREAD_LIBS) \
@ -211,6 +216,7 @@ EXTRA_DIST = \
libtcp-portmon.c \
libtcp-portmon.h \
rss.h \
prss.h \
weather.h \
llua.h \
mail.h \
@ -242,7 +248,8 @@ EXTRA_DIST = \
sony.h \
users.c \
imlib2.c \
imlib2.h
imlib2.h \
ccurl_thread.h
# vi:set ts=4 sw=4 noet ai nocindent syntax=automake:

View File

@ -513,20 +513,3 @@ unsigned int round_to_int(float f)
}
}
/* 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;
}

View File

@ -89,14 +89,4 @@ int get_battery_perct(const char *bat);
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 */

View File

@ -158,7 +158,7 @@ static void reload_config(void);
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)
{
@ -208,6 +208,9 @@ 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 */
@ -908,6 +911,11 @@ static void free_text_objects(struct text_object *root, int internal)
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);
@ -954,6 +962,7 @@ static void free_text_objects(struct text_object *root, int internal)
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;
@ -1245,7 +1254,7 @@ long current_text_color;
/* 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();
@ -1257,8 +1266,6 @@ static struct text_object *construct_text_object(const char *s,
#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) { \
@ -1821,7 +1828,7 @@ static struct text_object *construct_text_object(const char *s,
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) {
@ -2110,7 +2117,7 @@ static struct text_object *construct_text_object(const char *s,
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) {
@ -2120,7 +2127,7 @@ static struct text_object *construct_text_object(const char *s,
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) {
@ -2595,7 +2602,7 @@ static struct text_object *construct_text_object(const char *s,
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);
@ -2603,7 +2610,7 @@ static struct text_object *construct_text_object(const char *s,
} 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);
@ -2611,7 +2618,7 @@ static struct text_object *construct_text_object(const char *s,
} 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);
@ -2619,7 +2626,7 @@ static struct text_object *construct_text_object(const char *s,
} 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);
@ -2816,30 +2823,43 @@ static struct text_object *construct_text_object(const char *s,
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));
@ -2849,14 +2869,14 @@ static struct text_object *construct_text_object(const char *s,
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);
@ -2876,12 +2896,12 @@ static struct text_object *construct_text_object(const char *s,
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);
@ -2969,14 +2989,14 @@ static struct text_object *construct_text_object(const char *s,
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");
}
@ -3001,7 +3021,7 @@ static struct text_object *construct_text_object(const char *s,
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>");
}
@ -3045,9 +3065,9 @@ static struct text_object *construct_text_object(const char *s,
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>");
}
@ -3371,7 +3391,7 @@ static size_t remove_comments(char *string)
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;
@ -3490,8 +3510,7 @@ static int extract_variable_text_internal(struct text_object *retval, const char
}
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);
}
@ -3543,12 +3562,12 @@ static void extract_variable_text(const char *p)
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;
}
@ -4439,8 +4458,10 @@ static void generate_text_internal(char *p, int p_max_size,
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");
}
@ -4631,87 +4652,30 @@ static void generate_text_internal(char *p, int p_max_size,
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);
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 {
strncpy(p, "either invalid xoap keys file or compiled without xoap support", p_max_size);
ERR("error processing weather data, check that you have a valid XOAP key if using XOAP.");
}
}
#endif
@ -7636,11 +7600,14 @@ void clean_up(void *memtofree1, void* memtofree2)
#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();

View File

@ -87,17 +87,21 @@ char *strndup(const char *s, size_t n);
#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"
@ -196,9 +200,6 @@ enum {
INFO_XMMS2 = 22,
#endif
INFO_ENTROPY = 23,
#ifdef RSS
INFO_RSS = 24,
#endif
#ifdef IBM
INFO_SMAPI = 25,
#endif

View File

@ -24,29 +24,19 @@
#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;
}
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 prss_parse_doc(doc);
prss_parse_doc(data, doc);
}
void prss_free(PRSS *data)
@ -57,7 +47,6 @@ void prss_free(PRSS *data)
xmlFreeDoc(data->_data);
free(data->version);
free(data->items);
free(data);
}
static inline void prss_null(PRSS *p)
@ -169,6 +158,7 @@ static inline int parse_rss_2_0(PRSS *res, xmlNodePtr root)
}
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;
@ -198,6 +188,7 @@ static inline int parse_rss_1_0(PRSS *res, xmlNodePtr root)
}
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;
@ -216,13 +207,12 @@ static inline int parse_rss_0_9x(PRSS *res, xmlNodePtr root)
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;
@ -230,24 +220,15 @@ PRSS *prss_parse_doc(xmlDocPtr 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;
}

View File

@ -51,8 +51,7 @@ typedef struct PRSS_ {
} 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); */

209
src/rss.c
View File

@ -24,137 +24,110 @@
#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;
void rss_free_info(void)
{
ccurl_location_t *tail = locations_head;
while (tail) {
if (tail->result) prss_free((PRSS*)tail->result); /* clean up old data */
tail = tail->next;
}
ccurl_free_locations(&locations_head);
}
void rss_process_info(char *p, int p_max_size, char *uri, char *action, int
act_par, int interval, unsigned int nrspaces)
{
PRSS *data;
} feed;
char *str;
int num_feeds = 0;
feed feeds[MAX_FEEDS];
int rss_delay(int *wait_time, int delay)
{
time_t now = time(NULL);
// make it minutes
if (delay < 1) {
delay = 1;
}
delay *= 60;
if (!*wait_time) {
*wait_time = now + delay;
return 1;
}
if (now >= *wait_time + delay) {
*wait_time = now + delay;
return 1;
}
return 0;
}
void init_rss_info(void)
{
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);
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;
timed_thread_lock(curloc->p_timed_thread);
data = (PRSS*)curloc->result;
// 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;
}
}
}
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);
if (data == NULL) {
snprintf(p, p_max_size, "prss: Error reading RSS data\n");
} else {
ERR("No data from server");
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;
}
curl_easy_cleanup(curl);
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;
curfeed->data = curdata;
p[0] = 0;
return curdata;
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);
}
}
}
timed_thread_unlock(curloc->p_timed_thread);
}

View File

@ -3,8 +3,8 @@
#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_*/

View File

@ -375,6 +375,9 @@ enum text_object_type {
#ifdef EVE
OBJ_eve,
#endif /* EVE */
#ifdef HAVE_CURL
OBJ_curl,
#endif /* HAVE_CURL */
#ifdef RSS
OBJ_rss,
#endif /* RSS */
@ -538,14 +541,19 @@ struct text_object {
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
@ -553,7 +561,6 @@ struct text_object {
char *uri;
char *data_type;
int interval;
timed_thread *p_timed_thread;
} weather;
#endif
struct {

View File

@ -30,14 +30,12 @@
#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 */
@ -63,57 +61,11 @@ const char *WC_CODES[NUM_WC_CODES] = {
"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)
void weather_free_info(void)
{
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)
{
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) {
@ -489,9 +441,10 @@ static inline void parse_token(PWEATHER *res, char *token) {
}
}
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
@ -532,60 +485,7 @@ static void parse_weather(PWEATHER *res, const char *data)
}
}
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",
@ -593,96 +493,93 @@ void process_weather_info(char *p, int p_max_size, char *uri, char *data_type, i
"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 */
}

View File

@ -55,8 +55,7 @@ typedef struct PWEATHER_ {
} 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_*/