libgweather r507 - in trunk: . libgweather
- From: danw svn gnome org
- To: svn-commits-list gnome org
- Subject: libgweather r507 - in trunk: . libgweather
- Date: Tue, 25 Nov 2008 14:44:18 +0000 (UTC)
Author: danw
Date: Tue Nov 25 14:44:17 2008
New Revision: 507
URL: http://svn.gnome.org/viewvc/libgweather?rev=507&view=rev
Log:
2008-11-25 Milan Crha <mcrha redhat com>
** Fix for bug #538787
* libgweather/weather.h:
* libgweather/weather.c:
* libgweather/weather-iwin.c:
Extending API to be able to get WeatherInfo values as numbers.
Modified:
trunk/ChangeLog
trunk/libgweather/weather-iwin.c
trunk/libgweather/weather-priv.h
trunk/libgweather/weather.c
trunk/libgweather/weather.h
Modified: trunk/libgweather/weather-iwin.c
==============================================================================
--- trunk/libgweather/weather-iwin.c (original)
+++ trunk/libgweather/weather-iwin.c Tue Nov 25 14:44:17 2008
@@ -24,6 +24,8 @@
#include <stdlib.h>
#include <string.h>
+#include <libxml/parser.h>
+
#define GWEATHER_I_KNOW_THIS_IS_UNSTABLE
#include "weather.h"
#include "weather-priv.h"
@@ -40,8 +42,8 @@
while (0 != *ptr) {
if (ptr[0] == '\n' && ptr[1] == '.') {
- /* This removes the preamble by shifting the relevant data
- * down to the start of the buffer. */
+ /* This removes the preamble by shifting the relevant data
+ * down to the start of the buffer. */
if (NULL == startLine) {
memmove (forecast, ptr, strlen (ptr) + 1);
ptr = forecast;
@@ -69,6 +71,310 @@
return forecast;
}
+static gboolean
+hasAttr (xmlNode *node, const char *attr_name, const char *attr_value)
+{
+ xmlChar *attr;
+ gboolean res = FALSE;
+
+ if (!node)
+ return res;
+
+ attr = xmlGetProp (node, (const xmlChar *) attr_name);
+
+ if (!attr)
+ return res;
+
+ res = g_str_equal ((const char *)attr, attr_value);
+
+ xmlFree (attr);
+
+ return res;
+}
+
+static GSList *
+parseForecastXml (const char *buff, WeatherInfo *master_info)
+{
+ GSList *res = NULL;
+ xmlDocPtr doc;
+ xmlNode *root, *node;
+
+ g_return_val_if_fail (master_info != NULL, NULL);
+
+ if (!buff || !*buff)
+ return NULL;
+
+ #define XC (const xmlChar *)
+ #define isElem(_node,_name) g_str_equal ((const char *)_node->name, _name)
+
+ doc = xmlParseMemory (buff, strlen (buff));
+ if (!doc)
+ return NULL;
+
+ /* Description at http://www.weather.gov/mdl/XML/Design/MDL_XML_Design.pdf */
+ root = xmlDocGetRootElement (doc);
+ for (node = root->xmlChildrenNode; node; node = node->next) {
+ if (node->name == NULL || node->type != XML_ELEMENT_NODE)
+ continue;
+
+ if (isElem (node, "data")) {
+ xmlNode *n;
+ char *time_layout = NULL;
+ time_t update_times[7] = {0};
+
+ for (n = node->children; n; n = n->next) {
+ if (!n->name)
+ continue;
+
+ if (isElem (n, "time-layout")) {
+ if (!time_layout && hasAttr (n, "summarization", "24hourly")) {
+ xmlNode *c;
+ int count = 0;
+
+ for (c = n->children; c && (count < 7 || !time_layout); c = c->next) {
+ if (c->name && !time_layout && isElem (c, "layout-key")) {
+ xmlChar *val = xmlNodeGetContent (c);
+
+ if (val) {
+ time_layout = g_strdup ((const char *)val);
+ xmlFree (val);
+ }
+ } else if (c->name && isElem (c, "start-valid-time")) {
+ xmlChar *val = xmlNodeGetContent (c);
+
+ if (val) {
+ struct tm t;
+ char sign;
+ int gmt1 = 0, gmt2 = 0;
+
+ memset (&t, 0, sizeof (struct tm));
+ if (sscanf ((const char *)val, "%04d-%02d-%02dT%02d:%02d:%02d%c%02d:%02d", &t.tm_year, &t.tm_mon, &t.tm_mday, &t.tm_hour, &t.tm_min, &t.tm_sec, &sign, &gmt1, &gmt2) == 9) {
+ t.tm_mon--;
+ t.tm_year -= 1900;
+ update_times[count] = mktime (&t) + ((sign == '-' ? -1 : 1) * ((60 * gmt1) + gmt2) * 60);
+ } else {
+ update_times[count] = 0;
+ }
+
+ count++;
+
+ xmlFree (val);
+ }
+ }
+ }
+
+ if (count != 7) {
+ /* There can be more than one time-layout element, the other
+ with only few children, which is not the one to use. */
+ g_free (time_layout);
+ time_layout = NULL;
+ }
+ }
+ } else if (isElem (n, "parameters")) {
+ xmlNode *p;
+
+ /* time-layout should be always before parameters */
+ if (!time_layout)
+ break;
+
+ if (!res) {
+ int i;
+
+ for (i = 0; i < 7; i++) {
+ WeatherInfo *nfo = weather_info_clone (master_info);
+
+ if (nfo) {
+ nfo->valid = FALSE;
+ nfo->forecast_type = FORECAST_ZONE;
+ nfo->update = update_times [i];
+ nfo->sky = -1;
+ nfo->temperature_unit = TEMP_UNIT_FAHRENHEIT;
+ nfo->temp = -1000.0;
+ nfo->temp_min = -1000.0;
+ nfo->temp_max = -1000.0;
+ nfo->tempMinMaxValid = FALSE;
+ nfo->cond.significant = FALSE;
+ nfo->cond.phenomenon = PHENOMENON_NONE;
+ nfo->cond.qualifier = QUALIFIER_NONE;
+ nfo->dew = -1000.0;
+ nfo->wind = -1;
+ nfo->windspeed = -1;
+ nfo->pressure = -1.0;
+ nfo->visibility = -1.0;
+ nfo->sunValid = FALSE;
+ nfo->sunrise = 0;
+ nfo->sunset = 0;
+ g_free (nfo->forecast);
+ nfo->forecast = NULL;
+ res = g_slist_append (res, nfo);
+ }
+ }
+ }
+
+ for (p = n->children; p; p = p->next) {
+ if (p->name && isElem (p, "temperature") && hasAttr (p, "time-layout", time_layout)) {
+ xmlNode *c;
+ GSList *at = res;
+ gboolean is_max = hasAttr (p, "type", "maximum");
+
+ if (!is_max && !hasAttr (p, "type", "minimum"))
+ break;
+
+ for (c = p->children; c && at; c = c->next) {
+ if (isElem (c, "value")) {
+ WeatherInfo *nfo = (WeatherInfo *)at->data;
+ xmlChar *val = xmlNodeGetContent (c);
+
+ /* can pass some values as <value xsi:nil="true"/> */
+ if (!val) {
+ if (is_max)
+ nfo->temp_max = nfo->temp_min;
+ else
+ nfo->temp_min = nfo->temp_max;
+ } else {
+ if (is_max)
+ nfo->temp_max = atof ((const char *)val);
+ else
+ nfo->temp_min = atof ((const char *)val);
+
+ xmlFree (val);
+ }
+
+ nfo->tempMinMaxValid = nfo->tempMinMaxValid || (nfo->temp_max > -999.0 && nfo->temp_min > -999.0);
+ nfo->valid = nfo->tempMinMaxValid;
+
+ at = at->next;
+ }
+ }
+ } else if (p->name && isElem (p, "weather") && hasAttr (p, "time-layout", time_layout)) {
+ xmlNode *c;
+ GSList *at = res;
+
+ for (c = p->children; c && at; c = c->next) {
+ if (c->name && isElem (c, "weather-conditions")) {
+ WeatherInfo *nfo = at->data;
+ xmlChar *val = xmlGetProp (c, XC "weather-summary");
+
+ if (val && nfo) {
+ /* Checking from top to bottom, if 'value' contains 'name', then that win,
+ thus put longer (more precise) values to the top. */
+ int i;
+ struct _ph_list {
+ const char *name;
+ WeatherConditionPhenomenon ph;
+ } ph_list[] = {
+ { "Ice Crystals", PHENOMENON_ICE_CRYSTALS } ,
+ { "Volcanic Ash", PHENOMENON_VOLCANIC_ASH } ,
+ { "Blowing Sand", PHENOMENON_SANDSTORM } ,
+ { "Blowing Dust", PHENOMENON_DUSTSTORM } ,
+ { "Blowing Snow", PHENOMENON_FUNNEL_CLOUD } ,
+ { "Drizzle", PHENOMENON_DRIZZLE } ,
+ { "Rain", PHENOMENON_RAIN } ,
+ { "Snow", PHENOMENON_SNOW } ,
+ { "Fog", PHENOMENON_FOG } ,
+ { "Smoke", PHENOMENON_SMOKE } ,
+ { "Sand", PHENOMENON_SAND } ,
+ { "Haze", PHENOMENON_HAZE } ,
+ { "Dust", PHENOMENON_DUST } /*,
+ { "", PHENOMENON_SNOW_GRAINS } ,
+ { "", PHENOMENON_ICE_PELLETS } ,
+ { "", PHENOMENON_HAIL } ,
+ { "", PHENOMENON_SMALL_HAIL } ,
+ { "", PHENOMENON_UNKNOWN_PRECIPITATION } ,
+ { "", PHENOMENON_MIST } ,
+ { "", PHENOMENON_SPRAY } ,
+ { "", PHENOMENON_SQUALL } ,
+ { "", PHENOMENON_TORNADO } ,
+ { "", PHENOMENON_DUST_WHIRLS } */
+ };
+ struct _sky_list {
+ const char *name;
+ WeatherSky sky;
+ } sky_list[] = {
+ { "Mostly Sunny", SKY_BROKEN } ,
+ { "Mostly Clear", SKY_BROKEN } ,
+ { "Partly Cloudy", SKY_SCATTERED } ,
+ { "Mostly Cloudy", SKY_FEW } ,
+ { "Sunny", SKY_CLEAR } ,
+ { "Clear", SKY_CLEAR } ,
+ { "Cloudy", SKY_OVERCAST } ,
+ { "Clouds", SKY_SCATTERED } ,
+ { "Rain", SKY_SCATTERED } ,
+ { "Snow", SKY_SCATTERED }
+ };
+
+ nfo->valid = TRUE;
+ g_free (nfo->forecast);
+ nfo->forecast = g_strdup ((const char *)val);
+
+ for (i = 0; i < G_N_ELEMENTS (ph_list); i++) {
+ if (strstr ((const char *)val, ph_list [i].name)) {
+ nfo->cond.phenomenon = ph_list [i].ph;
+ break;
+ }
+ }
+
+ for (i = 0; i < G_N_ELEMENTS (sky_list); i++) {
+ if (strstr ((const char *)val, sky_list [i].name)) {
+ nfo->sky = sky_list [i].sky;
+ break;
+ }
+ }
+ }
+
+ at = at->next;
+ }
+ }
+ }
+ }
+
+ if (res) {
+ gboolean have_any = FALSE;
+ GSList *r;
+
+ /* Remove invalid forecast data from the list.
+ They should be all valid or all invalid. */
+ for (r = res; r; r = r->next) {
+ WeatherInfo *nfo = r->data;
+
+ if (!nfo || !nfo->valid) {
+ if (r->data)
+ weather_info_free (r->data);
+
+ r->data = NULL;
+ } else {
+ have_any = TRUE;
+
+ if (nfo->tempMinMaxValid)
+ nfo->temp = (nfo->temp_min + nfo->temp_max) / 2.0;
+ }
+ }
+
+ if (!have_any) {
+ /* data members are freed already */
+ g_slist_free (res);
+ res = NULL;
+ }
+ }
+
+ break;
+ }
+ }
+
+ g_free (time_layout);
+
+ /* stop seeking XML */
+ break;
+ }
+ }
+ xmlFreeDoc (doc);
+
+ #undef XC
+ #undef isElem
+
+ return res;
+}
+
static void
iwin_finish (SoupSession *session, SoupMessage *msg, gpointer data)
{
@@ -78,13 +384,17 @@
if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
/* forecast data is not really interesting anyway ;) */
- g_warning ("Failed to get IWIN forecast data: %d %s\n",
- msg->status_code, msg->reason_phrase);
+ g_warning ("Failed to get IWIN forecast data: %d %s\n",
+ msg->status_code, msg->reason_phrase);
request_done (info, FALSE);
- return;
+ return;
}
+ if (info->forecast_type == FORECAST_LIST)
+ info->forecast_list = parseForecastXml (msg->response_body->data, info);
+ else
info->forecast = formatWeatherMsg (g_strdup (msg->response_body->data));
+
request_done (info, TRUE);
}
@@ -104,18 +414,41 @@
return;
if (info->forecast) {
- g_free (info->forecast);
- info->forecast = NULL;
+ g_free (info->forecast);
+ info->forecast = NULL;
+ }
+
+ free_forecast_list (info);
+
+ if (info->forecast_type == FORECAST_LIST) {
+ /* see the description here: http://www.weather.gov/forecasts/xml/ */
+ if (loc->latlon_valid) {
+ struct tm tm;
+ time_t now = time (NULL);
+
+ localtime_r (&now, &tm);
+
+ url = g_strdup_printf ("http://www.weather.gov/forecasts/xml/sample_products/browser_interface/ndfdBrowserClientByDay.php?&lat=%.02f&lon=%.02f&format=24+hourly&startDate=%04d-%02d-%02d&numDays=7",
+ RADIANS_TO_DEGREES (loc->latitude), RADIANS_TO_DEGREES (loc->longitude), 1900 + tm.tm_year, 1 + tm.tm_mon, tm.tm_mday);
+
+ msg = soup_message_new ("GET", url);
+ g_free (url);
+ soup_session_queue_message (info->session, msg, iwin_finish, info);
+
+ info->requests_pending++;
+ }
+
+ return;
}
if (loc->zone[0] == ':') {
- /* Met Office Region Names */
- metoffice_start_open (info);
- return;
+ /* Met Office Region Names */
+ metoffice_start_open (info);
+ return;
} else if (loc->zone[0] == '@') {
- /* Australian BOM forecasts */
- bom_start_open (info);
- return;
+ /* Australian BOM forecasts */
+ bom_start_open (info);
+ return;
}
/* The zone for Pittsburgh (for example) is given as PAZ021 in the locations
@@ -125,8 +458,8 @@
zone = g_ascii_strdown (loc->zone, -1);
state = g_strndup (zone, 2);
- url = g_strdup_printf ("http://weather.noaa.gov/pub/data/forecasts/zone/%s/%s.txt",
- state, zone);
+ url = g_strdup_printf ("http://weather.noaa.gov/pub/data/forecasts/zone/%s/%s.txt", state, zone);
+
g_free (zone);
g_free (state);
Modified: trunk/libgweather/weather-priv.h
==============================================================================
--- trunk/libgweather/weather-priv.h (original)
+++ trunk/libgweather/weather-priv.h Tue Nov 25 14:44:17 2008
@@ -21,6 +21,7 @@
#include <time.h>
#include <libintl.h>
+#include <math.h>
#include <libsoup/soup.h>
#include "weather.h"
@@ -40,79 +41,6 @@
* Weather information.
*/
-enum _WeatherWindDirection {
- WIND_VARIABLE,
- WIND_N, WIND_NNE, WIND_NE, WIND_ENE,
- WIND_E, WIND_ESE, WIND_SE, WIND_SSE,
- WIND_S, WIND_SSW, WIND_SW, WIND_WSW,
- WIND_W, WIND_WNW, WIND_NW, WIND_NNW
-};
-
-typedef enum _WeatherWindDirection WeatherWindDirection;
-
-enum _WeatherSky {
- SKY_INVALID = -1,
- SKY_CLEAR,
- SKY_BROKEN,
- SKY_SCATTERED,
- SKY_FEW,
- SKY_OVERCAST
-};
-
-typedef enum _WeatherSky WeatherSky;
-
-enum _WeatherConditionPhenomenon {
- PHENOMENON_NONE,
-
- PHENOMENON_DRIZZLE,
- PHENOMENON_RAIN,
- PHENOMENON_SNOW,
- PHENOMENON_SNOW_GRAINS,
- PHENOMENON_ICE_CRYSTALS,
- PHENOMENON_ICE_PELLETS,
- PHENOMENON_HAIL,
- PHENOMENON_SMALL_HAIL,
- PHENOMENON_UNKNOWN_PRECIPITATION,
-
- PHENOMENON_MIST,
- PHENOMENON_FOG,
- PHENOMENON_SMOKE,
- PHENOMENON_VOLCANIC_ASH,
- PHENOMENON_SAND,
- PHENOMENON_HAZE,
- PHENOMENON_SPRAY,
- PHENOMENON_DUST,
-
- PHENOMENON_SQUALL,
- PHENOMENON_SANDSTORM,
- PHENOMENON_DUSTSTORM,
- PHENOMENON_FUNNEL_CLOUD,
- PHENOMENON_TORNADO,
- PHENOMENON_DUST_WHIRLS
-};
-
-typedef enum _WeatherConditionPhenomenon WeatherConditionPhenomenon;
-
-enum _WeatherConditionQualifier {
- QUALIFIER_NONE,
-
- QUALIFIER_VICINITY,
-
- QUALIFIER_LIGHT,
- QUALIFIER_MODERATE,
- QUALIFIER_HEAVY,
- QUALIFIER_SHALLOW,
- QUALIFIER_PATCHES,
- QUALIFIER_PARTIAL,
- QUALIFIER_THUNDERSTORM,
- QUALIFIER_BLOWING,
- QUALIFIER_SHOWERS,
- QUALIFIER_DRIFTING,
- QUALIFIER_FREEZING
-};
-
-typedef enum _WeatherConditionQualifier WeatherConditionQualifier;
-
struct _WeatherConditions {
gboolean significant;
WeatherConditionPhenomenon phenomenon;
@@ -139,11 +67,14 @@
gboolean valid;
gboolean network_error;
gboolean sunValid;
+ gboolean tempMinMaxValid;
WeatherLocation *location;
WeatherUpdate update;
WeatherSky sky;
WeatherConditions cond;
WeatherTemperature temp;
+ WeatherTemperature temp_min;
+ WeatherTemperature temp_max;
WeatherTemperature dew;
WeatherWindDirection wind;
WeatherWindSpeed windspeed;
@@ -152,6 +83,7 @@
WeatherUpdate sunrise;
WeatherUpdate sunset;
gchar *forecast;
+ GSList *forecast_list; /* list of WeatherInfo* for the forecast, NULL if not available */
gchar *radar_buffer;
gchar *radar_url;
GdkPixbufLoader *radar_loader;
@@ -219,5 +151,7 @@
gboolean calc_sun (WeatherInfo *info);
+void free_forecast_list (WeatherInfo *info);
+
#endif /* __WEATHER_PRIV_H_ */
Modified: trunk/libgweather/weather.c
==============================================================================
--- trunk/libgweather/weather.c (original)
+++ trunk/libgweather/weather.c Tue Nov 25 14:44:17 2008
@@ -332,8 +332,25 @@
info->finish_cb (info, info->cb_data);
}
-/* Relative humidity computation - thanks to <Olof Oberg modopaper modogroup com> */
+/* it's OK to pass in NULL */
+void
+free_forecast_list (WeatherInfo *info)
+{
+ GSList *p;
+
+ if (!info)
+ return;
+
+ for (p = info->forecast_list; p; p = p->next)
+ weather_info_free (p->data);
+
+ if (info->forecast_list) {
+ g_slist_free (info->forecast_list);
+ info->forecast_list = NULL;
+ }
+}
+/* Relative humidity computation - thanks to <Olof Oberg modopaper modogroup com> */
static inline gdouble
calc_humidity (gdouble temp, gdouble dewp)
@@ -490,8 +507,10 @@
location = info->location;
if (info->forecast)
g_free (info->forecast);
-
info->forecast = NULL;
+
+ free_forecast_list (info);
+
if (info->radar != NULL) {
g_object_unref (info->radar);
info->radar = NULL;
@@ -519,6 +538,9 @@
info->cond.phenomenon = PHENOMENON_NONE;
info->cond.qualifier = QUALIFIER_NONE;
info->temp = -1000.0;
+ info->tempMinMaxValid = FALSE;
+ info->temp_min = -1000.0;
+ info->temp_max = -1000.0;
info->dew = -1000.0;
info->wind = -1;
info->windspeed = -1;
@@ -528,6 +550,7 @@
info->sunrise = 0;
info->sunset = 0;
info->forecast = NULL;
+ info->forecast_list = NULL;
info->radar = NULL;
info->radar_url = prefs->radar && prefs->radar_custom_url ?
g_strdup (prefs->radar_custom_url) : NULL;
@@ -576,6 +599,17 @@
clone->forecast = g_strdup (info->forecast);
clone->radar_url = g_strdup (info->radar_url);
+ if (info->forecast_list) {
+ GSList *p;
+
+ clone->forecast_list = NULL;
+ for (p = info->forecast_list; p; p = p->next) {
+ clone->forecast_list = g_slist_prepend (clone->forecast_list, weather_info_clone (p->data));
+ }
+
+ clone->forecast_list = g_slist_reverse (clone->forecast_list);
+ }
+
clone->radar = info->radar;
if (clone->radar != NULL)
g_object_ref (clone->radar);
@@ -599,6 +633,8 @@
g_free (info->forecast);
info->forecast = NULL;
+ free_forecast_list (info);
+
if (info->radar != NULL) {
g_object_unref (info->radar);
info->radar = NULL;
@@ -621,6 +657,28 @@
return info->network_error;
}
+void
+weather_info_to_metric (WeatherInfo *info)
+{
+ g_return_if_fail(info != NULL);
+
+ info->temperature_unit = TEMP_UNIT_CENTIGRADE;
+ info->speed_unit = SPEED_UNIT_MS;
+ info->pressure_unit = PRESSURE_UNIT_HPA;
+ info->distance_unit = DISTANCE_UNIT_METERS;
+}
+
+void
+weather_info_to_imperial (WeatherInfo *info)
+{
+ g_return_if_fail(info != NULL);
+
+ info->temperature_unit = TEMP_UNIT_FAHRENHEIT;
+ info->speed_unit = SPEED_UNIT_MPH;
+ info->pressure_unit = PRESSURE_UNIT_INCH_HG;
+ info->distance_unit = DISTANCE_UNIT_MILES;
+}
+
const WeatherLocation *
weather_info_get_location (WeatherInfo *info)
{
@@ -753,6 +811,32 @@
}
const gchar *
+weather_info_get_temp_min (WeatherInfo *info)
+{
+ g_return_val_if_fail (info != NULL, NULL);
+
+ if (!info->valid || !info->tempMinMaxValid)
+ return "-";
+ if (info->temp_min < -500.0)
+ return _("Unknown");
+
+ return temperature_string (info->temp_min, info->temperature_unit, FALSE);
+}
+
+const gchar *
+weather_info_get_temp_max (WeatherInfo *info)
+{
+ g_return_val_if_fail (info != NULL, NULL);
+
+ if (!info->valid || !info->tempMinMaxValid)
+ return "-";
+ if (info->temp_max < -500.0)
+ return _("Unknown");
+
+ return temperature_string (info->temp_max, info->temperature_unit, FALSE);
+}
+
+const gchar *
weather_info_get_dew (WeatherInfo *info)
{
g_return_val_if_fail (info != NULL, NULL);
@@ -996,6 +1080,26 @@
return info->forecast;
}
+/**
+ * weather_info_get_forecast_list:
+ * Returns list of WeatherInfo* objects for the forecast.
+ * The list is owned by the 'info' object thus is alive as long
+ * as the 'info'. This list is filled only when requested with
+ * type FORECAST_LIST and if available for given location.
+ * The 'update' property is the date/time when the forecast info
+ * is used for.
+ **/
+GSList *
+weather_info_get_forecast_list (WeatherInfo *info)
+{
+ g_return_val_if_fail (info != NULL, NULL);
+
+ if (!info->valid)
+ return NULL;
+
+ return info->forecast_list;
+}
+
GdkPixbufAnimation *
weather_info_get_radar (WeatherInfo *info)
{
@@ -1113,3 +1217,338 @@
return NULL;
}
+
+static gboolean
+temperature_value (gdouble far, TempUnit to_unit, gdouble *value, TempUnit def_unit)
+{
+ gboolean ok = TRUE;
+
+ *value = 0.0;
+ if (far < -500.0)
+ return FALSE;
+
+ if (to_unit == TEMP_UNIT_DEFAULT)
+ to_unit = def_unit;
+
+ switch (to_unit) {
+ case TEMP_UNIT_FAHRENHEIT:
+ *value = far;
+ break;
+ case TEMP_UNIT_CENTIGRADE:
+ *value = TEMP_F_TO_C (far);
+ break;
+ case TEMP_UNIT_KELVIN:
+ *value = TEMP_F_TO_K (far);
+ break;
+ case TEMP_UNIT_INVALID:
+ case TEMP_UNIT_DEFAULT:
+ default:
+ ok = FALSE;
+ break;
+ }
+
+ return ok;
+}
+
+static gboolean
+speed_value (gdouble knots, SpeedUnit to_unit, gdouble *value, SpeedUnit def_unit)
+{
+ gboolean ok = TRUE;
+
+ *value = -1.0;
+
+ if (knots < 0.0)
+ return FALSE;
+
+ if (to_unit == SPEED_UNIT_DEFAULT)
+ to_unit = def_unit;
+
+ switch (to_unit) {
+ case SPEED_UNIT_KNOTS:
+ *value = knots;
+ break;
+ case SPEED_UNIT_MPH:
+ *value = WINDSPEED_KNOTS_TO_MPH (knots);
+ break;
+ case SPEED_UNIT_KPH:
+ *value = WINDSPEED_KNOTS_TO_KPH (knots);
+ break;
+ case SPEED_UNIT_MS:
+ *value = WINDSPEED_KNOTS_TO_MS (knots);
+ break;
+ case SPEED_UNIT_BFT:
+ *value = WINDSPEED_KNOTS_TO_BFT (knots);
+ break;
+ case SPEED_UNIT_INVALID:
+ case SPEED_UNIT_DEFAULT:
+ default:
+ ok = FALSE;
+ break;
+ }
+
+ return ok;
+}
+
+static gboolean
+pressure_value (gdouble inHg, PressureUnit to_unit, gdouble *value, PressureUnit def_unit)
+{
+ gboolean ok = TRUE;
+
+ *value = -1.0;
+
+ if (inHg < 0.0)
+ return FALSE;
+
+ if (to_unit == PRESSURE_UNIT_DEFAULT)
+ to_unit = def_unit;
+
+ switch (to_unit) {
+ case PRESSURE_UNIT_INCH_HG:
+ *value = inHg;
+ break;
+ case PRESSURE_UNIT_MM_HG:
+ *value = PRESSURE_INCH_TO_MM (inHg);
+ break;
+ case PRESSURE_UNIT_KPA:
+ *value = PRESSURE_INCH_TO_KPA (inHg);
+ break;
+ case PRESSURE_UNIT_HPA:
+ *value = PRESSURE_INCH_TO_HPA (inHg);
+ break;
+ case PRESSURE_UNIT_MB:
+ *value = PRESSURE_INCH_TO_MB (inHg);
+ break;
+ case PRESSURE_UNIT_ATM:
+ *value = PRESSURE_INCH_TO_ATM (inHg);
+ break;
+ case PRESSURE_UNIT_INVALID:
+ case PRESSURE_UNIT_DEFAULT:
+ default:
+ ok = FALSE;
+ break;
+ }
+
+ return ok;
+}
+
+static gboolean
+distance_value (gdouble miles, DistanceUnit to_unit, gdouble *value, DistanceUnit def_unit)
+{
+ gboolean ok = TRUE;
+
+ *value = -1.0;
+
+ if (miles < 0.0)
+ return FALSE;
+
+ if (to_unit == DISTANCE_UNIT_DEFAULT)
+ to_unit = def_unit;
+
+ switch (to_unit) {
+ case DISTANCE_UNIT_MILES:
+ *value = miles;
+ break;
+ case DISTANCE_UNIT_KM:
+ *value = VISIBILITY_SM_TO_KM (miles);
+ break;
+ case DISTANCE_UNIT_METERS:
+ *value = VISIBILITY_SM_TO_M (miles);
+ break;
+ case DISTANCE_UNIT_INVALID:
+ case DISTANCE_UNIT_DEFAULT:
+ default:
+ ok = FALSE;
+ break;
+ }
+
+ return ok;
+}
+
+gboolean
+weather_info_get_value_sky (WeatherInfo *info, WeatherSky *sky)
+{
+ g_return_val_if_fail (info != NULL, FALSE);
+ g_return_val_if_fail (sky != NULL, FALSE);
+
+ if (!info->valid)
+ return FALSE;
+
+ if (info->sky < 0 || info->sky >= (sizeof (sky_str) / sizeof (char *)))
+ return FALSE;
+
+ *sky = info->sky;
+
+ return TRUE;
+}
+
+gboolean
+weather_info_get_value_conditions (WeatherInfo *info, WeatherConditionPhenomenon *phenomenon, WeatherConditionQualifier *qualifier)
+{
+ g_return_val_if_fail (info != NULL, FALSE);
+ g_return_val_if_fail (phenomenon != NULL, FALSE);
+ g_return_val_if_fail (qualifier != NULL, FALSE);
+
+ if (!info->valid)
+ return FALSE;
+
+ if (!info->cond.significant)
+ return FALSE;
+
+ if (!(info->cond.phenomenon >= 0 &&
+ info->cond.phenomenon < 24 &&
+ info->cond.qualifier >= 0 &&
+ info->cond.qualifier < 13))
+ return FALSE;
+
+ *phenomenon = info->cond.phenomenon;
+ *qualifier = info->cond.qualifier;
+
+ return TRUE;
+}
+
+gboolean
+weather_info_get_value_temp (WeatherInfo *info, TempUnit unit, gdouble *value)
+{
+ g_return_val_if_fail (info != NULL, FALSE);
+ g_return_val_if_fail (value != NULL, FALSE);
+
+ if (!info->valid)
+ return FALSE;
+
+ return temperature_value (info->temp, unit, value, info->temperature_unit);
+}
+
+gboolean
+weather_info_get_value_temp_min (WeatherInfo *info, TempUnit unit, gdouble *value)
+{
+ g_return_val_if_fail (info != NULL, FALSE);
+ g_return_val_if_fail (value != NULL, FALSE);
+
+ if (!info->valid || !info->tempMinMaxValid)
+ return FALSE;
+
+ return temperature_value (info->temp_min, unit, value, info->temperature_unit);
+}
+
+gboolean
+weather_info_get_value_temp_max (WeatherInfo *info, TempUnit unit, gdouble *value)
+{
+ g_return_val_if_fail (info != NULL, FALSE);
+ g_return_val_if_fail (value != NULL, FALSE);
+
+ if (!info->valid || !info->tempMinMaxValid)
+ return FALSE;
+
+ return temperature_value (info->temp_max, unit, value, info->temperature_unit);
+}
+
+gboolean
+weather_info_get_value_dew (WeatherInfo *info, TempUnit unit, gdouble *value)
+{
+ g_return_val_if_fail (info != NULL, FALSE);
+ g_return_val_if_fail (value != NULL, FALSE);
+
+ if (!info->valid)
+ return FALSE;
+
+ return temperature_value (info->dew, unit, value, info->temperature_unit);
+}
+
+gboolean
+weather_info_get_value_apparent (WeatherInfo *info, TempUnit unit, gdouble *value)
+{
+ g_return_val_if_fail (info != NULL, FALSE);
+ g_return_val_if_fail (value != NULL, FALSE);
+
+ if (!info->valid)
+ return FALSE;
+
+ return temperature_value (calc_apparent (info), unit, value, info->temperature_unit);
+}
+
+gboolean
+weather_info_get_value_update (WeatherInfo *info, time_t *value)
+{
+ g_return_val_if_fail (info != NULL, FALSE);
+ g_return_val_if_fail (value != NULL, FALSE);
+
+ if (!info->valid)
+ return FALSE;
+
+ *value = info->update;
+
+ return *value != 0;
+}
+
+gboolean
+weather_info_get_value_sunrise (WeatherInfo *info, time_t *value)
+{
+ g_return_val_if_fail (info != NULL, FALSE);
+ g_return_val_if_fail (value != NULL, FALSE);
+
+ if (!info->valid || !info->sunValid)
+ return FALSE;
+
+ *value = info->sunrise;
+
+ return *value != 0;
+}
+
+gboolean
+weather_info_get_value_sunset (WeatherInfo *info, time_t *value)
+{
+ g_return_val_if_fail (info != NULL, FALSE);
+ g_return_val_if_fail (value != NULL, FALSE);
+
+ if (!info->valid || !info->sunValid)
+ return FALSE;
+
+ *value = info->sunset;
+
+ return *value != 0;
+}
+
+gboolean
+weather_info_get_value_wind (WeatherInfo *info, SpeedUnit unit, gdouble *speed, WeatherWindDirection *direction)
+{
+ gboolean res = FALSE;
+
+ g_return_val_if_fail (info != NULL, FALSE);
+ g_return_val_if_fail (speed != NULL, FALSE);
+ g_return_val_if_fail (direction != NULL, FALSE);
+
+ if (!info->valid)
+ return FALSE;
+
+ if (info->windspeed < 0.0 || info->wind < 0 || info->wind >= (sizeof (wind_direction_str) / sizeof (char *)))
+ return FALSE;
+
+ res = speed_value (info->windspeed, unit, speed, info->speed_unit);
+ *direction = info->wind;
+
+ return res;
+}
+
+gboolean
+weather_info_get_value_pressure (WeatherInfo *info, PressureUnit unit, gdouble *value)
+{
+ g_return_val_if_fail (info != NULL, FALSE);
+ g_return_val_if_fail (value != NULL, FALSE);
+
+ if (!info->valid)
+ return FALSE;
+
+ return pressure_value (info->pressure, unit, value, info->pressure_unit);
+}
+
+gboolean
+weather_info_get_value_visibility (WeatherInfo *info, DistanceUnit unit, gdouble *value)
+{
+ g_return_val_if_fail (info != NULL, FALSE);
+ g_return_val_if_fail (value != NULL, FALSE);
+
+ if (!info->valid)
+ return FALSE;
+
+ return distance_value (info->visibility, unit, value, info->distance_unit);
+}
Modified: trunk/libgweather/weather.h
==============================================================================
--- trunk/libgweather/weather.h (original)
+++ trunk/libgweather/weather.h Tue Nov 25 14:44:17 2008
@@ -67,7 +67,8 @@
typedef enum _WeatherForecastType {
FORECAST_STATE,
- FORECAST_ZONE
+ FORECAST_ZONE,
+ FORECAST_LIST
} WeatherForecastType;
typedef enum {
@@ -153,6 +154,8 @@
const gchar * weather_info_get_sky (WeatherInfo *info);
const gchar * weather_info_get_conditions (WeatherInfo *info);
const gchar * weather_info_get_temp (WeatherInfo *info);
+const gchar * weather_info_get_temp_min (WeatherInfo *info);
+const gchar * weather_info_get_temp_max (WeatherInfo *info);
const gchar * weather_info_get_dew (WeatherInfo *info);
const gchar * weather_info_get_humidity (WeatherInfo *info);
const gchar * weather_info_get_wind (WeatherInfo *info);
@@ -162,6 +165,7 @@
const gchar * weather_info_get_sunrise (WeatherInfo *info);
const gchar * weather_info_get_sunset (WeatherInfo *info);
const gchar * weather_info_get_forecast (WeatherInfo *info);
+GSList * weather_info_get_forecast_list (WeatherInfo *info);
GdkPixbufAnimation * weather_info_get_radar (WeatherInfo *info);
const gchar * weather_info_get_temp_summary (WeatherInfo *info);
@@ -169,6 +173,96 @@
const gchar * weather_info_get_icon_name (WeatherInfo *info);
gint weather_info_next_sun_event (WeatherInfo *info);
+
+/* values retrieving functions */
+
+enum _WeatherWindDirection {
+ WIND_VARIABLE,
+ WIND_N, WIND_NNE, WIND_NE, WIND_ENE,
+ WIND_E, WIND_ESE, WIND_SE, WIND_SSE,
+ WIND_S, WIND_SSW, WIND_SW, WIND_WSW,
+ WIND_W, WIND_WNW, WIND_NW, WIND_NNW
+};
+
+typedef enum _WeatherWindDirection WeatherWindDirection;
+
+enum _WeatherSky {
+ SKY_INVALID = -1,
+ SKY_CLEAR,
+ SKY_BROKEN,
+ SKY_SCATTERED,
+ SKY_FEW,
+ SKY_OVERCAST
+};
+
+typedef enum _WeatherSky WeatherSky;
+
+enum _WeatherConditionPhenomenon {
+ PHENOMENON_NONE,
+
+ PHENOMENON_DRIZZLE,
+ PHENOMENON_RAIN,
+ PHENOMENON_SNOW,
+ PHENOMENON_SNOW_GRAINS,
+ PHENOMENON_ICE_CRYSTALS,
+ PHENOMENON_ICE_PELLETS,
+ PHENOMENON_HAIL,
+ PHENOMENON_SMALL_HAIL,
+ PHENOMENON_UNKNOWN_PRECIPITATION,
+
+ PHENOMENON_MIST,
+ PHENOMENON_FOG,
+ PHENOMENON_SMOKE,
+ PHENOMENON_VOLCANIC_ASH,
+ PHENOMENON_SAND,
+ PHENOMENON_HAZE,
+ PHENOMENON_SPRAY,
+ PHENOMENON_DUST,
+
+ PHENOMENON_SQUALL,
+ PHENOMENON_SANDSTORM,
+ PHENOMENON_DUSTSTORM,
+ PHENOMENON_FUNNEL_CLOUD,
+ PHENOMENON_TORNADO,
+ PHENOMENON_DUST_WHIRLS
+};
+
+typedef enum _WeatherConditionPhenomenon WeatherConditionPhenomenon;
+
+enum _WeatherConditionQualifier {
+ QUALIFIER_NONE,
+
+ QUALIFIER_VICINITY,
+
+ QUALIFIER_LIGHT,
+ QUALIFIER_MODERATE,
+ QUALIFIER_HEAVY,
+ QUALIFIER_SHALLOW,
+ QUALIFIER_PATCHES,
+ QUALIFIER_PARTIAL,
+ QUALIFIER_THUNDERSTORM,
+ QUALIFIER_BLOWING,
+ QUALIFIER_SHOWERS,
+ QUALIFIER_DRIFTING,
+ QUALIFIER_FREEZING
+};
+
+typedef enum _WeatherConditionQualifier WeatherConditionQualifier;
+
+gboolean weather_info_get_value_update (WeatherInfo *info, time_t *value);
+gboolean weather_info_get_value_sky (WeatherInfo *info, WeatherSky *sky);
+gboolean weather_info_get_value_conditions (WeatherInfo *info, WeatherConditionPhenomenon *phenomenon, WeatherConditionQualifier *qualifier);
+gboolean weather_info_get_value_temp (WeatherInfo *info, TempUnit unit, gdouble *value);
+gboolean weather_info_get_value_temp_min (WeatherInfo *info, TempUnit unit, gdouble *value);
+gboolean weather_info_get_value_temp_max (WeatherInfo *info, TempUnit unit, gdouble *value);
+gboolean weather_info_get_value_dew (WeatherInfo *info, TempUnit unit, gdouble *value);
+gboolean weather_info_get_value_apparent (WeatherInfo *info, TempUnit unit, gdouble *value);
+gboolean weather_info_get_value_wind (WeatherInfo *info, SpeedUnit unit, gdouble *speed, WeatherWindDirection *direction);
+gboolean weather_info_get_value_pressure (WeatherInfo *info, PressureUnit unit, gdouble *value);
+gboolean weather_info_get_value_visibility (WeatherInfo *info, DistanceUnit unit, gdouble *value);
+gboolean weather_info_get_value_sunrise (WeatherInfo *info, time_t *value);
+gboolean weather_info_get_value_sunset (WeatherInfo *info, time_t *value);
+
G_END_DECLS
#endif /* __WEATHER_H_ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]