From bfd9423677aab4372bc89edc0f18723c5190d04d Mon Sep 17 00:00:00 2001 From: Kaj-Michael Lang Date: Tue, 22 Jan 2008 20:30:26 +0200 Subject: [PATCH] Start to rewrite the GPS system to support location information from multiple sources. --- configure.ac | 2 + src/bluetooth-scan.h | 30 +++ src/bt.h | 54 ----- src/cb.c | 57 +++--- src/config-gconf.c | 25 ++- src/filter-gui.c | 1 - src/gps-bluetooth-bluez.c | 184 +---------------- src/gps-bluetooth-hildon.c | 81 +------- src/gps-browse.c | 2 +- src/gps-conn.c | 7 +- src/gps-conn.h | 4 +- src/gps-nmea-parse.c | 216 ++++++-------------- src/gps.c | 399 ++++++++++++++++++++++++++++++++++++- src/gps.h | 83 +++++--- src/maemo-osso.c | 13 +- src/map-download.c | 1 - src/map-repo.c | 4 +- src/map.c | 67 ++++--- src/map.h | 18 +- src/mapper.c | 16 +- src/osm-db.c | 6 +- src/route.c | 26 +-- src/settings-gui.c | 22 +- src/settings.h | 1 - src/track.c | 4 +- src/ui-common.c | 18 +- 26 files changed, 686 insertions(+), 655 deletions(-) create mode 100644 src/bluetooth-scan.h delete mode 100644 src/bt.h diff --git a/configure.ac b/configure.ac index fcb15e8..deb236f 100644 --- a/configure.ac +++ b/configure.ac @@ -106,10 +106,12 @@ if test "x$enable_btdbus" = "xno" ; then WITH_BLUEZ_DBUS_BT=no else WITH_BLUEZ_DBUS_BT=yes + WITH_BLUEZ=yes PKG_CHECK_MODULES(BLUEZ, bluez) AC_SUBST(BLUEZ_LIBS) AC_SUBST(BLUEZ_CFLAGS) AC_DEFINE([WITH_BLUEZ_DBUS_BT], 1, [bluez D-Bus bluetooth]) + AC_DEFINE([WITH_BLUEZ], 1, [Bluez RFCOMM]) fi AM_CONDITIONAL(HAVE_HILDON_DBUS_BT, [test "$enable_itbtdbus" = "yes"]) diff --git a/src/bluetooth-scan.h b/src/bluetooth-scan.h new file mode 100644 index 0000000..bccc3ef --- /dev/null +++ b/src/bluetooth-scan.h @@ -0,0 +1,30 @@ +#ifndef _MAPPER_BLUETOOTH_SCAN_H +#define _MAPPER_BLUETOOTH_SCAN_H + +#include "config.h" + +#include + +#include "utils.h" +#include "gps.h" +#include "mapper-types.h" + +typedef struct _ScanInfo ScanInfo; +struct _ScanInfo { + GtkWidget *settings_dialog; + GtkWidget *txt_rcvr_mac; + GtkWidget *scan_dialog; + GtkWidget *banner; + GtkListStore *store; + guint sid; +#ifdef WITH_HILDON_DBUS_BT + DBusGProxy *req_proxy; + DBusGProxy *sig_proxy; +#endif +}; + +gint scan_start_search(ScanInfo * scan_info); +gboolean scan_bluetooth(GtkWidget * widget, ScanInfo * scan_info); +gboolean scan_bluetooth_idle(ScanInfo * scan_info); + +#endif diff --git a/src/bt.h b/src/bt.h deleted file mode 100644 index 635de12..0000000 --- a/src/bt.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef _MAPPER_BT_H -#define _MAPPER_BT_H - -#include "config.h" - -#include - -#include "utils.h" -#include "mapper-types.h" - -/** This enumerated type defines the possible connection states. */ -typedef enum { - /** The receiver is "off", meaning that either the bluetooth radio is - * off or the user has requested not to connect to the GPS receiver. - * No gtk_banner is visible. */ - RCVR_OFF, - - /** The connection with the receiver is down. A gtk_banner is visible with - * the text, "Connecting to GPS receiver". */ - RCVR_DOWN, - - /** The connection with the receiver is up, but a GPS fix is not available. - * A gtk_banner is visible with the text, "(Re-)Establishing GPS fix". */ - RCVR_UP, - - /** The connection with the receiver is up and a GPS fix IS available. - * No gtk_banner is visible. */ - RCVR_FIXED -} ConnState; - -typedef struct _ScanInfo ScanInfo; -struct _ScanInfo { - GtkWidget *settings_dialog; - GtkWidget *txt_rcvr_mac; - GtkWidget *scan_dialog; - GtkWidget *banner; - GtkListStore *store; - guint sid; -#ifdef WITH_HILDON_DBUS_BT - DBusGProxy *req_proxy; - DBusGProxy *sig_proxy; -#endif -}; - -ConnState _conn_state; - -void rcvr_disconnect(void); -void rcvr_connect_later(void); -gint scan_start_search(ScanInfo * scan_info); -gboolean rcvr_connect_now(void); -gboolean scan_bluetooth(GtkWidget * widget, ScanInfo * scan_info); -gboolean scan_bluetooth_idle(ScanInfo * scan_info); - -#endif diff --git a/src/cb.c b/src/cb.c index 96370a9..567933b 100644 --- a/src/cb.c +++ b/src/cb.c @@ -50,7 +50,6 @@ #include "gps.h" #include "map.h" #include "mapper-types.h" -#include "bt.h" #include "ui-common.h" #include "db.h" #include "latlon.h" @@ -271,7 +270,7 @@ switch (value) { break; } -MACRO_RECALC_CENTER(new_center_unitx, new_center_unity); +MACRO_RECALC_CENTER(_gps->data, new_center_unitx, new_center_unity); map_center_unit(new_center_unitx, new_center_unity); return TRUE; } @@ -311,7 +310,7 @@ gboolean menu_cb_goto_gps(GtkAction *action) { _center_mode = CENTER_LATLON; -map_center_unit(_gps->unitx, _gps->unity); +map_center_unit(_gps->data.unitx, _gps->data.unity); map_update_location_from_center(); MACRO_BANNER_SHOW_INFO(_window, _("At GPS coordinates.")); return TRUE; @@ -340,8 +339,8 @@ poi_info *p; if (_center_mode > 0) { /* Auto-Center is enabled - use the GPS position. */ - lat=_gps->lat; - lon=_gps->lon; + lat=_gps->data.lat; + lon=_gps->data.lon; } else { /* Auto-Center is disabled - use the view center. */ unit2latlon(_center.unitx, _center.unity, lat, lon); @@ -390,14 +389,14 @@ return TRUE; gboolean cb_zoom_auto(GtkAction * action) { -map_set_autozoom(TRUE); +map_set_autozoom(TRUE, _gps->data.speed); return TRUE; } gboolean cb_zoom_base(GtkAction * action) { -map_set_autozoom(FALSE); +map_set_autozoom(FALSE, 0); map_set_zoom(3); return TRUE; } @@ -405,7 +404,7 @@ return TRUE; gboolean cb_zoomin(GtkAction * action) { -map_set_autozoom(FALSE); +map_set_autozoom(FALSE, 0); g_idle_add((GSourceFunc)map_zoom_in, NULL); return TRUE; } @@ -413,7 +412,7 @@ return TRUE; gboolean cb_zoomout(GtkAction * action) { -map_set_autozoom(FALSE); +map_set_autozoom(FALSE, 0); g_idle_add((GSourceFunc)map_zoom_out, NULL); return TRUE; } @@ -434,17 +433,15 @@ gboolean menu_cb_enable_gps(GtkAction * action) { if ((_enable_gps = gtk_toggle_action_get_active(GTK_TOGGLE_ACTION(action)))) { - if (_rcvr_mac) { - gps_conn_set_state(RCVR_DOWN); - rcvr_connect_now(); - } else { + gps_conn_set_state(_gps, RCVR_DOWN); + if (gps_connect_now(_gps)==FALSE) { popup_error(_window, _("Cannot enable GPS until a GPS Receiver MAC is set in the Settings dialog box.")); set_action_activate("gps_enable", FALSE); } } else { - if (_conn_state > RCVR_OFF) - gps_conn_set_state(RCVR_OFF); - rcvr_disconnect(); + if (_gps->io.conn > RCVR_OFF) + gps_conn_set_state(_gps, RCVR_OFF); + gps_disconnect(_gps); track_add(0, FALSE); _speed_excess=FALSE; } @@ -455,7 +452,7 @@ set_action_sensitive("autocenter_latlon", _enable_gps); set_action_sensitive("autocenter_lead", _enable_gps); map_move_mark(); -gps_show_info(_gps); +gps_show_info(&_gps->data); return TRUE; } @@ -478,9 +475,9 @@ menu_cb_settings(GtkAction * action) if (settings_dialog()) { /* Settings have changed - reconnect to receiver. */ if (_enable_gps) { - gps_conn_set_state(RCVR_DOWN); - rcvr_disconnect(); - rcvr_connect_now(); + gps_conn_set_state(_gps, RCVR_DOWN); + gps_disconnect(_gps); + gps_connect_now(_gps); } } MACRO_RECALC_FOCUS_BASE(); @@ -743,7 +740,7 @@ gdouble lat, lon; unit2latlon(unitx, unity, lat, lon); g_snprintf(buffer, sizeof(buffer), "%s: %.02lf %s", _("Distance"), - calculate_distance(_gps->lat, _gps->lon, lat, lon) * UNITS_CONVERT[_units], UNITS_TEXT[_units]); + calculate_distance(_gps->data.lat, _gps->data.lon, lat, lon) * UNITS_CONVERT[_units], UNITS_TEXT[_units]); MACRO_BANNER_SHOW_INFO(_window, buffer); } @@ -940,8 +937,8 @@ poi_info poi; gdouble lat, lon; if (_center_mode>0) { - lat=_gps->lat; - lon=_gps->lon; + lat=_gps->data.lat; + lon=_gps->data.lon; } else { unit2latlon(_center.unitx, _center.unity, lat, lon); } @@ -958,8 +955,8 @@ const gchar *name = gtk_action_get_name(action); poi_info *p; if (_center_mode>0) { - lat=_gps->lat; - lon=_gps->lon; + lat=_gps->data.lat; + lon=_gps->data.lon; } else { unit2latlon(_center.unitx, _center.unity, lat, lon); } @@ -985,8 +982,8 @@ menu_cb_search_address(GtkAction *action) gdouble lat, lon; if (_center_mode>0) { - lat=_gps->lat; - lon=_gps->lon; + lat=_gps->data.lat; + lon=_gps->data.lon; } else { unit2latlon(_center.unitx, _center.unity, lat, lon); } @@ -1027,9 +1024,9 @@ return TRUE; gboolean cmenu_cb_loc_set_gps(GtkAction * action) { -_gps->unitx = x2unit(_cmenu_position_x); -_gps->unity = y2unit(_cmenu_position_y); -unit2latlon(_gps->unitx, _gps->unity, _gps->lat, _gps->lon); +_gps->data.unitx = x2unit(_cmenu_position_x); +_gps->data.unity = y2unit(_cmenu_position_y); +unit2latlon(_gps->data.unitx, _gps->data.unity, _gps->data.lat, _gps->data.lon); /* Move mark to new location. */ map_refresh_mark(); diff --git a/src/config-gconf.c b/src/config-gconf.c index 2eec3af..cafda29 100644 --- a/src/config-gconf.c +++ b/src/config-gconf.c @@ -50,7 +50,6 @@ #include "db.h" #include "poi.h" #include "gps.h" -#include "bt.h" #include "ui-common.h" #include "settings.h" #include "gpx.h" @@ -236,8 +235,8 @@ config_dir = gnome_vfs_expand_initial_tilde(CONFIG_DIR_NAME); g_mkdir_with_parents(config_dir, 0700); /* Save Receiver MAC from GConf. */ -if (_rcvr_mac) - gconf_client_set_string(gconf_client, GCONF_KEY_RCVR_MAC, _rcvr_mac, NULL); +if (_gps->io.address) + gconf_client_set_string(gconf_client, GCONF_KEY_RCVR_MAC, _gps->io.address, NULL); else gconf_client_unset(gconf_client, GCONF_KEY_RCVR_MAC, NULL); @@ -289,8 +288,8 @@ gconf_client_set_string(gconf_client, INFO_FONT_TEXT[_info_font_size], NULL); /* Save last latitude/longiture. */ -gconf_client_set_float(gconf_client, GCONF_KEY_LAT, _gps->lat, NULL); -gconf_client_set_float(gconf_client, GCONF_KEY_LON, _gps->lon, NULL); +gconf_client_set_float(gconf_client, GCONF_KEY_LAT, _gps->data.lat, NULL); +gconf_client_set_float(gconf_client, GCONF_KEY_LON, _gps->data.lon, NULL); /* Save last center latitude/longitude. */ unit2latlon(_center.unitx, _center.unity, center_lat, center_lon); @@ -424,7 +423,7 @@ config_dir = gnome_vfs_expand_initial_tilde(CONFIG_DIR_NAME); g_mkdir_with_parents(config_dir, 0700); /* Get Receiver MAC from GConf. Default is scanned via hci_inquiry. */ -_rcvr_mac = gconf_client_get_string(gconf_client, GCONF_KEY_RCVR_MAC, NULL); +_gps->io.address = gconf_client_get_string(gconf_client, GCONF_KEY_RCVR_MAC, NULL); /* Get Auto-Download. Default is FALSE. */ _auto_download = gconf_client_get_bool(gconf_client, GCONF_KEY_AUTO_DOWNLOAD, NULL); @@ -562,10 +561,10 @@ BOUND(_speed_limit, 1, 200); _auto_download = gconf_client_get_bool(gconf_client, GCONF_KEY_AUTO_DOWNLOAD, NULL); /* Get saved location */ -_gps->lat = gconf_client_get_float(gconf_client, GCONF_KEY_LAT, NULL); -_gps->lon = gconf_client_get_float(gconf_client, GCONF_KEY_LON, NULL); -if (_gps->lat==0.0) _gps->lat=64.20; -if (_gps->lon==0.0) _gps->lon=22.20; +_gps->data.lat = gconf_client_get_float(gconf_client, GCONF_KEY_LAT, NULL); +_gps->data.lon = gconf_client_get_float(gconf_client, GCONF_KEY_LON, NULL); +if (_gps->data.lat==0.0) _gps->data.lat=64.20; +if (_gps->data.lon==0.0) _gps->data.lon=22.20; /* Home */ _home.valid=TRUE; @@ -602,7 +601,7 @@ if (_home.valid==FALSE) { center_lat = gconf_value_get_float(value); gconf_value_free(value); } else { - center_lat = _gps->lat; + center_lat = _gps->data.lat; } /* Get last saved longitude. Default is last saved longitude. */ @@ -611,7 +610,7 @@ if (_home.valid==FALSE) { center_lon = gconf_value_get_float(value); gconf_value_free(value); } else { - center_lon = _gps->lon; + center_lon = _gps->data.lon; } latlon2unit(center_lat, center_lon, _center.unitx, _center.unity); @@ -700,7 +699,7 @@ if (value) { } /* Initialize _conn_state based on _enable_gps-> */ -_conn_state = (_enable_gps ? RCVR_DOWN : RCVR_OFF); +_gps->io.conn = (_enable_gps ? RCVR_DOWN : RCVR_OFF); /* Load the route locations. */ { diff --git a/src/filter-gui.c b/src/filter-gui.c index d04f16d..251d02d 100644 --- a/src/filter-gui.c +++ b/src/filter-gui.c @@ -38,7 +38,6 @@ #include "gps.h" #include "map.h" #include "mapper-types.h" -#include "bt.h" #include "ui-common.h" #include "settings.h" #include "filter.h" diff --git a/src/gps-bluetooth-bluez.c b/src/gps-bluetooth-bluez.c index 8617fcd..ff03391 100644 --- a/src/gps-bluetooth-bluez.c +++ b/src/gps-bluetooth-bluez.c @@ -21,7 +21,7 @@ #include #include -#include "bt.h" +#include "bluetooth-scan.h" #include "gps.h" #include "map.h" #include "utils.h" @@ -30,193 +30,13 @@ #include "ui-common.h" #include "gps-conn.h" -struct sockaddr_rc _rcvr_addr = { 0 }; - -static gint fd; - -static gboolean -channel_cb_connect(GIOChannel * src, GIOCondition condition, gpointer data) -{ -gint error, size = sizeof(error); - -if (*_rcvr_mac != '/' && (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &size) || error)) { - g_printf("Error connecting to receiver; retrying...\n"); - /* Try again. */ - rcvr_disconnect(); - rcvr_connect_later(); -} else { - g_printf("Connected to receiver!\n"); - gps_conn_set_state(RCVR_UP); - _input_sid = g_io_add_watch_full(_channel, G_PRIORITY_LOW, G_IO_IN | G_IO_PRI, channel_cb_input, NULL, NULL); -} - -_connect_sid = 0; -return FALSE; -} - -static gboolean -rcvr_connect_bt(void) -{ -int r, e; -r = connect(fd, (struct sockaddr *)&_rcvr_addr, sizeof(_rcvr_addr)); -e = errno; - -/* The socket is non blocking so handle it */ -if (r != 0) { - switch (e) { - case EAGAIN: - case EBUSY: - case EINPROGRESS: - case EALREADY: - g_printf("*** Connection in progress... %d %d\n", e, r); - perror("INFO: "); - return TRUE; - break; - case EHOSTUNREACH: - g_printf("*** Bluetooth/GPS device not found.\n"); - rcvr_disconnect(); -#if 0 - popup_error(_window, _("No bluetooth or GPS device found.")); - set_action_activate("gps_enable", FALSE); -#endif - return FALSE; - break; - default: - /* Connection failed. Disconnect and try again later. */ - g_printf("### Connect failed, retrying... %d %d\n", e, r); - perror("ERROR: "); - rcvr_disconnect(); - rcvr_connect_later(); - return FALSE; - break; - } -} -return TRUE; -} - gint scan_start_search(ScanInfo * scan_info) { -scan_info->sid = g_idle_add((GSourceFunc)scan_bluetooth_idle, scan_info); +scan_info->sid=g_idle_add((GSourceFunc)scan_bluetooth_idle, scan_info); return 0; } -/** - * Disconnect from the receiver. This method cleans up any and everything - * that might be associated with the receiver. - */ -void -rcvr_disconnect(void) -{ -/* Remove watches. */ -if (_clater_sid) { - g_source_remove(_clater_sid); - _clater_sid = 0; -} -if (_error_sid) { - g_source_remove(_error_sid); - _error_sid = 0; -} -if (_connect_sid) { - g_source_remove(_connect_sid); - _connect_sid = 0; -} -if (_input_sid) { - g_source_remove(_input_sid); - _input_sid = 0; -} - -/* Destroy the GIOChannel object. */ -if (_channel) { - g_io_channel_shutdown(_channel, FALSE, NULL); - g_io_channel_unref(_channel); - _channel = NULL; -} - -/* Close the file descriptor. */ -if (fd != -1) { - close(fd); - fd = -1; -} -} - -/** - * Connect to the receiver. - * This method assumes that fd is -1 and _channel is NULL. If unsure, call - * rcvr_disconnect() first. - * Since this is an idle function, this function returns whether or not it - * should be called again, which is always FALSE. - */ -gboolean -rcvr_connect_now() -{ -if (!_rcvr_mac) - return FALSE; - -_rcvr_addr.rc_family = AF_BLUETOOTH; -_rcvr_addr.rc_channel = 1; -str2ba(_rcvr_mac, &_rcvr_addr.rc_bdaddr); - -#if 0 -_rcvr_addr.rc_channel = gconf_client_get_int(gconf_client, GCONF_KEY_RCVR_CHAN, NULL); -if (_rcvr_addr.rc_channel < 1) - _rcvr_addr.rc_channel = 1; -#endif - -if (_conn_state == RCVR_DOWN && _rcvr_mac) { -#ifndef DEBUG_GPS - /* Create the file descriptor. */ - if (*_rcvr_mac == '/') - fd = open(_rcvr_mac, O_RDONLY); - else - fd = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); - - /* If file descriptor creation failed, try again later. Note that - * there is no need to call rcvr_disconnect() because the file - * descriptor creation is the first step, so if it fails, there's - * nothing to clean up. */ - if (fd == -1) { - g_printf("Failed to create socket\n"); - rcvr_connect_later(); - } else { - /* Reset GPS read buffer */ - _gps_read_buf_curr = _gps_read_buf; - *_gps_read_buf_curr = '\0'; - _gps_read_buf_last = _gps_read_buf + GPS_READ_BUF_SIZE - 1; - - /* Create channel and add watches. */ - _channel = g_io_channel_unix_new(fd); - g_io_channel_set_encoding(_channel, NULL, NULL); - g_io_channel_set_flags(_channel, G_IO_FLAG_NONBLOCK, NULL); - _error_sid = g_io_add_watch_full(_channel, G_PRIORITY_HIGH_IDLE, - G_IO_ERR | G_IO_HUP, channel_cb_error, NULL, NULL); - _connect_sid = g_io_add_watch_full(_channel, G_PRIORITY_HIGH_IDLE, - G_IO_OUT, channel_cb_connect, NULL, NULL); - if (*_rcvr_mac != '/') { - rcvr_connect_bt(); - } else { - g_printf("Using dev node: %s\n", _rcvr_mac); - } - } -#else - /* We're in DEBUG mode, so instead of connecting, skip to FIXED. */ - gps_conn_set_state(RCVR_FIXED); -#endif -} - -_clater_sid = 0; -return FALSE; -} - -/** - * Place a request to connect about 1 second after the function is called. - */ -void -rcvr_connect_later(void) -{ -_clater_sid = g_timeout_add(1000, (GSourceFunc) rcvr_connect_now, NULL); -} - gboolean scan_bluetooth_idle(ScanInfo * scan_info) { diff --git a/src/gps-bluetooth-hildon.c b/src/gps-bluetooth-hildon.c index 97050f9..e36d6bb 100644 --- a/src/gps-bluetooth-hildon.c +++ b/src/gps-bluetooth-hildon.c @@ -42,75 +42,6 @@ static guint errors; static gint fd; -void rcvr_connect_later(); /* Forward declaration. */ - -/*****************************************************************************/ - -static gboolean -channel_cb_connect(GIOChannel * src, GIOCondition condition, gpointer data) -{ -_gps_read_buf_curr = _gps_read_buf; -_gps_read_buf_last = _gps_read_buf + GPS_READ_BUF_SIZE - 1; -gps_conn_set_state(RCVR_UP); -_input_sid = g_io_add_watch_full(_channel, G_PRIORITY_HIGH_IDLE, G_IO_IN | G_IO_PRI, channel_cb_input, NULL, NULL); -_connect_sid = 0; -errors=0; -return FALSE; -} - -/** - * Disconnect from the receiver. This method cleans up any and everything - * that might be associated with the receiver. - */ -void -rcvr_disconnect() -{ -GError *error = NULL; - -/* Remove watches. */ -if (_clater_sid) { - g_source_remove(_clater_sid); - _clater_sid = 0; -} -if (_error_sid) { - g_source_remove(_error_sid); - _error_sid = 0; -} -if (_connect_sid) { - g_source_remove(_connect_sid); - _connect_sid = 0; -} -if (_input_sid) { - g_source_remove(_input_sid); - _input_sid = 0; -} - -/* Destroy the GIOChannel object. */ -if (_channel) { - g_io_channel_shutdown(_channel, FALSE, NULL); - g_io_channel_unref(_channel); - _channel = NULL; -} - -/* Close the file descriptor. */ -if (fd != -1) { - close(fd); - fd = -1; -} - -if (_rfcomm_req_proxy) { - dbus_g_proxy_call(_rfcomm_req_proxy, - BTCOND_RFCOMM_CANCEL_CONNECT_REQ, &error, - G_TYPE_STRING, _rcvr_mac, G_TYPE_STRING, - "SPP", G_TYPE_INVALID, G_TYPE_INVALID); - error = NULL; - dbus_g_proxy_call(_rfcomm_req_proxy, - BTCOND_RFCOMM_DISCONNECT_REQ, &error, - G_TYPE_STRING, _rcvr_mac, G_TYPE_STRING, - "SPP", G_TYPE_INVALID, G_TYPE_INVALID); -} -} - void rcvr_connect_fd(gchar *fdpath) { @@ -216,15 +147,6 @@ _clater_sid = 0; return FALSE; } -/** - * Place a request to connect about 1 second after the function is called. - */ -void -rcvr_connect_later() -{ -_clater_sid = g_timeout_add(1000, (GSourceFunc)rcvr_connect_now, NULL); -} - /** * Bluetooth device scanning functions below */ @@ -259,8 +181,7 @@ if (NULL == (scan_info->sig_proxy = dbus_g_proxy_new_for_name(dbus_conn, BTSEARC return 2; } -dbus_g_object_register_marshaller(_bt_maemo_VOID__STRING_STRING_POINTER_UCHAR_UINT, - G_TYPE_NONE, G_TYPE_STRING, G_TYPE_STRING, DBUS_TYPE_G_UCHAR_ARRAY, G_TYPE_UCHAR, G_TYPE_UINT, G_TYPE_INVALID); +dbus_g_object_register_marshaller(_bt_maemo_VOID__STRING_STRING_POINTER_UCHAR_UINT, G_TYPE_NONE, G_TYPE_STRING, G_TYPE_STRING, DBUS_TYPE_G_UCHAR_ARRAY, G_TYPE_UCHAR, G_TYPE_UINT, G_TYPE_INVALID); dbus_g_proxy_add_signal(scan_info->sig_proxy, BTSEARCH_DEV_FOUND_SIG, G_TYPE_STRING, G_TYPE_STRING, DBUS_TYPE_G_UCHAR_ARRAY, G_TYPE_UCHAR, G_TYPE_UINT, G_TYPE_INVALID); dbus_g_proxy_connect_signal(scan_info->sig_proxy, BTSEARCH_DEV_FOUND_SIG, G_CALLBACK(scan_cb_dev_found), scan_info, NULL); diff --git a/src/gps-browse.c b/src/gps-browse.c index e6f8178..57b8703 100644 --- a/src/gps-browse.c +++ b/src/gps-browse.c @@ -47,7 +47,7 @@ #include "utils.h" #include "mapper-types.h" -#include "bt.h" +#include "bluetooth-scan.h" /** * Scan for all bluetooth devices. This method can take a few seconds, diff --git a/src/gps-conn.c b/src/gps-conn.c index 5f0b874..6a37a1e 100644 --- a/src/gps-conn.c +++ b/src/gps-conn.c @@ -46,7 +46,6 @@ static GtkWidget *fix_banner = NULL; #include "settings.h" #include "gps.h" #include "map.h" -#include "bt.h" #include "ui-common.h" #include "gps-conn.h" @@ -54,9 +53,9 @@ static GtkWidget *fix_banner = NULL; * Set the connection state. This function controls all connection-related banners. */ void -gps_conn_set_state(ConnState new_conn_state) +gps_conn_set_state(Gps *gps, GpsConnState new_conn_state) { -switch (_conn_state = new_conn_state) { +switch (gps->io.conn=new_conn_state) { case RCVR_OFF: case RCVR_FIXED: if (connect_banner) { @@ -93,7 +92,7 @@ switch (_conn_state = new_conn_state) { } void -gps_conn_set_progress(gdouble fix) +gps_conn_set_progress(Gps *gps, gdouble fix) { #ifdef WITH_HILDON hildon_banner_set_fraction(fix_banner, fix); diff --git a/src/gps-conn.h b/src/gps-conn.h index 4067421..f4dc4d4 100644 --- a/src/gps-conn.h +++ b/src/gps-conn.h @@ -1,7 +1,7 @@ #ifndef _MAPPER_GPS_CONN_H #define _MAPPER_GPS_CONN_H -void gps_conn_set_state(ConnState new_conn_state); -void gps_conn_set_progress(gdouble fix); +void gps_conn_set_state(Gps *gps, GpsConnState new_conn_state); +void gps_conn_set_progress(Gps *gps, gdouble fix); #endif diff --git a/src/gps-nmea-parse.c b/src/gps-nmea-parse.c index 195014d..2971ee2 100644 --- a/src/gps-nmea-parse.c +++ b/src/gps-nmea-parse.c @@ -39,7 +39,6 @@ #include #include "utils.h" -#include "bt.h" #include "gps.h" #include "mapper-types.h" #include "ui-common.h" @@ -52,23 +51,8 @@ #include "gtkgps.h" #include "gtkcompass.h" -gboolean -channel_cb_error(GIOChannel *src, GIOCondition condition, gpointer data) -{ -/* An error has occurred - re-connect(). */ -rcvr_disconnect(); -track_add(NULL, FALSE); -_speed_excess = FALSE; - -if (_conn_state > RCVR_OFF) { - gps_conn_set_state(RCVR_DOWN); - rcvr_connect_later(); -} -return FALSE; -} - static void -channel_parse_rmc(gchar * sentence) +gps_nmea_parse_rmc(Gps *gps, gchar * sentence) { /* Recommended Minimum Navigation Information C * 1) UTC Time @@ -102,14 +86,14 @@ channel_parse_rmc(gchar * sentence) /* Token is now Status. */ if (token && *token == 'A') { /* Data is valid. */ - if (_conn_state != RCVR_FIXED) { + if (gps->io.conn != RCVR_FIXED) { newly_fixed = TRUE; - gps_conn_set_state(RCVR_FIXED); + gps_conn_set_state(gps, RCVR_FIXED); } } else { /* Data is invalid - not enough satellites?. */ - if (_conn_state != RCVR_UP) { - gps_conn_set_state(RCVR_UP); + if (gps->io.conn != RCVR_UP) { + gps_conn_set_state(gps, RCVR_UP); track_add(NULL, FALSE); } } @@ -123,13 +107,13 @@ channel_parse_rmc(gchar * sentence) MACRO_PARSE_FLOAT(tmpd, dpoint - 2); dpoint[-2] = '\0'; MACRO_PARSE_INT(tmpi, token); - _gps->lat = tmpi + (tmpd * (1.0 / 60.0)); + gps->data.lat = tmpi + (tmpd * (1.0 / 60.0)); } /* Parse N or S. */ token = strsep(&sentence, DELIM); if (token && *token == 'S') - _gps->lat = -_gps->lat; + gps->data.lat = -gps->data.lat; /* Parse the longitude. */ token = strsep(&sentence, DELIM); @@ -140,27 +124,27 @@ channel_parse_rmc(gchar * sentence) MACRO_PARSE_FLOAT(tmpd, dpoint - 2); dpoint[-2] = '\0'; MACRO_PARSE_INT(tmpi, token); - _gps->lon = tmpi + (tmpd * (1.0 / 60.0)); + gps->data.lon = tmpi + (tmpd * (1.0 / 60.0)); } /* Parse E or W. */ token = strsep(&sentence, DELIM); if (token && *token == 'W') - _gps->lon = -_gps->lon; + gps->data.lon = -gps->data.lon; /* Parse speed over ground, knots. */ token = strsep(&sentence, DELIM); if (token && *token) { - MACRO_PARSE_FLOAT(_gps->speed, token); - if (_gps->fix > FIX_NOFIX) { - _gps->maxspeed=MAX(_gps->maxspeed, _gps->speed); + MACRO_PARSE_FLOAT(gps->data.speed, token); + if (gps->data.fix > FIX_NOFIX) { + gps->data.maxspeed=MAX(gps->data.maxspeed, gps->data.speed); } } /* Parse heading, degrees from true north. */ token = strsep(&sentence, DELIM); if (token && *token) { - MACRO_PARSE_FLOAT(_gps->heading, token); + MACRO_PARSE_FLOAT(gps->data.heading, token); } /* Parse date. */ @@ -170,25 +154,25 @@ channel_parse_rmc(gchar * sentence) gpsdate[6] = '\0'; /* Make sure time is 6 chars long. */ strcat(gpsdate, token); strptime(gpsdate, "%H%M%S%d%m%y", &time); - _gps->time = mktime(&time) + _gmtoffset; + gps->data.time = mktime(&time) + _gmtoffset; } else - _gps->time = time(NULL); + gps->data.time = time(NULL); /* Add new data to track only if we have a fix */ _track_store=TRUE; - gps_integerize_data(_gps); - gps_display_data_speed(info_banner.speed, _gps->speed); + gps_data_integerize(&gps->data); + gps_display_data_speed(info_banner.speed, gps->data.speed); - if ((_conn_state==RCVR_FIXED) && (_track_store==TRUE) && filter_check(&filter, _gps, &map_loc)==TRUE) { + if ((gps->io.conn==RCVR_FIXED) && (_track_store==TRUE) && filter_check(&filter, &gps->data, &map_loc)==TRUE) { track_add(_gps, newly_fixed); - _gps->lheading=_gps->heading; + gps->data.lheading=gps->data.heading; map_refresh_mark(); } } static void -channel_parse_gga(gchar * sentence) +gps_nmea_parse_gga(Gps *gps, gchar * sentence) { /* GGA Global Positioning System Fix Data 1. Fix Time @@ -235,7 +219,7 @@ channel_parse_gga(gchar * sentence) /* Parse Fix quality */ token = strsep(&sentence, DELIM); if (token && *token) - MACRO_PARSE_INT(_gps->fixquality, token); + MACRO_PARSE_INT(gps->data.fixquality, token); /* Skip number of satellites */ token = strsep(&sentence, DELIM); @@ -243,18 +227,18 @@ channel_parse_gga(gchar * sentence) /* Parse Horizontal dilution of position */ token = strsep(&sentence, DELIM); if (token && *token) - MACRO_PARSE_INT(_gps->hdop, token); + MACRO_PARSE_INT(gps->data.hdop, token); /* Altitude */ token = strsep(&sentence, DELIM); if (token && *token) { - MACRO_PARSE_FLOAT(_gps->altitude, token); + MACRO_PARSE_FLOAT(gps->data.altitude, token); } else - _gps->altitude = NAN; + gps->data.altitude = NAN; } static void -channel_parse_gsa(gchar * sentence) +gps_nmea_parse_gsa(Gps *gps, gchar * sentence) { /* GPS DOP and active satellites * 1) Auto selection of 2D or 3D fix (M = manual) @@ -270,7 +254,7 @@ channel_parse_gsa(gchar * sentence) guint i,si; gint satforfix[12]; - vprintf("%s(): %s\n", __PRETTY_FUNCTION__, sentence); + g_debug("%s(): %s\n", __PRETTY_FUNCTION__, sentence); #define DELIM "," @@ -280,9 +264,9 @@ channel_parse_gsa(gchar * sentence) /* 3D fix. */ token = strsep(&sentence, DELIM); if (token && *token) - MACRO_PARSE_INT(_gps->fix, token); + MACRO_PARSE_INT(gps->data.fix, token); - _gps->satinuse = 0; + gps->data.satinuse = 0; for (i = 0; i < 12; i++) { gint fprn; token = strsep(&sentence, DELIM); @@ -291,33 +275,33 @@ channel_parse_gsa(gchar * sentence) else fprn=-1; satforfix[i]=fprn; - _gps->sat[i].fix=FALSE; + gps->data.sat[i].fix=FALSE; } for (i=0;i<12;i++) for (si=0;si<12;si++) { - if (_gps->sat[i].prn==satforfix[si]) - _gps->sat[i].fix=TRUE; + if (gps->data.sat[i].prn==satforfix[si]) + gps->data.sat[i].fix=TRUE; } /* PDOP */ token = strsep(&sentence, DELIM); if (token && *token) - MACRO_PARSE_FLOAT(_gps->pdop, token); + MACRO_PARSE_FLOAT(gps->data.pdop, token); /* HDOP */ token = strsep(&sentence, DELIM); if (token && *token) - MACRO_PARSE_FLOAT(_gps->hdop, token); + MACRO_PARSE_FLOAT(gps->data.hdop, token); /* VDOP */ token = strsep(&sentence, DELIM); if (token && *token) - MACRO_PARSE_FLOAT(_gps->vdop, token); + MACRO_PARSE_FLOAT(gps->data.vdop, token); } static void -channel_parse_gsv(gchar * sentence) +gps_nmea_parse_gsv(Gps *gps, gchar * sentence) { /* Must be GSV - Satellites in view * 1) total number of messages @@ -350,9 +334,9 @@ channel_parse_gsv(gchar * sentence) /* Parse number of satellites in view. */ token = strsep(&sentence, DELIM); if (token && *token) { - MACRO_PARSE_INT(_gps->satinview, token); - if (_gps->satinview > 12) /* Handle buggy NMEA. */ - _gps->satinview = 12; + MACRO_PARSE_INT(gps->data.satinview, token); + if (gps->data.satinview > 12) /* Handle buggy NMEA. */ + gps->data.satinview = 12; } /* Loop until there are no more satellites to parse. */ @@ -360,23 +344,23 @@ channel_parse_gsv(gchar * sentence) /* Get token for Satellite Number. */ token = strsep(&sentence, DELIM); if (token && *token) - _gps->sat[satcnt].prn = atoi(token); + gps->data.sat[satcnt].prn = atoi(token); /* Get token for elevation in degrees (0-90). */ token = strsep(&sentence, DELIM); if (token && *token) - _gps->sat[satcnt].elevation = atoi(token); + gps->data.sat[satcnt].elevation = atoi(token); /* Get token for azimuth in degrees to true north (0-359). */ token = strsep(&sentence, DELIM); if (token && *token) - _gps->sat[satcnt].azimuth = atoi(token); + gps->data.sat[satcnt].azimuth = atoi(token); /* Get token for SNR. */ token = strsep(&sentence, DELIM); - if (token && *token && (_gps->sat[satcnt].snr = atoi(token))) { + if (token && *token && (gps->data.sat[satcnt].snr = atoi(token))) { /* SNR is non-zero - add to total and count as used. */ - running_total += _gps->sat[satcnt].snr; + running_total += gps->data.sat[satcnt].snr; num_sats_used++; } satcnt++; @@ -385,13 +369,13 @@ channel_parse_gsv(gchar * sentence) if (msgcnt == nummsgs) { /* This is the last message. Calculate signal strength. */ if (num_sats_used) { - if (_conn_state == RCVR_UP) { + if (gps->io.conn==RCVR_UP) { gdouble fraction = running_total * sqrt(num_sats_used) / num_sats_used / 100.0; BOUND(fraction, 0.0, 1.0); - gps_conn_set_progress(fraction); + gps_conn_set_progress(gps, fraction); } - running_total = 0; - num_sats_used = 0; + running_total=0; + num_sats_used=0; } satcnt = 0; @@ -400,100 +384,28 @@ channel_parse_gsv(gchar * sentence) } } -static gboolean -channel_parse_buffer(gpointer data) +gboolean +gps_nmea_parse(gchar *data) { -gchar *buf=(gchar *)data; - -if (!strncmp(buf + 3, "GSV", 3)) { - if (_conn_state == RCVR_UP) - channel_parse_gsv(buf + 7); -} else if (!strncmp(buf + 3, "RMC", 3)) - channel_parse_rmc(buf + 7); -else if (!strncmp(buf + 3, "GGA", 3)) - channel_parse_gga(buf + 7); -else if (!strncmp(buf + 3, "GSA", 3)) - channel_parse_gsa(buf + 7); -else g_print("Unknown NMEA: [%s]\n", buf); - -g_free(buf); +Gps *gps=_gps; + +if (!strncmp(data + 3, "GSV", 3)) { + if (gps->io.conn==RCVR_UP) + gps_nmea_parse_gsv(gps, data + 7); +} else if (!strncmp(data + 3, "RMC", 3)) + gps_nmea_parse_rmc(gps, data + 7); +else if (!strncmp(data + 3, "GGA", 3)) + gps_nmea_parse_gga(gps, data + 7); +else if (!strncmp(data + 3, "GSA", 3)) + gps_nmea_parse_gsa(gps, data + 7); +else g_debug("Unknown NMEA: [%s]\n", data); +g_free(data); if (_gps_info) - gps_display_data(_gps); + gps_display_data(&gps->data); if (_satdetails_on) - gps_display_details(_gps); + gps_display_details(&gps->data); return FALSE; } - -gboolean -channel_cb_input(GIOChannel *src, GIOCondition condition, gpointer data) -{ -gsize bytes_read; -GIOStatus status; -gchar *eol; - -vprintf("%s(%d)\n", __PRETTY_FUNCTION__, condition); - -status=g_io_channel_read_chars(_channel, _gps_read_buf_curr, _gps_read_buf_last - _gps_read_buf_curr, &bytes_read, NULL); - -switch (status) { - case G_IO_STATUS_NORMAL: - _gps_read_buf_curr += bytes_read; - *_gps_read_buf_curr = '\0'; /* append a \0 so we can read as string */ - while ((eol = strchr(_gps_read_buf, '\n'))) { - gchar *sptr = _gps_read_buf + 1; /* Skip the $ */ - guint csum = 0; - if (*_gps_read_buf == '$') { - /* This is the beginning of a sentence; okay to parse. */ - *eol = '\0'; /* overwrite \n with \0 */ - while (*sptr && *sptr != '*') - csum ^= *sptr++; - - /* If we're at a \0 (meaning there is no checksum), or if the - * checksum is good, then parse the sentence. */ - if (!*sptr || csum == strtol(sptr + 1, NULL, 16)) { - gchar *data; - - if (*sptr) - *sptr = '\0'; /* take checksum out of the buffer. */ - - data=g_strdup(_gps_read_buf); - g_idle_add_full(G_PRIORITY_HIGH_IDLE, (GSourceFunc)channel_parse_buffer, data, NULL); - } else { - /* There was a checksum, and it was bad. */ - g_printerr("%s: Bad checksum in NMEA sentence:\n%s\n", __PRETTY_FUNCTION__, _gps_read_buf); - } - } - - /* If eol is at or after (_gps_read_buf_curr - 1) */ - if (eol >= (_gps_read_buf_curr - 1)) { - /* Last read was a newline - reset read buffer */ - _gps_read_buf_curr = _gps_read_buf; - *_gps_read_buf_curr = '\0'; - } else { - /* Move the next line to the front of the buffer. */ - memmove(_gps_read_buf, eol + 1, _gps_read_buf_curr - eol); /* include terminating 0 */ - /* Subtract _curr so that it's pointing at the new \0. */ - _gps_read_buf_curr -= (eol - _gps_read_buf + 1); - } - } - break; - case G_IO_STATUS_ERROR: - case G_IO_STATUS_EOF: - rcvr_disconnect(); - rcvr_connect_later(); - return FALSE; - break; - case G_IO_STATUS_AGAIN: - return TRUE; - break; - default: - g_assert_not_reached(); - break; -} - -vprintf("%s(): return TRUE\n", __PRETTY_FUNCTION__); -return TRUE; -} diff --git a/src/gps.c b/src/gps.c index 4c9e63d..098b17b 100644 --- a/src/gps.c +++ b/src/gps.c @@ -23,31 +23,408 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + #include "gps.h" #include "latlon.h" #include "map.h" +#include "gps-nmea-parse.h" +#include "track.h" + +static gboolean gps_channel_cb_error(GIOChannel *src, GIOCondition condition, gpointer data); +static gboolean gps_channel_cb_input(GIOChannel *src, GIOCondition condition, gpointer data); +static gboolean gps_channel_cb_connect(GIOChannel * src, GIOCondition condition, gpointer data); +static gboolean gps_connect_socket(Gps *gps); -GpsData * -gps_init(void) +/** + * Init GPS structure + */ +Gps * +gps_new(void) { -GpsData *gps; +Gps *gps; -gps=g_slice_new0(GpsData); -gps->fix=FIX_NOFIX; -gps_integerize_data(gps); +gps=g_slice_new0(Gps); +gps->data.fix=FIX_NOFIX; +gps->io.fd=-1; +gps->io.conn=RCVR_OFF; +gps_data_integerize(&gps->data); return gps; } /** * Convert the float lat/lon/speed/heading data into integer units. + * Also calculate offsets. */ void -gps_integerize_data(GpsData *gps) +gps_data_integerize(GpsData *gpsdata) { gdouble tmp; -tmp=(gps->heading*(1.f/180.f))*G_PI; -latlon2unit(gps->lat, gps->lon, gps->unitx, gps->unity); -gps->vel_offsetx=(gint)(floor(gps->speed*sin(tmp)+0.5f)); -gps->vel_offsety=-(gint)(floor(gps->speed*cos(tmp)+0.5f)); +tmp=(gpsdata->heading*(1.f/180.f))*G_PI; +latlon2unit(gpsdata->lat, gpsdata->lon, gpsdata->unitx, gpsdata->unity); +gpsdata->vel_offsetx=(gint)(floor(gpsdata->speed*sin(tmp)+0.5f)); +gpsdata->vel_offsety=-(gint)(floor(gpsdata->speed*cos(tmp)+0.5f)); +} + +/** + * Place a request to connect about 1 second after the function is called. + */ +void +gps_connect_later(Gps *gps) +{ +g_assert(gps); +g_assert(gps->io.clater_sid!=0); +gps->io.clater_sid=g_timeout_add(1000, (GSourceFunc)gps_connect_now, gps); +} + +gboolean +gps_connect(Gps *gps) +{ +switch (gps->io.type) { + case GPS_IO_FILE: + return TRUE; + break; + case GPS_IO_RFCOMM: + case GPS_IO_TCP: + case GPS_IO_GPSD: + gps_connect_socket(gps); + break; + case GPS_IO_GYPSY: + return FALSE; + break; + default: + break; +} +return FALSE; +} + +static gboolean +gps_connect_socket(Gps *gps) +{ +gint r, e; +switch (gps->io.type) { +#ifdef WITH_BLUEZ + case GPS_IO_RFCOMM: + r=connect(gps->io.fd, (struct sockaddr *)&gps->io.rcvr_addr_rc, sizeof(gps->io.rcvr_addr_rc)); + break; +#endif + case GPS_IO_TCP: + case GPS_IO_GPSD: + r=connect(gps->io.fd, (struct sockaddr *)&gps->io.rcvr_addr_in, sizeof(gps->io.rcvr_addr_in)); + break; + default: + return FALSE; +} +e=errno; + +/* The socket is non blocking so handle it */ +if (r != 0) { + switch (e) { + case EAGAIN: + case EBUSY: + case EINPROGRESS: + case EALREADY: + g_printf("*** Connection in progress... %d %d\n", e, r); + perror("INFO: "); + return TRUE; + break; + case EHOSTUNREACH: + g_printf("*** Bluetooth/GPS device not found.\n"); + gps_disconnect(gps); +#if 0 + set_action_activate("gps_enable", FALSE); + popup_error(_window, _("No bluetooth or GPS device found.")); +#endif + return FALSE; + break; + default: + /* Connection failed. Disconnect and try again later. */ + g_printf("### Connect failed, retrying... %d %d\n", e, r); + perror("ERROR: "); + gps_disconnect(gps); + gps_connect_later(gps); + return FALSE; + break; + } } +return TRUE; +} + +void +gps_disconnect(Gps *gps) +{ +g_assert(gps); + +/* Remove watches. */ +if (gps->io.clater_sid) { + g_source_remove(gps->io.clater_sid); + gps->io.clater_sid=0; +} +if (gps->io.error_sid) { + g_source_remove(gps->io.error_sid); + gps->io.error_sid=0; +} +if (gps->io.connect_sid) { + g_source_remove(gps->io.connect_sid); + gps->io.connect_sid=0; +} +if (gps->io.input_sid) { + g_source_remove(gps->io.input_sid); + gps->io.input_sid=0; +} + +/* Destroy the GIOChannel object. */ +if (gps->io.channel) { + g_io_channel_shutdown(gps->io.channel, FALSE, NULL); + g_io_channel_unref(gps->io.channel); + gps->io.channel=NULL; +} + +/* Close the file descriptor. */ +if (gps->io.fd!=-1) { + close(gps->io.fd); + gps->io.fd=-1; +} + +#ifdef WITH_HILDON_DBUS_BT +if (gps->io.type==GPS_IO_HILDON_DBUS && gps->io.rfcomm_req_proxy) { + GError *error = NULL; + + dbus_g_proxy_call(gps->io.rfcomm_req_proxy, BTCOND_RFCOMM_CANCEL_CONNECT_REQ, &error, G_TYPE_STRING, gps->io.address, G_TYPE_STRING, "SPP", G_TYPE_INVALID, G_TYPE_INVALID); + error = NULL; + dbus_g_proxy_call(gps->io.rfcomm_req_proxy, BTCOND_RFCOMM_DISCONNECT_REQ, &error,G_TYPE_STRING, gps->io.address, G_TYPE_STRING, "SPP", G_TYPE_INVALID, G_TYPE_INVALID); + } +} +#endif + +} + +/** + * Connect to the receiver. + * This method assumes that fd is -1 and _channel is NULL. If unsure, call + * gps_disconnect() first. + * Since this is an idle function, this function returns whether or not it + * should be called again, which is always FALSE. + */ +gboolean +gps_connect_now(Gps *gps) +{ +gint fd; + +g_assert(gps); + +switch (gps->io.type) { + case GPS_IO_FILE: + if (*gps->io.address=='/') + gps->io.fd=open(gps->io.address, O_RDONLY); + else + return FALSE; + break; + case GPS_IO_TCP: + case GPS_IO_GPSD: + if (gps->io.conn==RCVR_DOWN && gps->io.address) { + fd=socket(AF_INET, SOCK_STREAM, 0); + if (fd==-1) { + g_debug("Failed to create socket\n"); + gps_connect_later(gps); + return FALSE; + } + memcpy(&gps->io.rcvr_addr_in.sin_addr.s_addr, gps->io.address, strlen(gps->io.address)); + gps->io.rcvr_addr_in.sin_family = AF_INET; + gps->io.rcvr_addr_in.sin_port = htons(gps->io.port); + gps->io.fd=fd; + } else { + return FALSE; + } + break; + case GPS_IO_RFCOMM: +#ifdef WITH_BLUEZ + if (!gps->io.address) + return FALSE; + + if (gps->io.conn==RCVR_DOWN && gps->io.address) { + fd=socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); + + /* If file descriptor creation failed, try again later. Note that + * there is no need to call rcvr_disconnect() because the file + * descriptor creation is the first step, so if it fails, there's + * nothing to clean up. */ + if (fd==-1) { + g_debug("Failed to create socket\n"); + gps_connect_later(gps); + return FALSE; + } + gps->io.fd=fd; + gps->io.rcvr_addr_rc.rc_family=AF_BLUETOOTH; + gps->io.rcvr_addr_rc.rc_channel=1; + str2ba(gps->io.address, &gps->io.rcvr_addr_rc.rc_bdaddr); + } +#endif + return FALSE; + break; + default: + return FALSE; + break; +} + +/* Reset GPS read buffer */ +gps->io.curr=gps->io.buffer; +*gps->io.curr = '\0'; +gps->io.last=gps->io.buffer+GPS_READ_BUF_SIZE-1; + +/* Create channel and add watches. */ +gps->io.channel=g_io_channel_unix_new(gps->io.fd); +g_io_channel_set_encoding(gps->io.channel, NULL, NULL); +g_io_channel_set_flags(gps->io.channel, G_IO_FLAG_NONBLOCK, NULL); +gps->io.error_sid=g_io_add_watch_full(gps->io.channel, G_PRIORITY_HIGH_IDLE, G_IO_ERR | G_IO_HUP, gps_channel_cb_error, NULL, NULL); +gps->io.connect_sid=g_io_add_watch_full(gps->io.channel, G_PRIORITY_HIGH_IDLE, G_IO_OUT, gps_channel_cb_connect, NULL, NULL); +gps->io.clater_sid=0; +gps_connect(gps); +return FALSE; +} + +/** + * Connection callback + */ +static gboolean +gps_channel_cb_connect(GIOChannel * src, GIOCondition condition, gpointer data) +{ +gint error, size = sizeof(error); +Gps *gps=(Gps *)data; + +g_assert(data); + +gps->io.curr=gps->io.buffer; +gps->io.last=gps->io.buffer+GPS_READ_BUF_SIZE-1; + +switch (gps->io.type) { + case GPS_IO_TCP: + case GPS_IO_RFCOMM: + case GPS_IO_GPSD: + if ((getsockopt(gps->io.fd, SOL_SOCKET, SO_ERROR, &error, &size) || error)) { + g_printf("Error connecting to receiver; retrying...\n"); + gps_disconnect(gps); + gps_connect_later(gps); + gps->io.connect_sid=0; + return FALSE; + } + break; + case GPS_IO_FILE: + + break; + default: + return FALSE; + break; +} + +g_printf("Connected to receiver!\n"); +gps_conn_set_state(gps, RCVR_UP); +gps->io.input_sid=g_io_add_watch_full(gps->io.channel, G_PRIORITY_HIGH_IDLE, G_IO_IN | G_IO_PRI, gps_channel_cb_input, gps, NULL); +gps->io.errors=0; +gps->io.connect_sid=0; +return FALSE; +} + +static gboolean +gps_channel_cb_error(GIOChannel *src, GIOCondition condition, gpointer data) +{ +Gps *gps=(Gps *)data; + +g_assert(data); +/* An error has occurred - re-connect(). */ +gps_disconnect(gps); +track_add(NULL, FALSE); +/* _speed_excess = FALSE; */ + +if (gps->io.conn > RCVR_OFF) { + gps_conn_set_state(gps, RCVR_DOWN); + gps_connect_later(gps); +} +return FALSE; +} + +static gboolean +gps_channel_cb_input(GIOChannel *src, GIOCondition condition, gpointer data) +{ +gsize bytes_read; +GIOStatus status; +gchar *eol; +Gps *gps=(Gps *)data; + +g_debug("%s(%d)\n", __PRETTY_FUNCTION__, condition); +g_assert(data); + +status=g_io_channel_read_chars(gps->io.channel, gps->io.curr, gps->io.last-gps->io.curr, &bytes_read, NULL); +switch (status) { + case G_IO_STATUS_NORMAL: + gps->io.curr += bytes_read; + *gps->io.curr = '\0'; /* append a \0 so we can read as string */ + while ((eol = strchr(gps->io.buffer, '\n'))) { + gchar *sptr = gps->io.buffer + 1; /* Skip the $ */ + guint csum = 0; + if (*gps->io.buffer=='$') { + /* This is the beginning of a sentence; okay to parse. */ + *eol = '\0'; /* overwrite \n with \0 */ + while (*sptr && *sptr != '*') + csum ^= *sptr++; + + /* If we're at a \0 (meaning there is no checksum), or if the + * checksum is good, then parse the sentence. */ + if (!*sptr || csum == strtol(sptr + 1, NULL, 16)) { + gchar *data; + + if (*sptr) + *sptr = '\0'; /* take checksum out of the buffer. */ + + data=g_strdup(gps->io.buffer); + g_idle_add_full(G_PRIORITY_HIGH_IDLE, (GSourceFunc)gps_nmea_parse, data, NULL); + } else { + /* There was a checksum, and it was bad. */ + g_printerr("%s: Bad checksum in NMEA sentence:\n%s\n", __PRETTY_FUNCTION__, gps->io.buffer); + } + } + + /* If eol is at or after (_gps_read_buf_curr - 1) */ + if (eol >= (gps->io.curr - 1)) { + /* Last read was a newline - reset read buffer */ + gps->io.curr = gps->io.buffer; + *gps->io.curr = '\0'; + } else { + /* Move the next line to the front of the buffer. */ + memmove(gps->io.buffer, eol + 1, gps->io.curr - eol); /* include terminating 0 */ + /* Subtract _curr so that it's pointing at the new \0. */ + gps->io.curr -= (eol - gps->io.buffer + 1); + } + } + break; + case G_IO_STATUS_ERROR: + case G_IO_STATUS_EOF: + gps_disconnect(gps); + gps_connect_later(gps); + return FALSE; + break; + case G_IO_STATUS_AGAIN: + return TRUE; + break; + default: + g_assert_not_reached(); + break; +} + +return TRUE; +} + diff --git a/src/gps.h b/src/gps.h index ddcaf76..db0592a 100644 --- a/src/gps.h +++ b/src/gps.h @@ -15,65 +15,96 @@ #include #include #include +#include +#include +#include +#include + +#ifdef WITH_BLUEZ +#include +#include +#include +#include +#endif #include "path.h" #include "utils.h" #include "mapper-types.h" #include "gpsdata.h" -#define GPS_READ_BUF_SIZE 1024 +#define GPS_READ_BUF_SIZE (1024) /** * Types of GPS data sources */ typedef enum { - GPS_IO_DIRECT=1, - GPS_IO_FILE, - GPS_IO_TCP, - GPS_IO_GPSD, - GPS_IO_GYPSY + GPS_IO_RFCOMM=1, /* Bluetooth rfcomm socket */ + GPS_IO_HILDON_DBUS, /* Request rfcomm using hildon bluetooth D-Bus */ + GPS_IO_BLUEZ_DBUS, /* Request rfcomm using bluez bluetooth D-Bus*/ + GPS_IO_FILE, /* File or (serial) device node */ + GPS_IO_TCP, /* TCP */ + GPS_IO_GPSD, /* TCP connection to gpsd (as TCP, but will send a request for NMEA mode */ + GPS_IO_GYPSY, /* Gypsy events */ + GPS_IO_SIMULATION /* Random movement */ } GpsIOSourceType; +/** This enumerated type defines the possible connection states. */ +typedef enum { + RCVR_OFF, + RCVR_DOWN, + RCVR_UP, + RCVR_FIXED +} GpsConnState; + /** - * GPS IO variables + * GPS IO struct * */ typedef struct _GpsIO GpsIO; struct _GpsIO { gint fd; + gchar *address; /* BT MAC, File path or IP */ + guint port; + GpsIOSourceType type; + GpsConnState conn; GIOChannel *channel; DBusGProxy *rfcomm_req_proxy; - GpsIOSourceType src_type; +#ifdef WITH_BLUEZ + struct sockaddr_rc rcvr_addr_rc; +#endif + struct sockaddr_in rcvr_addr_in; guint connect_sid; guint error_sid; guint input_sid; guint clater_sid; - gchar buf[GPS_READ_BUF_SIZE]; + guint errors; + gchar buffer[GPS_READ_BUF_SIZE]; gchar *curr; gchar *last; + gchar *nmea; }; -GpsIO gpsio; -GpsData *_gps; +/** + * Gps + */ +typedef struct _Gps Gps; +struct _Gps { + gchar *name; /* Name of the connection */ + GpsIO io; + GpsData data; +}; -gchar _gps_read_buf[GPS_READ_BUF_SIZE]; -gchar *_gps_read_buf_curr; -gchar *_gps_read_buf_last; +Gps *_gps; +gint _gmtoffset; DBusGProxy *_rfcomm_req_proxy; -GIOChannel *_channel; -guint _connect_sid; -guint _error_sid; -guint _input_sid; -guint _clater_sid; - -gint _gmtoffset; - -GpsData *gps_init(void); -void gps_integerize_data(GpsData *gps); +Gps *gps_new(void); +void gps_data_integerize(GpsData *gpsdata); -gboolean channel_cb_error(GIOChannel * src, GIOCondition condition, gpointer data); -gboolean channel_cb_input(GIOChannel * src, GIOCondition condition, gpointer data); +gboolean gps_connect(Gps *gps); +gboolean gps_connect_now(Gps *gps); +void gps_connect_later(Gps *gps); +void gps_disconnect(Gps *gps); #endif diff --git a/src/maemo-osso.c b/src/maemo-osso.c index 203cd88..97d16b0 100644 --- a/src/maemo-osso.c +++ b/src/maemo-osso.c @@ -44,7 +44,6 @@ #include "map-download.h" #include "route.h" #include "mapper-types.h" -#include "bt.h" #include "gps.h" #include "settings-gconf.h" #include "settings.h" @@ -70,11 +69,11 @@ if (state->system_inactivity_ind) { if (_must_save_data) _must_save_data = FALSE; else { - if (_conn_state > RCVR_OFF) { + if (_gps->io.conn > RCVR_OFF) { if (gconf_client_get_bool(gconf_client, GCONF_KEY_DISCONNECT_ON_COVER, NULL)) { gconf_client_clear_cache(gconf_client); - gps_conn_set_state(RCVR_OFF); - rcvr_disconnect(); + gps_conn_set_state(_gps, RCVR_OFF); + gps_disconnect(_gps); track_add(0, FALSE); /* Pretend autoroute is in progress to avoid download. */ if (_autoroute_data.enabled) @@ -92,9 +91,9 @@ if (state->system_inactivity_ind) { } else if (state->memory_low_ind) { poi_icon_hash_clear(); } else { - if (_conn_state == RCVR_OFF && _enable_gps) { - gps_conn_set_state(RCVR_DOWN); - rcvr_connect_later(); + if (_gps->io.conn == RCVR_OFF && _enable_gps) { + gps_conn_set_state(gps, RCVR_DOWN); + gps_connect_later(gps); if (_autoroute_data.enabled) _autoroute_data.in_progress = TRUE; } diff --git a/src/map-download.c b/src/map-download.c index f1cac2b..0b272d6 100644 --- a/src/map-download.c +++ b/src/map-download.c @@ -50,7 +50,6 @@ #include "poi.h" #include "route.h" #include "gps.h" -#include "bt.h" #include "mapper-types.h" #include "ui-common.h" #include "settings.h" diff --git a/src/map-repo.c b/src/map-repo.c index 9ba59e6..0a22759 100644 --- a/src/map-repo.c +++ b/src/map-repo.c @@ -1171,9 +1171,9 @@ gboolean menu_cb_mapman(GtkAction * action) /* Initialize fields. Do no use g_ascii_formatd; these strings will be * output (and parsed) as locale-dependent. */ - g_snprintf(buffer, sizeof(buffer), "%.06f", _gps->lat); + g_snprintf(buffer, sizeof(buffer), "%.06f", _gps->data.lat); gtk_label_set_text(GTK_LABEL(lbl_gps_lat), buffer); - g_snprintf(buffer, sizeof(buffer), "%.06f", _gps->lon); + g_snprintf(buffer, sizeof(buffer), "%.06f", _gps->data.lon); gtk_label_set_text(GTK_LABEL(lbl_gps_lon), buffer); unit2latlon(_center.unitx, _center.unity, lat, lon); diff --git a/src/map.c b/src/map.c index e1223c6..0a37589 100644 --- a/src/map.c +++ b/src/map.c @@ -50,7 +50,6 @@ #include "route.h" #include "track.h" #include "gps.h" -#include "bt.h" #include "mapper-types.h" #include "ui-common.h" #include "settings.h" @@ -218,11 +217,11 @@ return TRUE; * _map_widget. This method does not queue the draw area. */ static void -map_draw_mark(void) +map_draw_mark(Gps *gps) { -gdk_draw_arc(_map_widget->window, _conn_state == RCVR_FIXED ? _gc[COLORABLE_MARK] : _gc[COLORABLE_MARK_OLD], FALSE, +gdk_draw_arc(_map_widget->window, gps->io.conn == RCVR_FIXED ? _gc[COLORABLE_MARK] : _gc[COLORABLE_MARK_OLD], FALSE, mark_x1 - _draw_width, mark_y1 - _draw_width, 2 * _draw_width, 2 * _draw_width, 0, 360 * 64); -gdk_draw_line(_map_widget->window, _conn_state == RCVR_FIXED ? (_show_velvec ? _gc[COLORABLE_MARK_VELOCITY] : _gc[COLORABLE_MARK]) : _gc[COLORABLE_MARK_OLD], +gdk_draw_line(_map_widget->window, gps->io.conn == RCVR_FIXED ? (_show_velvec ? _gc[COLORABLE_MARK_VELOCITY] : _gc[COLORABLE_MARK]) : _gc[COLORABLE_MARK_OLD], mark_x1, mark_y1, mark_x2, mark_y2); } @@ -231,12 +230,12 @@ gdk_draw_line(_map_widget->window, _conn_state == RCVR_FIXED ? (_show_velvec ? _ * units in preparation for drawing the mark with map_draw_mark(). */ void -map_set_mark(void) +map_set_mark(GpsData *gps) { -mark_x1 = unit2x(_gps->unitx); -mark_y1 = unit2y(_gps->unity); -mark_x2 = mark_x1 + (_show_velvec ? _gps->vel_offsetx : 0); -mark_y2 = mark_y1 + (_show_velvec ? _gps->vel_offsety : 0); +mark_x1 = unit2x(gps->unitx); +mark_y1 = unit2y(gps->unity); +mark_x2 = mark_x1 + (_show_velvec ? gps->vel_offsetx : 0); +mark_y2 = mark_y1 + (_show_velvec ? gps->vel_offsety : 0); mark_minx = MIN(mark_x1, mark_x2) - (2 * _draw_width); mark_miny = MIN(mark_y1, mark_y2) - (2 * _draw_width); mark_width = abs(mark_x1 - mark_x2) + (4 * _draw_width); @@ -458,7 +457,7 @@ _zoom = new_zoom / _curr_repo->view_zoom_steps * _curr_repo->view_zoom_steps; _world_size_tiles = unit2tile(WORLD_SIZE_UNITS); /* If we're leading, update the center to reflect new zoom level. */ -MACRO_RECALC_CENTER(_center.unitx, _center.unity); +MACRO_RECALC_CENTER(_gps->data, _center.unitx, _center.unity); /* Update center bounds to reflect new zoom level. */ _min_center.unitx = pixel2unit(grid2pixel(_screen_grids_halfwidth)); @@ -478,7 +477,7 @@ MACRO_RECALC_OFFSET(); MACRO_RECALC_FOCUS_BASE(); MACRO_RECALC_FOCUS_SIZE(); -map_set_mark(); +map_set_mark(&_gps->data); map_force_redraw(); } @@ -565,7 +564,7 @@ if (new_base_tilex != _base_tilex || new_base_tiley != _base_tiley) { MACRO_RECALC_OFFSET(); MACRO_RECALC_FOCUS_BASE(); -map_set_mark(); +map_set_mark(&_gps->data); MACRO_QUEUE_DRAW_AREA(); } @@ -605,7 +604,7 @@ if (pos->valid==FALSE) _center_mode=CENTER_MANUAL; map_center_latlon(pos->lat, pos->lon); -map_set_autozoom(FALSE); +map_set_autozoom(FALSE, 0); g_idle_add_full(G_PRIORITY_HIGH_IDLE,(GSourceFunc)map_update_location_from_center, NULL, NULL); return TRUE; } @@ -624,7 +623,7 @@ gtk_widget_queue_draw_area(_map_widget, mark_minx<0 ? 0 : mark_minx, mark_miny<0 ? 0 : mark_miny, mark_width, mark_height); -map_set_mark(); +map_set_mark(&_gps->data); gtk_widget_queue_draw_area(_map_widget, mark_minx<0 ? 0 : mark_minx, mark_miny<0 ? 0 : mark_miny, @@ -632,9 +631,9 @@ gtk_widget_queue_draw_area(_map_widget, } gboolean -map_update_location_from_gps(void) +map_update_location_from_gps(Gps *gps) { -map_update_location(_gps->lat, _gps->lon, FALSE); +map_update_location(gps->data.lat, gps->data.lon, FALSE); return FALSE; } @@ -645,11 +644,13 @@ gdouble lat, lon; /* Force re-validation of place if user is clicking around */ map_loc.valid=FALSE; /* XXX: hmm, not the right place for this */ +#if 0 if (_gps->fix==FIX_NOFIX) { - _gps->unitx=_center.unitx; - _gps->unity=_center.unity; - unit2latlon(_gps->unitx, _gps->unity, _gps->lat, _gps->lon); + _gps->data.unitx=_center.unitx; + _gps->data.unity=_center.unity; + unit2latlon(_gps->data.unitx, _gps->data.unity, _gps->data.lat, _gps->data.lon); } +#endif unit2latlon(_center.unitx, _center.unity, lat, lon); map_update_location(lat, lon, TRUE); return FALSE; @@ -708,7 +709,7 @@ map_refresh_mark(void) guint new_center_unitx; guint new_center_unity; -MACRO_RECALC_CENTER(new_center_unitx, new_center_unity); +MACRO_RECALC_CENTER(_gps->data, new_center_unitx, new_center_unity); if ((new_center_unitx - _focus.unitx) < _focus_unitwidth && (new_center_unity - _focus.unity) < _focus_unitheight) /* We're not changing the view - just move the mark. */ @@ -905,7 +906,7 @@ GdkGC *gc; gfloat cur_speed; gchar *buffer; -cur_speed = _gps->speed * UNITS_CONVERT[_units]; +cur_speed = _gps->data.speed * UNITS_CONVERT[_units]; gc=(cur_speed > _speed_limit) ? speed_gc1 : speed_gc2; buffer = g_strdup_printf("%0.0f", cur_speed); map_information_text(10, 10, gc, buffer); @@ -996,7 +997,7 @@ gdk_draw_drawable(GDK_DRAWABLE(_map_widget->window), event->area.x + _offsetx, event->area.y + _offsety, event->area.x, event->area.y, event->area.width, event->area.height); -map_draw_mark(); +map_draw_mark(_gps); /* Draw scale, if necessary. */ if (_show_scale) @@ -1046,11 +1047,11 @@ gint iz; if (zoom_timeout_sid==0) return FALSE; -z=(z+_gps->speed+1)/5; +z=(z+_gps->data.speed+1)/5; if (z>5) z=5.0; else if (z<1) z=1.0; iz=(gint)roundf(z); #ifdef DEBUG -g_printf("Setting autozoom to: %f %d S:%f\n", z, iz, _gps->speed); +g_printf("Setting autozoom to: %f %d S:%f\n", z, iz, _gps->data.speed); #endif if (iz>last) iz=last+1; @@ -1063,11 +1064,11 @@ return TRUE; } void -map_set_autozoom(gboolean az) +map_set_autozoom(gboolean az, gfloat speed) { if (az==TRUE) { MACRO_BANNER_SHOW_INFO(_window, "Autozoom enabled"); - zoom_timeout_sid=g_timeout_add(_gps->speed<5 ? 2000 : 5000, (GSourceFunc) map_autozoomer, NULL); + zoom_timeout_sid=g_timeout_add(speed<5 ? 2000 : 5000, (GSourceFunc) map_autozoomer, NULL); return; } else { if (zoom_timeout_sid) { @@ -1089,11 +1090,11 @@ cmenu_route_add_way(x, y); static void map_draw_track(gint x, gint y) { -_gps->unitx=x2unit((gint) (x + 0.5)); -_gps->unity=y2unit((gint) (y + 0.5)); -unit2latlon(_gps->unitx, _gps->unity, _gps->lat, _gps->lon); -_gps->speed=20.f; -gps_integerize_data(_gps); +_gps->data.unitx=x2unit((gint) (x + 0.5)); +_gps->data.unity=y2unit((gint) (y + 0.5)); +unit2latlon(_gps->data.unitx, _gps->data.unity, _gps->data.lat, _gps->data.lon); +_gps->data.speed=20.f; +gps_data_integerize(&_gps->data); track_add(time(NULL), FALSE); map_refresh_mark(); } @@ -1193,8 +1194,8 @@ inp=TRUE; ilat=lat2mp_int(lat); ilon=lon2mp_int(lon); -if (_gps->fix>1 && !force) - osm_set_way_range_from_speed(_gps->speed); +if (_gps->data.fix>1 && !force) + osm_set_way_range_from_speed(_gps->data.speed); else osm_set_way_range(OSM_RANGE_WAY/4); diff --git a/src/map.h b/src/map.h index 7b77afd..f1c1539 100644 --- a/src/map.h +++ b/src/map.h @@ -70,22 +70,22 @@ #define unit2y(unit) (unit2pixel(unit) - tile2pixel(_base_tiley) - _offsety) #define y2unit(y) (pixel2unit(y + _offsety) + tile2unit(_base_tiley)) -#define leadx2unit() (_gps->unitx + (_lead_ratio) * pixel2unit(_gps->vel_offsetx)) -#define leady2unit() (_gps->unity + (0.6f*_lead_ratio)*pixel2unit(_gps->vel_offsety)) +#define leadx2unit(mgps) (mgps.unitx + (_lead_ratio) * pixel2unit(mgps.vel_offsetx)) +#define leady2unit(mgps) (mgps.unity + (0.6f*_lead_ratio)*pixel2unit(mgps.vel_offsety)) /* Pans are done two "grids" at a time, or 64 pixels. */ #define PAN_UNITS (grid2unit(2)) -#define MACRO_RECALC_CENTER(center_unitx, center_unity) { \ +#define MACRO_RECALC_CENTER(mgps, center_unitx, center_unity) { \ switch(_center_mode) \ { \ case CENTER_LEAD: \ - center_unitx = leadx2unit(); \ - center_unity = leady2unit(); \ + center_unitx = leadx2unit(mgps); \ + center_unity = leady2unit(mgps); \ break; \ case CENTER_LATLON: \ - center_unitx = _gps->unitx; \ - center_unity = _gps->unity; \ + center_unitx = mgps.unitx; \ + center_unity = mgps.unity; \ break; \ default: \ center_unitx = _center.unitx; \ @@ -186,11 +186,11 @@ gboolean map_key_zoom_timeout(); int map_zoom(gint zdir); gboolean map_zoom_in(void); gboolean map_zoom_out(void); -void map_set_autozoom(gboolean az); +void map_set_autozoom(gboolean az, gfloat speed); void map_render_path(Path * path, GdkGC ** gc); void map_pan(gint delta_unitx, gint delta_unity); void map_move_mark(void); -void map_set_mark(void); +void map_set_mark(GpsData *gps); void map_render_data(void); void map_render_tile(guint tilex, guint tiley, guint destx, guint desty, gboolean fast_fail); diff --git a/src/mapper.c b/src/mapper.c index dc0a4e4..ae3599d 100644 --- a/src/mapper.c +++ b/src/mapper.c @@ -61,7 +61,6 @@ #include "map.h" #include "route.h" #include "track.h" -#include "bt.h" #include "ui-common.h" #include "db.h" #include "osm-db.h" @@ -122,7 +121,7 @@ mapper_destroy(void) { config_save(); config_save_repo(); -rcvr_disconnect(); +gps_disconnect(_gps); map_download_deinit(); #if defined (WITH_GST) && defined (WITH_ESPEAK) speak_deinit(); @@ -200,10 +199,17 @@ gchar *w="Starting"; switch (mis) { case MAPPER_INIT_START: - _conn_state = RCVR_OFF; curl_global_init(CURL_GLOBAL_NOTHING); gnome_vfs_init(); - _gps=gps_init(); + _gps=gps_new(); + _gps->io.type=GPS_IO_SIMULATION; +#ifdef WITH_BLUEZ + _gps->io.type=GPS_IO_RFCOMM; +#endif +#ifdef WITH_HILDON_DBUS_BT + _gps->io.type=GPS_IO_HILDON_DBUS; +#endif + _gps->io.conn = RCVR_OFF; timezone_init(); gpx_init(); variables_init(); @@ -292,6 +298,8 @@ switch (mis) { break; case MAPPER_INIT_DONE: progress_dialog_remove(init_dialog); + if (_enable_gps) + gps_connect_now(_gps); return FALSE; break; } diff --git a/src/osm-db.c b/src/osm-db.c index 566b25d..be7537f 100644 --- a/src/osm-db.c +++ b/src/osm-db.c @@ -908,7 +908,7 @@ if (map_loc->valid==FALSE) { /* Check if we are still near the same way as last time */ if (map_loc->street && osm_way_distance(lat, lon, map_loc->street->node_f, map_loc->street->node_t, &dist)==TRUE) { /* We are probably on the same way as last time */ - if ( (dist>(gdouble)way_dist_range) || (fabs(_gps->heading-map_loc->heading)>10.0)) { + if ( (dist>(gdouble)way_dist_range) || (fabs(_gps->data.heading-map_loc->heading)>10.0)) { /* We have moved a large amount, check way again */ g_printf("*** dist %f over range, checking again\n", dist); osm_way_free(map_loc->street); @@ -951,8 +951,8 @@ if (map_loc->street && osm_way_distance(lat, lon, map_loc->street->node_f, map_l } if (map_loc->changed==TRUE) { - map_loc->heading=_gps->heading; - map_loc->speed=_gps->speed; + map_loc->heading=_gps->data.heading; + map_loc->speed=_gps->data.speed; } #if 0 diff --git a/src/route.c b/src/route.c index 43dcfed..e52df7a 100644 --- a/src/route.c +++ b/src/route.c @@ -138,8 +138,8 @@ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toggle))) { gchar buffer[80]; gchar strlat[32]; gchar strlon[32]; - g_ascii_formatd(strlat, 32, "%.06f", _gps->lat); - g_ascii_formatd(strlon, 32, "%.06f", _gps->lon); + g_ascii_formatd(strlat, 32, "%.06f", _gps->data.lat); + g_ascii_formatd(strlon, 32, "%.06f", _gps->data.lon); g_snprintf(buffer, sizeof(buffer), "%s, %s", strlat, strlon); gtk_entry_set_text(GTK_ENTRY(oti->txt_from), buffer); } else if (toggle == oti->rad_use_route) { @@ -218,8 +218,8 @@ auto_route_dl_idle() { gchar latstr[32], lonstr[32], *latlonstr; -g_ascii_dtostr(latstr, 32, _gps->lat); -g_ascii_dtostr(lonstr, 32, _gps->lon); +g_ascii_dtostr(latstr, 32, _gps->data.lat); +g_ascii_dtostr(lonstr, 32, _gps->data.lon); latlonstr = g_strdup_printf("%s,%s", latstr, lonstr); _autoroute_data.src_str = g_strdup_printf(_route_dl_url, latlonstr, _autoroute_data.dest); @@ -537,14 +537,14 @@ if (_next_way) { /* First, set near_dist_squared with the new distance from * _near_point. */ near = _near_point; - near_dist_squared = DISTANCE_SQUARED(*_gps, *near); + near_dist_squared = DISTANCE_SQUARED(_gps->data, *near); /* Now, search _route for a closer point. If quick is TRUE, then we'll * only search forward, only as long as we keep finding closer points. */ for (curr = _near_point; curr++ != _route.tail;) { if (curr->unity) { - guint dist_squared = DISTANCE_SQUARED(*_gps, *curr); + guint dist_squared = DISTANCE_SQUARED(_gps->data, *curr); if (dist_squared <= near_dist_squared) { near = curr; near_dist_squared = dist_squared; @@ -559,8 +559,8 @@ if (_next_way) { for (wnext = wcurr = _next_way; wcurr != _route.wtail; wcurr++) { if (wcurr->point < near || (wcurr->point == near && quick - && (_next_wpt && (DISTANCE_SQUARED(*_gps, *near) > _next_way_dist_squared - && DISTANCE_SQUARED(*_gps, *_next_wpt) < _next_wpt_dist_squared)))) + && (_next_wpt && (DISTANCE_SQUARED(_gps->data, *near) > _next_way_dist_squared + && DISTANCE_SQUARED(_gps->data, *_next_wpt) < _next_wpt_dist_squared)))) /* Okay, this else if expression warrants explanation. If the * nearest track point happens to be a waypoint, then we want to * check if we have "passed" that waypoint. To check this, we @@ -575,8 +575,8 @@ if (_next_way) { } if (wnext == _route.wtail && (wnext->point < near || (wnext->point == near && quick - && (_next_wpt && (DISTANCE_SQUARED (*_gps, *near) > _next_way_dist_squared - && DISTANCE_SQUARED(*_gps, *_next_wpt) < _next_wpt_dist_squared))))) + && (_next_wpt && (DISTANCE_SQUARED (_gps->data, *near) > _next_way_dist_squared + && DISTANCE_SQUARED(_gps->data, *_next_wpt) < _next_wpt_dist_squared))))) { _next_way = NULL; _next_wpt = NULL; @@ -602,9 +602,9 @@ if (_next_way) { } ret = TRUE; } - _next_way_dist_squared = DISTANCE_SQUARED(*_gps, *wnext->point); + _next_way_dist_squared = DISTANCE_SQUARED(_gps->data, *wnext->point); if (_next_wpt) - _next_wpt_dist_squared = DISTANCE_SQUARED(*_gps, *_next_wpt); + _next_wpt_dist_squared = DISTANCE_SQUARED(_gps->data, *_next_wpt); } } return ret; @@ -658,7 +658,7 @@ if (point == NULL && _next_way) if (point == NULL) return FALSE; -unit2latlon(_gps->unitx, _gps->unity, lat1, lon1); +unit2latlon(_gps->data.unitx, _gps->data.unity, lat1, lon1); if (point > _near_point) { Point *curr; /* Skip _near_point in case we have already passed it. */ diff --git a/src/settings-gui.c b/src/settings-gui.c index 14caacb..50ea67a 100644 --- a/src/settings-gui.c +++ b/src/settings-gui.c @@ -28,11 +28,10 @@ #include "map.h" #include "mapper-types.h" #include "latlon.h" -#include "bt.h" #include "ui-common.h" #include "settings.h" #include "db.h" - +#include "bluetooth-scan.h" #include "hildon-wrappers.h" #include "help.h" @@ -564,11 +563,8 @@ settings_dialog(void) g_signal_connect(G_OBJECT(btn_browsedb), "clicked", G_CALLBACK(settings_dialog_browse_forfile), &browse_info); /* Initialize fields. */ - if (_rcvr_mac) - gtk_entry_set_text(GTK_ENTRY(txt_rcvr_mac), _rcvr_mac); - - if (_mapper_db) - gtk_entry_set_text(GTK_ENTRY(txt_mapper_db), _mapper_db); + gtk_entry_set_text(GTK_ENTRY(txt_rcvr_mac), _gps->io.address ? _gps->io.address : ""); + gtk_entry_set_text(GTK_ENTRY(txt_mapper_db), _mapper_db ? _mapper_db : ""); hildon_number_editor_set_value(HILDON_NUMBER_EDITOR(num_poi_zoom), _poi_zoom); hildon_controlbar_set_value(HILDON_CONTROLBAR(num_center_ratio), _center_ratio); @@ -592,9 +588,9 @@ settings_dialog(void) /* Set _rcvr_mac if necessary. */ if (!*gtk_entry_get_text(GTK_ENTRY(txt_rcvr_mac))) { /* User specified no rcvr mac - set _rcvr_mac to NULL. */ - if (_rcvr_mac) { - g_free(_rcvr_mac); - _rcvr_mac = NULL; + if (_gps->io.address) { + g_free(_gps->io.address); + _gps->io.address = NULL; rcvr_changed = TRUE; set_action_sensitive("gps_details", FALSE); } @@ -604,10 +600,10 @@ settings_dialog(void) rcvr_changed = TRUE; set_action_sensitive("gps_details", FALSE); } - } else if (!_rcvr_mac || strcmp(_rcvr_mac, gtk_entry_get_text(GTK_ENTRY(txt_rcvr_mac)))) { + } else if (!_gps->io.address || strcmp(_gps->io.address, gtk_entry_get_text(GTK_ENTRY(txt_rcvr_mac)))) { /* User specified a new rcvr mac. */ - g_free(_rcvr_mac); - _rcvr_mac = g_strdup(gtk_entry_get_text(GTK_ENTRY(txt_rcvr_mac))); + g_free(_gps->io.address); + _gps->io.address = g_strdup(gtk_entry_get_text(GTK_ENTRY(txt_rcvr_mac))); rcvr_changed = TRUE; } diff --git a/src/settings.h b/src/settings.h index b55a5ff..8d1de74 100644 --- a/src/settings.h +++ b/src/settings.h @@ -8,7 +8,6 @@ #include "settings-gconf.h" /** CONFIGURATION INFORMATION. */ -gchar *_rcvr_mac; gchar *_route_dir_uri; gchar *_track_file_uri; gchar *_route_dl_url; diff --git a/src/track.c b/src/track.c index 3764143..b8284d0 100644 --- a/src/track.c +++ b/src/track.c @@ -58,7 +58,7 @@ track_calculate_distance_from(Point *point) gdouble lat1, lon1, lat2, lon2; gdouble sum = 0.0; Point *curr; -unit2latlon(_gps->unitx, _gps->unity, lat1, lon1); +unit2latlon(_gps->data.unitx, _gps->data.unity, lat1, lon1); /* Skip _track.tail because that should be _gps. */ for (curr = _track.tail; curr > point; --curr) { @@ -298,7 +298,7 @@ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), table = gtk_table_new(2, 2 gtk_table_attach(GTK_TABLE(table), label = gtk_label_new(_("Lat, Lon")), 0, 1, 0, 1, GTK_FILL, 0, 2, 4); gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f); -unit2latlon(_gps->unitx, _gps->unity, lat, lon); +unit2latlon(_gps->data.unitx, _gps->data.unity, lat, lon); lat_format(_degformat, lat, tmp1); lon_format(_degformat, lon, tmp2); p_latlon = g_strdup_printf("%s, %s", tmp1, tmp2); diff --git a/src/ui-common.c b/src/ui-common.c index 3c8a094..90bfa38 100644 --- a/src/ui-common.c +++ b/src/ui-common.c @@ -28,7 +28,6 @@ #include "gps.h" #include "map.h" #include "mapper-types.h" -#include "bt.h" #include "ui-common.h" #include "db.h" @@ -389,7 +388,7 @@ static gint done_here = 0; if (!been_here++) { /* Set connection state first, to avoid going into this if twice. */ - if (!_rcvr_mac && _enable_gps) { + if (!_gps->io.address && _enable_gps) { GtkWidget *confirm; gtk_window_present(GTK_WINDOW(_window)); @@ -416,9 +415,6 @@ if (!been_here++) { gtk_main_quit(); } } - /* Connect to receiver. */ - if (_enable_gps && _rcvr_mac) - rcvr_connect_now(); done_here++; /* Don't ask... */ } @@ -427,9 +423,9 @@ if (done_here) { /* Re-enable any banners that might have been up. */ { - ConnState old_state = _conn_state; - gps_conn_set_state(RCVR_OFF); - gps_conn_set_state(old_state); + GpsConnState old_state = _gps->io.conn; + gps_conn_set_state(_gps, RCVR_OFF); + gps_conn_set_state(_gps, old_state); } } @@ -747,16 +743,16 @@ gtk_paned_add2(GTK_PANED(hbox), _map_widget); /* GPS Tab */ vbox = gtk_vbox_new(FALSE, 0); label = gtk_label_new("Gps"); -_gps_sat_view = gtk_gps_new(GTK_GPS_MODE_SKY, _gps); +_gps_sat_view = gtk_gps_new(GTK_GPS_MODE_SKY, &_gps->data); gtk_box_pack_start(GTK_BOX(vbox), _gps_sat_view, TRUE, TRUE, 0); -_gps_sat_view = gtk_gps_new(GTK_GPS_MODE_SIGNAL, _gps); +_gps_sat_view = gtk_gps_new(GTK_GPS_MODE_SIGNAL, &_gps->data); gtk_box_pack_start(GTK_BOX(vbox), _gps_sat_view, TRUE, TRUE, 0); ui_notebook.gps=gtk_notebook_append_page(notebook, vbox, label); /* Heading Tab */ vbox = gtk_vbox_new(FALSE, 0); label = gtk_label_new("Heading"); -_tab_compass = gtk_compass_new(_gps); +_tab_compass = gtk_compass_new(&_gps->data); gtk_box_pack_start(GTK_BOX(vbox), _tab_compass, TRUE, TRUE, 0); ui_notebook.heading=gtk_notebook_append_page(notebook, vbox, label); -- 2.39.5