Add PannableArea to display settings
[pedometerwidget] / pedometer_widget_home.py
1 import gtk
2 import cairo
3 import hildondesktop
4 import gobject
5 import os
6 import time
7 import hildon
8 import gnome.gconf as gconf
9 from threading import Thread
10
11 #gobject.threads_init()
12 #gtk.gdk.threads_init()
13
14 PATH="/apps/pedometerhomewidget"
15 COUNTER=PATH+"/counter"
16 TIMER=PATH+"/timer"
17 MODE=PATH+"/mode"
18 HEIGHT=PATH+"/height"
19 UNIT=PATH+"/unit"
20 ASPECT=PATH+"/aspect"
21 LOGGING=PATH+"/logging"
22
23 ICONSPATH = "/opt/pedometerhomewidget/"
24
25 class PedoIntervalCounter:
26     MIN_THRESHOLD = 500
27     MIN_TIME_STEPS = 0.5
28     x = []
29     y = []
30     z = []
31     t = []
32
33     #TODO: check if last detected step is at the end of the interval
34
35     def __init__(self, coords, tval):
36         self.x = coords[0]
37         self.y = coords[1]
38         self.z = coords[2]
39         self.t = tval
40
41     def setThreshold(self, value):
42         self.MIN_THRESHOLD = value
43
44     def setTimeSteps(self, value):
45         self.MIN_TIME_STEPS = value
46
47     def calc_mean(self, vals):
48         sum = 0
49         for i in vals:
50             sum+=i
51         if len(vals) > 0:
52             return sum / len(vals)
53         return 0
54
55     def calc_stdev(self, vals):
56         rez = 0
57         mean = self.calc_mean(vals)
58         for i in vals:
59             rez+=pow(abs(mean-i),2)
60         return math.sqrt(rez/len(vals))
61
62     def calc_threshold(self, vals):
63         vmax = max(vals)
64         vmin = min(vals)
65         mean = self.calc_mean(vals)
66         threshold = max (abs(mean-vmax), abs(mean-vmin))
67         return threshold
68
69     def count_steps(self, vals, t):
70         threshold = self.MIN_THRESHOLD
71         mean = self.calc_mean(vals)
72         cnt = 0
73
74         i=0
75         while i < len(vals):
76             if abs(vals[i] - mean) > threshold:
77                 cnt+=1
78                 ntime = t[i] + 0.5
79                 while i < len(vals) and t[i] < ntime:
80                     i+=1
81             i+=1
82         return cnt
83
84     def get_best_values(self, x, y, z):
85         dev1 = self.calc_stdev(x)
86         dev2 = self.calc_stdev(y)
87         dev3 = self.calc_stdev(z)
88         dev_max = max(dev1, dev2, dev3)
89
90         if ( abs(dev1 - dev_max ) < 0.001):
91             logger.info("X chosen as best axis, stdev %f" % dev1)
92             return x
93         elif (abs(dev2 - dev_max) < 0.001):
94             logger.info("Y chosen as best axis, stdev %f" % dev2)
95             return y
96         else:
97             logger.info("Z chosen as best axis, stdev %f" % dev3)
98             return z
99
100     def number_steps(self):
101         vals = self.get_best_values(self.x, self.y, self.z)
102         return self.count_steps(vals, self.t)
103
104 class PedoCounter(Thread):
105     COORD_FNAME = "/sys/class/i2c-adapter/i2c-3/3-001d/coord"
106     COORD_FNAME_SDK = "/home/andrei/pedometer-widget-0.1/date.txt"
107     LOGFILE = "/home/user/log_pedometer"
108     COORD_GET_INTERVAL = 0.01
109     COUNT_INTERVAL = 5
110
111     STEP_LENGTH = 0.7
112
113     MIN_THRESHOLD = 500
114     MIN_TIME_STEPS = 0.5
115
116     counter = 0
117     stop_requested = False
118     update_function = None
119     logging = False
120
121     mode = 0
122
123     def __init__(self, update_function = None):
124         Thread.__init__(self)
125         if not os.path.exists(self.COORD_FNAME):
126             self.COORD_FNAME = self.COORD_FNAME_SDK
127
128         self.update_function = update_function
129
130     def set_mode(self, mode):
131         #runnig, higher threshold to prevent fake steps
132         self.mode = mode
133         if mode == 1:
134             self.MIN_THRESHOLD = 650
135             self.MIN_TIME_STEPS = 0.35
136         #walking
137         else:
138             self.MIN_THRESHOLD = 500
139             self.MIN_TIME_STEPS = 0.5
140
141     def set_logging(self, value):
142         self.logging = value
143
144     #set height, will affect the distance
145     def set_height(self, height_interval):
146         if height_interval == 0:
147             self.STEP_LENGTH = 0.59
148         elif height_interval == 1:
149             self.STEP_LENGTH = 0.64
150         elif height_interval == 2:
151             self.STEP_LENGTH = 0.71
152         elif height_interval == 3:
153             self.STEP_LENGTH = 0.77
154         elif height_interval == 4:
155             self.STEP_LENGTH = 0.83
156         #increase step length if RUNNING
157         if self.mode == 1:
158             self.STEP_LENGTH *= 1.45
159
160     def get_rotation(self):
161         f = open(self.COORD_FNAME, 'r')
162         coords = [int(w) for w in f.readline().split()]
163         f.close()
164         return coords
165
166     def reset_counter(self):
167         counter = 0
168
169     def get_counter(self):
170         return counter
171
172     def start_interval(self):
173         logger.info("New interval started")
174         stime = time.time()
175         t=[]
176         coords = [[], [], []]
177         while not self.stop_requested and (len(t) == 0 or t[-1] < 5):
178             x,y,z = self.get_rotation()
179             coords[0].append(int(x))
180             coords[1].append(int(y))
181             coords[2].append(int(z))
182             now = time.time()-stime
183             if self.logging:
184                 self.file.write("%d %d %d %f\n" %(coords[0][-1], coords[1][-1], coords[2][-1], now))
185
186             t.append(now)
187             time.sleep(self.COORD_GET_INTERVAL)
188         pic = PedoIntervalCounter(coords, t)
189         cnt = pic.number_steps()
190
191         logger.info("Number of steps detected for last interval %d, number of coords: %d" % (cnt, len(t)))
192
193         self.counter += cnt
194         logger.info("Total number of steps : %d" % self.counter)
195         return cnt
196
197     def request_stop(self):
198         self.stop_requested = True
199
200     def run(self):
201         logger.info("Thread started")
202         if self.logging:
203             fname = "%d_%d_%d_%d_%d_%d" % time.localtime()[0:6]
204             self.file = open(self.LOGFILE + fname + ".txt", "w")
205
206         while 1 and not self.stop_requested:
207             last_cnt = self.start_interval()
208             if self.update_function is not None:
209                 gobject.idle_add(self.update_function, self.counter, last_cnt)
210
211         if self.logging:
212             self.file.close()
213
214         logger.info("Thread has finished")
215
216     def get_distance(self, steps=None):
217         if steps == None:
218             steps = self.counter
219         return self.STEP_LENGTH * steps;
220
221 class CustomButton(hildon.Button):
222     def __init__(self, icon):
223         hildon.Button.__init__(self, gtk.HILDON_SIZE_AUTO_WIDTH, hildon.BUTTON_ARRANGEMENT_VERTICAL)
224         self.icon = icon
225         self.set_size_request(int(32*1.4), int(30*1.0))
226         self.retval = self.connect("expose_event", self.expose)
227
228     def set_icon(self, icon):
229         self.icon = icon
230
231     def expose(self, widget, event):
232         self.context = widget.window.cairo_create()
233         self.context.rectangle(event.area.x, event.area.y,
234                             event.area.width, event.area.height)
235
236         self.context.clip()
237         rect = self.get_allocation()
238         self.context.rectangle(rect.x, rect.y, rect.width, rect.height)
239         self.context.set_source_rgba(1, 1, 1, 0)
240
241         style = self.rc_get_style()
242         color = style.lookup_color("DefaultBackgroundColor")
243         if self.state == gtk.STATE_ACTIVE:
244             style = self.rc_get_style()
245             color = style.lookup_color("SelectionColor")
246             self.context.set_source_rgba (color.red/65535.0, color.green/65335.0, color.blue/65535.0, 0.75);
247         self.context.fill()
248
249         #img = cairo.ImageSurface.create_from_png(self.icon)
250
251         #self.context.set_source_surface(img)
252         #self.context.set_source_surface(img, rect.width/2 - img.get_width() /2, 0)
253         img = gtk.Image()
254         img.set_from_file(self.icon)
255         buf = img.get_pixbuf()
256         buf =  buf.scale_simple(int(32 * 1.5), int(30 * 1.5), gtk.gdk.INTERP_BILINEAR)
257
258         self.context.set_source_pixbuf(buf, rect.x+(event.area.width/2-15)-8, rect.y+1)
259         self.context.scale(200,200)
260         self.context.paint()
261
262         return self.retval
263
264 class PedometerHomePlugin(hildondesktop.HomePluginItem):
265     button = None
266
267     #labels for current steps
268     labels = ["timer", "count", "dist", "avgSpeed"]
269     #labelsC = { "timer" : None, "count" : None, "dist" : None, "avgSpeed" : None }
270
271     #labels for all time steps
272     #labelsT = { "timer" : None, "count" : None, "dist" : None, "avgSpeed" : None }
273     labelsC = {}
274     labelsT = {}
275
276     pedometer = None
277     startTime = None
278
279     totalCounter = 0
280     totalTime = 0
281     mode = 0
282     height = 0
283     unit = 0
284
285     counter = 0
286     time = 0
287     aspect = 0
288     logging = False
289
290     def __init__(self):
291
292         gtk.gdk.threads_init()
293         #gobject.threads_init()
294         hildondesktop.HomePluginItem.__init__(self)
295
296         self.client = gconf.client_get_default()
297         try:
298             self.totalCounter = self.client.get_int(COUNTER)
299             self.totalTime = self.client.get_int(TIMER)
300             self.mode = self.client.get_int(MODE)
301             self.height = self.client.get_int(HEIGHT)
302             self.unit = self.client.get_int(UNIT)
303             self.aspect = self.client.get_int(ASPECT)
304             self.logging = self.client.get_bool(LOGGING)
305         except:
306             self.client.set_int(COUNTER, 0)
307             self.client.set_int(TIMER, 0)
308             self.client.set_int(MODE, 0)
309             self.client.set_int(HEIGHT, 0)
310             self.client.set_int(UNIT, 0)
311             self.client.set_int(ASPECT, 0)
312             self.client.set_bool(LOGGING, False)
313
314         self.pedometer = PedoCounter(self.update_values)
315         self.pedometer.set_mode(self.mode)
316         self.pedometer.set_height(self.height)
317
318         #self.button = gtk.Button("Start")
319         self.button = CustomButton(ICONSPATH + "play.png")
320         self.button.connect("clicked", self.button_clicked)
321
322         self.create_labels(self.labelsC)
323         self.create_labels(self.labelsT)
324
325         self.update_ui_values(self.labelsC, 0, 0)
326         self.update_ui_values(self.labelsT, self.totalTime, self.totalCounter)
327
328         mainHBox = gtk.HBox(spacing=1)
329
330         descVBox = gtk.VBox(spacing=1)
331         descVBox.add(self.new_label_heading())
332         descVBox.add(self.new_label_heading("Time:"))
333         descVBox.add(self.new_label_heading("Steps:"))
334         descVBox.add(self.new_label_heading("Distance:"))
335         descVBox.add(self.new_label_heading("Avg Speed:"))
336
337         currentVBox = gtk.VBox(spacing=1)
338         currentVBox.add(self.new_label_heading("Current"))
339         currentVBox.add(self.labelsC["timer"])
340         currentVBox.add(self.labelsC["count"])
341         currentVBox.add(self.labelsC["dist"])
342         currentVBox.add(self.labelsC["avgSpeed"])
343         self.currentBox = currentVBox
344
345         totalVBox = gtk.VBox(spacing=1)
346         totalVBox.add(self.new_label_heading("Total"))
347         totalVBox.add(self.labelsT["timer"])
348         totalVBox.add(self.labelsT["count"])
349         totalVBox.add(self.labelsT["dist"])
350         totalVBox.add(self.labelsT["avgSpeed"])
351         self.totalBox = totalVBox
352
353         buttonVBox = gtk.VBox(spacing=1)
354         buttonVBox.add(self.new_label_heading(""))
355         buttonVBox.add(self.button)
356         buttonVBox.add(self.new_label_heading(""))
357
358         mainHBox.add(buttonVBox)
359         mainHBox.add(descVBox)
360         mainHBox.add(currentVBox)
361         mainHBox.add(totalVBox)
362
363         self.mainhbox = mainHBox
364
365         mainHBox.show_all()
366         self.add(mainHBox)
367         self.update_aspect()
368
369         self.connect("unrealize", self.close_requested)
370         self.set_settings(True)
371         self.connect("show-settings", self.show_settings)
372
373     def new_label_heading(self, title=""):
374         l = gtk.Label(title)
375         hildon.hildon_helper_set_logical_font(l, "SmallSystemFont")
376         return l
377
378     def create_labels(self, new_labels):
379         for label in self.labels:
380             l = gtk.Label()
381             hildon.hildon_helper_set_logical_font(l, "SmallSystemFont")
382             hildon.hildon_helper_set_logical_color(l, gtk.RC_FG, gtk.STATE_NORMAL, "ActiveTextColor")
383             new_labels[label] = l
384
385     def update_aspect(self):
386         if self.aspect == 0:
387             self.currentBox.show_all()
388             self.totalBox.show_all()
389         elif self.aspect == 1:
390             self.currentBox.show_all()
391             self.totalBox.hide_all()
392         else:
393             self.currentBox.hide_all()
394             self.totalBox.show_all()
395
396     def update_ui_values(self, labels, timer, steps):
397         def get_str_distance(meters):
398             if meters > 1000:
399                 if self.unit == 0:
400                     return "%.2f km" % (meters/1000)
401                 else:
402                     return "%.2f mi" % (meters/1609.344)
403             else:
404                 if self.unit == 0:
405                     return "%d m" % meters
406                 else:
407                     return "%d ft" % int(meters*3.2808)
408
409         def get_avg_speed(timer, dist):
410             suffix = ""
411             conv = 0
412             if self.unit:
413                 suffix = "mi/h"
414                 conv = 2.23693629
415             else:
416                 suffix = "km/h"
417                 conv = 3.6
418
419             if timer == 0:
420                 return "N/A " + suffix
421             speed = 1.0 *dist / timer
422             #convert from meters per second to km/h or mi/h
423             speed *= conv
424             return "%.2f %s" % (speed, suffix)
425
426         tdelta = timer
427         hours = int(tdelta / 3600)
428         tdelta -= 3600 * hours
429         mins = int(tdelta / 60)
430         tdelta -= 60 * mins
431         secs = int(tdelta)
432
433         strtime = "%.2d:%.2d:%.2d" % ( hours, mins, secs)
434
435         labels["timer"].set_label(strtime)
436         labels["count"].set_label(str(steps))
437
438         dist = self.pedometer.get_distance(steps)
439
440         labels["dist"].set_label(get_str_distance(dist))
441         labels["avgSpeed"].set_label(get_avg_speed(timer, dist))
442
443     def update_current(self):
444         self.update_ui_values(self.labelsC, self.time, self.counter)
445
446     def update_total(self):
447         self.update_ui_values(self.labelsT, self.totalTime, self.totalCounter)
448
449     def show_settings(self, widget):
450         def reset_total_counter(arg):
451             widget.totalCounter = 0
452             widget.totalTime = 0
453             widget.update_total()
454             hildon.hildon_banner_show_information(self,"None", "Total counter was resetted")
455
456         def selector_changed(selector, data):
457             widget.mode = selector.get_active(0)
458             widget.client.set_int(MODE, widget.mode)
459             widget.pedometer.set_mode(widget.mode)
460             widget.pedometer.set_height(widget.height)
461             widget.update_current()
462             widget.update_total()
463
464         def selectorH_changed(selector, data):
465             widget.height = selectorH.get_active(0)
466             widget.client.set_int(HEIGHT, widget.height)
467             widget.pedometer.set_height(widget.height)
468             widget.update_current()
469             widget.update_total()
470
471
472         def selectorUnit_changed(selector, data):
473             widget.unit = selectorUnit.get_active(0)
474             widget.client.set_int(UNIT, widget.unit)
475             widget.update_current()
476             widget.update_total()
477
478         def selectorUI_changed(selector, data):
479             widget.aspect = selectorUI.get_active(0)
480             widget.client.set_int(ASPECT, widget.aspect)
481             widget.update_aspect()
482
483         def logButton_changed(checkButton):
484             widget.logging = checkButton.get_active()
485             widget.client.set_bool(LOGGING, widget.logging)
486
487         dialog = gtk.Dialog()
488         dialog.set_transient_for(self)
489         dialog.set_title("Settings")
490
491         dialog.add_button("OK", gtk.RESPONSE_OK)
492         button = hildon.Button(gtk.HILDON_SIZE_AUTO_WIDTH | gtk.HILDON_SIZE_FINGER_HEIGHT, hildon.BUTTON_ARRANGEMENT_VERTICAL)
493         button.set_title("Reset total counter")
494         button.set_alignment(0, 0.8, 1, 1)
495         button.connect("clicked", reset_total_counter)
496
497         selector = hildon.TouchSelector(text=True)
498         selector.set_column_selection_mode(hildon.TOUCH_SELECTOR_SELECTION_MODE_SINGLE)
499         selector.append_text("Walk")
500         selector.append_text("Run")
501         selector.connect("changed", selector_changed)
502
503         modePicker = hildon.PickerButton(gtk.HILDON_SIZE_AUTO_WIDTH | gtk.HILDON_SIZE_FINGER_HEIGHT, hildon.BUTTON_ARRANGEMENT_VERTICAL)
504         modePicker.set_alignment(0.0, 0.5, 1.0, 1.0)
505         modePicker.set_title("Select mode")
506         modePicker.set_selector(selector)
507         modePicker.set_active(widget.mode)
508
509         selectorH = hildon.TouchSelector(text=True)
510         selectorH.set_column_selection_mode(hildon.TOUCH_SELECTOR_SELECTION_MODE_SINGLE)
511         selectorH.append_text("< 1.50 m")
512         selectorH.append_text("1.50 - 1.65 m")
513         selectorH.append_text("1.66 - 1.80 m")
514         selectorH.append_text("1.81 - 1.95 m")
515         selectorH.append_text(" > 1.95 m")
516         selectorH.connect("changed", selectorH_changed)
517
518         heightPicker = hildon.PickerButton(gtk.HILDON_SIZE_AUTO_WIDTH | gtk.HILDON_SIZE_FINGER_HEIGHT, hildon.BUTTON_ARRANGEMENT_VERTICAL)
519         heightPicker.set_alignment(0.0, 0.5, 1.0, 1.0)
520         heightPicker.set_title("Select height")
521         heightPicker.set_selector(selectorH)
522         heightPicker.set_active(widget.height)
523
524         selectorUnit = hildon.TouchSelector(text=True)
525         selectorUnit.set_column_selection_mode(hildon.TOUCH_SELECTOR_SELECTION_MODE_SINGLE)
526         selectorUnit.append_text("Metric (km)")
527         selectorUnit.append_text("English (mi)")
528         selectorUnit.connect("changed", selectorUnit_changed)
529
530         unitPicker = hildon.PickerButton(gtk.HILDON_SIZE_AUTO_WIDTH | gtk.HILDON_SIZE_FINGER_HEIGHT, hildon.BUTTON_ARRANGEMENT_VERTICAL)
531         unitPicker.set_alignment(0.0, 0.5, 1.0, 1.0)
532         unitPicker.set_title("Units")
533         unitPicker.set_selector(selectorUnit)
534         unitPicker.set_active(widget.unit)
535
536         selectorUI = hildon.TouchSelector(text=True)
537         selectorUI = hildon.TouchSelector(text=True)
538         selectorUI.set_column_selection_mode(hildon.TOUCH_SELECTOR_SELECTION_MODE_SINGLE)
539         selectorUI.append_text("Show current + total")
540         selectorUI.append_text("Show only current")
541         selectorUI.append_text("Show only total")
542         selectorUI.connect("changed", selectorUI_changed)
543
544         UIPicker = hildon.PickerButton(gtk.HILDON_SIZE_AUTO_WIDTH | gtk.HILDON_SIZE_FINGER_HEIGHT, hildon.BUTTON_ARRANGEMENT_VERTICAL)
545         UIPicker.set_alignment(0.0, 0.5, 1.0, 1.0)
546         UIPicker.set_title("Widget aspect")
547         UIPicker.set_selector(selectorUI)
548         UIPicker.set_active(widget.aspect)
549
550         logButton = hildon.CheckButton(gtk.HILDON_SIZE_AUTO_WIDTH | gtk.HILDON_SIZE_FINGER_HEIGHT)
551         logButton.set_label("Log data")
552         logButton.set_active(widget.logging)
553         logButton.connect("toggled", logButton_changed)
554
555         pan_area = hildon.PannableArea()
556         vbox = gtk.VBox()
557         vbox.add(button)
558         vbox.add(modePicker)
559         vbox.add(heightPicker)
560         vbox.add(unitPicker)
561         vbox.add(UIPicker)
562         vbox.add(logButton)
563
564         pan_area.add_with_viewport(vbox)
565         pan_area.set_size_request(-1, 600)
566         dialog.vbox.add(pan_area)
567         dialog.show_all()
568         response = dialog.run()
569         #hildon.hildon_banner_show_information(self, "None", "You have to Stop/Start the counter to apply the new settings")
570         dialog.destroy()
571
572     def close_requested(self, widget):
573         if self.pedometer is None:
574             return
575
576         self.pedometer.request_stop()
577         if self.pedometer.isAlive():
578             self.pedometer.join()
579
580     def update_values(self, totalCurent, lastInterval):
581         self.totalCounter += lastInterval
582         self.counter = totalCurent
583
584         tdelta = time.time() - self.time - self.startTime
585         self.time += tdelta
586         self.totalTime += tdelta
587
588         self.update_current()
589         self.update_total()
590
591     def button_clicked(self, button):
592         if self.pedometer is not None and self.pedometer.isAlive():
593             #counter is running
594             self.pedometer.request_stop()
595             self.pedometer.join()
596             self.client.set_int(COUNTER, self.totalCounter)
597             self.client.set_int(TIMER, int(self.totalTime))
598             #self.button.set_label("Start")
599             self.button.set_icon(ICONSPATH + "play.png")
600         else:
601             self.pedometer = PedoCounter(self.update_values)
602             self.pedometer.set_mode(self.mode)
603             self.pedometer.set_height(self.height)
604             self.pedometer.set_logging(self.logging)
605
606             self.time = 0
607             self.counter = 0
608
609             self.update_current()
610
611             self.pedometer.start()
612             self.startTime = time.time()
613             #self.button.set_label("Stop")
614             self.button.set_icon(ICONSPATH + "stop.png")
615
616     def do_expose_event(self, event):
617         cr = self.window.cairo_create()
618         cr.region(event.window.get_clip_region())
619         cr.clip()
620         #cr.set_source_rgba(0.4, 0.64, 0.564, 0.5)
621         style = self.rc_get_style()
622         color = style.lookup_color("DefaultBackgroundColor")
623         cr.set_source_rgba (color.red/65535.0, color.green/65335.0, color.blue/65535.0, 0.75);
624
625         radius = 5
626         width = self.allocation.width
627         height = self.allocation.height
628
629         x = self.allocation.x
630         y = self.allocation.y
631
632         cr.move_to(x+radius, y)
633         cr.line_to(x + width - radius, y)
634         cr.curve_to(x + width - radius, y, x + width, y, x + width, y + radius)
635         cr.line_to(x + width, y + height - radius)
636         cr.curve_to(x + width, y + height - radius, x + width, y + height, x + width - radius, y + height)
637         cr.line_to(x + radius, y + height)
638         cr.curve_to(x + radius, y + height, x, y + height, x, y + height - radius)
639         cr.line_to(x, y + radius)
640         cr.curve_to(x, y + radius, x, y, x + radius, y)
641
642         cr.set_operator(cairo.OPERATOR_SOURCE)
643         cr.fill_preserve()
644
645         color = style.lookup_color("ActiveTextColor")
646         cr.set_source_rgba (color.red/65535.0, color.green/65335.0, color.blue/65535.0, 0.5);
647         cr.set_line_width(1)
648         cr.stroke()
649
650         hildondesktop.HomePluginItem.do_expose_event(self, event)
651
652     def do_realize(self):
653         screen = self.get_screen()
654         self.set_colormap(screen.get_rgba_colormap())
655         self.set_app_paintable(True)
656         hildondesktop.HomePluginItem.do_realize(self)
657
658 hd_plugin_type = PedometerHomePlugin
659
660 # The code below is just for testing purposes.
661 # It allows to run the widget as a standalone process.
662 if __name__ == "__main__":
663     import gobject
664     gobject.type_register(hd_plugin_type)
665     obj = gobject.new(hd_plugin_type, plugin_id="plugin_id")
666     obj.show_all()
667     gtk.main()
668
669 ############### old pedometer.py ###
670 import math
671 import logging
672
673 from threading import Thread
674
675 logger = logging.getLogger("pedometer")
676 logger.setLevel(logging.INFO)
677
678 ch = logging.StreamHandler()
679 formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
680 ch.setFormatter(formatter)
681 logger.addHandler(ch)
682