Copyright file added.
[jspeed] / src / location.cpp
1 /*
2  * This file is part of jSpeed.
3  *
4  * jSpeed is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * jSpeed is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with jSpeed.  If not, see <http://www.gnu.org/licenses/>.
16  *
17  */
18
19 #include <QtCore/QDebug>
20 #include "location.h"
21
22 namespace
23 {
24     static double const KM_MULTIPLIER = 1.0;
25     static double const MILE_MULTIPLIER = 0.621371192;
26     static double const METER_MULTIPLIER = 1.0;
27     static double const FEET_MULTIPLIER = 3.2808399;
28 }
29
30 Location::Unit Location::unit_ = Location::KM;
31
32 Location::Location(QObject* parent): QObject(parent), started_(false),
33 control_(0), device_(0)
34 {
35     g_type_init();
36 }
37
38 Location::~Location()
39 {
40     end();
41 }
42
43 void Location::start()
44 {
45     control_ = location_gpsd_control_get_default();
46     device_ = (LocationGPSDevice*) g_object_new(LOCATION_TYPE_GPS_DEVICE, NULL);
47
48     g_object_set(G_OBJECT(control_),
49                  "preferred-method", LOCATION_METHOD_USER_SELECTED,
50                  "preferred-interval", LOCATION_INTERVAL_DEFAULT,
51                  NULL);
52
53     g_signal_connect(control_, "error-verbose", G_CALLBACK(onError), this);
54     g_signal_connect(device_, "changed", G_CALLBACK(onChanged), this);
55
56     location_gpsd_control_start(control_);
57
58     started_ = true;
59 }
60
61 void Location::end()
62 {
63     if(!started_)
64     {
65         return;
66     }
67
68     location_gpsd_control_stop(control_);
69
70     g_object_unref(device_);
71     device_ = 0;
72     g_object_unref(control_);
73     control_ = 0;
74
75     started_ = false;
76 }
77
78 bool Location::hasFix() const
79 {
80     if(!started_)
81     {
82         return false;
83     }
84
85     return (device_->status == LOCATION_GPS_DEVICE_STATUS_FIX);
86 }
87
88 double Location::getSignalStrength() const
89 {
90     if(!hasFix())
91     {
92         return 0.0;
93     }
94
95     if(device_->satellites_in_view == 0)
96     {
97         return 0.0;
98     }
99
100     double val = (device_->satellites_in_use / static_cast<double>(device_->satellites_in_view)) * 100.0;
101
102     if(val > 100.0)
103     {
104         val = 100.0;
105     }
106
107     return val;
108 }
109
110 void Location::setUnit(Location::Unit unit)
111 {
112     unit_ = unit;
113 }
114
115 Location::Unit Location::getUnit()
116 {
117     return unit_;
118 }
119
120 double Location::getUnitMultiplier()
121 {
122     if(unit_ == MILE)
123     {
124         return MILE_MULTIPLIER;
125     }
126
127     return KM_MULTIPLIER;
128 }
129
130 double Location::getMeterMultiplier()
131 {
132     if(unit_ == MILE)
133     {
134         return FEET_MULTIPLIER;
135     }
136
137     return METER_MULTIPLIER;
138 }
139
140 void Location::onChanged(LocationGPSDevice *device, gpointer data)
141 {
142     if(device && device->fix &&
143        !(device->fix->fields & LOCATION_GPS_DEVICE_NONE_SET))
144     {
145
146         Fix fix;
147         fix.unit = unit_;
148         fix.time = device->fix->time;
149         fix.ept = device->fix->ept;
150
151         if (device->fix->fields & LOCATION_GPS_DEVICE_LATLONG_SET)
152         {
153             fix.latitude = device->fix->latitude;
154             fix.longitude = device->fix->longitude;
155             fix.eph = device->fix->eph;
156         }
157
158         if(device->fix->fields & LOCATION_GPS_DEVICE_ALTITUDE_SET)
159         {
160             fix.altitude = device->fix->altitude * getMeterMultiplier();
161             fix.epv = device->fix->epv;
162         }
163
164         if(device->fix->fields & LOCATION_GPS_DEVICE_SPEED_SET)
165         {
166             fix.kmSpeed = device->fix->speed;
167             fix.speed = device->fix->speed * getUnitMultiplier();
168             fix.eps = device->fix->eps;
169         }
170
171         if(device->fix->fields & LOCATION_GPS_DEVICE_TRACK_SET)
172         {
173             fix.track = device->fix->track;
174             fix.epd = device->fix->epd;
175         }
176
177         if(device->fix->fields & LOCATION_GPS_DEVICE_CLIMB_SET)
178         {
179             fix.climb = device->fix->climb;
180             fix.epc = device->fix->epc;
181         }
182
183         Location* meh = (Location*) data;
184         meh->emit locationChanged(fix);
185     }
186 }
187
188 void Location::onError(LocationGPSDControl *control, LocationGPSDControlError error, gpointer data)
189 {
190     Q_UNUSED(control);
191
192     Error err = SYSTEM_ERROR;
193
194     switch(error)
195     {
196     case LOCATION_ERROR_USER_REJECTED_DIALOG:
197         err = USER_REJECTED_DIALOG;
198         break;
199     case LOCATION_ERROR_USER_REJECTED_SETTINGS:
200         err = USER_REJECTED_SETTINGS;
201         break;
202     case LOCATION_ERROR_BT_GPS_NOT_AVAILABLE:
203         err = GPS_NOT_AVAILABLE;
204         break;
205     case LOCATION_ERROR_METHOD_NOT_ALLOWED_IN_OFFLINE_MODE:
206         err = NOT_ALLOWED_IN_OFFLINE_MODE;
207         break;
208     case LOCATION_ERROR_SYSTEM:
209         err = SYSTEM_ERROR;
210         break;
211     }
212
213     Location* meh = (Location*) data;
214     meh->emit locationError(err);
215 }
216
217 Location::Fix::Fix()
218 {
219     unit = KM;
220     kmSpeed = 0.0;
221     time = 0.0;
222     ept = 0.0;
223     latitude = 0.0;
224     longitude = 0.0;
225     eph = 0.0;
226     altitude = 0.0;
227     epv = 0.0;
228     track = 0.0;
229     epd = 0.0;
230     speed = 0.0;
231     eps = 0.0;
232     climb = 0.0;
233     epc = 0.0;
234 }