~ubuntu-branches/ubuntu/trusty/libgweather/trusty-updates

« back to all changes in this revision

Viewing changes to libgweather/weather-yrno.c

  • Committer: Package Import Robot
  • Author(s): Jeremy Bicha
  • Date: 2013-05-27 11:58:15 UTC
  • mfrom: (13.1.4 experimental)
  • Revision ID: package-import@ubuntu.com-20130527115815-l51yffuy20gbv9q0
Tags: 3.8.0-1ubuntu1
* Sync with Debian (LP: #1184168). Remaining changes: 
  - debian/control.in, debian/rules:
    + Run autoreconf
  - debian/rules:
    + Generate POT files on build
  - debian/patches/01_gettext_not_xml.patch: 
    + using gettext rather than add translations to the xml databases
  - debian/patches/02_no_external_gettext.patch:
    + Can't have both IT_PROG_INTLTOOL and AM_GNU_GETTEXT

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
 
2
/* weather-yrno.c - Yr.no Weather service.
 
3
 *
 
4
 * Copyright 2012 Giovanni Campagna <scampa.giovanni@gmail.com>
 
5
 *
 
6
 * This program is free software; you can redistribute it and/or
 
7
 * modify it under the terms of the GNU General Public License as
 
8
 * published by the Free Software Foundation; either version 2 of the
 
9
 * License, or (at your option) any later version.
 
10
 *
 
11
 * This program is distributed in the hope that it will be useful, but
 
12
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 
14
 * General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU General Public License
 
17
 * along with this program; if not, see
 
18
 * <http://www.gnu.org/licenses/>.
 
19
 */
 
20
 
 
21
#ifdef HAVE_CONFIG_H
 
22
#include <config.h>
 
23
#endif
 
24
 
 
25
#define _GNU_SOURCE /* for strptime */
 
26
#include <time.h>
 
27
#include <stdlib.h>
 
28
#include <string.h>
 
29
#include <stdio.h>
 
30
 
 
31
#include <glib.h>
 
32
 
 
33
#include <libxml/parser.h>
 
34
#include <libxml/xpath.h>
 
35
#include <libxml/xpathInternals.h>
 
36
 
 
37
#define GWEATHER_I_KNOW_THIS_IS_UNSTABLE
 
38
#include "weather-priv.h"
 
39
 
 
40
#define XC(t) ((const xmlChar *)(t))
 
41
 
 
42
/* Reference for symbols at http://om.yr.no/forklaring/symbol/ */
 
43
static struct {
 
44
    GWeatherSky sky;
 
45
    GWeatherConditions condition;
 
46
} symbols[] = {
 
47
    { GWEATHER_SKY_CLEAR,     { FALSE, GWEATHER_PHENOMENON_NONE, GWEATHER_QUALIFIER_NONE } }, /* Sun / clear sky */
 
48
    { GWEATHER_SKY_BROKEN,    { FALSE, GWEATHER_PHENOMENON_NONE, GWEATHER_QUALIFIER_NONE } }, /* Fair */
 
49
    { GWEATHER_SKY_SCATTERED, { FALSE, GWEATHER_PHENOMENON_NONE, GWEATHER_QUALIFIER_NONE } }, /* Partly cloudy */
 
50
    { GWEATHER_SKY_OVERCAST,  { FALSE, GWEATHER_PHENOMENON_NONE, GWEATHER_QUALIFIER_NONE } }, /* Cloudy */
 
51
    { GWEATHER_SKY_BROKEN,    { TRUE, GWEATHER_PHENOMENON_RAIN, GWEATHER_QUALIFIER_SHOWERS } }, /* Rain showers */
 
52
    { GWEATHER_SKY_BROKEN,    { TRUE, GWEATHER_PHENOMENON_RAIN, GWEATHER_QUALIFIER_THUNDERSTORM } }, /* Rain showers with thunder */
 
53
    { GWEATHER_SKY_BROKEN,    { TRUE, GWEATHER_PHENOMENON_ICE_PELLETS, GWEATHER_QUALIFIER_SHOWERS } }, /* Sleet showers */
 
54
    { GWEATHER_SKY_OVERCAST,  { TRUE, GWEATHER_PHENOMENON_SNOW, GWEATHER_QUALIFIER_SHOWERS } }, /* Snow showers */
 
55
    { GWEATHER_SKY_OVERCAST,  { TRUE, GWEATHER_PHENOMENON_RAIN, GWEATHER_QUALIFIER_NONE } }, /* Rain */
 
56
    { GWEATHER_SKY_OVERCAST,  { TRUE, GWEATHER_PHENOMENON_RAIN, GWEATHER_QUALIFIER_HEAVY } }, /* Heavy rain */
 
57
    { GWEATHER_SKY_OVERCAST,  { TRUE, GWEATHER_PHENOMENON_RAIN, GWEATHER_QUALIFIER_THUNDERSTORM } }, /* Rain and thunder */
 
58
    { GWEATHER_SKY_OVERCAST,  { TRUE, GWEATHER_PHENOMENON_ICE_PELLETS, GWEATHER_QUALIFIER_NONE } }, /* Sleet */
 
59
    { GWEATHER_SKY_OVERCAST,  { TRUE, GWEATHER_PHENOMENON_SNOW, GWEATHER_QUALIFIER_NONE } }, /* Snow */
 
60
    { GWEATHER_SKY_OVERCAST,  { TRUE, GWEATHER_PHENOMENON_SNOW, GWEATHER_QUALIFIER_THUNDERSTORM } }, /* Snow and thunder */
 
61
    { GWEATHER_SKY_CLEAR,     { TRUE, GWEATHER_PHENOMENON_FOG, GWEATHER_QUALIFIER_NONE } }, /* Fog */
 
62
    { GWEATHER_SKY_BROKEN,    { TRUE, GWEATHER_PHENOMENON_ICE_PELLETS, GWEATHER_QUALIFIER_THUNDERSTORM } }, /* Sleet showers and thunder */
 
63
    { GWEATHER_SKY_BROKEN,    { TRUE, GWEATHER_PHENOMENON_SNOW, GWEATHER_QUALIFIER_THUNDERSTORM } }, /* Snow showers and thunder */
 
64
    { GWEATHER_SKY_OVERCAST,  { TRUE, GWEATHER_PHENOMENON_RAIN, GWEATHER_QUALIFIER_HEAVY } }, /* Rain and thunder */
 
65
    { GWEATHER_SKY_OVERCAST,  { TRUE, GWEATHER_PHENOMENON_ICE_PELLETS, GWEATHER_QUALIFIER_HEAVY } } /* Sleet and thunder */
 
66
};
 
67
 
 
68
static struct {
 
69
    const char *name;
 
70
    GWeatherWindDirection direction;
 
71
} wind_directions[] = {
 
72
    { "N", GWEATHER_WIND_N },
 
73
    { "NNE", GWEATHER_WIND_NNE },
 
74
    { "NE", GWEATHER_WIND_NE },
 
75
    { "ENE", GWEATHER_WIND_ENE },
 
76
    { "E", GWEATHER_WIND_E },
 
77
    { "ESE", GWEATHER_WIND_ESE },
 
78
    { "SE", GWEATHER_WIND_SE },
 
79
    { "SSE", GWEATHER_WIND_SSE },
 
80
    { "S", GWEATHER_WIND_S },
 
81
    { "SSW", GWEATHER_WIND_SSW },
 
82
    { "SW", GWEATHER_WIND_SW },
 
83
    { "WSW", GWEATHER_WIND_WSW },
 
84
    { "W", GWEATHER_WIND_W },
 
85
    { "WNW", GWEATHER_WIND_WNW },
 
86
    { "NW", GWEATHER_WIND_NW },
 
87
    { "NNW", GWEATHER_WIND_NNW },
 
88
};
 
89
 
 
90
static time_t
 
91
date_to_time_t (const xmlChar *str, const char * tzid)
 
92
{
 
93
    struct tm time = { 0 };
 
94
    GTimeZone *tz;
 
95
    GDateTime *dt;
 
96
    time_t rval;
 
97
    char *after;
 
98
 
 
99
    after = strptime ((const char*) str, "%Y-%m-%dT%T", &time);
 
100
    if (after == NULL) {
 
101
        g_warning ("Cannot parse date string \"%s\"", str);
 
102
        return 0;
 
103
    }
 
104
 
 
105
    if (*after == 'Z')
 
106
        tzid = "UTC";
 
107
 
 
108
    tz = g_time_zone_new (tzid);
 
109
    dt = g_date_time_new (tz,
 
110
                          time.tm_year + 1900,
 
111
                          time.tm_mon + 1,
 
112
                          time.tm_mday,
 
113
                          time.tm_hour,
 
114
                          time.tm_min,
 
115
                          time.tm_sec);
 
116
 
 
117
    rval = g_date_time_to_unix (dt);
 
118
 
 
119
    g_time_zone_unref (tz);
 
120
    g_date_time_unref (dt);
 
121
 
 
122
    return rval;
 
123
}
 
124
 
 
125
static inline void
 
126
read_symbol (GWeatherInfo *info,
 
127
             xmlNodePtr    node)
 
128
{
 
129
    xmlChar *val;
 
130
    int symbol;
 
131
    GWeatherInfoPrivate *priv = info->priv;
 
132
 
 
133
    val = xmlGetProp (node, XC("number"));
 
134
 
 
135
    symbol = strtol ((char*) val, NULL, 0) - 1;
 
136
    if (symbol >= 0 && symbol < G_N_ELEMENTS (symbols)) {
 
137
        priv->valid = TRUE;
 
138
        priv->sky = symbols[symbol].sky;
 
139
        priv->cond = symbols[symbol].condition;
 
140
    }
 
141
}
 
142
 
 
143
static inline void
 
144
read_wind_direction (GWeatherInfo *info,
 
145
                     xmlNodePtr    node)
 
146
{
 
147
    xmlChar *val;
 
148
    int i;
 
149
 
 
150
    val = xmlGetProp (node, XC("code"));
 
151
    if (val == NULL)
 
152
        val = xmlGetProp (node, XC("name"));
 
153
    if (val == NULL)
 
154
        return;
 
155
 
 
156
    for (i = 0; i < G_N_ELEMENTS (wind_directions); i++) {
 
157
        if (strcmp ((char*) val, wind_directions[i].name) == 0) {
 
158
            info->priv->wind = wind_directions[i].direction;
 
159
            return;
 
160
        }
 
161
    }
 
162
}
 
163
 
 
164
static inline void
 
165
read_wind_speed (GWeatherInfo *info,
 
166
                 xmlNodePtr    node)
 
167
{
 
168
    xmlChar *val;
 
169
    double mps;
 
170
 
 
171
    val = xmlGetProp (node, XC("mps"));
 
172
    if (val == NULL)
 
173
        return;
 
174
 
 
175
    mps = g_ascii_strtod ((char*) val, NULL);
 
176
    info->priv->windspeed = WINDSPEED_MS_TO_KNOTS (mps);
 
177
}
 
178
 
 
179
static inline void
 
180
read_temperature (GWeatherInfo *info,
 
181
                  xmlNodePtr    node)
 
182
{
 
183
    xmlChar *val;
 
184
    double celsius;
 
185
 
 
186
    val = xmlGetProp (node, XC("value"));
 
187
    if (val == NULL)
 
188
        return;
 
189
 
 
190
    celsius = g_ascii_strtod ((char*) val, NULL);
 
191
    info->priv->temp = TEMP_C_TO_F (celsius);
 
192
}
 
193
 
 
194
static inline void
 
195
read_pressure (GWeatherInfo *info,
 
196
               xmlNodePtr    node)
 
197
{
 
198
    xmlChar *val;
 
199
    double hpa;
 
200
 
 
201
    val = xmlGetProp (node, XC("value"));
 
202
    if (val == NULL)
 
203
        return;
 
204
 
 
205
    hpa = g_ascii_strtod ((char*) val, NULL);
 
206
    info->priv->pressure = PRESSURE_MBAR_TO_INCH (hpa);
 
207
}
 
208
 
 
209
static inline void
 
210
read_child_node (GWeatherInfo *info,
 
211
                 xmlNodePtr    node)
 
212
{
 
213
    if (strcmp ((char*) node->name, "symbol") == 0)
 
214
        read_symbol (info, node);
 
215
    else if (strcmp ((char*) node->name, "windDirection") == 0)
 
216
        read_wind_direction (info, node);
 
217
    else if (strcmp ((char*) node->name, "windSpeed") == 0)
 
218
        read_wind_speed (info, node);
 
219
    else if (strcmp ((char*) node->name, "temperature") == 0)
 
220
        read_temperature (info, node);
 
221
    else if (strcmp ((char*) node->name, "pressure") == 0)
 
222
        read_pressure (info, node);
 
223
}
 
224
 
 
225
static inline void
 
226
fill_info_from_node (GWeatherInfo *info,
 
227
                     xmlNodePtr    node)
 
228
{
 
229
    xmlNodePtr child;
 
230
 
 
231
    for (child = node->children; child != NULL; child = child->next) {
 
232
        if (child->type == XML_ELEMENT_NODE)
 
233
            read_child_node (info, child);
 
234
    }
 
235
}
 
236
 
 
237
static GWeatherInfo *
 
238
make_info_from_node_old (GWeatherInfo *master_info,
 
239
                         xmlNodePtr    node)
 
240
{
 
241
    GWeatherInfo *info;
 
242
    GWeatherInfoPrivate *priv;
 
243
    xmlChar *val;
 
244
 
 
245
    g_return_val_if_fail (node->type == XML_ELEMENT_NODE, NULL);
 
246
 
 
247
    info = _gweather_info_new_clone (master_info);
 
248
    priv = info->priv;
 
249
 
 
250
    val = xmlGetProp (node, XC("from"));
 
251
    priv->current_time = priv->update = date_to_time_t (val, info->priv->location.tz_hint);
 
252
    xmlFree (val);
 
253
 
 
254
    fill_info_from_node (info, node);
 
255
 
 
256
    return info;
 
257
}
 
258
 
 
259
static char *
 
260
make_attribution_from_node (xmlNodePtr node)
 
261
{
 
262
    xmlChar *url;
 
263
    xmlChar *text;
 
264
    char *res;
 
265
 
 
266
    url = xmlGetProp (node, XC("url"));
 
267
    text = xmlGetProp (node, XC("text"));
 
268
 
 
269
    /* Small hack to avoid linking the entire label, and to have
 
270
       This is still compliant with the guidelines, as far as I
 
271
       understand it.
 
272
       The label is a legal attribution and cannot be translated.
 
273
    */
 
274
    if (strcmp ((char*) text,
 
275
                "Weather forecast from yr.no, delivered by the"
 
276
                " Norwegian Meteorological Institute and the NRK") == 0)
 
277
        res = g_strdup_printf ("Weather forecast from yr.no, delivered by"
 
278
                               " the <a href=\"%s\">Norwegian Meteorological"
 
279
                               " Institude and the NRK</a>", url);
 
280
    else
 
281
        res = g_strdup_printf ("<a href=\"%s\">%s</a>", url, text);
 
282
 
 
283
    xmlFree (url);
 
284
    xmlFree (text);
 
285
 
 
286
    return res;
 
287
}
 
288
 
 
289
static void
 
290
parse_forecast_xml_old (GWeatherInfo    *master_info,
 
291
                        SoupMessageBody *body)
 
292
{
 
293
    GWeatherInfoPrivate *priv;
 
294
    xmlDocPtr doc;
 
295
    xmlXPathContextPtr xpath_ctx;
 
296
    xmlXPathObjectPtr xpath_result;
 
297
    int i;
 
298
 
 
299
    priv = master_info->priv;
 
300
 
 
301
    doc = xmlParseMemory (body->data, body->length);
 
302
    if (!doc)
 
303
        return;
 
304
 
 
305
    xpath_ctx = xmlXPathNewContext (doc);
 
306
    xpath_result = xmlXPathEval (XC("/weatherdata/forecast/tabular/time"), xpath_ctx);
 
307
 
 
308
    if (!xpath_result || xpath_result->type != XPATH_NODESET)
 
309
        goto out;
 
310
 
 
311
    for (i = 0; i < xpath_result->nodesetval->nodeNr; i++) {
 
312
        xmlNodePtr node;
 
313
        GWeatherInfo *info;
 
314
 
 
315
        node = xpath_result->nodesetval->nodeTab[i];
 
316
        info = make_info_from_node_old (master_info, node);
 
317
 
 
318
        priv->forecast_list = g_slist_append (priv->forecast_list, info);
 
319
    }
 
320
 
 
321
    xmlXPathFreeObject (xpath_result);
 
322
 
 
323
    xpath_result = xmlXPathEval (XC("/weatherdata/credit/link"), xpath_ctx);
 
324
    if (!xpath_result || xpath_result->type != XPATH_NODESET)
 
325
        goto out;
 
326
 
 
327
    priv->forecast_attribution = make_attribution_from_node (xpath_result->nodesetval->nodeTab[0]);
 
328
 
 
329
 out:
 
330
    if (xpath_result)
 
331
        xmlXPathFreeObject (xpath_result);
 
332
    xmlXPathFreeContext (xpath_ctx);
 
333
    xmlFreeDoc (doc);
 
334
}
 
335
 
 
336
 
 
337
 
 
338
static void
 
339
parse_forecast_xml_new (GWeatherInfo    *master_info,
 
340
                        SoupMessageBody *body)
 
341
{
 
342
    GWeatherInfoPrivate *priv;
 
343
    xmlDocPtr doc;
 
344
    xmlXPathContextPtr xpath_ctx;
 
345
    xmlXPathObjectPtr xpath_result;
 
346
    int i;
 
347
 
 
348
    priv = master_info->priv;
 
349
 
 
350
    doc = xmlParseMemory (body->data, body->length);
 
351
    if (!doc)
 
352
        return;
 
353
 
 
354
    xpath_ctx = xmlXPathNewContext (doc);
 
355
    xpath_result = xmlXPathEval (XC("/weatherdata/product/time"), xpath_ctx);
 
356
 
 
357
    if (!xpath_result || xpath_result->type != XPATH_NODESET)
 
358
        goto out;
 
359
 
 
360
    for (i = 0; i < xpath_result->nodesetval->nodeNr; i++) {
 
361
        xmlNodePtr node;
 
362
        GWeatherInfo *info;
 
363
        xmlChar *val;
 
364
        time_t from_time, to_time;
 
365
        xmlNode *location;
 
366
 
 
367
        node = xpath_result->nodesetval->nodeTab[i];
 
368
 
 
369
        val = xmlGetProp (node, XC("from"));
 
370
        from_time = date_to_time_t (val, priv->location.tz_hint);
 
371
        xmlFree (val);
 
372
 
 
373
        val = xmlGetProp (node, XC("to"));
 
374
        to_time = date_to_time_t (val, priv->location.tz_hint);
 
375
        xmlFree (val);
 
376
 
 
377
        /* New API has forecast in a list of "master" elements
 
378
           with details (indicated by from==to) and "slave" elements
 
379
           that hold only precipitation and symbol. For our purpose,
 
380
           the master element is enough, except that we actually
 
381
           want that symbol. So pick the symbol from the next element.
 
382
           Additionally, compared to the old API the new API has one
 
383
           <location> element inside each <time> element.
 
384
        */
 
385
        if (from_time == to_time) {
 
386
            info = _gweather_info_new_clone (master_info);
 
387
            info->priv->current_time = info->priv->update = from_time;
 
388
 
 
389
            for (location = node->children;
 
390
                 location && location->type != XML_ELEMENT_NODE;
 
391
                 location = location->next);
 
392
            if (location)
 
393
                fill_info_from_node (info, location);
 
394
 
 
395
            if (i < xpath_result->nodesetval->nodeNr - 1) {
 
396
                i++;
 
397
                node = xpath_result->nodesetval->nodeTab[i];
 
398
 
 
399
                for (location = node->children;
 
400
                     location && location->type != XML_ELEMENT_NODE;
 
401
                     location = location->next);
 
402
                if (location)
 
403
                    fill_info_from_node (info, location);
 
404
            }
 
405
 
 
406
            priv->forecast_list = g_slist_append (priv->forecast_list, info);
 
407
        }
 
408
    }
 
409
 
 
410
    xmlXPathFreeObject (xpath_result);
 
411
 
 
412
    /* The new (documented but not advertised) API is less strict in the
 
413
       format of the attribution, and just requires a generic CC-BY compatible
 
414
       attribution with a link to their service.
 
415
 
 
416
       That's very nice of them!
 
417
    */
 
418
    priv->forecast_attribution = g_strdup(_("Weather data from the <a href=\"http://yr.no/\">Norwegian Meteorological Institute</a>"));
 
419
 
 
420
 out:
 
421
    xmlXPathFreeContext (xpath_ctx);
 
422
    xmlFreeDoc (doc);
 
423
}
 
424
 
 
425
static void
 
426
yrno_finish_old (SoupSession *session,
 
427
                 SoupMessage *msg,
 
428
                 gpointer     user_data)
 
429
{
 
430
    GWeatherInfo *info = GWEATHER_INFO (user_data);
 
431
 
 
432
    if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
 
433
        /* forecast data is not really interesting anyway ;) */
 
434
        g_message ("Failed to get Yr.no forecast data: %d %s\n",
 
435
                   msg->status_code, msg->reason_phrase);
 
436
        _gweather_info_request_done (info);
 
437
        return;
 
438
    }
 
439
 
 
440
    parse_forecast_xml_old (info, msg->response_body);
 
441
    _gweather_info_request_done (info);
 
442
}
 
443
 
 
444
static gboolean
 
445
yrno_start_open_old (GWeatherInfo *info)
 
446
{
 
447
    GWeatherInfoPrivate *priv;
 
448
    gchar *url;
 
449
    SoupMessage *message;
 
450
    const char *country = NULL;
 
451
    const char *adm_division = NULL;
 
452
    char *city_name = NULL;
 
453
    GWeatherLocation *glocation;
 
454
 
 
455
    priv = info->priv;
 
456
 
 
457
    if (priv->forecast_type != GWEATHER_FORECAST_LIST)
 
458
        return FALSE;
 
459
 
 
460
    glocation = priv->glocation;
 
461
    while (glocation) {
 
462
        if (glocation->level == GWEATHER_LOCATION_CITY)
 
463
            city_name = glocation->name;
 
464
        if (glocation->level == GWEATHER_LOCATION_ADM1 ||
 
465
            glocation->level == GWEATHER_LOCATION_ADM2)
 
466
            adm_division = glocation->name;
 
467
        if (glocation->level == GWEATHER_LOCATION_COUNTRY)
 
468
            country = glocation->name;
 
469
        glocation = glocation->parent;
 
470
    }
 
471
 
 
472
    if (city_name == NULL || adm_division == NULL || country == NULL)
 
473
        return FALSE;
 
474
 
 
475
    url = g_strdup_printf("http://yr.no/place/%s/%s/%s/forecast.xml", country, adm_division, city_name);
 
476
 
 
477
    message = soup_message_new ("GET", url);
 
478
    soup_session_queue_message (priv->session, message, yrno_finish_old, info);
 
479
 
 
480
    priv->requests_pending++;
 
481
 
 
482
    g_free (url);
 
483
 
 
484
    return TRUE;
 
485
}
 
486
 
 
487
static void
 
488
yrno_finish_new (SoupSession *session,
 
489
                 SoupMessage *msg,
 
490
                 gpointer     user_data)
 
491
{
 
492
    GWeatherInfo *info = GWEATHER_INFO (user_data);
 
493
 
 
494
    if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
 
495
        /* forecast data is not really interesting anyway ;) */
 
496
        g_message ("Failed to get Yr.no forecast data: %d %s\n",
 
497
                   msg->status_code, msg->reason_phrase);
 
498
        _gweather_info_request_done (info);
 
499
        return;
 
500
    }
 
501
 
 
502
    parse_forecast_xml_new (info, msg->response_body);
 
503
 
 
504
    _gweather_info_request_done (info);
 
505
}
 
506
 
 
507
static gboolean
 
508
yrno_start_open_new (GWeatherInfo *info)
 
509
{
 
510
    GWeatherInfoPrivate *priv;
 
511
    gchar *url;
 
512
    SoupMessage *message;
 
513
    WeatherLocation *loc;
 
514
    gchar latstr[G_ASCII_DTOSTR_BUF_SIZE], lonstr[G_ASCII_DTOSTR_BUF_SIZE];
 
515
 
 
516
    priv = info->priv;
 
517
    loc = &priv->location;
 
518
 
 
519
    if (!loc->latlon_valid ||
 
520
        priv->forecast_type != GWEATHER_FORECAST_LIST)
 
521
        return FALSE;
 
522
 
 
523
    /* see the description here: http://api.yr.no/weatherapi/ */
 
524
 
 
525
    g_ascii_dtostr (latstr, sizeof(latstr), RADIANS_TO_DEGREES (loc->latitude));
 
526
    g_ascii_dtostr (lonstr, sizeof(lonstr), RADIANS_TO_DEGREES (loc->longitude));
 
527
 
 
528
    url = g_strdup_printf("http://api.yr.no/weatherapi/locationforecast/1.8/?lat=%s;lon=%s", latstr, lonstr);
 
529
 
 
530
    message = soup_message_new ("GET", url);
 
531
    soup_session_queue_message (priv->session, message, yrno_finish_new, info);
 
532
 
 
533
    priv->requests_pending++;
 
534
 
 
535
    g_free (url);
 
536
 
 
537
    return TRUE;
 
538
}
 
539
 
 
540
gboolean
 
541
yrno_start_open (GWeatherInfo *info)
 
542
{
 
543
    if (yrno_start_open_new (info))
 
544
        return TRUE;
 
545
 
 
546
    return yrno_start_open_old (info);
 
547
}