remove response data, add locator class and sort gigs by distance
[gigfinder] / gig_finder.py
index e2f1c19..6e2be69 100644 (file)
@@ -18,6 +18,9 @@ import gtk
 import hildon
 import location
 import time
+import gobject
+
+gtk.gdk.threads_init()
 
 class GigParser:
 
@@ -86,6 +89,47 @@ class GigParser:
                         result.tm_min, 
                         result.tm_sec)
 
+class LocationUpdater:
+
+    def __init__(self):
+        self.lat = None
+        self.long = None
+        self.loop = gobject.MainLoop()
+
+        self.control = location.GPSDControl.get_default()
+        self.control.set_properties(preferred_method=location.METHOD_USER_SELECTED,
+                               preferred_interval=location.INTERVAL_DEFAULT)
+        self.control.connect("error-verbose", self.on_error, self.loop)
+        self.control.connect("gpsd-stopped", self.on_stop, self.loop)
+
+        self.device = location.GPSDevice()
+        self.device.connect("changed", self.on_changed, self.control)
+
+    def update_location(self):
+        """ Run the loop and update lat and long """
+        self.device.reset_last_known()
+        gobject.idle_add(self.start_location, self.control)
+        self.loop.run()
+
+    def on_error(self, control, error, data):
+        print "location error: %d... quitting" % error
+        data.quit()
+
+    def on_changed(self, device, data):
+        if not device:
+            return
+        if device.fix:
+            if device.fix[1] & location.GPS_DEVICE_LATLONG_SET:
+                self.lat, self.long = device.fix[4:6]
+                data.stop()
+
+    def on_stop(self, control, data):
+        print "quitting"
+        data.quit()
+
+    def start_location(self, data):
+        data.start()
+        return False
 
 class GigFinder:
 
@@ -111,7 +155,9 @@ class GigFinder:
 
         self.win.add(pannable_area)
 
-        self.update_gigs()
+        self.location_updater = LocationUpdater()
+        self.location_updater.update_location()
+        gobject.idle_add(self.update_gigs)
 
     def main(self):
         self.win.show_all()
@@ -119,11 +165,34 @@ class GigFinder:
 
     def update_gigs(self):
         """ Get gig info """
-        parser = GigParser()
-        self.get_lat_long()
+        hildon.hildon_gtk_window_set_progress_indicator(self.win, 1)
+
+        # if no gps fix wait
+        while not location.GPS_DEVICE_LATLONG_SET:
+            time.sleep(1)
+
         xml = self.get_xml()
-        events = parser.parse_xml(xml, self.lat, self.long)
+        parser = GigParser()
+        events = parser.parse_xml(xml, self.location_updater.lat,
+                self.location_updater.long)
+        events = self.sort_gigs(events)
+        self.win.set_title('Gig Finder (%s)' % len(events))
         self.add_events(events)
+        hildon.hildon_gtk_window_set_progress_indicator(self.win, 0)
+
+    def distance_cmp(self, x, y):
+        """ compare distances for list sort """
+        if x > y:
+            return 1
+        elif x == y:
+            return 0
+        else:
+            return -1
+
+    def sort_gigs(self, events):
+        """ sort gig by distance """
+        events.sort(cmp=self.distance_cmp, key=lambda x: x['distance'])
+        return events
         
     def get_xml(self):
         """ Return xml from lastfm """
@@ -131,21 +200,11 @@ class GigFinder:
         params = urllib.urlencode({'method': method,
                                    'api_key': self.api_key,
                                    'distance': self.distance,
-                                   'long': self.long,
-                                   'lat': self.lat})
+                                   'long': self.location_updater.long,
+                                   'lat': self.location_updater.lat})
         response = urllib.urlopen(self.url_base, params)
         return response.read()
 
-    def get_lat_long(self):
-        """ Access gps and return current long lats """
-        # TODO: Improve geolocation code, very crude atm
-        control = location.GPSDControl.get_default()
-        device = location.GPSDevice()
-        control.start()
-        fix = device.fix
-        control.stop()
-        self.lat, self.long = fix[4:6]
-        #self.lat, self.long = ('51.546228', '-0.075016')
 
     def show_details(self, widget, data):
         """ Open new window showing gig details """
@@ -167,7 +226,7 @@ class GigFinder:
         buffer.insert(end, '%s\n' % data['title'])
         buffer.insert(end, 'Artists: %s\n' % data['artists'])
         buffer.insert(end, 'Venue: %s\n' % data['venue'])
-        buffer.insert(end, data['address'])
+        buffer.insert(end, '%s\n' % data['address'])
         buffer.insert(end, 'When: %s\n' % data['date'].strftime('%H:%M'))
         buffer.insert(end, '\n')
         scroll.add_with_viewport(view)
@@ -184,16 +243,11 @@ class GigFinder:
             button.connect("clicked", self.show_details, event)
             self.table.attach(button, 0, 1, pos, pos+1)
             pos += 1
+        self.table.show_all()
 
-
-
-    #hildon.hildon_gtk_window_set_progress_indicator(win, 1)
     #banner = hildon.hildon_banner_show_information(win,
     #                                               "Updating", 
     #                                               "Retrieving gig info")
-    #banner.hide()
-    #hildon.hildon_gtk_window_set_progress_indicator(win, 0)
-
    
 if __name__ == "__main__":
     finder = GigFinder()