Merge branch 'master' into gregoa
[gregoa/zavai.git] / test / test-gsm-receive.vala
1 /*
2  * test-gsm-receive - Play with receiving GSM data
3  *
4  * Copyright (C) 2010  Enrico Zini <enrico@enricozini.org>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 using GLib;
22
23 public DBus.Connection sbus;
24
25 //string VERSION = "0.1";
26
27 public class GSMReceive: Object //, zavai.Resource
28 {
29     public dynamic DBus.Object device;
30     public dynamic DBus.Object network;
31     public dynamic DBus.Object sim;
32     public dynamic DBus.Object call;
33
34     public GSMReceive()
35     {
36         //zavai.gsm.gsm.request("GSMReceive");
37
38         device = sbus.get_object(
39                     "org.freesmartphone.ogsmd",
40                     "/org/freesmartphone/GSM/Device",
41                     "org.freesmartphone.GSM.Device");
42
43         network = sbus.get_object(
44             "org.freesmartphone.ogsmd", 
45             "/org/freesmartphone/GSM/Device",
46             "org.freesmartphone.GSM.Network");
47         sim = sbus.get_object(
48             "org.freesmartphone.ogsmd", 
49             "/org/freesmartphone/GSM/Device",
50             "org.freesmartphone.GSM.SIM");
51
52         call = sbus.get_object(
53                 "org.freesmartphone.ogsmd",
54                 "/org/freesmartphone/GSM/Device",
55                 "org.freesmartphone.GSM.Call");
56
57         stderr.printf("Antenna is %s\n", device.GetAntennaPower() ? "on" : "off");
58         stderr.printf("Signal strength: %d\n", network.GetSignalStrength());
59         stderr.printf("Calling identification: %s\n", network.GetCallingIdentification());
60         GLib.HashTable<string, GLib.Value?> status = network.GetStatus();
61         stderr.printf("Network status:\n");
62         dump_table(status);
63
64         network.Status += on_network_Status;
65         network.SignalStrength += on_network_SignalStrength;
66         call.CallStatus += on_call_Status;
67         sim.IncomingStoredMessage += on_sim_IncomingStoredMessage;
68     }
69
70     public void shutdown()
71     {
72         //zavai.gsm.gsm.release("GSMReceive");
73     }
74
75     protected void dump_table(HashTable<string, Value?> vals)
76     {
77         vals.for_each((pk, pv) => {
78                 string k = (string)pk;
79                 Value? v = (Value?)pv;
80                 stderr.printf("K: %s V: %s\n", k, v == null ? "(null)" : v.strdup_contents());
81         });
82     }
83
84     public void on_sim_IncomingStoredMessage(DBus.Object sender, int index)
85     {
86         stderr.printf("INCOMING STORED MESSAGE %d\n", index);
87         dump_message(index);
88     }
89
90     public void dump_message(int index)
91     {
92         string state, sender, msg;
93         GLib.HashTable<string, GLib.Value?> info;
94         sim.RetrieveMessage(index, out state, out sender, out msg, out info);
95         stderr.printf("state: %s\n", state);
96         stderr.printf("sender: %s\n", sender);
97         stderr.printf("msg: %s\n", msg);
98         dump_table(info);
99     }
100
101     public void on_network_SignalStrength(DBus.Object sender, int strength)
102     {
103         stderr.printf("SIGNAL STRENGTH %d\n", strength);
104     }
105
106     public void on_network_Status(DBus.Object sender, HashTable<string, Value?> status)
107     {
108         stderr.printf("NETWORK STATUS\n");
109         dump_table(status);
110
111         // dbg("cbNetworkStatus %s" % formatDict(status))
112     }
113
114     public void on_call_Status(DBus.Object sender, int index, string status, HashTable<string, Value?> properties)
115     {
116         stderr.printf("CALL STATUS %d %s\n", index, status);
117         dump_table(properties);
118         /*
119         dbg("cbCallStatus %d, %s, %s" % (id, status, formatDict(properties)))
120         self.status = status
121         if status == "incoming":
122             if "peer" in properties and properties["peer"] == "+358942832031":
123                 self.gsm_call_iface.ReleaseAll()
124                 os.system("kapula-debug-call-handler &")
125             else:
126                 os.system("alsactl restore -f /etc/alsa-scenarios/stereoout-maxvolume.state")
127                 os.system("vibrator-start")
128                 os.system("ringtone-start")
129                 os.system("ledctrl --on-time 400 --off-time 200 gta02-aux:red");
130         if status == "release":
131             os.system("ringtone-stop")
132             os.system("vibrator-stop")
133             os.system("ledctrl --off gta02-aux:red");
134         */
135     }
136
137
138 /*
139         def onIncomingUssd( self, mode, message ):
140                 logger.info( "USSD Message: %s" % message )
141                         self.main.groups["alert"].activate( "<title>Operator Message</title>%s" % message, [("OK")] )
142     def onCallStatus( self, id, status, properties ):
143         self.call = id
144         self.update_status(status)
145         if not status in ["release"]:
146             if "peer" in properties:
147                 self.part_text_set( "label", self.main.groups["contacts"].tryNumberToName( properties[ "peer" ] ) )
148                 self.part_text_set( "sublabel", properties[ "peer" ] )
149             else:
150                 self.part_text_set( "label", _("unknown number") )
151                 self.part_text_set( "sublabel", "" )
152
153     @edje.decorators.signal_callback( "mouse,clicked,1", "button_*" )
154     def on_edje_signal_dialer_button_pressed(self, emission, source):
155         key = source.split("_", 1)[1]
156         if key in ("0", "1", "2", "3", "4", "5", "6", "7", "8", "9"):
157             dbus_object.gsm_call_iface.SendDtmf( key )
158             self.text.append(key)
159         elif key in "star":
160             dbus_object.gsm_call_iface.SendDtmf( "*" )
161             self.text.append("*")
162         elif key in "hash":
163             dbus_object.gsm_call_iface.SendDtmf( "#" )
164             self.text += "#"
165         # The trailing whitespace is a workaround for the one char invisible
166         # bug due to some problems with scaling of text parts.
167         self.part_text_set("label", "".join(self.text)+" ")
168
169     @edje.decorators.signal_callback("call_button_pressed", "button_right")
170     def on_edje_signal_call_button_right_pressed(self, emission, source):
171         self.main.transition_to("call")
172
173     def sendMessage( self, index ):
174         logger.info( "trying to send message w/ index %d..." % index )
175         dbus_object.gsm_sim_iface.SendStoredMessage( index, reply_handler=self.cbSendReply, error_handler=self.cbSendError )
176
177     def cbSendReply( self, reference, timestamp ):
178         logger.info( "sent message successfully w/ reference number %d (timestamp: %s)" % ( reference, timestamp ) )
179
180     def cbSendError( self, e ):
181         logger.error( "could not send message. leaving in outgoing. error was: %s" % e )
182
183     def cbStoreReply( self, result ):
184         logger.info( "stored message lives at SIM position %d" % result )
185         self.sendMessage( result )
186         if not self.busy:
187             dbus_object.gsm_sim_iface.RetrieveMessagebook(
188                 "all",
189                 reply_handler=self.cbMessagebookReply,
190                 error_handler=self.cbMessagebookError
191             )
192             self.busy = True
193
194     def cbStoreError( self, e ):
195         logger.warning( "error while storing message - %s" % e.get_dbus_name() )
196         if e.get_dbus_name() == "org.freesmartphone.GSM.SIM.MemoryFull":
197             self.main.groups["alert"].activate( "<title>Failed to send message</title>SIM Memory Full", [("OK")] )
198
199     def cbSend1( self, selected, cb_data ):
200         self.main.groups["text_edit"].setup(
201             "sms",
202             "", # text
203             selected[0], # title
204             selected[1], # reference
205             self.cbSend2
206         )
207
208     def cbSend2( self, text, number ):
209         if dbus_object.gsm_device_obj:
210             dbus_object.gsm_sim_iface.StoreMessage(
211                 number, text, {},
212                 reply_handler=self.cbStoreReply,
213                 error_handler=self.cbStoreError
214             )
215
216     def cbDelete( self, result, reference ):
217         if result == "abort":
218             return
219         if dbus_object.gsm_device_obj:
220             dbus_object.gsm_sim_iface.DeleteMessage(
221                 reference
222             )
223         for i in range( len( self.messagebook ) ):
224             if self.messagebook[i][0] == reference:
225                 del self.messagebook[i]
226                 break
227         self.updateList()
228
229     def cbForward( self, selected, text ):
230         if dbus_object.gsm_device_obj:
231             dbus_object.gsm_sim_iface.StoreMessage(
232                 selected[1], text, {},
233                 reply_handler=self.cbStoreReply,
234                 error_handler=self.cbStoreError
235             )
236
237     def cbReply( self, text, number):
238         if dbus_object.gsm_device_obj:
239             dbus_object.gsm_sim_iface.StoreMessage(
240                 number, text, {},
241                 reply_handler=self.cbStoreReply,
242                 error_handler=self.cbStoreError
243             )
244
245     def cbMenu( self, result ):
246         if result == _("send"):
247             self.main.groups["contacts"].prepare()
248             if self.main.groups["contacts"].ready:
249                 self.main.groups["list_choose"].setup(
250                     "sms",
251                     [ (x[1], x[2]) for x in  self.main.groups["contacts"].phonebook],
252                     None,
253                     self.cbSend1
254                 )
255         elif result == _("delete"):
256             self.main.groups["alert"].activate(
257                 _("delete?"),
258                 (_("abort"), _("delete")),
259                 self.current[self.selected][0], # reference
260                 self.cbDelete
261             )
262         elif result == _("forward"):
263             self.main.groups["contacts"].prepare()
264             if self.main.groups["contacts"].ready:
265                 self.main.groups["list_choose"].setup(
266                     "sms",
267                     [ (x[1], x[2] ) for x in  self.main.groups["contacts"].phonebook],
268                     self.current[self.selected][3],
269                     self.cbForward
270                 )
271         elif result == _("reply"):
272             self.main.groups["text_edit"].setup(
273                 "sms",
274                 "", # text
275                 self.current[self.selected][2], # title = number
276                 self.current[self.selected][2], # reference = number
277                 self.cbReply
278             )
279
280     def cbMessagebookReply( self, result ):
281         logger.info( "retrieved messagebook: %s" % result )
282         self.busy = False
283         self.messagebook = result
284         self.ready = True
285         self.updateList()
286         self.main.groups["main"].targets["sms"] = True
287         self.main.groups["main"].update()
288         if not self.newindex is None:
289             message = [x for x in self.messagebook if x[0] == self.newindex]
290             self.newindex = None
291             if message and self.main.current_group == self.main.groups["main"]:
292                 message = message[0]
293                 if "read" in message[1]:
294                     from_to = _("From")
295                     timestamp = message[4]["timestamp"]
296                 else:
297                     from_to = _("To")
298                     timestamp = _("Unknown")
299                 from_text = self.main.groups["contacts"].tryNumberToName( message[2] )
300                 self.main.groups["text_show"].setup(
301                     "sms",
302                     _("%s: %s<br>Date: %s<p>%s") % (
303                         from_to,
304                         from_text,
305                         timestamp,
306                         textblock_escape( message[3] ).replace( '\n', '<br>' )
307                     )
308                 )
309             if dbus_object.gsm_device_obj:
310                 messagebookInfo = dbus_object.gsm_sim_iface.GetMessagebookInfo()
311                 if messagebookInfo["used"] == messagebookInfo["last"]:
312                     self.main.groups["alert"].activate( "<title>Warning</title>SIM Memory Full", [("OK")] )
313
314     def cbMessagebookError( self, e ):
315         logger.warning( "error while retrieving messagebook" )
316         self.busy = False
317
318     def onIncomingMessage( self, index ):
319         logger.info( "new message! Retrieving messagebook..." )
320         self.newindex = index
321         if not self.busy:
322             dbus_object.gsm_sim_iface.RetrieveMessagebook(
323                 "all",
324                 reply_handler=self.cbMessagebookReply,
325                 error_handler=self.cbMessagebookError
326             )
327             self.busy = True
328
329     def prepare( self ):
330         if not self.ready and not self.busy:
331             if dbus_object.gsm_device_obj:
332                 logger.info( "retrieving messagebook..." )
333                 dbus_object.gsm_sim_iface.RetrieveMessagebook(
334                     "all",
335                     reply_handler=self.cbMessagebookReply,
336                     error_handler=self.cbMessagebookError
337                 )
338                 self.busy = True
339             else:
340                 # Fake messagebook...
341                 self.cbMessagebookReply( [
342                     (0, "read", "+4544555", "Hello World!"),
343                     (1, "read", "+456663443", "Zhone!"),
344                     (2, "read", "+456663443", "Hi Guy\nGuess what, I now "+
345                         "know to write multi-line SMSs.\nIsn't that "+
346                         "nice?\n\nSome Buddy"),
347                     (3, "read", "Flash SMS", "An SMS without digits. Strange, isn't it?"),
348                 ] )
349
350     def onReadyStatus( self, status ):
351         logger.debug( "SIM is ready: %s" % status )
352         if status:
353             # Force update
354             self.ready = False
355             self.prepare()
356
357     def onShow( self ):
358         self.prepare()
359         self.updateList()
360
361     def updateList( self):
362         self.main.groups["contacts"].prepare()
363         self.pages = max( ( len( self.messagebook ) - 1 ) / 6 + 1, 1 )
364         if self.page >= self.pages:
365             self.page = self.pages - 1
366         if self.page < 0:
367             self.page = 0
368         self.current = self.messagebook[self.page*6:(self.page+1)*6]
369         text = u"".join( [u"□"]*self.page+[u"▣"]+[u"□"]*(self.pages-self.page-1) )
370         self.part_text_set( "pager", text )
371         for i in range( 0, len( self.current ) ):
372             main_text = self.main.groups["contacts"].tryNumberToName( self.current[i][2] )
373             self.part_text_set( "label_main_list_%i" % i, main_text )
374             sub_text = " ".join(self.current[i][3].splitlines())
375             self.part_text_set( "label_sub_list_%i" % i, u"(%s) %s" % ( self.current[i][1], sub_text ) )
376         for i in range( len( self.current ), 6):
377             self.part_text_set( "label_main_list_%i" % i, u"" )
378             self.part_text_set( "label_sub_list_%i" % i, u"" )
379         self.selected = None
380         for i in range( 6 ):
381             self.signal_emit( "deactivate_target_list_%i" % i, "" )
382
383
384     @edje.decorators.signal_callback( "mouse,clicked,1", "target_list_*" )
385     def on_edje_signal_button_list_pressed( self, emission, source ):
386         id = int( source.split( "_" )[-1] )
387         if self.selected == id:
388             return
389         if self.selected is not None:
390             self.signal_emit( "deactivate_target_list_%i" % self.selected, "" )
391         self.signal_emit( "activate_target_list_%i" % id, "" )
392         self.selected = id
393
394     @edje.decorators.signal_callback( "mouse,clicked,1", "button_action_left" )
395     def on_edje_signal_button_action_left_pressed( self, emission, source ):
396         self.page -= 1
397         self.updateList()
398
399     @edje.decorators.signal_callback( "mouse,clicked,1", "button_action_right" )
400     def on_edje_signal_button_action_right_pressed( self, emission, source ):
401         self.page += 1
402         self.updateList()
403
404     @edje.decorators.signal_callback( "mouse,clicked,1", "button_action_open" )
405     def on_edje_signal_button_action_open_pressed( self, emission, source ):
406         if self.selected is not None:
407             if "read" in self.current[self.selected][1]:
408                 from_to = _("From")
409                 timestamp = self.current[self.selected][4]["timestamp"]
410             else:
411                 from_to = _("To")
412                 timestamp = _("Unknown")
413             from_text = self.main.groups["contacts"].tryNumberToName( self.current[self.selected][2] )
414             self.main.groups["text_show"].setup(
415                 "sms",
416                 _("%s: %s<br>Date: %s<p>%s") % (
417                     from_to,
418                     from_text,
419                     timestamp,
420                     textblock_escape( self.current[self.selected][3] ).replace( '\n', '<br>' )
421                 )
422             )
423
424     @edje.decorators.signal_callback( "mouse,clicked,1", "button_bottom_middle" )
425     def on_edje_signal_button_bottom_middle_pressed( self, emission, source ):
426         self.main.groups["menu"].activate( ( _("send"), _("delete"), _("forward"), _("reply") ), self.cbMenu )
427         self.main.groups["menu"].part_text_set( "target_label_cancel", _("cancel") )
428 */
429 }
430
431 static int main (string[] args) {
432         Gtk.init (ref args);
433     // Gst.init (ref args);
434
435         // Set up zavai
436         sbus = DBus.Bus.get(DBus.BusType.SYSTEM);
437
438     // Core infrastructure
439 //      zavai.config = new zavai.Config();
440 //      zavai.config.argv0 = args[0];
441 //      zavai.registry = new zavai.Registry();
442
443     // Additional infrastructure
444         //zavai.gsm.init();
445         //zavai.log.init();
446
447     // PLAY here
448     var gr = new GSMReceive();
449
450         if (args.length > 1)
451                 gr.dump_message(args[1].to_int());
452
453         Gtk.main();
454
455         // zavai.info("Shutting down")
456         // zavai.registry.shutdown();
457
458         return 0;
459 }