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:
parent
80a71ea8bd
commit
c05c157ead
@ -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
|
||||
|
15
doc/docs.xml
15
doc/docs.xml
@ -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.
|
||||
|
@ -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>
|
||||
|
@ -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:
|
||||
|
17
src/common.c
17
src/common.c
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
10
src/common.h
10
src/common.h
@ -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 */
|
||||
|
183
src/conky.c
183
src/conky.c
@ -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();
|
||||
|
13
src/conky.h
13
src/conky.h
@ -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
|
||||
|
45
src/prss.c
45
src/prss.c
@ -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;
|
||||
}
|
||||
|
@ -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
209
src/rss.c
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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_*/
|
||||
|
@ -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 {
|
||||
|
205
src/weather.c
205
src/weather.c
@ -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 */
|
||||
}
|
||||
|
||||
|
@ -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_*/
|
||||
|
Loading…
Reference in New Issue
Block a user