1 /* vim: set et ts=8 sw=8: */
2 /* where-am-i.c
3 *
4 * Copyright 2013 Red Hat, Inc.
5 *
6 * Geoclue is free software; you can redistribute it and/or modify it under
7 * the terms of the GNU General Public License as published by the Free
8 * Software Foundation; either version 2 of the License, or (at your option)
9 * any later version.
10 *
11 * Geoclue is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14 * details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with Geoclue; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 *
20 * Author: Zeeshan Ali (Khattak) <zeeshanak@gnome.org>
21 */
22
23 #include <config.h>
24
25 #include <stdlib.h>
26 #include <locale.h>
27 #include <glib/gi18n.h>
28 #include <geoclue.h>
29
30 /* Commandline options */
31 static gint timeout = 30; /* seconds */
32 static GClueAccuracyLevel accuracy_level = GCLUE_ACCURACY_LEVEL_EXACT;
33 static gint time_threshold;
34
35 static GOptionEntry entries[] =
36 {
37 { "timeout",
38 't',
39 0,
40 G_OPTION_ARG_INT,
41 &timeout,
42 N_("Exit after T seconds. Default: 30"),
43 "T" },
44 { "time-threshold",
45 'i',
46 0,
47 G_OPTION_ARG_INT,
48 &time_threshold,
49 N_("Only report location update after T seconds. "
50 "Default: 0 (report new location without any delay)"),
51 "T" },
52 { "accuracy-level",
53 'a',
54 0,
55 G_OPTION_ARG_INT,
56 &accuracy_level,
57 N_("Request accuracy level A. "
58 "Country = 1, "
59 "City = 4, "
60 "Neighborhood = 5, "
61 "Street = 6, "
62 "Exact = 8."),
63 "A" },
64 { NULL }
65 };
66
67 GClueSimple *simple = NULL;
68 GClueClient *client = NULL;
69 GMainLoop *main_loop;
70
71 static gboolean
on_location_timeout(gpointer user_data)72 on_location_timeout (gpointer user_data)
73 {
74 g_clear_object (&client);
75 g_clear_object (&simple);
76 g_main_loop_quit (main_loop);
77
78 return FALSE;
79 }
80
81 static void
print_location(GClueSimple * simple)82 print_location (GClueSimple *simple)
83 {
84 GClueLocation *location;
85 gdouble altitude, speed, heading;
86 GVariant *timestamp;
87 GTimeVal tv = { 0 };
88 const char *desc;
89
90 location = gclue_simple_get_location (simple);
91 g_print ("\nNew location:\n");
92 g_print ("Latitude: %f°\nLongitude: %f°\nAccuracy: %f meters\n",
93 gclue_location_get_latitude (location),
94 gclue_location_get_longitude (location),
95 gclue_location_get_accuracy (location));
96
97 altitude = gclue_location_get_altitude (location);
98 if (altitude != -G_MAXDOUBLE)
99 g_print ("Altitude: %f meters\n", altitude);
100 speed = gclue_location_get_speed (location);
101 if (speed >= 0)
102 g_print ("Speed: %f meters/second\n", speed);
103 heading = gclue_location_get_heading (location);
104 if (heading >= 0)
105 g_print ("Heading: %f°\n", heading);
106
107 desc = gclue_location_get_description (location);
108 if (strlen (desc) > 0)
109 g_print ("Description: %s\n", desc);
110
111 timestamp = gclue_location_get_timestamp (location);
112 if (timestamp) {
113 GDateTime *date_time;
114 gchar *str;
115
116 g_variant_get (timestamp, "(tt)", &tv.tv_sec, &tv.tv_usec);
117
118 date_time = g_date_time_new_from_timeval_local (&tv);
119 str = g_date_time_format
120 (date_time,
121 "%c (%s seconds since the Epoch)");
122 g_date_time_unref (date_time);
123
124 g_print ("Timestamp: %s\n", str);
125 g_free (str);
126 }
127 }
128
129 static void
on_client_active_notify(GClueClient * client,GParamSpec * pspec,gpointer user_data)130 on_client_active_notify (GClueClient *client,
131 GParamSpec *pspec,
132 gpointer user_data)
133 {
134 if (gclue_client_get_active (client))
135 return;
136
137 g_print ("Geolocation disabled. Quitting..\n");
138 on_location_timeout (NULL);
139 }
140
141 static void
on_simple_ready(GObject * source_object,GAsyncResult * res,gpointer user_data)142 on_simple_ready (GObject *source_object,
143 GAsyncResult *res,
144 gpointer user_data)
145 {
146 GError *error = NULL;
147
148 simple = gclue_simple_new_finish (res, &error);
149 if (error != NULL) {
150 g_critical ("Failed to connect to GeoClue2 service: %s", error->message);
151
152 exit (-1);
153 }
154 client = gclue_simple_get_client (simple);
155 g_object_ref (client);
156 g_print ("Client object: %s\n",
157 g_dbus_proxy_get_object_path (G_DBUS_PROXY (client)));
158 if (time_threshold > 0) {
159 gclue_client_set_time_threshold (client, time_threshold);
160 }
161
162 print_location (simple);
163
164 g_signal_connect (simple,
165 "notify::location",
166 G_CALLBACK (print_location),
167 NULL);
168 g_signal_connect (client,
169 "notify::active",
170 G_CALLBACK (on_client_active_notify),
171 NULL);
172 }
173
174 gint
main(gint argc,gchar * argv[])175 main (gint argc, gchar *argv[])
176 {
177 GOptionContext *context;
178 GError *error = NULL;
179
180 setlocale (LC_ALL, "");
181 textdomain (GETTEXT_PACKAGE);
182 bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
183 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
184
185 context = g_option_context_new ("- Where am I?");
186 g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
187 if (!g_option_context_parse (context, &argc, &argv, &error)) {
188 g_critical ("option parsing failed: %s\n", error->message);
189 exit (-1);
190 }
191 g_option_context_free (context);
192
193 g_timeout_add_seconds (timeout, on_location_timeout, NULL);
194
195 gclue_simple_new ("geoclue-where-am-i",
196 accuracy_level,
197 NULL,
198 on_simple_ready,
199 NULL);
200
201 main_loop = g_main_loop_new (NULL, FALSE);
202 g_main_loop_run (main_loop);
203
204 return EXIT_SUCCESS;
205 }
206