Use correct cast
[libchamplain:vpoluceno-clone.git] / champlain / champlain-map-source-factory.c
1 /*
2  * Copyright (C) 2009 Pierre-Luc Beaudoin <pierre-luc@pierlux.com>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17  */
18
19 /**
20  * SECTION:champlain-map-source-factory
21  * @short_description: Manages #ChamplainMapSource instances
22  *
23  * This factory manages the create of #ChamplainMapSource. It contains names
24  * and constructor functions for each available map sources in libchamplain.
25  * You can add your own with #champlain_map_source_factory_register.
26  *
27  * To get the wanted map source, use #champlain_map_source_factory_create. It
28  * will return a ready to use #ChamplainMapSource.
29  *
30  * To get the list of registered map sources, use
31  * #champlain_map_source_factory_dup_list.
32  *
33  */
34 #include "config.h"
35
36 #include "champlain-map-source-factory.h"
37
38 #define DEBUG_FLAG CHAMPLAIN_DEBUG_NETWORK
39 #include "champlain-debug.h"
40
41 #include "champlain.h"
42 #ifdef CHAMPLAIN_HAS_MEMPHIS
43 #include "champlain-memphis.h"
44 #endif
45 #include "champlain-file-cache.h"
46 #include "champlain-defines.h"
47 #include "champlain-enum-types.h"
48 #include "champlain-map-source.h"
49 #include "champlain-marshal.h"
50 #include "champlain-private.h"
51 #include "champlain-network-tile-source.h"
52 #include "champlain-map-source-chain.h"
53 #include "champlain-error-tile-source.h"
54
55 #include <glib.h>
56 #include <string.h>
57
58 enum
59 {
60   /* normal signals */
61   LAST_SIGNAL
62 };
63
64 enum
65 {
66   PROP_0,
67 };
68
69 /* static guint champlain_map_source_factory_signals[LAST_SIGNAL] = { 0, }; */
70 static ChamplainMapSourceFactory *instance = NULL;
71
72 G_DEFINE_TYPE (ChamplainMapSourceFactory, champlain_map_source_factory, G_TYPE_OBJECT);
73
74 #define GET_PRIVATE(obj)    (G_TYPE_INSTANCE_GET_PRIVATE((obj), CHAMPLAIN_TYPE_MAP_SOURCE_FACTORY, ChamplainMapSourceFactoryPrivate))
75
76 struct _ChamplainMapSourceFactoryPrivate
77 {
78   GSList *registered_sources;
79 };
80
81 static ChamplainMapSource * champlain_map_source_new_generic (
82     ChamplainMapSourceDesc *desc, gpointer data);
83
84 #ifdef CHAMPLAIN_HAS_MEMPHIS
85 static ChamplainMapSource * champlain_map_source_new_memphis (
86     ChamplainMapSourceDesc *desc, gpointer user_data);
87 #endif
88
89 static void
90 champlain_map_source_factory_get_property (GObject *object,
91     guint prop_id,
92     G_GNUC_UNUSED GValue *value,
93     GParamSpec *pspec)
94 {
95   //ChamplainMapSourceFactory *map_source_factory = CHAMPLAIN_MAP_SOURCE_FACTORY(object);
96   //ChamplainMapSourceFactoryPrivate *priv = map_source_factory->priv;
97
98   switch (prop_id)
99     {
100       default:
101         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
102     }
103 }
104
105 static void
106 champlain_map_source_factory_set_property (GObject *object,
107     guint prop_id,
108     G_GNUC_UNUSED const GValue *value,
109     GParamSpec *pspec)
110 {
111   //ChamplainMapSourceFactory *map_source_factory = CHAMPLAIN_MAP_SOURCE_FACTORY(object);
112   //ChamplainMapSourceFactoryPrivate *priv = map_source_factory->priv;
113
114   switch (prop_id)
115     {
116       default:
117         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
118     }
119 }
120
121 static void
122 champlain_map_source_factory_finalize (GObject *object)
123 {
124   ChamplainMapSourceFactory *factory = CHAMPLAIN_MAP_SOURCE_FACTORY (object);
125
126   g_slist_free (factory->priv->registered_sources);
127
128   G_OBJECT_CLASS (champlain_map_source_factory_parent_class)->finalize (object);
129 }
130
131 static GObject *
132 champlain_map_source_factory_constructor (GType type,
133     guint n_construct_params,
134     GObjectConstructParam *construct_params)
135 {
136   GObject *retval;
137
138   if (instance == NULL)
139     {
140       retval = G_OBJECT_CLASS (champlain_map_source_factory_parent_class)->constructor
141           (type, n_construct_params, construct_params);
142
143       instance = CHAMPLAIN_MAP_SOURCE_FACTORY (retval);
144       g_object_add_weak_pointer (retval, (gpointer *) &instance);
145     }
146   else
147     {
148       retval = g_object_ref (instance);
149     }
150
151   return retval;
152 }
153
154 static void
155 champlain_map_source_factory_class_init (ChamplainMapSourceFactoryClass *klass)
156 {
157   g_type_class_add_private (klass, sizeof (ChamplainMapSourceFactoryPrivate));
158
159   GObjectClass *object_class = G_OBJECT_CLASS (klass);
160
161   object_class->constructor = champlain_map_source_factory_constructor;
162   object_class->finalize = champlain_map_source_factory_finalize;
163   object_class->get_property = champlain_map_source_factory_get_property;
164   object_class->set_property = champlain_map_source_factory_set_property;
165 }
166
167 static
168 ChamplainMapSourceDesc OSM_MAPNIK_DESC =
169   {
170     CHAMPLAIN_MAP_SOURCE_OSM_MAPNIK,
171     "OpenStreetMap Mapnik",
172     "Map data is CC-BY-SA 2.0 OpenStreetMap contributors",
173     "http://creativecommons.org/licenses/by-sa/2.0/",
174     0,
175     18,
176     CHAMPLAIN_MAP_PROJECTION_MERCATOR,
177     champlain_map_source_new_generic,
178     "http://tile.openstreetmap.org/#Z#/#X#/#Y#.png",
179     NULL
180   };
181
182 static
183 ChamplainMapSourceDesc OSM_OSMARENDER_DESC =
184   {
185     CHAMPLAIN_MAP_SOURCE_OSM_OSMARENDER,
186     "OpenStreetMap Osmarender",
187     "Map data is CC-BY-SA 2.0 OpenStreetMap contributors",
188     "http://creativecommons.org/licenses/by-sa/2.0/",
189     0,
190     17,
191     CHAMPLAIN_MAP_PROJECTION_MERCATOR,
192     champlain_map_source_new_generic,
193     "http://tah.openstreetmap.org/Tiles/tile/#Z#/#X#/#Y#.png",
194     NULL
195   };
196
197 static
198 ChamplainMapSourceDesc OSM_CYCLEMAP_DESC =
199   {
200     CHAMPLAIN_MAP_SOURCE_OSM_CYCLE_MAP,
201     "OpenStreetMap Cycle Map",
202     "Map data is CC-BY-SA 2.0 OpenStreetMap contributors",
203     "http://creativecommons.org/licenses/by-sa/2.0/",
204     0,
205     18,
206     CHAMPLAIN_MAP_PROJECTION_MERCATOR,
207     champlain_map_source_new_generic,
208     "http://andy.sandbox.cloudmade.com/tiles/cycle/#Z#/#X#/#Y#.png",
209     NULL
210   };
211
212 static
213 ChamplainMapSourceDesc OSM_TRANSPORTMAP_DESC =
214   {
215     CHAMPLAIN_MAP_SOURCE_OSM_TRANSPORT_MAP,
216     "OpenStreetMap Transport Map",
217     "Map data is CC-BY-SA 2.0 OpenStreetMap contributors",
218     "http://creativecommons.org/licenses/by-sa/2.0/",
219     0,
220     18,
221     CHAMPLAIN_MAP_PROJECTION_MERCATOR,
222     champlain_map_source_new_generic,
223     "http://tile.xn--pnvkarte-m4a.de/tilegen/#Z#/#X#/#Y#.png",
224     NULL
225   };
226
227 #if 0
228 /* Disabling until OpenArealMap works again */
229 static
230 ChamplainMapSourceDesc OAM_DESC =
231   {
232     CHAMPLAIN_MAP_SOURCE_OAM,
233     "OpenAerialMap",
234     "(CC) BY 3.0 OpenAerialMap contributors",
235     "http://creativecommons.org/licenses/by/3.0/",
236     0,
237     17,
238     CHAMPLAIN_MAP_PROJECTION_MERCATOR,
239     champlain_map_source_new_generic,
240     "http://tile.openaerialmap.org/tiles/1.0.0/openaerialmap-900913/#Z#/#X#/#Y#.jpg",
241     NULL
242   };
243 #endif
244
245 static
246 ChamplainMapSourceDesc MFF_RELIEF_DESC =
247   {
248     CHAMPLAIN_MAP_SOURCE_MFF_RELIEF,
249     "Maps for Free Relief",
250     "Map data available under GNU Free Documentation license, Version 1.2 or later",
251     "http://www.gnu.org/copyleft/fdl.html",
252     0,
253     11,
254     CHAMPLAIN_MAP_PROJECTION_MERCATOR,
255     champlain_map_source_new_generic,
256     "http://maps-for-free.com/layer/relief/z#Z#/row#Y#/#Z#_#X#-#Y#.jpg",
257     NULL
258   };
259
260 #ifdef CHAMPLAIN_HAS_MEMPHIS
261 static
262 ChamplainMapSourceDesc MEMPHIS_LOCAL_DESC =
263   {
264     CHAMPLAIN_MAP_SOURCE_MEMPHIS_LOCAL,
265     "OpenStreetMap Memphis Local Map",
266     "(CC) BY 2.0 OpenStreetMap contributors",
267     "http://creativecommons.org/licenses/by/2.0/",
268     12,
269     18,
270     CHAMPLAIN_MAP_PROJECTION_MERCATOR,
271     champlain_map_source_new_memphis,
272     "",
273     NULL
274   };
275
276 static
277 ChamplainMapSourceDesc MEMPHIS_NETWORK_DESC =
278   {
279     CHAMPLAIN_MAP_SOURCE_MEMPHIS_NETWORK,
280     "OpenStreetMap Memphis Network Map",
281     "(CC) BY 2.0 OpenStreetMap contributors",
282     "http://creativecommons.org/licenses/by/2.0/",
283     12,
284     18,
285     CHAMPLAIN_MAP_PROJECTION_MERCATOR,
286     champlain_map_source_new_memphis,
287     "",
288     NULL
289   };
290 #endif
291
292 static void
293 champlain_map_source_factory_init (ChamplainMapSourceFactory *factory)
294 {
295   ChamplainMapSourceFactoryPrivate *priv = GET_PRIVATE (factory);
296
297   factory->priv = priv;
298
299   priv->registered_sources = NULL;
300
301   champlain_map_source_factory_register (factory, &OSM_MAPNIK_DESC,
302       OSM_MAPNIK_DESC.constructor, OSM_MAPNIK_DESC.data);
303   champlain_map_source_factory_register (factory, &OSM_CYCLEMAP_DESC,
304       OSM_CYCLEMAP_DESC.constructor, OSM_CYCLEMAP_DESC.data);
305   champlain_map_source_factory_register (factory, &OSM_TRANSPORTMAP_DESC,
306       OSM_TRANSPORTMAP_DESC.constructor, OSM_TRANSPORTMAP_DESC.data);
307   champlain_map_source_factory_register (factory, &OSM_OSMARENDER_DESC,
308       OSM_OSMARENDER_DESC.constructor, OSM_OSMARENDER_DESC.data);
309 #if 0
310   champlain_map_source_factory_register (factory, &OAM_DESC,
311       OAM_DESC.constructor, OAM_DESC.data);
312 #endif
313   champlain_map_source_factory_register (factory, &MFF_RELIEF_DESC,
314       MFF_RELIEF_DESC.constructor, MFF_RELIEF_DESC.data);
315 #ifdef CHAMPLAIN_HAS_MEMPHIS
316   champlain_map_source_factory_register (factory, &MEMPHIS_LOCAL_DESC,
317       MEMPHIS_LOCAL_DESC.constructor, MEMPHIS_LOCAL_DESC.data);
318   champlain_map_source_factory_register (factory, &MEMPHIS_NETWORK_DESC,
319       MEMPHIS_NETWORK_DESC.constructor, MEMPHIS_NETWORK_DESC.data);
320 #endif
321 }
322
323 /**
324  * champlain_map_source_factory_dup_default:
325  *
326  * A method to obtain the singleton object.
327  *
328  * Returns: the singleton #ChamplainMapSourceFactory, it should be freed
329  * using #g_object_unref when not needed.
330  *
331  * Since: 0.4
332  */
333 ChamplainMapSourceFactory *
334 champlain_map_source_factory_dup_default (void)
335 {
336   return g_object_new (CHAMPLAIN_TYPE_MAP_SOURCE_FACTORY, NULL);
337 }
338
339 /**
340  * champlain_map_source_factory_dup_list:
341  * @factory: the Factory
342  *
343  * Get the list of registered map sources.
344  *
345  * Returns: the list of registered map sources, the items should not be freed,
346  * the list should be freed with #g_slist_free.
347  *
348  * Since: 0.4
349  */
350 GSList *
351 champlain_map_source_factory_dup_list (ChamplainMapSourceFactory *factory)
352 {
353   return g_slist_copy (factory->priv->registered_sources);
354 }
355
356 /**
357  * champlain_map_source_factory_create:
358  * @factory: the Factory
359  * @id: the wanted map source id
360  *
361  * The id should not contain any character that can't be in a filename as it
362  * will be used as the cache directory name for that map source.
363  *
364  * Returns: a ready to use #ChamplainMapSource matching the given name, returns
365  * NULL is none match.
366  *
367  * Since: 0.4
368  */
369 ChamplainMapSource *
370 champlain_map_source_factory_create (ChamplainMapSourceFactory *factory,
371     const gchar *id)
372 {
373   GSList *item;
374
375   item = factory->priv->registered_sources;
376
377   while (item != NULL)
378     {
379       ChamplainMapSourceDesc *desc = CHAMPLAIN_MAP_SOURCE_DESC (item->data);
380       if (strcmp (desc->id, id) == 0)
381         return desc->constructor (desc, desc->data);
382       item = g_slist_next (item);
383     }
384
385   return NULL;
386 }
387
388 /**
389  * champlain_map_source_factory_create_cached_source:
390  * @factory: the Factory
391  * @id: the wanted map source id
392  *
393  * Creates a cached map source.
394  *
395  * Returns: a ready to use #ChamplainMapSourceChain consisting of
396  * #ChamplainFileCache, #ChamplainMapSource matching the given name, and
397  * #ChamplainErrorTileSource.
398  *
399  * Since: 0.6
400  */
401 ChamplainMapSource * champlain_map_source_factory_create_cached_source (ChamplainMapSourceFactory *factory,
402     const gchar *id)
403 {
404   ChamplainMapSourceChain *source_chain;
405   ChamplainMapSource *tile_source;
406   ChamplainMapSource *error_source;
407   ChamplainMapSource *file_cache;
408   guint tile_size;
409
410   tile_source = champlain_map_source_factory_create (factory, id);
411
412   tile_size = champlain_map_source_get_tile_size (tile_source);
413   error_source = CHAMPLAIN_MAP_SOURCE(champlain_error_tile_source_new_full (tile_size));
414
415   file_cache = CHAMPLAIN_MAP_SOURCE(champlain_file_cache_new ());
416
417   source_chain = champlain_map_source_chain_new ();
418   champlain_map_source_chain_push (source_chain, error_source);
419   champlain_map_source_chain_push (source_chain, tile_source);
420   champlain_map_source_chain_push (source_chain, file_cache);
421
422   return CHAMPLAIN_MAP_SOURCE(source_chain);
423 }
424
425 /**
426  * champlain_map_source_factory_register:
427  * @factory: A #ChamplainMapSourceFactory
428  * @desc: the description of the map source
429  * @constructor: the new map source constructor function
430  * @data: data to be passed to the constructor function, or NULL
431  *
432  * Registers the new map source with the given constructor.  When this map
433  * source is requested, the given constructor will be used to build the
434  * map source.  #ChamplainMapSourceFactory will take ownership of the passed
435  * #ChamplainMapSourceDesc, so don't free it. They will not be freed either so
436  * you can use static structs here.
437  *
438  * Returns: TRUE if the registration suceeded.
439  *
440  * Since: 0.4
441  */
442 gboolean
443 champlain_map_source_factory_register (ChamplainMapSourceFactory *factory,
444     ChamplainMapSourceDesc *desc,
445     ChamplainMapSourceConstructor constructor,
446     gpointer data)
447 {
448
449   /* FIXME: check for existing factory with that name? */
450   desc->constructor = constructor;
451   desc->data = data;
452   factory->priv->registered_sources = g_slist_append (factory->priv->registered_sources, desc);
453   return TRUE;
454 }
455
456 static ChamplainMapSource *
457 champlain_map_source_new_generic (
458     ChamplainMapSourceDesc *desc, G_GNUC_UNUSED gpointer user_data)
459 {
460   return CHAMPLAIN_MAP_SOURCE (champlain_network_tile_source_new_full (
461       desc->id,
462       desc->name,
463       desc->license,
464       desc->license_uri,
465       desc->min_zoom_level,
466       desc->max_zoom_level,
467       256,
468       desc->projection,
469       desc->uri_format));
470 }
471
472 #ifdef CHAMPLAIN_HAS_MEMPHIS
473 static ChamplainMapSource *
474 champlain_map_source_new_memphis (ChamplainMapSourceDesc *desc,
475     G_GNUC_UNUSED gpointer user_data)
476 {
477   ChamplainMapDataSource *map_data_source;
478
479   if (g_strcmp0 (desc->id, CHAMPLAIN_MAP_SOURCE_MEMPHIS_LOCAL) == 0)
480     {
481       map_data_source = CHAMPLAIN_MAP_DATA_SOURCE (champlain_local_map_data_source_new ());
482
483       /* Abuse the uri_format field to store an initial data path (optional) */
484       if (desc->uri_format && g_strcmp0 (desc->uri_format, "") != 0)
485         champlain_local_map_data_source_load_map_data (
486             CHAMPLAIN_LOCAL_MAP_DATA_SOURCE (map_data_source),
487             desc->uri_format);
488     }
489   else if (g_strcmp0 (desc->id, CHAMPLAIN_MAP_SOURCE_MEMPHIS_NETWORK) == 0)
490       map_data_source = CHAMPLAIN_MAP_DATA_SOURCE (champlain_network_map_data_source_new ());
491   else
492     return NULL;
493
494   return CHAMPLAIN_MAP_SOURCE (champlain_memphis_tile_source_new_full (
495       desc->id,
496       desc->name,
497       desc->license,
498       desc->license_uri,
499       desc->min_zoom_level,
500       desc->max_zoom_level,
501       256,
502       desc->projection,
503       map_data_source));
504 }
505 #endif
506