Author: akv
Date: 2013-05-31 23:35:07 +0200 (Fri, 31 May 2013)
New Revision: 4400

Added:
   trunk/src/rs-geo-db.c
   trunk/src/rs-geo-db.h
Modified:
   trunk/configure.in
   trunk/librawstudio/rs-settings.h
   trunk/src/Makefile.am
   trunk/src/application.h
   trunk/src/gtk-interface.c
   trunk/src/rs-actions.c
   trunk/src/rs-cache.c
   trunk/src/rs-photo.c
Log:
Initial commit of geo-tagging code (gui disabled for now).

Modified: trunk/configure.in
===================================================================
--- trunk/configure.in  2013-05-08 23:22:56 UTC (rev 4399)
+++ trunk/configure.in  2013-05-31 21:35:07 UTC (rev 4400)
@@ -133,6 +133,10 @@
 AC_SUBST(FLICKCURL_CFLAGS)
 AC_SUBST(FLICKCURL_LIBS)
 
+PKG_CHECK_MODULES(OSMGPSMAP, [osmgpsmap])
+AC_SUBST(OSMGPSMAP_CFLAGS)
+AC_SUBST(OSMGPSMAP_LIBS)
+
 GETTEXT_PACKAGE=rawstudio
 AC_SUBST(GETTEXT_PACKAGE)
 AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GETTEXT_PACKAGE", [Gettext package.])

Modified: trunk/librawstudio/rs-settings.h
===================================================================
--- trunk/librawstudio/rs-settings.h    2013-05-08 23:22:56 UTC (rev 4399)
+++ trunk/librawstudio/rs-settings.h    2013-05-31 21:35:07 UTC (rev 4400)
@@ -59,6 +59,7 @@
        MASK_CHANNELMIXER = MASK_CHANNELMIXER_RED | MASK_CHANNELMIXER_GREEN | 
MASK_CHANNELMIXER_BLUE,
        MASK_VIGNETTING  = (1<<15),
        MASK_PROFILE  = (1<<16),
+       MASK_TIME_OFFSET     = (1<<17),
        MASK_TRANSFORM     = (1<<30),
        MASK_ALL            = 0x00ffffff,
 } RSSettingsMask;

Modified: trunk/src/Makefile.am
===================================================================
--- trunk/src/Makefile.am       2013-05-08 23:22:56 UTC (rev 4399)
+++ trunk/src/Makefile.am       2013-05-31 21:35:07 UTC (rev 4400)
@@ -3,7 +3,7 @@
 INCLUDES = \
        -DPACKAGE_DATA_DIR=\""$(datadir)"\" \
        -DPACKAGE_LOCALE_DIR=\""$(prefix)/$(DATADIRNAME)/locale"\" \
-       @PACKAGE_CFLAGS@ @GCONF_CFLAGS@ @LENSFUN_CFLAGS@ @LIBGPHOTO2_CFLAGS@ 
@DBUS_CFLAGS@ \
+       @PACKAGE_CFLAGS@ @GCONF_CFLAGS@ @LENSFUN_CFLAGS@ @LIBGPHOTO2_CFLAGS@ 
@DBUS_CFLAGS@ @OSMGPSMAP_CFLAGS@ \
        -I$(top_srcdir)/librawstudio/ \
        -I$(top_srcdir)/
 
@@ -46,7 +46,8 @@
        rs-dir-selector.c rs-dir-selector.h \
        rs-tag-gui.c rs-tag-gui.h\
        rs-tethered-shooting.c rs-tethered-shooting.h \
-       rs-enfuse.c rs-enfuse.h
+       rs-enfuse.c rs-enfuse.h \
+       rs-geo-db.c rs-geo-db.h
 
-rawstudio_LDADD = ../librawstudio/librawstudio-@[email protected] @PACKAGE_LIBS@ 
@GCONF_LIBS@ @LENSFUN_LIBS@ @LIBGPHOTO2_LIBS@ @DBUS_LIBS@ $(INTLLIBS)
+rawstudio_LDADD = ../librawstudio/librawstudio-@[email protected] @PACKAGE_LIBS@ 
@GCONF_LIBS@ @LENSFUN_LIBS@ @LIBGPHOTO2_LIBS@ @DBUS_LIBS@ @OSMGPSMAP_LIBS@ 
$(INTLLIBS)
 

Modified: trunk/src/application.h
===================================================================
--- trunk/src/application.h     2013-05-08 23:22:56 UTC (rev 4399)
+++ trunk/src/application.h     2013-05-31 21:35:07 UTC (rev 4400)
@@ -65,9 +65,9 @@
        RSFilter *auto_wb_filter;
        gdouble *auto_wb_mul;
        RS_MAIN_SIGNAL* signal;
+       gint time_offset;
 } RS_PHOTO;
 
-
 typedef struct {
        RS_PHOTO *photo;
        RSSettings *settings_buffer;
@@ -76,6 +76,7 @@
        RS_RECT crop_buffer;
        gdouble angle_buffer;
        guint orientation_buffer;
+       gint time_offset_buffer;
        gint current_setting;
        RS_QUEUE *queue;
        RSStore *store;

Modified: trunk/src/gtk-interface.c
===================================================================
--- trunk/src/gtk-interface.c   2013-05-08 23:22:56 UTC (rev 4399)
+++ trunk/src/gtk-interface.c   2013-05-31 21:35:07 UTC (rev 4400)
@@ -43,6 +43,7 @@
 #include "rs-toolbox.h"
 #include "rs-library.h"
 #include "rs-tag-gui.h"
+#include "rs-geo-db.h"
 
 static GtkStatusbar *statusbar;
 static gboolean fullscreen;
@@ -1574,6 +1575,10 @@
        gtk_box_pack_start (GTK_BOX(open_box), library_expander, FALSE, TRUE, 
0);
        gtk_box_pack_start (GTK_BOX(open_box), directory_expander, TRUE, TRUE, 
0);
 
+       GtkWidget *geolocbox = gtk_vbox_new(FALSE, 0);
+       RSGeoDb *geodb = rs_geo_db_get_singleton();
+       GtkWidget *map = rs_geo_db_get_widget(geodb);
+       gtk_box_pack_start (GTK_BOX(geolocbox), map, TRUE, TRUE, 0);
        
        if (client_mode)
                rs->toolbox = tools;
@@ -1581,6 +1586,7 @@
        {
                rs->toolbox = gtk_notebook_new();
                gtk_notebook_append_page(GTK_NOTEBOOK(rs->toolbox), tools, 
gtk_label_new(_("Tools")));
+               //gtk_notebook_append_page(GTK_NOTEBOOK(rs->toolbox), 
geolocbox, gtk_label_new(_("Map")));
                gtk_notebook_append_page(GTK_NOTEBOOK(rs->toolbox), batchbox, 
gtk_label_new(_("Batch")));
                gtk_notebook_append_page(GTK_NOTEBOOK(rs->toolbox), open_box, 
gtk_label_new(_("Open")));
        }

Modified: trunk/src/rs-actions.c
===================================================================
--- trunk/src/rs-actions.c      2013-05-08 23:22:56 UTC (rev 4399)
+++ trunk/src/rs-actions.c      2013-05-31 21:35:07 UTC (rev 4400)
@@ -43,6 +43,7 @@
 #include "rs-toolbox.h"
 #include "rs-tethered-shooting.h"
 #include "rs-enfuse.h"
+#include "rs-geo-db.h"
 
 static GtkActionGroup *core_action_group = NULL;
 static GStaticMutex rs_actions_spinlock = G_STATIC_MUTEX_INIT;
@@ -479,10 +480,10 @@
 
 static const gint COPY_MASK_ALL = 
MASK_PROFILE|MASK_EXPOSURE|MASK_SATURATION|MASK_HUE|
        
MASK_CONTRAST|MASK_WB|MASK_SHARPEN|MASK_DENOISE_LUMA|MASK_DENOISE_CHROMA|
-       MASK_CHANNELMIXER|MASK_TCA|MASK_VIGNETTING|MASK_CURVE;
+       MASK_CHANNELMIXER|MASK_TCA|MASK_VIGNETTING|MASK_CURVE|MASK_TIME_OFFSET;
 
 /* Widgets for copy dialog */
-static GtkWidget *cb_profile, *cb_exposure, *cb_saturation, *cb_hue, 
*cb_contrast, *cb_whitebalance, *cb_curve, *cb_sharpen, *cb_denoise_luma, 
*cb_denoise_chroma, *cb_channelmixer, *cb_tca, *cb_vignetting,*cb_transform, 
*b_all_none;
+static GtkWidget *cb_profile, *cb_exposure, *cb_saturation, *cb_hue, 
*cb_contrast, *cb_whitebalance, *cb_curve, *cb_sharpen, *cb_denoise_luma, 
*cb_denoise_chroma, *cb_channelmixer, *cb_tca, *cb_vignetting,*cb_transform, 
*cb_time_offset, *b_all_none;
 
 static void
 all_none_clicked(GtkButton *button, gpointer user_data)
@@ -516,6 +517,7 @@
        cb_vignetting = gtk_check_button_new_with_label (_("Vignetting"));
        cb_curve = gtk_check_button_new_with_label (_("Curve"));
        cb_transform = gtk_check_button_new_with_label (_("Transform"));
+       cb_time_offset = gtk_check_button_new_with_label (_("Time offset 
(GPS)"));
        b_all_none = gtk_button_new_with_label (_("Select All/None"));
 
        g_signal_connect(b_all_none, "clicked", G_CALLBACK(all_none_clicked), 
NULL);
@@ -537,6 +539,7 @@
        gtk_box_pack_start (GTK_BOX (cb_box), cb_vignetting, FALSE, TRUE, 0);
        gtk_box_pack_start (GTK_BOX (cb_box), cb_curve, FALSE, TRUE, 0);
        gtk_box_pack_start (GTK_BOX (cb_box), cb_transform, FALSE, FALSE, 0);
+       gtk_box_pack_start (GTK_BOX (cb_box), cb_time_offset, FALSE, FALSE, 0);
        gtk_box_pack_start (GTK_BOX (cb_box), b_all_none, FALSE, TRUE, 0);
 
        dialog = gui_dialog_make_from_widget(GTK_STOCK_DIALOG_QUESTION, 
_("Select Settings to Copy"), cb_box);
@@ -563,6 +566,7 @@
        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cb_vignetting), !!(mask 
& MASK_VIGNETTING));
        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cb_curve), !!(mask & 
MASK_CURVE));
        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cb_transform), !!(mask & 
MASK_TRANSFORM));
+       gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cb_time_offset), !!(mask 
& MASK_TIME_OFFSET));
 }
 
 static gint
@@ -597,6 +601,8 @@
                mask |= MASK_CURVE;
        if (GTK_TOGGLE_BUTTON(cb_transform)->active)
                mask |= MASK_TRANSFORM;
+       if (GTK_TOGGLE_BUTTON(cb_time_offset)->active)
+               mask |= MASK_TIME_OFFSET;
        return mask;
 }
 
@@ -632,6 +638,7 @@
                        rs->crop_buffer.x1 = -1;
                rs->angle_buffer = rs->photo->angle;
                rs->orientation_buffer = rs->photo->orientation;
+               rs->time_offset_buffer = rs->photo->time_offset;
 
                gui_status_notify(_("Copied settings"));
        }
@@ -699,6 +706,11 @@
                                                rs_photo_set_dcp_profile(photo, 
rs->dcp_buffer);
                                        else if (rs->icc_buffer)
                                                rs_photo_set_icc_profile(photo, 
rs->icc_buffer);
+                               }
+                               if (mask & MASK_TIME_OFFSET)
+                               {
+                                       RSGeoDb *geodb = 
rs_geo_db_get_singleton();
+                                       rs_geo_db_set_offset(geodb, photo, 
rs->time_offset_buffer);
                                }       
                                rs_cache_save(photo, (new_mask | mask) & 
MASK_ALL);
                                g_object_unref(photo);
@@ -721,6 +733,11 @@
                                        rs_photo_set_angle(rs->photo, 
rs->angle_buffer, FALSE);
                                        rs_photo_set_crop(rs->photo, 
&rs->crop_buffer);
                                }
+                               if (mask & MASK_TIME_OFFSET)
+                               {
+                                       RSGeoDb *geodb = 
rs_geo_db_get_singleton();
+                                       rs_geo_db_set_offset(geodb, photo, 
rs->time_offset_buffer);
+                               }
                        }
 
                        if (rs->photo)

Modified: trunk/src/rs-cache.c
===================================================================
--- trunk/src/rs-cache.c        2013-05-08 23:22:56 UTC (rev 4399)
+++ trunk/src/rs-cache.c        2013-05-31 21:35:07 UTC (rev 4400)
@@ -125,6 +125,11 @@
                rs_cache_save_settings(photo->settings[id], mask, writer);
                xmlTextWriterEndElement(writer);
        }
+       if (photo->time_offset)
+       {
+               xmlTextWriterWriteFormatElement(writer, BAD_CAST "time_offset", 
"%d", photo->time_offset);
+       }
+
        int ret = xmlTextWriterEndDocument(writer);
        xmlFreeTextWriter(writer);
        g_free(cachename);
@@ -517,6 +522,15 @@
                        g_strfreev(vals);
                        xmlFree(val);
                }
+               else if ((!xmlStrcmp(cur->name, BAD_CAST "time_offset")))
+               {
+                       val = xmlNodeListGetString(doc, cur->xmlChildrenNode, 
1);
+                       if (val)
+                       {
+                               photo->time_offset = atoi((gchar *) val);
+                               xmlFree(val);
+                       }
+               }
                cur = cur->next;
        }
 

Added: trunk/src/rs-geo-db.c
===================================================================
--- trunk/src/rs-geo-db.c                               (rev 0)
+++ trunk/src/rs-geo-db.c       2013-05-31 21:35:07 UTC (rev 4400)
@@ -0,0 +1,453 @@
+#include <rawstudio.h>
+#include <application.h>
+#include <glib.h>
+#include <libxml/encoding.h>
+#include <libxml/xmlwriter.h>
+#include <sqlite3.h>
+#include "osm-gps-map.h"
+#include "rs-geo-db.h"
+#include "gtk-progress.h"
+
+struct _RSGeoDb {
+       GObject parent;
+
+       OsmGpsMap *map;
+       sqlite3 *db;
+       GtkAdjustment *offset_adj;
+};
+
+G_DEFINE_TYPE (RSGeoDb, rs_geo_db, GTK_TYPE_OBJECT)
+
+static void
+rs_geo_db_finalize (GObject *object)
+{
+       RSGeoDb *geodb = RS_GEO_DB(object);
+
+       sqlite3_close(geodb->db);
+
+       if (G_OBJECT_CLASS (rs_geo_db_parent_class)->finalize)
+               G_OBJECT_CLASS (rs_geo_db_parent_class)->finalize (object);
+}
+
+static void
+dispose(GObject *object)
+{
+       G_OBJECT_CLASS(rs_geo_db_parent_class)->dispose(object);
+}
+
+
+static void
+rs_geo_db_class_init (RSGeoDbClass *klass)
+{
+       GObjectClass *object_class = G_OBJECT_CLASS (klass);
+       object_class->dispose = dispose;
+       object_class->finalize = rs_geo_db_finalize;
+}
+
+static void
+rs_geo_db_init (RSGeoDb *geodb)
+{
+       gchar *database = g_strdup_printf("%s/.rawstudio/geo.db", 
g_get_home_dir());
+
+       if(sqlite3_open(database, &geodb->db))
+       {
+               gchar *msg = g_strdup_printf("Could not open database %s", 
database);
+               g_warning("sqlite3: %s\n", msg);
+               g_free(msg);
+               sqlite3_close(geodb->db);
+       }
+       g_free(database);
+
+       sqlite3_stmt *stmt;
+       gint rc;
+
+       if (rc);
+
+       sqlite3_prepare_v2(geodb->db, "create table imports (id INTEGER PRIMARY 
KEY, checksum VARCHAR(1024) UNIQUE, priority INTEGER);", -1, &stmt, NULL);
+       rc = sqlite3_step(stmt);
+       sqlite3_finalize(stmt);
+
+       sqlite3_prepare_v2(geodb->db, "CREATE TABLE trkpts (time INTEGER 
PRIMARY KEY, lon DOUBLE, lat DOUBLE, ele DOUBLE, import INTEGER, FOREIGN 
KEY(import) REFERENCES imports(id));", -1, &stmt, NULL);
+       rc = sqlite3_step(stmt);
+       sqlite3_finalize(stmt);
+}
+
+
+RSGeoDb *
+rs_geo_db_new(void)
+{
+       return g_object_new (RS_TYPE_GEO_DB, NULL);
+}
+
+RSGeoDb *
+rs_geo_db_get_singleton(void)
+{
+       static RSGeoDb *geodb = NULL;
+       static GStaticMutex lock = G_STATIC_MUTEX_INIT;
+
+       g_static_mutex_lock(&lock);
+       if (!geodb)
+       {
+               geodb = rs_geo_db_new();
+       }
+       g_static_mutex_unlock(&lock);
+
+       return geodb;
+}
+
+void load_gpx(gchar *gpxfile, gint priority, sqlite3 *db, gint num, gint total)
+{
+       sqlite3_stmt *stmt;
+       gint rc;
+
+       if (rc); /* FIXME */
+
+       xmlDocPtr doc;
+       xmlNodePtr cur;
+       xmlNodePtr trk = NULL;
+       xmlNodePtr trkseg = NULL;
+       xmlNodePtr trkpt = NULL;
+       xmlChar *val;
+
+       gdouble lon = 0.0, lat = 0.0, ele = 0.0;
+       gchar *year, *month, *day, *hour, *min, *sec;
+       GDateTime *timestamp = NULL;
+
+       doc = xmlParseFile(gpxfile);
+       if (!doc)
+               return;
+
+       gchar *checksum = rs_file_checksum(gpxfile);
+       gint import_id = 0;
+  
+       sqlite3_prepare_v2(db, "INSERT INTO imports (checksum, priority) VALUES 
(?1, ?2);", -1, &stmt, NULL);
+       rc = sqlite3_bind_text(stmt, 1, checksum, -1, SQLITE_TRANSIENT);
+       rc = sqlite3_bind_int (stmt, 2, priority);
+       rc = sqlite3_step(stmt);
+       import_id = sqlite3_last_insert_rowid(db);
+       sqlite3_finalize(stmt);  
+
+       if (import_id == 0)
+               return;
+
+       cur = xmlDocGetRootElement(doc);
+       cur = cur->xmlChildrenNode;
+
+       gint count = 0;
+
+       while(cur)
+       {
+               if ((!xmlStrcmp(cur->name, BAD_CAST "trk")))
+               {
+                       trk = cur->xmlChildrenNode;
+                       while (trk)
+                       {
+                               if ((!xmlStrcmp(trk->name, BAD_CAST "trkseg"))) 
+                               {
+                                       trkseg = trk->xmlChildrenNode;
+                                       while (trkseg)
+                                       {
+                                               if ((!xmlStrcmp(trkseg->name, 
BAD_CAST "trkpt"))) 
+                                               {
+                                                       count++;
+                                               }
+                                       trkseg = trkseg->next;
+                                       }
+                               }
+                               trk = trk->next;
+                       }
+               }
+       cur = cur->next;
+       }
+
+       RS_PROGRESS *progress = NULL;
+       gchar *title = g_strdup_printf("Loading GPX (%d/%d)...", num, total);
+       progress = gui_progress_new(title, count);
+       g_free(title);
+       GUI_CATCHUP();
+
+       cur = xmlDocGetRootElement(doc);
+       cur = cur->xmlChildrenNode;
+ 
+       while(cur)
+       {
+               if ((!xmlStrcmp(cur->name, BAD_CAST "trk")))
+               {
+                       trk = cur->xmlChildrenNode;
+                       while (trk)
+                       {
+                               if ((!xmlStrcmp(trk->name, BAD_CAST "trkseg"))) 
+                               {
+                                       trkseg = trk->xmlChildrenNode;
+                                       while (trkseg)
+                                       {
+                                               if ((!xmlStrcmp(trkseg->name, 
BAD_CAST "trkpt"))) 
+                                               {
+                                                       trkpt = 
trkseg->xmlChildrenNode;
+
+                                                       // Reset values
+                                                       lon = 0.0;
+                                                       lat = 0.0;
+                                                       ele = 0.0;
+
+                                                       while (trkpt)
+                                                       {
+                                                               if 
((!xmlStrcmp(trkpt->name, BAD_CAST "ele")))
+                                                               {
+                                                                       val = 
xmlNodeListGetString(doc, trkpt->xmlChildrenNode, 1);
+                                                                       ele = 
atof((gchar *) val);
+                                                                       
xmlFree(val);
+                                                               }
+                                                               if 
((!xmlStrcmp(trkpt->name, BAD_CAST "time"))) 
+                                                               {
+                                                                       val = 
xmlNodeListGetString(doc, trkpt->xmlChildrenNode, 1);
+                                                                       year = 
g_utf8_substring((gchar *) val, 0, 4);
+                                                                       month = 
g_utf8_substring((gchar *) val, 5, 7);
+                                                                       day = 
g_utf8_substring((gchar *) val, 8, 10);
+                                                                       hour = 
g_utf8_substring((gchar *) val, 11, 13);
+                                                                       min = 
g_utf8_substring((gchar *) val, 14, 16);
+                                                                       sec = 
g_utf8_substring((gchar *) val, 17, 19);
+                                                                       
xmlFree(val);
+                                                                       
timestamp = g_date_time_new_utc(atoi(year), atoi(month), atoi(day), atoi(hour), 
atoi(min), atoi(sec));
+                                                                       
g_free(year);
+                                                                       
g_free(month);
+                                                                       
g_free(day);
+                                                                       
g_free(hour);
+                                                                       
g_free(min);
+                                                                       
g_free(sec);
+                                                               }
+                                                               trkpt = 
trkpt->next;
+                                                       }
+                                                       val = 
xmlGetProp(trkseg, BAD_CAST "lat");
+                                                       lat = atof((gchar *) 
val);
+                                                       xmlFree(val);
+                     
+                                                       val = 
xmlGetProp(trkseg, BAD_CAST "lon");
+                                                       lon = atof((gchar *) 
val);
+                                                       if (lat && lon)
+                                                       {
+                                                               
sqlite3_prepare_v2(db, "INSERT INTO trkpts (time, lon, lat, ele, import) VALUES 
(?1, ?2, ?3, ?4, ?5);", -1, &stmt, NULL);
+                                                               rc = 
sqlite3_bind_int (stmt, 1, atoi(g_date_time_format(timestamp, "%s")));
+                                                               rc = 
sqlite3_bind_double (stmt, 2, lon);
+                                                               rc = 
sqlite3_bind_double (stmt, 3, lat);
+                                                               rc = 
sqlite3_bind_double (stmt, 4, ele);
+                                                               rc = 
sqlite3_bind_int (stmt, 5, import_id);
+                                                               rc = 
sqlite3_step(stmt);
+                                                               
sqlite3_finalize(stmt);  
+                                                       }
+                                                       
gui_progress_advance_one(progress);
+                                                       GUI_CATCHUP();
+                         
+                                                       
g_date_time_unref(timestamp);
+                                               }
+                                               trkseg = trkseg->next;
+                                       }
+                               }
+                               trk = trk->next;
+                       }
+               }
+               cur = cur->next;
+       }
+       gui_progress_free(progress);
+}
+
+
+void
+rs_geo_db_find_coordinate(RSGeoDb *geodb, gint timestamp, gdouble *lon, 
gdouble *lat, gdouble *ele)
+{
+       sqlite3 *db = geodb->db;
+  
+       sqlite3_stmt *stmt;
+       gint rc;
+
+       gint before_timestamp = 0;
+       gdouble before_lon = 0.0, before_lat = 0.0, before_ele = 0.0;
+
+       gint after_timestamp = 0;
+       gdouble after_lon = 0.0, after_lat = 0.0, after_ele = 0.0;
+
+       rc = sqlite3_prepare_v2(db, "SELECT * FROM trkpts WHERE time <= ?1 
ORDER BY TIME DESC LIMIT 1;", -1, &stmt, NULL);
+       rc = sqlite3_bind_int(stmt, 1, timestamp);
+       rc = sqlite3_step(stmt);
+       if (rc == SQLITE_ROW) 
+       {
+               before_timestamp = sqlite3_column_int(stmt, 0);
+               before_lon = sqlite3_column_double(stmt, 1);
+               before_lat = sqlite3_column_double(stmt, 2);
+               before_ele = sqlite3_column_double(stmt, 3);
+       }
+
+       rc = sqlite3_prepare_v2(db, "SELECT * FROM trkpts WHERE time >= ?1 
ORDER BY TIME ASC LIMIT 1;", -1, &stmt, NULL);
+       rc = sqlite3_bind_int(stmt, 1, timestamp);
+       rc = sqlite3_step(stmt);
+       if (rc == SQLITE_ROW) 
+       {
+               after_timestamp = sqlite3_column_int(stmt, 0);
+               after_lon = sqlite3_column_double(stmt, 1);
+               after_lat = sqlite3_column_double(stmt, 2);
+               after_ele = sqlite3_column_double(stmt, 3);
+       }
+
+       if (after_timestamp == before_timestamp)
+       {
+               *lon = after_lon;
+               *lat = after_lat;
+               *ele = after_ele;
+               return;
+       }
+
+       gint diff_timestamp = after_timestamp - before_timestamp;
+       gint diff = after_timestamp - timestamp;
+       gdouble diff_lon = (after_lon - before_lon) / diff_timestamp;
+       gdouble diff_lat = (after_lat - before_lat) / diff_timestamp;
+       gdouble diff_ele = (after_ele - before_ele) / diff_timestamp;
+
+       *lon = after_lon - diff*diff_lon;
+       *lat = after_lat - diff*diff_lat;
+       *ele = after_ele - diff*diff_ele;
+}
+
+void 
+rs_geo_db_set_coordinates(RSGeoDb *geodb, gdouble lon, gdouble lat)
+{
+       osm_gps_map_set_center((OsmGpsMap *) geodb->map, lat, lon);
+}
+
+void spinbutton_change (GtkAdjustment *adj, gpointer user_data)
+{
+       RS_BLOB *rs = (RS_BLOB *) user_data;
+       gdouble lon, lat, ele;
+       RSGeoDb *geodb = rs_geo_db_get_singleton();
+
+       gint time_offset= gtk_adjustment_get_value(adj);
+       rs->photo->time_offset = time_offset;
+  
+       rs_geo_db_find_coordinate(geodb, rs->photo->metadata->timestamp + 
time_offset, &lon, &lat, &ele);
+       rs_geo_db_set_coordinates(geodb, lon, lat);
+}
+
+void update_label (GtkAdjustment *adj, GtkLabel *label)
+{
+       gint offset = gtk_adjustment_get_value(adj);
+       gint hour = (gint) (offset%(60*60*60)/60/60);
+       gint min = (gint) (offset%(60*60)/60);
+       if (min < 0)
+               min *= -1;
+       gint sec = (gint) (offset%(60));
+       if (sec < 0)
+               sec *= -1;
+       gchar *text = g_strdup_printf("offset: %02d:%02d:%02d (h:m:s)\n", hour, 
min, sec);
+       gtk_label_set_text(label, text);
+}
+
+void import_gpx(GtkButton *button, RSGeoDb *geodb)
+{
+       GtkWidget *fc = gtk_file_chooser_dialog_new ("Import GPX ...", NULL, 
+                                                                               
                        GTK_FILE_CHOOSER_ACTION_OPEN,
+                                                                               
                        GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+                                                                               
                        GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL);
+       gtk_dialog_set_default_response(GTK_DIALOG(fc), GTK_RESPONSE_ACCEPT);
+
+       GtkFileFilter *filter = gtk_file_filter_new();
+       gtk_file_filter_set_name(filter, "GPX");
+       gtk_file_filter_add_pattern(filter, "*.gpx");
+       gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(fc), filter);
+       gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(fc), TRUE);
+
+       //gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER (fc), dir); // 
FIXME: save last used directory
+
+       if (gtk_dialog_run (GTK_DIALOG (fc)) == GTK_RESPONSE_ACCEPT)
+       {
+               GSList *filenames;
+               gchar *filename;
+               filenames = gtk_file_chooser_get_filenames (GTK_FILE_CHOOSER 
(fc));
+               gtk_widget_destroy(fc);
+               if (filenames)
+               {
+                       gint i;
+
+                       for(i=0;i<g_slist_length(filenames);i++)
+                       {
+                               filename = g_slist_nth_data(filenames, i);
+                               load_gpx(filename, 1, geodb->db, (i+1), 
g_slist_length(filenames));
+                               g_free(filename);
+                       }
+                       g_slist_free(filenames);
+               }
+       }
+       else
+    {
+               gtk_widget_destroy(fc);
+    }
+}
+
+void map_changed (OsmGpsMap *map, RSGeoDb *geodb)
+{
+       /* FIXME: save zoom */
+}
+
+GtkWidget *
+rs_geo_db_get_widget(RSGeoDb *geodb) {
+       OsmGpsMapSource_t source = OSM_GPS_MAP_SOURCE_VIRTUAL_EARTH_SATELLITE;
+
+       if ( !osm_gps_map_source_is_valid(source) )
+               return NULL;
+
+       GtkWidget *map = g_object_new (OSM_TYPE_GPS_MAP,
+                                                                       
"map-source", source,
+                                                                       
"tile-cache", "/tmp/",
+                                                                       NULL);
+
+       g_signal_connect(map, "changed", G_CALLBACK(map_changed), geodb);
+
+       OsmGpsMapLayer *osd = g_object_new (OSM_TYPE_GPS_MAP_OSD,
+                                                                               
"show-scale",TRUE,
+                                                                               
"show-coordinates",TRUE,
+                                                                               
"show-crosshair",TRUE,
+                                                                               
"show-dpad",TRUE,
+                                                                               
"show-zoom",TRUE,
+                                                                               
"show-gps-in-dpad",TRUE,
+                                                                               
"show-gps-in-zoom",FALSE,
+                                                                               
"dpad-radius", 30,
+                                                                               
NULL);
+
+       osm_gps_map_layer_add(OSM_GPS_MAP(map), osd);
+       g_object_unref(G_OBJECT(osd));
+
+       osm_gps_map_set_center((OsmGpsMap *) map, 57.0, 10.0);
+       gtk_widget_show_all (map);
+
+       geodb->map = (OsmGpsMap *) map;
+
+       GtkWidget *box = gtk_vbox_new(FALSE, 0);
+       gtk_box_pack_start (GTK_BOX(box), map, TRUE, TRUE, 0);
+
+       GtkWidget *offset_box = gtk_hbox_new(FALSE, 0);
+
+       GtkAdjustment *adj = (GtkAdjustment *) gtk_adjustment_new(0, -43200, 
43200, 1, 10, 0);
+       geodb->offset_adj = adj;
+       GtkWidget *spin = gtk_spin_button_new(GTK_ADJUSTMENT(adj), 1, 1);
+       GtkWidget *offset_label = gtk_label_new("offset: 00:00:00 (h:m:s)");
+       gtk_box_pack_start (GTK_BOX(box), offset_box, FALSE, FALSE, 5);
+
+       gtk_box_pack_start (GTK_BOX(offset_box), spin, TRUE, FALSE, 5);
+       gtk_box_pack_start (GTK_BOX(offset_box), offset_label, TRUE, FALSE, 5);
+
+       g_signal_connect(adj, "value_changed", G_CALLBACK(spinbutton_change), 
rs_get_blob());
+       g_signal_connect(adj, "value_changed", G_CALLBACK(update_label), 
offset_label);
+
+       GtkWidget *button = gtk_button_new_with_label("Import GPX file");
+       g_signal_connect(button, "clicked", G_CALLBACK(import_gpx), geodb);
+       gtk_box_pack_start (GTK_BOX(box), button, FALSE, FALSE, 5);
+
+       return box;
+}
+
+void rs_geo_db_set_offset(RSGeoDb *geodb, RS_PHOTO *photo, gint offset)
+{
+       photo->time_offset = offset;
+
+       RS_BLOB *rs = rs_get_blob();
+       if (rs->photo)
+               gtk_adjustment_set_value(geodb->offset_adj, photo->time_offset);
+}

Added: trunk/src/rs-geo-db.h
===================================================================
--- trunk/src/rs-geo-db.h                               (rev 0)
+++ trunk/src/rs-geo-db.h       2013-05-31 21:35:07 UTC (rev 4400)
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2006-2011 Anders Brander <[email protected]>,
+ * Anders Kvist <[email protected]> and Klaus Post <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
USA.
+ */
+
+#ifndef RS_GEO_DB_H
+#define RS_GEO_DB_H
+
+#include <rawstudio.h>
+#include "application.h"
+#include <sqlite3.h>
+#include "osm-gps-map.h"
+
+G_BEGIN_DECLS
+
+#define RS_TYPE_GEO_DB rs_geo_db_get_type()
+#define RS_GEO_DB(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), RS_TYPE_GEO_DB, 
RSGeoDb))
+#define RS_GEO_DB_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), 
RS_TYPE_GEO_DB, RSGeoDbClass))
+#define RS_IS_GEO_DB(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), RS_TYPE_GEO_DB))
+#define RS_IS_GEO_DB_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), 
RS_TYPE_GEO_DB))
+#define RS_GEO_DB_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), 
RS_TYPE_GEO_DB, RSGeoDbClass))
+
+typedef struct _RSGeoDb RSGeoDb;
+
+typedef struct {
+  GtkScrolledWindowClass parent_class;
+} RSGeoDbClass;
+
+GType rs_geo_db_get_type (void);
+
+extern RSGeoDb *
+rs_geo_db_new (void);
+RSGeoDb *rs_geo_db_get_singleton(void);
+
+extern GtkWidget * rs_geo_db_get_widget(RSGeoDb *geodb);
+extern void rs_geo_db_set_coordinates(RSGeoDb *geodb, gdouble lon, gdouble 
lat);
+void rs_geo_db_find_coordinate(RSGeoDb *geodb, gint timestamp, gdouble *lon, 
gdouble *lat, gdouble *ele);
+void rs_geo_db_set_offset(RSGeoDb *geodb, RS_PHOTO *time_offset, gint offset);
+
+#endif /* RS_GEO_DB */
+
+
+

Modified: trunk/src/rs-photo.c
===================================================================
--- trunk/src/rs-photo.c        2013-05-08 23:22:56 UTC (rev 4399)
+++ trunk/src/rs-photo.c        2013-05-31 21:35:07 UTC (rev 4400)
@@ -23,6 +23,7 @@
 #include "rs-cache.h"
 #include "rs-camera-db.h"
 #include "rs-profile-factory.h"
+#include "rs-geo-db.h"
 
 static void rs_photo_class_init (RS_PHOTOClass *klass);
 
@@ -152,6 +153,7 @@
        photo->exported = FALSE;
        photo->auto_wb_mul = NULL;
        photo->embedded_profile = NULL;
+       photo->time_offset = 0;
 }
 
 static void
@@ -422,6 +424,15 @@
                RSLensDb *lens_db = rs_lens_db_get_default();
                RSLens *lens = rs_lens_db_lookup_from_metadata(lens_db, meta);
 
+               gdouble lon, lat, ele;
+               RSGeoDb *geodb = rs_geo_db_get_singleton();
+               rs_geo_db_set_offset(geodb, photo, photo->time_offset);
+               if (photo->time_offset != 0) 
+               {
+                       rs_geo_db_find_coordinate(geodb, meta->timestamp + 
photo->time_offset, &lon, &lat, &ele);
+                       rs_geo_db_set_coordinates(geodb, lon, lat);
+               }
+
                /* Apply lens information to RSLensfun */
                if (lens)
                {


_______________________________________________
Rawstudio-commit mailing list
[email protected]
http://rawstudio.org/cgi-bin/mailman/listinfo/rawstudio-commit

Reply via email to