예제 #1
0
파일: babel.c 프로젝트: viking-gps/viking
/**
 * a_babel_convert_from_url_filter:
 * @vt: The #VikTrwLayer where to insert the collected data
 * @url: the URL to fetch
 * @input_type:   If input_type is %NULL, input must be GPX.
 * @babelfilters: The filter arguments to pass to gpsbabel
 * @cb:	          Optional callback function. Same usage as in a_babel_convert().
 * @user_data:    Passed along to cb
 * @options:      Download options. If %NULL then default download options will be used.
 *
 * Download the file pointed by the URL and optionally uses GPSBabel to convert from input_type.
 * If input_type and babelfilters are %NULL, gpsbabel is not used.
 *
 * Returns: %TRUE on successful invocation of GPSBabel or read of the GPX
 *
 */
gboolean a_babel_convert_from_url_filter ( VikTrwLayer *vt, const char *url, const char *input_type, const char *babelfilters, BabelStatusFunc cb, gpointer user_data, DownloadFileOptions *options )
{
  // If no download options specified, use defaults:
  DownloadFileOptions myoptions = { FALSE, FALSE, NULL, 2, NULL, NULL, NULL };
  if ( options )
    myoptions = *options;
  gint fd_src;
  int fetch_ret;
  gboolean ret = FALSE;
  gchar *name_src = NULL;
  gchar *babelargs = NULL;

  g_debug("%s: input_type=%s url=%s", __FUNCTION__, input_type, url);

  if ((fd_src = g_file_open_tmp("tmp-viking.XXXXXX", &name_src, NULL)) >= 0) {
    g_debug ("%s: temporary file: %s", __FUNCTION__, name_src);
    close(fd_src);
    (void)g_remove(name_src);

    fetch_ret = a_http_download_get_url(url, "", name_src, &myoptions, NULL);
    if (fetch_ret == DOWNLOAD_SUCCESS) {
      if (input_type != NULL || babelfilters != NULL) {
        babelargs = (input_type) ? g_strdup_printf(" -i %s", input_type) : g_strdup("");
        ret = a_babel_convert_from_filter( vt, babelargs, name_src, babelfilters, NULL, NULL, NULL );
      } else {
        /* Process directly the retrieved file */
        g_debug("%s: directly read GPX file %s", __FUNCTION__, name_src);
        FILE *f = g_fopen(name_src, "r");
        if (f) {
          gchar *dirpath = g_path_get_dirname ( name_src );
          ret = a_gpx_read_file ( vt, f, dirpath );
          g_free ( dirpath );
          fclose(f);
        }
        // Try to avoid adding the description if URL is OAuth signed
        if ( !g_ascii_strncasecmp(url, "?oauth_consumer_key=", 20) ) {
          VikTRWMetadata *meta = vik_trw_layer_get_metadata(vt);
          if ( meta && !meta->description ) {
            meta->description = g_strdup ( url );
          }
        }
      }
    }
    (void)util_remove(name_src);
    g_free(babelargs);
    g_free(name_src);
  }

  return ret;
}
static gboolean datasource_osm_my_traces_process ( VikTrwLayer *vtl, ProcessOptions *process_options, BabelStatusFunc status_cb, acq_dialog_widgets_t *adw, DownloadMapOptions *options_unused )
{
	//datasource_osm_my_traces_t *data = (datasource_osm_my_traces_t *)adw->user_data;

	gboolean result;

	gchar *user_pass = osm_get_login();

	// Support .zip + bzip2 files directly
	DownloadMapOptions options = { FALSE, FALSE, NULL, 2, NULL, user_pass, a_try_decompress_file }; // Allow a couple of redirects

	gchar *tmpname = a_download_uri_to_tmp_file ( DS_OSM_TRACES_GPX_FILES, &options );
	if ( !tmpname )
		return FALSE;

	xml_data *xd = g_malloc ( sizeof (xml_data) );
	//xd->xpath = g_string_new ( "" );
	xd->c_cdata = g_string_new ( "" );
	xd->current_tag = tt_unknown;
	xd->current_gpx_meta_data = new_gpx_meta_data_t();
	xd->list_of_gpx_meta_data = NULL;

	result = read_gpx_files_metadata_xml ( tmpname, xd );
	// Test already downloaded metadata file: eg:
	//result = read_gpx_files_metadata_xml ( "/tmp/viking-download.GI47PW", xd );

	if ( tmpname ) {
		(void)util_remove ( tmpname );
		g_free ( tmpname );
	}

	if ( ! result ) {
		g_free ( xd );
		return FALSE;
	}

	if ( g_list_length ( xd->list_of_gpx_meta_data ) == 0 ) {
		if (!vik_datasource_osm_my_traces_interface.is_thread)
			none_found ( GTK_WINDOW(adw->vw) );
		g_free ( xd );
		return FALSE;
	}

	xd->list_of_gpx_meta_data = g_list_reverse ( xd->list_of_gpx_meta_data );

	set_in_current_view_property ( vtl, adw->user_data, xd->list_of_gpx_meta_data );

    if (vik_datasource_osm_my_traces_interface.is_thread) gdk_threads_enter();
	GList *selected = select_from_list ( GTK_WINDOW(adw->vw), xd->list_of_gpx_meta_data, "Select GPS Traces", "Select the GPS traces you want to add." );
    if (vik_datasource_osm_my_traces_interface.is_thread) gdk_threads_leave();

	// If non thread - show program is 'doing something...'
	if ( !vik_datasource_osm_my_traces_interface.is_thread )
		vik_window_set_busy_cursor ( adw->vw );

	// If passed in on an existing layer - we will create everything into that.
	//  thus with many differing gpx's - this will combine all waypoints into this single layer!
	// Hence the preference is to create multiple layers
	//  and so this creation of the layers must be managed here

	gboolean create_new_layer = ( !vtl );

	// Only update the screen on the last layer acquired
	VikTrwLayer *vtl_last = vtl;
	gboolean got_something = FALSE;

	GList *selected_iterator = selected;
	while ( selected_iterator ) {

		VikTrwLayer *vtlX = vtl;

		if ( create_new_layer ) {
			// Have data but no layer - so create one
			vtlX = VIK_TRW_LAYER ( vik_layer_create ( VIK_LAYER_TRW, adw->vvp, FALSE ) );
			if ( ((gpx_meta_data_t*)selected_iterator->data)->name )
				vik_layer_rename ( VIK_LAYER ( vtlX ), ((gpx_meta_data_t*)selected_iterator->data)->name );
			else
				vik_layer_rename ( VIK_LAYER ( vtlX ), _("My OSM Traces") );
		}

		result = FALSE;
		gint gpx_id = ((gpx_meta_data_t*)selected_iterator->data)->id;
		if ( gpx_id ) {
			gchar *url = g_strdup_printf ( DS_OSM_TRACES_GPX_URL_FMT, gpx_id );

			// NB download type is GPX (or a compressed version)
			ProcessOptions my_po = *process_options;
			my_po.url = url;
			result = a_babel_convert_from ( vtlX, &my_po, status_cb, adw, &options );
			// TODO investigate using a progress bar:
			// http://developer.gnome.org/gtk/2.24/GtkProgressBar.html

			got_something = got_something || result;
			if ( !result ) {
				// Report errors to the status bar
				gchar* msg = g_strdup_printf ( _("Unable to get trace: %s"), url );
				vik_window_statusbar_update ( adw->vw, msg, VIK_STATUSBAR_INFO );
				g_free (msg);
			}
			g_free ( url );
		}

		if ( result ) {
			// Can use the layer
			vik_aggregate_layer_add_layer ( vik_layers_panel_get_top_layer (adw->vlp), VIK_LAYER(vtlX), TRUE );
			// Move to area of the track
			vik_layer_post_read ( VIK_LAYER(vtlX), vik_window_viewport(adw->vw), TRUE );
			vik_trw_layer_auto_set_view ( vtlX, vik_window_viewport(adw->vw) );
			vtl_last = vtlX;
		}
		else if ( create_new_layer ) {
			// Layer not needed as no data has been acquired
			g_object_unref ( vtlX );
		}

		selected_iterator = g_list_next ( selected_iterator );
	}

	// Free memory
	if ( xd->current_gpx_meta_data )
		free_gpx_meta_data ( xd->current_gpx_meta_data, NULL );
	g_free ( xd->current_gpx_meta_data );
	free_gpx_meta_data_list ( xd->list_of_gpx_meta_data );
	free_gpx_meta_data_list ( selected );
	g_free ( xd );
	g_free ( user_pass );

	// Would prefer to keep the update in acquire.c,
	//  however since we may create the layer - need to do the update here
	if ( got_something )
		vik_layer_emit_update ( VIK_LAYER(vtl_last) );

	// ATM The user is only informed if all getting *all* of the traces failed
	if ( selected )
		result = got_something;
	else
		// Process was cancelled but need to return that it proceeded as expected
		result = TRUE;

	if ( !vik_datasource_osm_my_traces_interface.is_thread )
		vik_window_clear_busy_cursor ( adw->vw );

	return result;
}