system-controller: added AIL support for getting application categories.
[profile/ivi/murphy.git] / packaging.in / murphy.lua
1 with_system_controller = false
2 with_amb = false
3 verbose = 0
4
5 m = murphy.get()
6
7 -- try loading the various logging plugins
8 m:try_load_plugin('systemd')
9 m:try_load_plugin('dlog')
10
11 -- load the console plugin
12 m:try_load_plugin('console')
13
14 m:try_load_plugin('console.disabled', 'webconsole', {
15                   address = 'wsck:127.0.0.1:3000/murphy',
16                   httpdir = '/usr/share/murphy/webconsole' });
17
18 -- load the dbus plugin
19 if m:plugin_exists('dbus') then
20     m:load_plugin('dbus')
21 end
22
23 -- load the native resource plugin
24 if m:plugin_exists('resource-native') then
25     m:load_plugin('resource-native')
26     m:info("native resource plugin loaded")
27 else
28     m:info("No native resource plugin found...")
29 end
30
31 -- load the dbus resource plugin
32 m:try_load_plugin('resource-dbus', {
33     dbus_bus = "system",
34     dbus_service = "org.Murphy",
35     dbus_track = true,
36     default_zone = "driver",
37     default_class = "implicit"
38 })
39
40 -- load the domain control plugin
41 if m:plugin_exists('domain-control') then
42     m:load_plugin('domain-control')
43 else
44     m:info("No domain-control plugin found...")
45 end
46
47 if m:plugin_exists('glib') then
48     m:load_plugin('glib')
49 else
50     m:info("No glib plugin found...")
51 end
52
53 -- load the AMB plugin
54 if m:plugin_exists('amb') then
55     m:try_load_plugin('amb')
56
57     if builtin.method.amb_initiate and
58        builtin.method.amb_update
59     then
60         with_amb = true
61     end
62 else
63     m:info("No amb plugin found...")
64 end
65
66 -- load the ASM resource plugin
67 if m:plugin_exists('resource-asm') then
68     m:try_load_plugin('resource-asm', {
69         zone = "driver",
70         share_mmplayer = "player:AVP,mandatory,exclusive,strict",
71         ignored_argv0 = "WebProcess"
72     })
73 else
74     m:info("No audio session manager plugin found...")
75 end
76
77 if m:plugin_exists('system-controller') then
78     with_system_controller = true
79 elseif m:plugin_exists('ivi-resource-manager') then
80     m:load_plugin('ivi-resource-manager')
81     with_system_controller = false
82 end
83
84 -- define application classes
85 application_class {
86     name     = "interrupt",
87     priority = 99,
88     modal    = true ,
89     share    = false,
90     order    = "fifo"
91 }
92
93 application_class {
94     name     = "emergency",
95     priority = 80,
96     modal    = false,
97     share    = false,
98     order    = "fifo"
99 }
100 application_class {
101     name     = "alert",
102     priority = 51,
103     modal    = false,
104     share    = false,
105     order    = "fifo"
106 }
107
108 application_class {
109     name     = "navigator",
110     priority = 50,
111     modal    = false,
112     share    = true,
113     order    = "fifo"
114 }
115
116 application_class {
117     name     = "phone",
118     priority = 6 ,
119     modal    = false,
120     share    = true ,
121     order    = "lifo"
122 }
123 application_class {
124     name     = "camera",
125     priority = 5,
126     modal    = false,
127     share    = false,
128     order    = "lifo"
129 }
130
131 application_class { name="event"    , priority=4 , modal=false, share=true , order="fifo" }
132 application_class { name="game"     , priority=3 , modal=false, share=false, order="lifo" }
133 --# doesn't need to be created here, ivi-resource-manager creates it if loaded
134 --#application_class { name="basic"    , priority=2 , modal=false, share=false, order="lifo" }
135 application_class { name="player"   , priority=1 , modal=false, share=true , order="lifo" }
136 application_class { name="implicit" , priority=0 , modal=false, share=false, order="lifo" }
137
138 -- define zone attributes
139 zone.attributes {
140     type = {mdb.string, "common", "rw"},
141     location = {mdb.string, "anywhere", "rw"}
142 }
143
144 -- define zones
145 zone {
146      name = "driver",
147      attributes = {
148          type = "common",
149          location = "front-left"
150      }
151 }
152
153 zone {
154      name = "passanger1",
155      attributes = {
156          type = "private",
157          location = "front-right"
158      }
159 }
160
161 zone {
162      name = "passanger2",
163      attributes = {
164          type = "private",
165          location = "back-left"
166      }
167 }
168
169 zone {
170      name = "passanger3",
171      attributes = {
172          type = "private",
173          location = "back-right"
174      }
175 }
176
177 zone {
178      name = "passanger4",
179      attributes = {
180          type = "private",
181          location = "back-left"
182      }
183 }
184
185
186 -- define resource classes
187 if not m:plugin_exists('ivi-resource-manager') and
188    not with_system_controller
189 then
190    resource.class {
191         name = "audio_playback",
192         shareable = true,
193         attributes = {
194             role = { mdb.string, "music", "rw" },
195             pid = { mdb.string, "<unknown>", "rw" },
196             policy = { mdb.string, "relaxed", "rw" }
197         }
198    }
199 end
200
201 resource.class {
202      name = "audio_recording",
203      shareable = true,
204      attributes = {
205          role   = { mdb.string, "music"    , "rw" },
206          pid    = { mdb.string, "<unknown>", "rw" },
207          policy = { mdb.string, "relaxed"  , "rw" }
208      }
209 }
210
211 resource.class {
212      name = "video_playback",
213      shareable = false,
214 }
215
216 resource.class {
217      name = "video_recording",
218      shareable = false
219 }
220
221 resource.class {
222      name = "speech_recognition",
223      shareable = true
224 }
225
226 resource.class {
227      name = "speech_synthesis",
228      shareable = true
229 }
230
231 if not m:plugin_exists('ivi-resource-manager') and
232    not with_system_controller
233 then
234     resource.method.veto = {
235         function(zone, rset, grant, owners, req_set)
236             return true
237          end
238     }
239 end
240
241 -- test for creating selections
242 mdb.select {
243            name = "audio_owner",
244            table = "audio_playback_owner",
245            columns = {"application_class"},
246            condition = "zone_name = 'driver'"
247 }
248
249 mdb.select {
250            name = "vehicle_speed",
251            table = "amb_vehicle_speed",
252            columns = {"value"},
253            condition = "key = 'VehicleSpeed'"
254 }
255
256 element.lua {
257    name    = "speed2volume",
258    inputs  = { speed = mdb.select.vehicle_speed, param = 9 },
259    outputs = {  mdb.table { name = "speedvol",
260                             index = {"zone", "device"},
261                             columns = {{"zone", mdb.string, 16},
262                                        {"device", mdb.string, 16},
263                                        {"value", mdb.floating}},
264                             create = true
265                            }
266              },
267    oldvolume = 0.0,
268    update  = function(self)
269                 speed = self.inputs.speed.single_value
270                 if (speed) then
271                     volume = (speed - 144.0) / 7.0
272                 else
273                     volume = 0.0
274                 end
275                 diff = volume - self.oldvolume
276                 if (diff*diff > self.inputs.param) then
277                     print("*** element "..self.name.." update "..volume)
278                     self.oldvolume = volume
279                     mdb.table.speedvol:replace({zone = "driver", device = "speakers", value = volume})
280                 end
281              end
282 }
283
284 mdb.select {
285     name = "amb_state",
286     table = "amb_state",
287     columns = { "state" },
288     condition = "id = 0"
289 }
290
291 -- Night mode processing chain
292
293 mdb.select {
294     name = "exterior_brightness",
295     table = "amb_exterior_brightness",
296     columns = { "value" },
297     condition = "key = 'ExteriorBrightness'"
298 }
299
300 element.lua {
301     name    = "nightmode",
302     inputs  = { brightness = mdb.select.exterior_brightness },
303     oldmode = -1;
304     outputs = {
305         mdb.table {
306             name = "amb_nightmode",
307             index = { "id" },
308             create = true,
309             columns = {
310                 { "id", mdb.unsigned },
311                 { "night_mode", mdb.unsigned }
312             }
313         }
314     },
315     update = function(self)
316         -- This is a trivial function to calculate night mode. Later, we will
317         -- need a better threshold value and hysteresis to prevent oscillation.
318
319         brightness = self.inputs.brightness.single_value
320
321         if not brightness then
322             return
323         end
324
325         print("*** element "..self.name.." update brightness: "..brightness)
326
327         if brightness > 300 then
328             mode = 0
329         else
330             mode = 1
331         end
332
333         print("*** resulting mode: ".. mode)
334
335         if not (mode == self.oldmode) then
336             mdb.table.amb_nightmode:replace({ id = 0, night_mode = mode })
337         end
338
339         self.oldmode = mode
340     end
341 }
342
343 mdb.select {
344     name = "select_night_mode",
345     table = "amb_nightmode",
346     columns = { "night_mode" },
347     condition = "id = 0"
348 }
349
350 if with_amb then
351     sink.lua {
352         name = "night_mode",
353         inputs = { NightMode = mdb.select.select_night_mode,
354                    amb_state = mdb.select.amb_state },
355         property = "NightMode",
356         type = "b",
357         initiate = builtin.method.amb_initiate,
358         update = builtin.method.amb_update
359     }
360 end
361
362 -- Night mode general handlers
363
364 sink.lua {
365     name = "nightmode_homescreen",
366     inputs = { owner = mdb.select.select_night_mode },
367     initiate = function(self)
368         -- data = mdb.select.select_night_mode.single_value
369         return true
370     end,
371     update = function(self)
372         data = mdb.select.select_night_mode.single_value
373
374         if verbose > 1 then
375             print("Night mode updated: " .. tostring(data))
376         end
377
378         if sc then
379             -- tell homescreen that night mode was updated
380             sc:send_message(homescreen, m:JSON({command=0x60001,arg=m:JSON({stateid=2,state=data})}))
381         end
382         return true
383     end
384 }
385
386 -- Driving mode processing chain
387
388 element.lua {
389     name    = "drivingmode",
390     inputs  = { speed = mdb.select.vehicle_speed },
391     oldmode = -1;
392     outputs = {
393         mdb.table {
394             name = "amb_drivingmode",
395             index = { "id" },
396             create = true,
397             columns = {
398                 { "id", mdb.unsigned },
399                 { "driving_mode", mdb.unsigned }
400             }
401         }
402     },
403     update = function(self)
404
405         speed = self.inputs.speed.single_value
406
407         if not speed then
408             return
409         end
410
411         if speed == 0 then
412             mode = 0
413         else
414             mode = 1
415         end
416
417         if not (mode == self.oldmode) then
418             mdb.table.amb_drivingmode:replace({ id = 0, driving_mode = mode })
419         end
420
421         self.oldmode = mode
422     end
423 }
424
425 mdb.select {
426     name = "select_driving_mode",
427     table = "amb_drivingmode",
428     columns = { "driving_mode" },
429     condition = "id = 0"
430 }
431
432 if with_amb then
433     sink.lua {
434         name = "driving_mode",
435         inputs = { DrivingMode = mdb.select.select_driving_mode,
436                    amb_state = mdb.select.amb_state },
437         property = "DrivingMode",
438         type = "u",
439         initiate = builtin.method.amb_initiate,
440         update = builtin.method.amb_update
441     }
442 end
443
444 -- turn signals (left, right)
445
446 mdb.select {
447     name = "winker",
448     table = "amb_turn_signal",
449     columns = { "value" },
450     condition = "key = 'TurnSignal'"
451 }
452
453 -- define three categories
454
455 mdb.select {
456     name = "undefined_applications",
457     table = "aul_applications",
458     columns = { "appid" },
459     condition = "category = '<undefined>'"
460 }
461
462 mdb.select {
463     name = "basic_applications",
464     table = "aul_applications",
465     columns = { "appid" },
466     condition = "category = 'basic'"
467 }
468
469 mdb.select {
470     name = "entertainment_applications",
471     table = "aul_applications",
472     columns = { "appid" },
473     condition = "category = 'entertainment'"
474 }
475
476 function ft(t)
477     -- filter the object garbage out of the tables
478     ret = {}
479
480     for k,v in pairs(t) do
481         if k ~= "userdata" and k ~= "new" then
482             ret[k] = v
483         end
484     end
485
486     return ret
487 end
488
489 function getApplication(appid)
490     local conf = nil
491
492     -- find the correct local application definition
493
494     for k,v in pairs(ft(application)) do
495         if appid == v.appid then
496             conf = v
497             break
498         end
499     end
500
501     return conf
502 end
503
504 function regulateApplications(t, regulation)
505     for k,v in pairs(ft(t)) do
506
507         -- iterate through the undefined and entertainment apps, see if
508         -- they have been overruled in local config
509
510         local conf = getApplication(v.appid)
511
512         if conf and conf.resource_class ~= "player" then
513             -- override, don't disable
514             resmgr:disable_screen_by_appid("*", "*", v.appid, false)
515         else
516             resmgr:disable_screen_by_appid("*", "*", v.appid, regulation == 1)
517         end
518     end
519 end
520
521 -- regulation (on), use "select_driving_mode"
522
523 sink.lua {
524     name = "driving_regulation",
525     inputs = { owner = mdb.select.select_driving_mode },
526     initiate = function(self)
527         -- local data = mdb.select.select_driving_mode.single_value
528         return true
529     end,
530     update = function(self)
531         local data = mdb.select.select_driving_mode.single_value
532
533         if verbose > 1 then
534             print("Driving mode updated: " .. tostring(data))
535         end
536
537         if not sc then
538             return true
539         end
540
541         -- tell homescreen that driving mode was updated
542         sc:send_message(homescreen, m:JSON({command=0x60001,arg=m:JSON({stateid=1,state=data})}))
543
544         --[[
545         -- bulk handle the applications that need requisites
546         r = requisite { driving = true }
547         resmgr:disable_screen_by_requisite("*", "*", r, data == 1)
548         --]]
549
550         regulateApplications(ft(mdb.select.entertainment_applications), data)
551         regulateApplications(ft(mdb.select.undefined_applications), data)
552
553         return true
554     end
555 }
556 --[[
557 sink.lua {
558     name = "regulated_app_change",
559     inputs = { undef = mdb.select.undefined_applications,
560                entertainment = mdb.select.entertainment_applications },
561     initiate = function(self)
562         return true
563     end,
564     update = function(self)
565         local data = mdb.select.select_driving_mode.single_value
566
567         if not sc then
568             return
569         end
570
571         if verbose > 1 then
572             print("regulated application list was changed")
573         end
574
575         regulateApplications(ft(mdb.select.entertainment_applications), data)
576         regulateApplications(ft(mdb.select.undefined_applications), data)
577
578         return true
579     end
580 }
581 --]]
582
583 -- shift position (parking, reverse, other)
584
585 mdb.select {
586     name = "gear_position",
587     table = "amb_gear_position",
588     columns = { "value" },
589     condition = "key = 'GearPosition'"
590 }
591
592 -- cameras (back, front, left, right)
593
594 element.lua {
595     name    = "camera_state",
596     inputs  = { winker = mdb.select.winker, gear = mdb.select.gear_position },
597     oldmode = -1;
598     outputs = {
599         mdb.table {
600             name = "target_camera_state",
601             index = { "id" },
602             create = true,
603             columns = {
604                 { "id", mdb.unsigned },
605                 { "front_camera", mdb.unsigned },
606                 { "back_camera", mdb.unsigned },
607                 { "right_camera", mdb.unsigned },
608                 { "left_camera", mdb.unsigned }
609             }
610         }
611     },
612     update = function(self)
613
614         front_camera = 0
615         back_camera = 0
616         right_camera = 0
617         left_camera = 0
618
619         if self.inputs.gear == 128 then
620             back_camera = 1
621         elseif self.inputs.winker == 1 then
622             right_camera = 1
623         elseif self.inputs.winker == 2 then
624             left_camera = 1
625         end
626
627         mdb.table.target_camera_state:replace({ id = 0, front_camera = front_camera, back_camera = back_camera, right_camera = right_camera, left_camera = left_camera })
628
629     end
630 }
631
632 -- load the telephony plugin
633 m:try_load_plugin('telephony')
634
635
636 -- system controller test setup
637
638 if not with_system_controller then
639    return
640 end
641
642 m:load_plugin('system-controller')
643
644 window_manager_operation_names = {
645     [1] = "create",
646     [2] = "destroy"
647 }
648
649 function window_manager_operation_name(oper)
650     local name = window_manager_operation_names[oper]
651     if name then return name end
652     return "<unknown " .. tostring(oper) .. ">"
653 end
654
655 window_operation_names = {
656     [1] = "create",
657     [2] = "destroy",
658     [3] = "name_change",
659     [4] = "visible",
660     [5] = "configure",
661     [6] = "active"
662 }
663
664 function window_operation_name(oper)
665     local name = window_operation_names[oper]
666     if name then return name end
667     return "<unknown " .. tostring(oper) .. ">"
668 end
669
670 layer_operation_names = {
671     [1] = "create",
672     [2] = "destroy",
673     [3] = "visible"
674 }
675
676 function layer_operation_name(oper)
677     local name = layer_operation_names[oper]
678     if name then return name end
679     return "<unknown " .. tostring(oper) .. ">"
680 end
681
682 input_manager_operation_names = {
683     [1] = "create",
684     [2] = "destroy",
685     [3] = "ready"
686 }
687
688 function input_manager_operation_name(oper)
689     local name = input_manager_operation_names[oper]
690     if name then return name end
691     return "<unknown " .. tostring(oper) .. ">"
692 end
693
694 input_operation_names = {
695     [1] = "create",
696     [2] = "destroy",
697     [3] = "update"
698 }
699
700 function input_operation_name(oper)
701     local name = input_operation_names[oper]
702     if name then return name end
703     return "<unknown " .. tostring(oper) .. ">"
704 end
705
706 code_operation_names = {
707     [1] = "create",
708     [2] = "destroy",
709     [3] = "state_change"
710 }
711
712 function code_operation_name(oper)
713     local name = code_operation_names[oper]
714     if name then return name end
715     return "<unknown " .. tostring(oper) .. ">"
716 end
717
718 command_names = {
719     [0x00001] = "send_appid",
720     [0x10001] = "create",
721     [0x10002] = "destroy",
722     [0x10003] = "show",
723     [0x10004] = "hide",
724     [0x10005] = "move",
725     [0x10006] = "change_active",
726     [0x10007] = "change_layer",
727     [0x10008] = "change_attr",
728     [0x10009] = "name",
729     [0x10011] = "map_thumb",
730     [0x10012] = "unmap_thumb",
731     [0x10020] = "show layer",
732     [0x10021] = "hide_layer",
733     [0x10022] = "change_layer_attr",
734     [0x20001] = "add_input",
735     [0x20002] = "del_input",
736     [0x20003] = "send_input",
737     [0x40001] = "acquire_res",
738     [0x40002] = "release_res",
739     [0x40003] = "deprive_res",
740     [0x40004] = "waiting_res",
741     [0x40005] = "revert_res",
742     [0x40011] = "create_res",
743     [0x40012] = "destroy_res",
744     [0x50001] = "set_region",
745     [0x50002] = "unset_region",
746     [0x60001] = "change_state"
747 }
748
749 function command_name(command)
750     local name = command_names[command]
751     if name then return name end
752     return "<unknown " .. tostring(command) .. ">"
753 end
754
755 input_layer = {
756    [3] = true, -- input
757    [4] = true, -- touch
758    [5] = true  -- cursor
759 }
760
761 resmgr = resource_manager {
762   screen_event_handler = function(self, ev)
763                              local event = ev.event
764                              local surface = ev.surface
765
766                              if event == "grant" then
767                                  if verbose > 0 then
768                                     print("*** make visible surface "..surface)
769                                  end
770                                  local a = animation({})
771                                  local r = m:JSON({surface = surface,
772                                                    visible = 1,
773                                                    raise   = 1})
774                                  wmgr:window_request(r,a,0)
775                                  elseif event == "revoke" then
776                                  if verbose > 0 then
777                                     print("*** hide surface "..surface)
778                                  end
779                                  local a = animation({})
780                                  local r = m:JSON({surface = ev.surface,
781                                                    visible = 0})
782                                  wmgr:window_request(r,a,0)
783
784                              elseif event == "create" then
785
786                                 if verbose > 0 then
787                                     print("*** screen resource event: " ..
788                                           tostring(ev))
789                                 end
790
791                                 local regulation = mdb.select.select_driving_mode.single_value
792
793                                 if regulation == 1 then
794
795                                     local blacklisted = false
796
797                                     -- applications which have their category set to "entertainment"
798                                     -- or "undefined" are blacklisted, meaning they should be regulated
799
800                                     for i,v in pairs(ft(mdb.select.undefined_applications)) do
801                                         if v.appid == ev.appid then
802                                             if verbose > 0 then
803                                                 print(ev.appid .. " was blacklisted (undefined)")
804                                             end
805                                             blacklisted = true
806                                             break
807                                         end
808                                     end
809
810                                     if not blacklisted then
811                                         for i,v in pairs(ft(mdb.select.entertainment_applications)) do
812                                             if v.appid == ev.appid then
813                                                 if verbose > 0 then
814                                                     print(ev.appid .. " was blacklisted (entertainment)")
815                                                 end
816                                                 blacklisted = true
817                                                 break
818                                             end
819                                         end
820                                     end
821
822                                     -- our local application config, which takes precedence
823                                     local conf = getApplication(ev.appid)
824
825                                     -- disable only non-whitelisted applications
826                                     if not conf or conf.resource_class == "player" then
827                                         if blacklisted then
828                                             if verbose > 0 then
829                                                 print("disabling screen for " .. ev.appid)
830                                             end
831                                             resmgr:disable_screen_by_appid("*", "*", ev.appid, true)
832                                         end
833                                     end
834                                 end
835
836                              elseif event == "destroy" then
837                                if verbose > 0 then
838                                     print("*** screen resource event: " ..
839                                           tostring(ev))
840                                  end
841                              else
842                                  if verbose > 0 then
843                                     print("*** screen resource event: " ..
844                                           tostring(ev))
845                                  end
846                              end
847                          end,
848   audio_event_handler = function(self, ev)
849                              local event = ev.event
850                              local appid = ev.appid
851                              local audioid = ev.audioid
852
853                              if event == "grant" then
854                                  if verbose > 0 or true then
855                                     print("*** grant audio to "..appid..
856                                           " ("..audioid..") in '" ..
857                                           ev.zone .. "' zone")
858                                  end
859                              elseif event == "revoke" then
860                                  if verbose > 0 or true then
861                                     print("*** revoke audio from "..appid..
862                                           " ("..audioid..") in '" ..
863                                           ev.zone .. "' zone")
864                                  end
865                              else
866                                  if verbose > 0 or true then
867                                     print("*** audio resource event: " ..
868                                           tostring(ev))
869                                  end
870                              end
871                         end
872 }
873
874 resclnt = resource_client {}
875
876 wmgr = window_manager {
877   geometry = function(self, w,h, v)
878                   if type(v) == "function" then
879                       return v(w,h)
880                   end
881                   return v
882              end,
883
884   application = function(self, appid)
885                      if appid then
886                          local app = application_lookup(appid)
887                          if not app then
888                              app = application_lookup("default")
889                          end
890                          return app
891                      end
892                      return { privileges = {screen="none", audio="none"} }
893                 end,
894
895   outputs = { { name  = "Center",
896                 id    = 0,
897                 zone  = "driver",
898                 areas = { Status = {
899                               id     = 0,
900                               pos_x  = 0,
901                               pos_y  = 0,
902                               width  = function(w,h) return w end,
903                               height = 64
904                           },
905                           Full = {
906                               id     = 1,
907                               pos_x  = 0,
908                               pos_y  = 64,
909                               width  = function(w,h) return w end,
910                               height = function(w,h) return h-64-128 end
911                           },
912                           Upper = {
913                               id     = 2,
914                               pos_x  = 0,
915                               pos_y  = 64,
916                               width  = function(w,h) return w end,
917                               height = function(w,h) return (h-64-128)/2 end
918                           },
919                           Lower = {
920                               id     = 3,
921                               pos_x  = 0,
922                               pos_y  = function(w,h) return (h-64-128)/2+64 end,
923                               width  = function(w,h) return w end,
924                               height = function(w,h) return (h-64-128)/2 end
925                           },
926                           UpperLeft = {
927                               id     = 4,
928                               pos_x  = 0,
929                               pos_y  = 64,
930                               width  = function(w,h) return w/2 end,
931                               height = function(w,h) return (h-64-128)/2 end
932                           },
933                           UpperRight = {
934                               id     = 5,
935                               pos_x  = function(w,h) return w/2 end,
936                               pos_y  = 64,
937                               width  = function(w,h) return w/2 end,
938                               height = function(w,h) return (h-64-128)/2 end
939                           },
940                           LowerLeft = {
941                               id     = 6,
942                               pos_x  = 0,
943                               pos_y  = function(w,h) return (h-64-128/2)+64 end,
944                               width  = function(w,h) return w/2 end,
945                               height = function(w,h) return (h-64-128)/2 end
946                           },
947                           LowerRight = {
948                               id     = 7,
949                               pos_x  = function(w,h) return w/2 end,
950                               pos_y  = function(w,h) return (h-64-128/2)+64 end,
951                               width  = function(w,h) return w/2 end,
952                               height = function(w,h) return (h-64-128)/2 end
953                           },
954                           SysApp = {
955                               id     = 8,
956                               pos_x  = 0,
957                               pos_y  = 64,
958                               width  = function(w,h) return w end,
959                               height = function(w,h) return h-64-128 end
960                           },
961                           ["SysApp.Left"] = {
962                               id     = 9,
963                               pos_x  = 0,
964                               pos_y  = 64,
965                               width  = function(w,h) return w/2-181 end,
966                               height = function(w,h) return h-64-128 end
967                           },
968                           ["SysApp.Right"] = {
969                               id     = 10,
970                               pos_x  = function(w,h) return w/2+181 end,
971                               pos_y  = 64,
972                               width  = function(w,h) return w/2-181 end,
973                               height = function(w,h) return h-64-128 end
974                           },
975                         }
976                },
977                { name  = "Mid",
978                  zone  = "driver",
979                  id    = 1
980                }
981
982   },
983   layers = { {      0, "Background"   , 1 },
984              {      1, "Application"  , 2 },
985              {      2, "Softkeyboard" , 4 },
986              {      3, "HomeScreen"   , 2 },
987              {      4, "ControlBar"   , 2 },
988              {      5, "InterruptApp" , 2 },
989              {      6, "OnScreen"     , 2 },
990              {    101, "Input"        , 3 },
991              {    102, "Cursor"       , 5 },
992              {    103, "Startup"      , 6 },
993              { 0x1000, "Background"   , 1 },
994              { 0x2000, "Normal"       , 2 },
995              { 0x3000, "Fullscreen"   , 2 },
996              { 0x4000, "InputPanel"   , 3 },
997              { 0xA000, "Touch"        , 4 },
998              { 0xB000, "Cursor"       , 5 },
999              { 0xC000, "Startup"      , 6 }
1000   },
1001
1002
1003   manager_update = function(self, oper)
1004                        if verbose > 0 then
1005                            print("### <== WINDOW MANAGER UPDATE:" ..
1006                                  window_manager_operation_name(oper))
1007                        end
1008                        if oper == 1 then
1009                            local umask = window_mask { raise   = true,
1010                                                        visible = true,
1011                                                        active  = true }
1012                            local rmask = window_mask { active  = true }
1013                            local req = m:JSON({
1014                                        passthrough_update  = umask:tointeger(),
1015                                        passthrough_request = rmask:tointeger()
1016                            })
1017                            self:manager_request(req)
1018                        end
1019                    end,
1020
1021   window_update = function(self, oper, win, mask)
1022                       if verbose > 0 then
1023                           print("### <== WINDOW UPDATE oper:" ..
1024                                 window_operation_name(oper) ..
1025                                 " mask: " .. tostring(mask))
1026                           if verbose > 1 then
1027                               print(win)
1028                           end
1029                       end
1030
1031                       local arg = m:JSON({ surface = win.surface,
1032                                            winname = win.name,
1033                       })
1034                       local command = 0
1035
1036                       if oper == 1 then -- create
1037                            local layertype = win.layertype
1038                            if layertype and input_layer[layertype] then
1039                                if verbose > 0 then
1040                                    print("ignoring input panel creation")
1041                                end
1042                                return
1043                            end
1044                            command     = 0x10001
1045                       elseif oper == 2 then -- destroy
1046                            command     = 0x10002
1047                       elseif oper == 3 then  -- namechange
1048                            command     = 0x10009
1049                       elseif oper == 4 or oper == 5 then --visible or configure
1050                            command     = 0x10008
1051                            arg.zone    = win.area
1052                            arg.node    = win.node
1053                            arg.layer   = win.layer
1054                            arg.pos_x   = win.pos_x
1055                            arg.pos_y   = win.pos_y
1056                            arg.width   = win.width
1057                            arg.height  = win.height
1058                            arg.raise   = win.raise
1059                            arg.visible = win.visible
1060                            arg.active  = win.active
1061                       elseif oper == 6 then -- active
1062                            command     = 0x10006
1063                            arg.active  = win.active
1064                       else
1065                            if verbose > 0 then
1066                                print("### nothing to do")
1067                            end
1068                            return
1069                       end
1070
1071                       local msg = m:JSON({ command = command,
1072                                            appid   = win.appid,
1073                                            pid     = win.pid,
1074                                            arg     = arg
1075                       })
1076                       if verbose > 0 then
1077                           print("### <== sending " ..
1078                                 command_name(msg.command) ..
1079                                 " window message to '" .. win.name .. "'")
1080                           if verbose > 1 then
1081                               print(msg)
1082                           end
1083                       end
1084                       sc:send_message(homescreen, msg)
1085
1086                       if oper == 1 then -- create
1087                           local i = input_layer[win.layertype]
1088                           local p = self:application(win.appid)
1089                           local s = p.privileges.screen
1090
1091                           if s == "system" then
1092                               local a = animation({})
1093                               local r = m:JSON({surface = win.surface,
1094                                                 visible = 1,
1095                                                 raise   = 1})
1096                               self:window_request(r,a,0)
1097                           else
1098                               if i then
1099                                   if verbose > 0 then
1100                                       print("do not make resource for " ..
1101                                             "input window")
1102                                   end
1103                               else
1104                                   resclnt:resource_set_create("screen",
1105                                                                "driver",
1106                                                                win.appid,
1107                                                                win.surface)
1108                               end
1109                           end
1110                       elseif oper == 2 then -- destroy
1111                           resclnt:resource_set_destroy("screen", win.surface)
1112                       elseif oper == 6 then -- active
1113                           if win.active then
1114                               local i = input_layer[win.layertype]
1115                               local p = self:application(win.appid)
1116                               local s = p.privileges.screen
1117                               local surface = win.surface
1118                               if not i and s ~= "system" then
1119                                  resclnt:resource_set_acquire("screen",surface)
1120                                  resmgr:window_raise(win.appid, surface, 1)
1121                               end
1122                           end
1123                       end
1124                   end,
1125
1126   layer_update = function(self, oper, layer, mask)
1127                       if verbose > 0 then
1128                           print("### LAYER UPDATE:" ..
1129                                 layer_operation_name(oper) ..
1130                                 " mask: " .. tostring(mask))
1131                           if verbose > 1 then
1132                               print(layer)
1133                           end
1134                       end
1135                       if oper == 3 then -- visible
1136                          local command = 0x10022
1137                          local msg = m:JSON({
1138                                          command = command,
1139                                          appid = "",
1140                                          arg = m:JSON({layer = layer.id,
1141                                                        visible = layer.visible
1142                                          })
1143                                 })
1144                          if verbose > 0 then
1145                             print("### <== sending "..command_name(command)..
1146                                   " layer message")
1147                             if verbose > 1 then
1148                                 print(msg)
1149                             end
1150                          end
1151                          sc:send_message(homescreen, msg)
1152                       else
1153                            if verbose > 0 then
1154                                print("### nothing to do")
1155                            end
1156                       end
1157                  end,
1158
1159   output_update = function(self, oper, out, mask)
1160                       local idx = out.index
1161                       if verbose > 0 then
1162                           print("### OUTPUT UPDATE:" .. oper ..
1163                                 " mask: "..tostring(mask))
1164                       end
1165                       print(out)
1166                       local outdef = self.outputs[idx+1]
1167                       if (oper == 1) then -- create
1168                           if outdef then
1169                               self:output_request(m:JSON({index = idx,
1170                                                           id    = outdef.id,
1171                                                           name  = outdef.name
1172                                                           }))
1173                           end
1174                       elseif (oper == 5) then -- done
1175                           local ads = outdef.areas
1176                           local on = outdef.name
1177                           if ads then
1178                               for name,ad in pairs(ads) do
1179                                   local can = wmgr:canonical_name(on.."."..name)
1180                                   local a = m:JSON({name   = name,
1181                                                     output = out.index})
1182                                   for fld,val in pairs(ad) do
1183                                       a[fld] = self:geometry(out.width,
1184                                                              out.height,
1185                                                              val)
1186                                    end
1187                                    self:area_create(a)
1188                                    resmgr:area_create(area[can], outdef.zone)
1189                               end
1190                           end
1191                       end
1192                   end
1193 }
1194
1195
1196 imgr = input_manager {
1197   inputs = {{ name = "G27 Racing Wheel",
1198               id = 0,
1199               switch = { [2] = {appid="org.tizen.ico.app-soundsample"      },
1200                          [3] = {appid="org.tizen.ico.homescreen", keycode=1},
1201                          [4] = {appid="org.tizen.ico.app-soundsample"      },
1202                          [5] = {appid="org.tizen.ico.homescreen", keycode=2}
1203              }}
1204   },
1205
1206   manager_update = function(self, oper)
1207                        if verbose > 0 then
1208                            print("### <== INPUT MANAGER UPDATE:" ..
1209                                  input_manager_operation_name(oper))
1210                        end
1211                    end,
1212
1213   input_update = function(self, oper, inp, mask)
1214                      if verbose > 0 then
1215                          print("### INPUT UPDATE:" ..
1216                                 input_operation_name(oper) ..
1217                                 " mask: " .. tostring(mask))
1218                           if verbose > 1 then
1219                               print(inp)
1220                           end
1221                       end
1222                  end,
1223   code_update  = function(self, oper, code, mask)
1224                      if verbose > 0 then
1225                          print("### CODE UPDATE: mask: " .. tostring(mask))
1226                          if verbose > 1 then
1227                              print(code)
1228                          end
1229                      end
1230                      local msg = m:JSON({ command = 1,
1231                                           appid = "org.tizen.ico.homescreen",
1232                                           arg = m:JSON({ device = code.device,
1233                                                          time = code.time,
1234                                                          input = code.input,
1235                                                          code = code.id,
1236                                                          state = code.state
1237                                            })
1238                      })
1239                      if verbose > 0 then
1240                          print("### <== sending " ..
1241                                command_name(msg.command) ..
1242                                " input message")
1243                          if verbose > 1 then
1244                              print(msg)
1245                          end
1246                      end
1247                      sc:send_message(homescreen, msg)
1248                  end
1249 }
1250
1251 sc = m:get_system_controller()
1252
1253 -- resource sets
1254 sets = {}
1255
1256 -- user manager
1257 um = m:UserManager()
1258
1259 connected = false
1260 homescreen = ""
1261
1262 -- these shoud be before wmgr:connect() is called
1263 if verbose > 0 then
1264    print("====== creating applications ======")
1265 end
1266 application {
1267     appid          = "default",
1268     area           = "Center.Full",
1269     privileges     = { screen = "none", audio = "none" },
1270     resource_class = "player",
1271     screen_priority = 0
1272 }
1273
1274 application {
1275     appid           = "weston",
1276     area            = "Center.Full",
1277     privileges      = { screen = "system", audio = "none" },
1278     resource_class  = "implicit",
1279     screen_priority = 30
1280 }
1281
1282 application {
1283     appid           = "org.tizen.ico.homescreen",
1284     area            = "Center.Full",
1285     privileges      = { screen = "system", audio = "system" },
1286     resource_class  = "player",
1287     screen_priority = 20
1288 }
1289
1290 application {
1291     appid           = "org.tizen.ico.statusbar",
1292     area            = "Center.Status",
1293     privileges      = { screen = "system", audio = "none" },
1294     resource_class  = "player",
1295     screen_priority = 20
1296 }
1297
1298 application {
1299     appid           = "org.tizen.ico.login",
1300     area            = "Center.Full",
1301     privileges      = { screen = "system", audio = "system" },
1302     resource_class  = "player",
1303     screen_priority = 20
1304 }
1305
1306 application {
1307     appid           = "org.tizen.ico.camera_left",
1308     area            = "Center.SysApp.Left",
1309     privileges      = { screen = "system", audio = "none" },
1310     requisites      = { screen = "blinker_left", audio = "none" },
1311     resource_class  = "player",
1312     screen_priority = 30
1313 }
1314
1315 application {
1316     appid           = "org.tizen.ico.camera_right",
1317     area            = "Center.SysApp.Right",
1318     privileges      = { screen = "system", audio = "none" },
1319     requisites      = { screen = "blinker_right", audio = "none" },
1320     resource_class  = "player",
1321     screen_priority = 30
1322 }
1323
1324 application {
1325     appid           = "net.zmap.navi",
1326     area            = "Center.Full",
1327     privileges      = { screen = "none", audio = "none" },
1328     resource_class  = "navigator",
1329     screen_priority = 30
1330 }
1331
1332 if sc then
1333     sc.client_handler = function (self, cid, msg)
1334         local command = msg.command
1335         if verbose > 0 then
1336             print('### ==> client handler:')
1337             if verbose > 1 then
1338                 print(msg)
1339             end
1340         end
1341         if not connected then
1342             print('Setting homescreen='..msg.appid)
1343             homescreen = msg.appid
1344             print('Trying to connect to wayland...')
1345             connected = wmgr:connect()
1346         end
1347         if connected and command then
1348             if command == 1 then -- send_appid
1349                 local driving_mode = mdb.select.select_driving_mode.single_value
1350                 local night_mode = mdb.select.select_night_mode.single_value
1351
1352                 if not driving_mode then driving_mode = 0 end
1353                 if not night_mode then night_mode = 0 end
1354
1355                 local reply = m:JSON({ command = 0x60001,
1356                                        arg     = m:JSON({ stateid = 1,
1357                                                           state   = driving_mode})
1358                                      })
1359                  if verbose > 0 then
1360                      print("### <== sending " ..
1361                            command_name(command) .. " message")
1362                      if verbose > 1 then
1363                          print(reply)
1364                      end
1365                  end
1366                  sc:send_message(homescreen, reply)
1367
1368                  reply = m:JSON({ command = 0x60001,
1369                                   arg     = m:JSON({ stateid = 2,
1370                                                      state   = night_mode})
1371                                 })
1372                  if verbose > 0 then
1373                      print("### <== sending " ..
1374                            command_name(command) .. " message")
1375                      if verbose > 1 then
1376                          print(reply)
1377                      end
1378                  end
1379                  sc:send_message(homescreen, reply)
1380             end
1381         end
1382     end
1383
1384     sc.generic_handler = function (self, cid, msg)
1385         if verbose > 0 then
1386             print('### ==> generic handler:')
1387             if verbose > 1 then
1388                print(msg)
1389             end
1390         end
1391     end
1392
1393     sc.window_handler = function (self, cid, msg)
1394         if verbose > 0 then
1395             print('### ==> received ' ..
1396                    command_name(msg.command) .. ' message')
1397             if verbose > 1 then
1398                 print(tostring(msg))
1399             end
1400         end
1401
1402         local a = animation({})
1403         local nores = false
1404         if msg.command == 0x10003 then       -- ico SHOW command
1405             local raise_mask = 0x01000000
1406             local lower_mask = 0x02000000
1407             local nores_mask = 0x40000000
1408             local time_mask  = 0x00ffffff
1409             msg.arg.visible = 1
1410             if msg.arg then
1411                 local time = 200
1412                 if  msg.arg.anim_time then
1413                     local t = msg.arg.anim_time
1414                     time = m:AND(t, time_mask)
1415                     nores = not m:AND(t, nores_mask)
1416                     if m:AND(t, raise_mask) then
1417                         msg.arg.raise = 1
1418                     elseif m:AND(t, lower_mask) then
1419                         msg.arg.raise = 0
1420                     end
1421                 end
1422                 if msg.arg.anim_name then
1423                     a.show = { msg.arg.anim_name, time }
1424                     print('time: ' .. tostring(a.show[2]))
1425                 end
1426             end
1427             if not nores then
1428                 local p = wmgr:application(msg.appid)
1429                 local s = p.privileges.screen
1430                 if s == "system" then
1431                     nores = true
1432                 end
1433             end
1434             if verbose > 2 then
1435                 print('### ==> SHOW')
1436                 print(tostring(msg.arg))
1437             end
1438             if nores then
1439                 wmgr:window_request(msg.arg, a, 0)
1440             else
1441                 local surface = msg.arg.surface
1442                 resclnt:resource_set_acquire("screen", surface)
1443                 resmgr:window_raise(msg.appid, surface, 1)
1444             end
1445         elseif msg.command == 0x10004 then   -- ico HIDE command
1446             local raise_mask = 0x01000000
1447             local lower_mask = 0x02000000
1448             local nores_mask = 0x40000000
1449             local time_mask  = 0x00ffffff
1450             msg.arg.visible = 0
1451             if msg.arg then
1452                 local time = 200
1453                 if msg.arg.anim_time then
1454                     local t = msg.arg.anim_time
1455                     time = m:AND(t, time_mask)
1456                     nores = not m:AND(t, nores_mask)
1457                 end
1458                 if msg.arg.anim_name then
1459                     a.hide = { msg.arg.anim_name, time }
1460                     print('hide animation time: ' .. tostring(a.hide[2]))
1461                 end
1462             end
1463             if not nores then
1464                 local p = wmgr:application(msg.appid)
1465                 local s = p.privileges.screen
1466                 if s == "system" then
1467                     nores = true
1468                 end
1469             end
1470             if verbose > 2 then
1471                 print('### ==> HIDE REQUEST')
1472                 print(tostring(msg.arg))
1473             end
1474             if nores then
1475                 wmgr:window_request(msg.arg, a, 0)
1476             else
1477                 resmgr:window_raise(msg.appid, msg.arg.surface, -1)
1478             end
1479         elseif msg.command == 0x10005 then   -- ico MOVE
1480             if verbose > 2 then
1481                 print('### ==> MOVE REQUEST')
1482                 print(tostring(msg.arg))
1483             end
1484             wmgr:window_request(msg.arg, a, 0)
1485             -- TODO: handle if area changed
1486         elseif msg.command == 0x10006 then   -- ico ACTIVE
1487             if not msg.arg.active then
1488                 msg.arg.active = 3 -- pointer + keyboard
1489             end
1490             if verbose > 2 then
1491                 print('### ==> ACTIVE REQUEST')
1492                 print(tostring(msg.arg))
1493             end
1494             wmgr:window_request(msg.arg, a, 0)
1495         elseif msg.command == 0x10007 then   -- ico CHANGE_LAYER
1496             if verbose > 2 then
1497                 print('### ==> CHANGE_LAYER REQUEST')
1498                 print(tostring(msg.arg))
1499             end
1500             --[[
1501             if msg.arg.layer ~= 4 or msg.arg.layer ~= 5 then
1502                 print("do not change layer for other than cursor or touch")
1503                 return
1504             end
1505             --]]
1506             wmgr:window_request(msg.arg, a, 0)
1507         elseif msg.command == 0x10011 then   -- ico MAP_THUMB
1508             local framerate = msg.arg.framerate
1509             if not framerate or framerate < 0 then
1510                 framerate = 0
1511             end
1512             msg.arg.map = 1
1513             if verbose > 2 then
1514                 print('### ==> MAP_THUMB REQUEST')
1515                 print(msg.arg)
1516                 print('framerate: '..framerate)
1517             end
1518             wmgr:window_request(msg.arg, a, framerate)
1519         elseif msg.command == 0x10012 then   -- ico UNMAP_THUMB
1520             msg.arg.map = 0
1521             if verbose > 2 then
1522                 print('### ==> UNMAP_THUMB REQUEST')
1523                 print(msg.arg)
1524             end
1525             wmgr:window_request(msg.arg, a, 0)
1526         elseif msg.command == 0x10020 then   -- ico SHOW_LAYER command
1527             msg.arg.visible = 1
1528             if verbose > 2 then
1529                 print('### ==> SHOW_LAYER REQUEST')
1530                 print(msg.arg)
1531             end
1532             wmgr:layer_request(msg.arg)
1533         elseif msg.command == 0x10021 then   -- ico HIDE_LAYER command
1534             msg.arg.visible = 0
1535             if verbose > 2 then
1536                 print('### ==> HIDE_LAYER REQUEST')
1537                 print(msg.arg)
1538             end
1539             wmgr:layer_request(msg.arg)
1540         end
1541     end
1542
1543     sc.input_handler = function (self, cid, msg)
1544         if verbose > 0 then
1545             print('### ==> input handler: ' .. command_name(msg.command))
1546             if verbose > 1 then
1547                 print(msg)
1548             end
1549         end
1550         if msg.command == 0x20001 then -- add_input
1551             msg.arg.appid = msg.appid
1552             if verbose > 2 then
1553                 print('### ==> ADD_INPUT REQUEST')
1554                 print(tostring(msg.arg))
1555             end
1556             imgr:input_request(msg.arg)
1557         elseif msg.command == 0x20002 then -- del_input
1558             msg.arg.appid = ''
1559             if verbose > 2 then
1560                 print('### ==> DEL_INPUT REQUEST')
1561                 print(tostring(msg.arg))
1562             end
1563             imgr:input_request(msg.arg)
1564         elseif msg.command == 0x20003 then -- send_input
1565         end
1566     end
1567
1568     sc.user_handler = function (self, cid, msg)
1569         if verbose > 0 then
1570             print('### ==> user handler: ' .. command_name(msg.command))
1571             if verbose > 1 then
1572                 print(msg)
1573             end
1574         end
1575
1576         if not um then
1577             print("User Manager not initialized")
1578             return
1579         end
1580
1581         if msg.command == 0x00030001 then -- MSG_CMD_CHANGE_USER
1582             print("command CHANGE_USER")
1583             if not msg.arg then
1584                 print("invalid message")
1585                 return
1586             end
1587
1588             username = msg.arg.user
1589             passwd = msg.arg.pass
1590
1591             if not username then
1592                 username = ""
1593             end
1594
1595             if not passwd then
1596                 passwd = ""
1597             end
1598
1599             success = um:changeUser(username, passwd)
1600
1601             if not success then
1602                 reply = m.JSON({
1603                     appid = msg.appid,
1604                     command = cmd
1605                 })
1606                 if sc:send_message(msg.appid, reply) then
1607                     print('*** sent authentication failed message')
1608                 else
1609                     print('*** failed to send authentication failed message')
1610                 end
1611             end
1612
1613         elseif msg.command == 0x00030002 then -- MSG_CMD_GET_USERLIST
1614             print("command GET_USERLIST")
1615             if not msg.appid then
1616                 print("invalid message")
1617                 return
1618             end
1619
1620             users, currentUser = um:getUserList()
1621
1622             if not users then
1623                 print("failed to get user list")
1624                 return
1625             end
1626
1627             nUsers = 0
1628
1629             for i,v in pairs(users) do
1630                 nUsers = nUsers + 1
1631             end
1632
1633             if not currentUser then
1634                 currentUser = ""
1635             end
1636
1637             if verbose > 1 then
1638                 print("current user: " .. currentUser)
1639                 print("user list:")
1640                 for i,v in pairs(users) do
1641                     print(v)
1642                 end
1643             end
1644
1645             reply = m.JSON({
1646                 appid = msg.appid,
1647                 command = cmd,
1648                 arg = m.JSON({
1649                     user_num = nUsers,
1650                     user_list = users,
1651                     user_login = currentUser
1652                 })
1653             })
1654
1655             if verbose > 1 then
1656                 print("### <== GetUserList reply: " .. tostring(reply))
1657             end
1658
1659             if sc:send_message(msg.appid, reply) then
1660                 print('*** reply OK')
1661             else
1662                 print('*** reply FAILED')
1663             end
1664
1665         elseif msg.command == 0x00030003 then -- MSG_CMD_GET_LASTINFO
1666             print("command GET_LASTINFO")
1667             if not msg.appid then
1668                 print("invalid message")
1669                 return
1670             end
1671
1672             lastInfo = um:getLastInfo(msg.appid)
1673
1674             if not lastInfo then
1675                 print("failed to get last info for app" .. msg.appid)
1676                 return
1677             end
1678
1679             reply = m.JSON({
1680                 appid = msg.appid,
1681                 command = cmd,
1682                 arg = m.JSON({
1683                     lastinfo = lastinfo
1684                 })
1685             })
1686
1687             if sc:send_message(msg.appid, reply) then
1688                 print('*** reply OK')
1689             else
1690                 print('*** reply FAILED')
1691             end
1692
1693         elseif msg.command == 0x00030004 then -- MSG_CMD_SET_LASTINFO
1694             print("command SET_LASTINFO")
1695             if not msg.arg or not msg.appid then
1696                 print("invalid message")
1697                 return
1698             end
1699
1700             lastInfo = um:setLastInfo(msg.appid, msg.arg.lastinfo)
1701         end
1702     end
1703
1704     sc.resource_handler = function (self, cid, msg)
1705         if verbose > 0 then
1706             print('### ==> resource handler: ' .. command_name(msg.command))
1707             if verbose > 1 then
1708                 print(msg)
1709             end
1710         end
1711
1712         createResourceSet = function (ctl, client, msg)
1713             cb = function(rset, data)
1714                 print("> resource callback")
1715
1716                 -- type is either basic (0) or interrupt (1)
1717                 requestType = 0
1718                 if msg.res.type then
1719                     requestType = msg.res.type
1720                 end
1721
1722                 if rset.acquired then
1723                     cmd = 0x00040001 -- acquire
1724                 else
1725                     cmd = 0x00040002 -- release
1726                 end
1727
1728                 reply = m.JSON({
1729                         appid = data.client,
1730                         command = cmd,
1731                         res = {
1732                             type = requestType
1733                         }
1734                     })
1735
1736                 if rset.resources.audio_playback then
1737                     reply.res.sound = {
1738                         zone = "driver",
1739                         name = msg.appid,
1740                         adjust = 0,
1741                         -- id = "0"
1742                     }
1743                 end
1744
1745                 if rset.resources.display then
1746                     reply.res.window = {
1747                         zone = "driver",
1748                         name = msg.appid,
1749                         -- id = "0"
1750                     }
1751                 end
1752
1753                 if rset.resources.input then
1754                     reply.res.input = {
1755                         name = msg.appid,
1756                         event = 0
1757                     }
1758                 end
1759                 print("sending message to client: " .. data.client)
1760
1761                 if sc:send_message(data.client, reply) then
1762                     print('*** reply OK')
1763                 else
1764                     print('*** reply FAILED')
1765                 end
1766             end
1767
1768             rset = m:ResourceSet({
1769                     application_class = "player",
1770                     zone = "driver", -- msg.zone ("full")
1771                     callback = cb
1772                 })
1773
1774             rset.data = {
1775                 cid = cid,
1776                 ctl = ctl
1777             }
1778
1779             if msg.res.sound then
1780                 rset:addResource({
1781                         resource_name = "audio_playback"
1782                     })
1783                 rset.resources.audio_playback.attributes.pid = tostring(msg.pid)
1784                 rset.resources.audio_playback.attributes.appid = msg.appid
1785                 print("sound name: " .. msg.res.sound.name)
1786                 print("sound zone:" .. msg.res.sound.zone)
1787                 print("sound adjust: " .. tostring(msg.res.sound.adjust))
1788                 if msg.res.sound.id then
1789                     print("sound id: " .. msg.res.sound.id)
1790                 end
1791             end
1792
1793             if msg.res.input then
1794                 rset:addResource({
1795                         resource_name = "input"
1796                     })
1797                 rset.resources.input.attributes.pid = tostring(msg.pid)
1798                 rset.resources.input.attributes.appid = msg.appid
1799                 print("input name: " .. msg.res.sound.name)
1800                 print("input event:" .. tostring(msg.res.input.event))
1801             end
1802
1803             if msg.res.window then
1804                 rset:addResource({
1805                         resource_name = "display"
1806                     })
1807                 rset.resources.display.attributes.pid = tostring(msg.pid)
1808                 rset.resources.display.attributes.appid = msg.appid
1809                 print("display name: " .. msg.res.display.name)
1810                 print("display zone:" .. msg.res.display.zone)
1811                 if msg.res.display.id then
1812                     print("display id: " .. msg.res.display.id)
1813                 end
1814             end
1815
1816             return rset
1817         end
1818
1819         -- parse the message
1820
1821         -- fields common to all messages:
1822         --      msg.command
1823         --      msg.appid
1824         --      msg.pid
1825
1826         if msg.command == 0x00040011 then -- MSG_CMD_CREATE_RES
1827             print("command CREATE")
1828
1829             if not sets.cid then
1830                 sets.cid = createResourceSet(self, cid, msg)
1831             end
1832
1833         elseif msg.command == 0x00040012 then -- MSG_CMD_DESTORY_RES
1834             print("command DESTROY")
1835
1836             if sets.cid then
1837                 sets.cid:release()
1838             end
1839
1840             sets.cid = nil -- garbage collecting
1841
1842         elseif msg.command == 0x00040001 then -- MSG_CMD_ACQUIRE_RES
1843             print("command ACQUIRE")
1844
1845             if not sets.cid then
1846                 sets.cid = createResourceSet(self, cid, msg)
1847             end
1848
1849             sets.cid:acquire()
1850
1851         elseif msg.command == 0x00040002 then -- MSG_CMD_RELEASE_RES
1852             print("command RELEASE")
1853
1854             if sets.cid then
1855                 sets.cid:release()
1856             end
1857
1858         elseif msg.command == 0x00040003 then -- MSG_CMD_DEPRIVE_RES
1859             print("command DEPRIVE")
1860
1861         elseif msg.command == 0x00040004 then -- MSG_CMD_WAITING_RES
1862             print("command WAITING")
1863
1864         elseif msg.command == 0x00040005 then -- MSG_CMD_REVERT_RES
1865             print("command REVERT")
1866         end
1867     end
1868
1869     sc.inputdev_handler = function (self, cid, msg)
1870         if verbose > 0 then
1871             print('*** inputdev handler: ' .. command_name(msg.command))
1872             if verbose > 1 then
1873                 print(msg)
1874             end
1875         end
1876     end
1877 end