system-controller: only override dst rectangle for apps.
[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 if m:plugin_exists("gam-resource-manager") then
54
55 function get_general_priorities(self)
56     print("*** get_general_priorities\n")
57     return { "USB Headset", "wiredHeadset", "speakers" }
58 end
59
60 function get_phone_priorities(self)
61     print("*** get_phone_priorities\n")
62     return { "wiredHeadset", "USB Headset" }
63 end
64
65 m:load_plugin('gam-resource-manager', {
66     config_dir = '/etc/murphy/gam',
67     decision_names = 'gam-wrtApplication-4',
68     max_active = 4,
69     app_mapping = {
70         ['t8j6HTRpuz.MediaPlayer'] = 'wrtApplication',
71         ['pacat'] = 'icoApplication'
72     },
73     app_default = 'icoApplication'
74 })
75
76 routing_sink_priority {
77     application_class = "player",
78     priority_queue = get_general_priorities
79 }
80
81 routing_sink_priority {
82     application_class = "game",
83     priority_queue = get_general_priorities
84 }
85
86 routing_sink_priority {
87     application_class = "implicit",
88     priority_queue = get_general_priorities
89 }
90
91 routing_sink_priority {
92     application_class = "phone",
93     priority_queue = get_phone_priorities
94 }
95
96 routing_sink_priority {
97     application_class = "basic",
98     priority_queue = get_phone_priorities
99 }
100
101 routing_sink_priority {
102     application_class = "event",
103     priority_queue = get_phone_priorities
104 }
105 end
106
107 -- load the AMB plugin
108 if m:plugin_exists('amb') then
109     m:try_load_plugin('amb')
110
111     if builtin.method.amb_initiate and
112        builtin.method.amb_update
113     then
114         with_amb = true
115     end
116 else
117     m:info("No amb plugin found...")
118 end
119
120 -- load the ASM resource plugin
121 if m:plugin_exists('resource-asm') then
122     m:try_load_plugin('resource-asm', {
123         zone = "driver",
124         share_mmplayer = "player:AVP,mandatory,exclusive,strict",
125         ignored_argv0 = "WebProcess"
126     })
127 else
128     m:info("No audio session manager plugin found...")
129 end
130
131 if m:plugin_exists('system-controller') then
132     with_system_controller = true
133 elseif m:plugin_exists('ivi-resource-manager') then
134     m:load_plugin('ivi-resource-manager')
135     with_system_controller = false
136 end
137
138 -- define application classes
139 application_class {
140     name     = "interrupt",
141     priority = 99,
142     modal    = true ,
143     share    = false,
144     order    = "fifo"
145 }
146
147 application_class {
148     name     = "emergency",
149     priority = 80,
150     modal    = false,
151     share    = false,
152     order    = "fifo"
153 }
154 application_class {
155     name     = "system",
156     priority = 52,
157     modal    = false,
158     share    = true,
159     order    = "lifo"
160 }
161 application_class {
162     name     = "alert",
163     priority = 51,
164     modal    = false,
165     share    = false,
166     order    = "fifo"
167 }
168
169 application_class {
170     name     = "navigator",
171     priority = 50,
172     modal    = false,
173     share    = true,
174     order    = "fifo"
175 }
176
177 application_class {
178     name     = "phone",
179     priority = 6 ,
180     modal    = false,
181     share    = false,
182     order    = "lifo"
183 }
184 application_class {
185     name     = "camera",
186     priority = 5,
187     modal    = false,
188     share    = false,
189     order    = "lifo"
190 }
191
192 application_class { name="event"    , priority=4 , modal=false, share=true , order="fifo" }
193 application_class { name="game"     , priority=3 , modal=false, share=false, order="lifo" }
194 --# doesn't need to be created here, ivi-resource-manager creates it if loaded
195 --#application_class { name="basic"    , priority=2 , modal=false, share=false, order="lifo" }
196 application_class { name="player"   , priority=1 , modal=false, share=true , order="lifo" }
197 application_class { name="implicit" , priority=0 , modal=false, share=false, order="lifo" }
198
199 -- define zone attributes
200 zone.attributes {
201     type = {mdb.string, "common", "rw"},
202     location = {mdb.string, "anywhere", "rw"}
203 }
204
205 -- define zones
206 zone {
207      name = "driver",
208      attributes = {
209          type = "common",
210          location = "front-left"
211      }
212 }
213
214 zone {
215      name = "passanger1",
216      attributes = {
217          type = "private",
218          location = "front-right"
219      }
220 }
221
222 zone {
223      name = "passanger2",
224      attributes = {
225          type = "private",
226          location = "back-left"
227      }
228 }
229
230 zone {
231      name = "passanger3",
232      attributes = {
233          type = "private",
234          location = "back-right"
235      }
236 }
237
238 zone {
239      name = "passanger4",
240      attributes = {
241          type = "private",
242          location = "back-left"
243      }
244 }
245
246
247 -- define resource classes
248 if not m:plugin_exists('ivi-resource-manager') and
249    not with_system_controller and
250    not m:plugin_exists('gam-resource-manager')
251 then
252    resource.class {
253         name = "audio_playback",
254         shareable = true,
255         attributes = {
256             role    = { mdb.string, "music", "rw" },
257             pid     = { mdb.string, "<unknown>", "rw" },
258             policy  = { mdb.string, "relaxed", "rw" },
259             source  = { mdb.string, "webkit", "rw" },
260             conn_id = { mdb.unsigned, 0, "rw" },
261             name    = { mdb.string, "<unknown>", "rw" },
262         }
263    }
264 end
265
266 if not m:plugin_exists('gam-resource-manager') then
267     resource.class {
268         name = "audio_recording",
269         shareable = true,
270         attributes = {
271              role   = { mdb.string, "music"    , "rw" },
272              pid    = { mdb.string, "<unknown>", "rw" },
273              policy = { mdb.string, "relaxed"  , "rw" },
274              name   = { mdb.string, "<unknown>", "rw" },
275          }
276     }
277 end
278
279 resource.class {
280      name = "video_playback",
281      shareable = false,
282 }
283
284 resource.class {
285      name = "video_recording",
286      shareable = false
287 }
288
289 resource.class {
290      name = "speech_recognition",
291      shareable = true
292 }
293
294 resource.class {
295      name = "speech_synthesis",
296      shareable = true
297 }
298
299 -- PulseAudio volume context
300 mdb.table {
301     name = "volume_context",
302     index = { "id" },
303     create = true,
304     columns = {
305         { "id", mdb.unsigned },
306         { "value", mdb.string, 64 },
307     }
308 }
309
310 -- put default volume context to the table
311 mdb.table.volume_context:insert({ id = 1, value = "default" })
312
313 if not m:plugin_exists('ivi-resource-manager') and
314    not with_system_controller
315 then
316     resource.method.veto = {
317         function(zone, rset, grant, owners, req_set)
318             return true
319          end
320     }
321 end
322
323 -- test for creating selections
324 mdb.select {
325            name = "audio_owner",
326            table = "audio_playback_owner",
327            columns = {"application_class"},
328            condition = "zone_name = 'driver'"
329 }
330
331 mdb.select {
332            name = "vehicle_speed",
333            table = "amb_vehicle_speed",
334            columns = {"value"},
335            condition = "key = 'VehicleSpeed'"
336 }
337
338 element.lua {
339    name    = "speed2volume",
340    inputs  = { speed = mdb.select.vehicle_speed, param = 9 },
341    outputs = {  mdb.table { name = "speedvol",
342                             index = {"zone", "device"},
343                             columns = {{"zone", mdb.string, 16},
344                                        {"device", mdb.string, 16},
345                                        {"value", mdb.floating}},
346                             create = true
347                            }
348              },
349    oldvolume = 0.0,
350    update  = function(self)
351                 speed = self.inputs.speed.single_value
352                 if (speed) then
353                     volume = (speed - 144.0) / 7.0
354                 else
355                     volume = 0.0
356                 end
357                 diff = volume - self.oldvolume
358                 if (diff*diff > self.inputs.param) then
359                     print("*** element "..self.name.." update "..volume)
360                     self.oldvolume = volume
361                     mdb.table.speedvol:replace({zone = "driver", device = "speakers", value = volume})
362                 end
363              end
364 }
365
366 mdb.select {
367     name = "amb_state",
368     table = "amb_state",
369     columns = { "state" },
370     condition = "id = 0"
371 }
372
373 -- Night mode processing chain
374
375 mdb.select {
376     name = "exterior_brightness",
377     table = "amb_exterior_brightness",
378     columns = { "value" },
379     condition = "key = 'ExteriorBrightness'"
380 }
381
382 element.lua {
383     name    = "nightmode",
384     inputs  = { brightness = mdb.select.exterior_brightness },
385     oldmode = -1;
386     outputs = {
387         mdb.table {
388             name = "amb_nightmode",
389             index = { "id" },
390             create = true,
391             columns = {
392                 { "id", mdb.unsigned },
393                 { "night_mode", mdb.unsigned }
394             }
395         }
396     },
397     update = function(self)
398         -- This is a trivial function to calculate night mode. Later, we will
399         -- need a better threshold value and hysteresis to prevent oscillation.
400
401         brightness = self.inputs.brightness.single_value
402
403         if not brightness then
404             return
405         end
406
407         print("*** element "..self.name.." update brightness: "..brightness)
408
409         if brightness > 300 then
410             mode = 0
411         else
412             mode = 1
413         end
414
415         print("*** resulting mode: ".. mode)
416
417         if not (mode == self.oldmode) then
418             mdb.table.amb_nightmode:replace({ id = 0, night_mode = mode })
419         end
420
421         self.oldmode = mode
422     end
423 }
424
425 mdb.select {
426     name = "select_night_mode",
427     table = "amb_nightmode",
428     columns = { "night_mode" },
429     condition = "id = 0"
430 }
431
432 if with_amb then
433     sink.lua {
434         name = "night_mode",
435         inputs = { NightMode = mdb.select.select_night_mode,
436                    amb_state = mdb.select.amb_state },
437         property = "NightMode",
438         type = "b",
439         initiate = builtin.method.amb_initiate,
440         update = builtin.method.amb_update
441     }
442 end
443
444 -- Night mode general handlers
445
446 if with_system_controller then
447     sink.lua {
448         name = "nightmode_homescreen",
449         inputs = { owner = mdb.select.select_night_mode },
450         initiate = function(self)
451                 -- data = mdb.select.select_night_mode.single_value
452                 return true
453             end,
454         update = function(self)
455                 send_night_mode_to(homescreen)
456             end
457     }
458 end
459
460 -- Driving mode processing chain
461
462 element.lua {
463     name    = "drivingmode",
464     inputs  = { speed = mdb.select.vehicle_speed },
465     oldmode = -1;
466     outputs = {
467         mdb.table {
468             name = "amb_drivingmode",
469             index = { "id" },
470             create = true,
471             columns = {
472                 { "id", mdb.unsigned },
473                 { "driving_mode", mdb.unsigned }
474             }
475         }
476     },
477     update = function(self)
478
479         speed = self.inputs.speed.single_value
480
481         if not speed then
482             return
483         end
484
485         if speed == 0 then
486             mode = 0
487         else
488             mode = 1
489         end
490
491         if not (mode == self.oldmode) then
492             mdb.table.amb_drivingmode:replace({ id = 0, driving_mode = mode })
493         end
494
495         self.oldmode = mode
496     end
497 }
498
499 mdb.select {
500     name = "select_driving_mode",
501     table = "amb_drivingmode",
502     columns = { "driving_mode" },
503     condition = "id = 0"
504 }
505
506 if with_amb then
507     sink.lua {
508         name = "driving_mode",
509         inputs = { DrivingMode = mdb.select.select_driving_mode,
510                    amb_state = mdb.select.amb_state },
511         property = "DrivingMode",
512         type = "u",
513         initiate = builtin.method.amb_initiate,
514         update = builtin.method.amb_update
515     }
516 end
517
518 -- turn signals (left, right)
519
520 mdb.select {
521     name = "winker",
522     table = "amb_turn_signal",
523     columns = { "value" },
524     condition = "key = 'TurnSignal'"
525 }
526
527 -- define three categories
528
529 mdb.select {
530     name = "undefined_applications",
531     table = "aul_applications",
532     columns = { "appid" },
533     condition = "category = '<undefined>'"
534 }
535
536 mdb.select {
537     name = "basic_applications",
538     table = "aul_applications",
539     columns = { "appid" },
540     condition = "category = 'basic'"
541 }
542
543 mdb.select {
544     name = "entertainment_applications",
545     table = "aul_applications",
546     columns = { "appid" },
547     condition = "category = 'entertainment'"
548 }
549
550 function ft(t)
551     -- filter the object garbage out of the tables
552     ret = {}
553
554     for k,v in pairs(t) do
555         if k ~= "userdata" and k ~= "new" then
556             ret[k] = v
557         end
558     end
559
560     return ret
561 end
562
563 function getApplication(appid)
564     local conf = nil
565
566     -- find the correct local application definition
567
568     for k,v in pairs(ft(application)) do
569         if appid == v.appid then
570             conf = v
571             break
572         end
573     end
574
575     return conf
576 end
577
578 function regulateApplications(t, regulation)
579     for k,v in pairs(ft(t)) do
580
581         whitelisted = false
582
583         -- our local application config, which takes precedence
584         local conf = getApplication(v.appid)
585
586         if conf then
587             if conf.resource_class ~= "player" then
588                 whitelisted = true
589             end
590
591                if conf.requisites and conf.requisites.screen then
592                 if conf.requisites.screen.driving then
593                     whitelisted = true
594                 end
595             end
596         end
597
598         if whitelisted then
599             -- override, don't disable
600             resmgr:disable_screen_by_appid("*", "*", v.appid, false, false)
601         else
602             resmgr:disable_screen_by_appid("*", "*", v.appid, regulation == 1, false)
603         end
604     end
605     resource.method.recalc("driver")
606 end
607
608 -- regulation (on), use "select_driving_mode"
609
610 sink.lua {
611     name = "driving_regulation",
612     inputs = { owner = mdb.select.select_driving_mode },
613     initiate = function(self)
614         -- local data = mdb.select.select_driving_mode.single_value
615         return true
616     end,
617     update = function(self)
618         local data = mdb.select.select_driving_mode.single_value
619
620         if verbose > 1 then
621             print("Driving mode updated: " .. tostring(data))
622         end
623
624         if not sc then
625             return true
626         end
627
628         -- tell homescreen that driving mode was updated
629         send_driving_mode_to(homescreen)
630
631         regulateApplications(ft(mdb.select.entertainment_applications), data)
632         regulateApplications(ft(mdb.select.undefined_applications), data)
633
634         return true
635     end
636 }
637 --[[
638 sink.lua {
639     name = "regulated_app_change",
640     inputs = { undef = mdb.select.undefined_applications,
641                entertainment = mdb.select.entertainment_applications },
642     initiate = function(self)
643         return true
644     end,
645     update = function(self)
646         local data = mdb.select.select_driving_mode.single_value
647
648         if not sc then
649             return
650         end
651
652         if verbose > 1 then
653             print("regulated application list was changed")
654         end
655
656         regulateApplications(ft(mdb.select.entertainment_applications), data)
657         regulateApplications(ft(mdb.select.undefined_applications), data)
658
659         return true
660     end
661 }
662 --]]
663
664 -- shift position (parking, reverse, other)
665
666 mdb.select {
667     name = "gear_position",
668     table = "amb_gear_position",
669     columns = { "value" },
670     condition = "key = 'GearPosition'"
671 }
672
673 -- cameras (back, front, left, right)
674
675 element.lua {
676     name    = "camera_state",
677     inputs  = { winker = mdb.select.winker, gear = mdb.select.gear_position },
678     oldmode = -1;
679     outputs = {
680         mdb.table {
681             name = "target_camera_state",
682             index = { "id" },
683             create = true,
684             columns = {
685                 { "id", mdb.unsigned },
686                 { "front_camera", mdb.unsigned },
687                 { "back_camera", mdb.unsigned },
688                 { "right_camera", mdb.unsigned },
689                 { "left_camera", mdb.unsigned }
690             }
691         }
692     },
693     update = function(self)
694
695         front_camera = 0
696         back_camera = 0
697         right_camera = 0
698         left_camera = 0
699
700         if self.inputs.gear == 128 then
701             back_camera = 1
702         elseif self.inputs.winker == 1 then
703             right_camera = 1
704         elseif self.inputs.winker == 2 then
705             left_camera = 1
706         end
707
708         mdb.table.target_camera_state:replace({ id = 0, front_camera = front_camera, back_camera = back_camera, right_camera = right_camera, left_camera = left_camera })
709
710     end
711 }
712
713 -- system controller test setup
714
715 if not with_system_controller then
716    -- ok, we should have 'audio_playback' defined by now
717    m:try_load_plugin('telephony')
718    return
719 end
720
721 m:load_plugin('system-controller')
722
723 onscreen_counter = 0
724
725 window_manager_operation_names = {
726     [1] = "create",
727     [2] = "destroy"
728 }
729
730 function window_manager_operation_name(oper)
731     local name = window_manager_operation_names[oper]
732     if name then return name end
733     return "<unknown " .. tostring(oper) .. ">"
734 end
735
736 window_operation_names = {
737     [1] = "create",
738     [2] = "destroy",
739     [3] = "name_change",
740     [4] = "visible",
741     [5] = "configure",
742     [6] = "active",
743     [7] = "map",
744     [8] = "hint"
745 }
746
747 function window_operation_name(oper)
748     local name = window_operation_names[oper]
749     if name then return name end
750     return "<unknown " .. tostring(oper) .. ">"
751 end
752
753 layer_operation_names = {
754     [1] = "create",
755     [2] = "destroy",
756     [3] = "visible"
757 }
758
759 function layer_operation_name(oper)
760     local name = layer_operation_names[oper]
761     if name then return name end
762     return "<unknown " .. tostring(oper) .. ">"
763 end
764
765 input_manager_operation_names = {
766     [1] = "create",
767     [2] = "destroy",
768     [3] = "ready"
769 }
770
771 function input_manager_operation_name(oper)
772     local name = input_manager_operation_names[oper]
773     if name then return name end
774     return "<unknown " .. tostring(oper) .. ">"
775 end
776
777 input_operation_names = {
778     [1] = "create",
779     [2] = "destroy",
780     [3] = "update"
781 }
782
783 function input_operation_name(oper)
784     local name = input_operation_names[oper]
785     if name then return name end
786     return "<unknown " .. tostring(oper) .. ">"
787 end
788
789 code_operation_names = {
790     [1] = "create",
791     [2] = "destroy",
792     [3] = "state_change"
793 }
794
795 function code_operation_name(oper)
796     local name = code_operation_names[oper]
797     if name then return name end
798     return "<unknown " .. tostring(oper) .. ">"
799 end
800
801 command_names = {
802     [0x00001] = "send_appid",
803     [0x10001] = "create",
804     [0x10002] = "destroy",
805     [0x10003] = "show",
806     [0x10004] = "hide",
807     [0x10005] = "move",
808     [0x10006] = "animation",
809     [0x10007] = "change_active",
810     [0x10008] = "change_layer",
811     [0x10009] = "change_attr",
812     [0x10010] = "name",
813     [0x10020] = "map_thumb",
814     [0x10021] = "unmap_thumb",
815     [0x10022] = "map_get",
816     [0x10030] = "show layer",
817     [0x10031] = "hide_layer",
818     [0x10032] = "change_layer_attr",
819     [0x20001] = "add_input",
820     [0x20002] = "del_input",
821     [0x30001] = "change_user",
822     [0x30002] = "get_userlist",
823     [0x30003] = "get_lastinfo",
824     [0x30004] = "set_lastinfo",
825     [0x40001] = "acquire_res",
826     [0x40002] = "release_res",
827     [0x40003] = "deprive_res",
828     [0x40004] = "waiting_res",
829     [0x40005] = "revert_res",
830     [0x40006] = "window_id_res",
831     [0x40011] = "create_res",
832     [0x40012] = "destroy_res",
833     [0x50001] = "set_region",
834     [0x50002] = "unset_region",
835     [0x60001] = "change_state"
836 }
837
838 function command_name(command)
839     local name = command_names[command]
840     if name then return name end
841     return "<unknown " .. tostring(command) .. ">"
842 end
843
844 input_layer = {
845    [101] = true, -- input
846    [102] = true, -- touch
847    [103] = true  -- cursor
848 }
849
850 -- some day this should be merged with wmgr.layers
851 ico_layer_type = {
852    [1]   = 0x1000, -- background
853    [2]   = 0x2000, -- application
854    [3]   = 0x2000, -- homescreen
855    [4]   = 0x2000, -- interrupt application
856    [5]   = 0x2000, -- onscreen application
857    [6]   = 0xc000, -- startup
858    [7]   = 0x3000, -- fullscreen
859    [101] = 0x4000, -- input
860    [102] = 0xa000, -- touch
861    [103] = 0xb000  -- cursor
862 }
863
864 resmgr = resource_manager {
865   screen_event_handler = function(self, ev)
866                              local event = ev.event
867                              local surface = ev.surface
868
869                              if event == "init" then
870                                  if verbose > 0 then
871                                      print("*** init screen resource allocation -- disable all 'player'")
872                                  end
873                                  resmgr:disable_audio_by_appid("*", "player", "*", true, false)
874                              elseif event == "preallocate" then
875                                  if verbose > 0 then
876                                      print("*** preallocate screen resource "..
877                                            "for '" .. ev.appid .. "' -- enable 'player', if any")
878                                  end
879                                  resmgr:disable_audio_by_appid("*", "player", ev.appid, false, false)
880                              elseif event == "grant" then
881                                  if verbose > 0 then
882                                     print("*** make visible surface "..surface)
883                                  end
884                                  local a = animation({})
885                                  local r = m:JSON({surface = surface,
886                                                    visible = 1,
887                                                    raise   = 1})
888                                  if ev.appid == onscreen then
889                                      onscreen_counter = onscreen_counter + 1
890                                      wmgr:layer_request(m:JSON({layer = 5, visible = 1}))
891                                  end
892
893                                  wmgr:window_request(r,a,0)
894                              elseif event == "revoke" then
895                                  if verbose > 0 then
896                                     print("*** hide surface "..surface)
897                                  end
898                                  local a = animation({})
899                                  local r = m:JSON({surface = ev.surface,
900                                                    visible = 0})
901                                  if ev.appid == onscreen then
902                                      onscreen_counter = onscreen_counter - 1
903                                      if onscreen_counter <= 0 then
904                                         onscreen_counter = 0
905                                         wmgr:layer_request(m:JSON({layer = 5, visible = 0}))
906                                      end
907                                  end
908                                  wmgr:window_request(r,a,0)
909
910                              elseif event == "create" then
911
912                                 if verbose > 0 then
913                                     print("*** screen resource event: " ..
914                                           tostring(ev))
915                                 end
916
917                                 local regulation = mdb.select.select_driving_mode.single_value
918
919                                 if regulation == 1 then
920
921                                     local blacklisted = false
922
923                                     -- applications which have their category set to "entertainment"
924                                     -- or "undefined" are blacklisted, meaning they should be regulated
925
926                                     for i,v in pairs(ft(mdb.select.undefined_applications)) do
927                                         if v.appid == ev.appid then
928                                             if verbose > 0 then
929                                                 print(ev.appid .. " was blacklisted (undefined)")
930                                             end
931                                             blacklisted = true
932                                             break
933                                         end
934                                     end
935
936                                     if not blacklisted then
937                                         for i,v in pairs(ft(mdb.select.entertainment_applications)) do
938                                             if v.appid == ev.appid then
939                                                 if verbose > 0 then
940                                                     print(ev.appid .. " was blacklisted (entertainment)")
941                                                 end
942                                                 blacklisted = true
943                                                 break
944                                             end
945                                         end
946                                     end
947
948                                     -- our local application config, which takes precedence
949                                     local conf = getApplication(ev.appid)
950
951                                     if not conf then
952                                         blacklisted = true
953                                     else
954                                         if conf.resource_class == "player" then
955                                             blacklisted = true
956                                         end
957
958                                         -- check the exceptions
959                                         if conf.requisites and conf.requisites.screen then
960                                             if conf.requisites.screen.driving then
961                                                 blacklisted = false
962                                             end
963                                         end
964                                     end
965
966                                     -- disable only non-whitelisted applications
967                                                     if blacklisted then
968                                         if verbose > 0 then
969                                             print("disabling screen for " .. ev.appid)
970                                         end
971                                         resmgr:disable_screen_by_appid("*", "*", ev.appid, true, true)
972                                     end
973                                 end
974
975                              elseif event == "destroy" then
976                                if verbose > 0 then
977                                     print("*** screen resource event: " ..
978                                           tostring(ev))
979                                  end
980                              else
981                                  if verbose > 0 then
982                                     print("*** screen resource event: " ..
983                                           tostring(ev))
984                                  end
985                              end
986                          end,
987   audio_event_handler = function(self, ev)
988                              local event = ev.event
989                              local appid = ev.appid
990                              local audioid = ev.audioid
991
992                              if event == "grant" then
993                                  if verbose > 0 then
994                                     print("*** grant audio to "..appid..
995                                           " ("..audioid..") in '" ..
996                                           ev.zone .. "' zone")
997                                  end
998                              elseif event == "revoke" then
999                                  if verbose > 0 then
1000                                     print("*** revoke audio from "..appid..
1001                                           " ("..audioid..") in '" ..
1002                                           ev.zone .. "' zone")
1003                                  end
1004                              else
1005                                  if verbose > 0 then
1006                                     print("*** audio resource event: " ..
1007                                           tostring(ev))
1008                                  end
1009                              end
1010                         end
1011 }
1012
1013 resclnt = resource_client {}
1014
1015 wmgr = window_manager {
1016   geometry = function(self, w,h, v)
1017                   if type(v) == "function" then
1018                       return v(w,h)
1019                   end
1020                   return v
1021              end,
1022
1023   application = function(self, appid)
1024                      if appid then
1025                          local app = application_lookup(appid)
1026                          if not app then
1027                              app = application_lookup("default")
1028                          end
1029                          return app
1030                      end
1031                      return { privileges = {screen="none", audio="none"} }
1032                 end,
1033
1034   output_order = { 1, 0 },
1035
1036   outputs = { { name  = "Mid",
1037                 id    = 1,
1038                 zone  = "driver",
1039                 areas = { Full = {
1040                               id     = 20,
1041                               pos_x  = 0,
1042                               pos_y  = 0,
1043                               width  = function(w,h) return w end,
1044                               height = function(w,h) return h end
1045                           },
1046                           Left = {
1047                               id     = 21,
1048                               pos_x  = 0,
1049                               pos_y  = 0,
1050                               width  = 320,
1051                               height = function(w,h) return h end
1052                           },
1053                           Right = {
1054                               id     = 22,
1055                               pos_x  = function(w,h) return w-320 end,
1056                               pos_y  = 0,
1057                               width  = 320,
1058                               height = function(w,h) return h end
1059                           }
1060                         }
1061                },
1062                { name  = "Center",
1063                  id    = 4,
1064                  zone  = "driver",
1065                  areas = { Status = {
1066                               id     = 0,
1067                               pos_x  = 0,
1068                               pos_y  = 0,
1069                               width  = function(w,h) return w end,
1070                               height = 64
1071                            },
1072                            Full = {
1073                               id     = 1,
1074                               pos_x  = 0,
1075                               pos_y  = 64,
1076                               width  = function(w,h) return w end,
1077                               height = function(w,h) return h-64-128 end
1078                            },
1079                            Upper = {
1080                               id     = 2,
1081                               pos_x  = 0,
1082                               pos_y  = 64,
1083                               width  = function(w,h) return w end,
1084                               height = function(w,h) return (h-64-128)/2 end
1085                            },
1086                            Lower = {
1087                               id     = 3,
1088                               pos_x  = 0,
1089                               pos_y  = function(w,h) return (h-64-128)/2+64 end,
1090                               width  = function(w,h) return w end,
1091                               height = function(w,h) return (h-64-128)/2 end
1092                            },
1093                            UpperLeft = {
1094                               id     = 4,
1095                               pos_x  = 0,
1096                               pos_y  = 64,
1097                               width  = function(w,h) return w/2 end,
1098                               height = function(w,h) return (h-64-128)/2 end
1099                            },
1100                            UpperRight = {
1101                               id     = 5,
1102                               pos_x  = function(w,h) return w/2 end,
1103                               pos_y  = 64,
1104                               width  = function(w,h) return w/2 end,
1105                               height = function(w,h) return (h-64-128)/2 end
1106                            },
1107                            LowerLeft = {
1108                               id     = 6,
1109                               pos_x  = 0,
1110                               pos_y  = function(w,h) return (h-64-128/2)+64 end,
1111                               width  = function(w,h) return w/2 end,
1112                               height = function(w,h) return (h-64-128)/2 end
1113                            },
1114                            LowerRight = {
1115                               id     = 7,
1116                               pos_x  = function(w,h) return w/2 end,
1117                               pos_y  = function(w,h) return (h-64-128/2)+64 end,
1118                               width  = function(w,h) return w/2 end,
1119                               height = function(w,h) return (h-64-128)/2 end
1120                            },
1121                            SysApp = {
1122                               id     = 8,
1123                               pos_x  = 0,
1124                               pos_y  = 64,
1125                               width  = function(w,h) return w end,
1126                               height = function(w,h) return h-64-128 end
1127                            },
1128                            ["SysApp.Left"] = {
1129                               id     = 9,
1130                               pos_x  = 0,
1131                               pos_y  = 64,
1132                               width  = function(w,h) return w/2-181 end,
1133                               height = function(w,h) return h-64-128 end
1134                            },
1135                            ["SysApp.Right"] = {
1136                               id     = 10,
1137                               pos_x  = function(w,h) return w/2+181 end,
1138                               pos_y  = 64,
1139                               width  = function(w,h) return w/2-181 end,
1140                               height = function(w,h) return h-64-128 end
1141                            },
1142                            MobileFull = {
1143                               id     = 11,
1144                               pos_x  = 0,
1145                               pos_y  = 64,
1146                               width  = function(w,h) return w end,
1147                               height = function(w,h) return h-64-128 end
1148                            },
1149                            MobileUpper = {
1150                               id     = 12,
1151                               pos_x  = 0,
1152                               pos_y  = 64,
1153                               width  = function(w,h) return w end,
1154                               height = function(w,h) return (h-64-128)/2 end
1155                            },
1156                            MobileLower = {
1157                               id     = 13,
1158                               pos_x  = 0,
1159                               pos_y  = function(w,h) return (h-64-128)/2+64 end,
1160                               width  = function(w,h) return w end,
1161                               height = function(w,h) return (h-64-128)/2 end
1162                            },
1163                            Control = {
1164                               id     = 14,
1165                               pos_x  = 0,
1166                               pos_y  = function(w,h) return h-128 end,
1167                               width  = function(w,h) return w end,
1168                               height = 128
1169                            },
1170                         }
1171               }
1172   },
1173              --    id   name            type  output
1174   layers = { {      0, "BackGround"   ,    1, "Center" },
1175              {      1, "Application"  ,    2, "Center" },
1176              {      2, "HomeScreen"   ,    3, "Center" },
1177              {      3, "ControlBar"   ,    3, "Center" },
1178              {      4, "InterruptApp" ,    4, "Center" },
1179              {      5, "OnScreen"     ,    5, "Center" },
1180              {      6, "Touch"        ,  102, "Center" },
1181              {      7, "Cursor"       ,  103, "Center" }
1182   },
1183
1184
1185   manager_update = function(self, oper)
1186                        if verbose > 0 then
1187                            print("### <== WINDOW MANAGER UPDATE:" ..
1188                                  window_manager_operation_name(oper))
1189                        end
1190                        if oper == 1 then
1191                            local wumask = window_mask { --raise   = true,
1192                                                         visible = true,
1193                                                         active  = true }
1194                            local wrmask = window_mask { raise   = true,
1195                                                         active  = true,
1196                                                         layer   = true }
1197                            local lumask = layer_mask  { visible = true }
1198                            local lrmask = layer_mask  { visible = true }
1199                            local req = m:JSON({
1200                                passthrough_window_update  = wumask:tointeger(),
1201                                passthrough_window_request = wrmask:tointeger(),
1202                                passthrough_layer_update   = lumask:tointeger(),
1203                                passthrough_layer_request  = lrmask:tointeger()
1204                            })
1205                            self:manager_request(req)
1206                        end
1207                    end,
1208
1209   window_update = function(self, oper, win, mask)
1210                       if verbose > 0 then
1211                           print("### <== WINDOW UPDATE oper:" ..
1212                                 window_operation_name(oper) ..
1213                                 " mask: " .. tostring(mask))
1214                           if verbose > 1 then
1215                               print(win)
1216                           end
1217                       end
1218
1219                       local arg = m:JSON({ surface = win.surface,
1220                                            winname = win.name
1221                       })
1222                       local command = 0
1223
1224                       if oper == 1 then -- create
1225                            local layertype = win.layertype
1226                            if layertype and input_layer[layertype] then
1227                                if verbose > 0 then
1228                                    print("ignoring input panel creation")
1229                                end
1230                                return
1231                            end
1232                            command     = 0x10001
1233                       elseif oper == 2 then -- destroy
1234                            command     = 0x10002
1235                       elseif oper == 3 then  -- namechange
1236                            command     = 0x10010
1237                       elseif oper == 4 or oper == 5 then -- visible/configure
1238                            command     = 0x10009
1239                            arg.zone    = win.area
1240                            arg.node    = win.node
1241                            if win.layertype then
1242                                arg.layertype = win.layertype
1243                            end
1244                            arg.layer   = win.layer
1245                            arg.pos_x   = win.pos_x
1246                            arg.pos_y   = win.pos_y
1247                            arg.width   = win.width
1248                            arg.height  = win.height
1249                            arg.raise   = win.raise
1250                            arg.visible = win.visible
1251                            if win.active == 0 then
1252                                arg.active = 0
1253                            else
1254                                arg.active = 1
1255                            end
1256                       elseif oper == 6 then -- active
1257                            if win.active == 0 then
1258                                if verbose > 0 then
1259                                    print("ignoring inactive event")
1260                                end
1261                                return
1262                            end
1263                            command = 0x10007
1264                       elseif oper == 7 then -- map
1265                            local map = win.map
1266                            if not map then
1267                                return
1268                            end
1269                            if win.mapped == 0 then
1270                                command = 0x10021
1271                            else
1272                                command = 0x10020
1273                            end
1274                            arg.attr = map.type
1275                            --arg.name = map.target
1276                            arg.width = map.width
1277                            arg.height = map.height
1278                            arg.stride = map.stride
1279                            arg.format = map.format
1280                       else
1281                            if verbose > 0 then
1282                                print("### nothing to do")
1283                            end
1284                            return
1285                       end
1286
1287                       local msg = m:JSON({ command = command,
1288                                            appid   = win.appid,
1289                                            pid     = win.pid,
1290                                            arg     = arg
1291                       })
1292                       if verbose > 0 then
1293                           print("### <== sending " ..
1294                                 command_name(msg.command) ..
1295                                 " window message to '" .. homescreen .. "'")
1296                           if verbose > 1 then
1297                               print(msg)
1298                           end
1299                       end
1300                       sc:send_message(homescreen, msg)
1301
1302                       if oper == 1 then -- create
1303                           local i = input_layer[win.layertype]
1304                           local p = self:application(win.appid)
1305                           local s = p.privileges.screen
1306
1307                           if s == "system" then
1308                               local a = animation({})
1309                               local r = m:JSON({surface = win.surface,
1310                                                 visible = 0,
1311                                                 raise   = 1})
1312                               self:window_request(r,a,0)
1313                           else
1314                               if i then
1315                                   if verbose > 0 then
1316                                       print("do not make resource for " ..
1317                                             "input window")
1318                                   end
1319                               else
1320                                   resclnt:resource_set_create("screen",
1321                                                                "driver",
1322                                                                win.appid,
1323                                                                win.surface)
1324                                   special_screen_sets[win.surface] = true
1325                               end
1326                           end
1327
1328                           if onscreen and win.appid == onscreen then
1329                               local resmsg = m:JSON({
1330                                         command = 0x40006, -- window_id_res
1331                                         appid   = win.appid,
1332                                         pid     = win.pid,
1333                                         res     = m:JSON({
1334                                             window  = m:JSON({
1335                                                 ECU     = "",
1336                                                 display = "",
1337                                                 layer   = "",
1338                                                 layout  = "",
1339                                                 area    = "",
1340                                                 dispatchApp = "",
1341                                                 role        = win.name,
1342                                                 resourceId  = win.surface
1343                                             })
1344                                         })
1345                               })
1346                               if verbose > 0 then
1347                                   print("### <== sending " ..
1348                                         command_name(resmsg.command) ..
1349                                         " message to '" .. onscreen .. "'")
1350                                   if verbose > 1 then
1351                                       print(resmsg)
1352                                   end
1353                               end
1354                               sc:send_message(onscreen, resmsg);
1355                           end
1356                       elseif oper == 2 then -- destroy
1357                           resclnt:resource_set_destroy("screen", win.surface)
1358                           special_screen_sets[win.surface] = nil
1359                       elseif oper == 6 then -- active
1360                           if win.active then
1361                               local i = input_layer[win.layertype]
1362                               local p = self:application(win.appid)
1363                               local s = p.privileges.screen
1364                               local surface = win.surface
1365                               if not i and s ~= "system" then
1366                                  resclnt:resource_set_acquire("screen",surface)
1367                                  resmgr:window_raise(win.appid, surface, 1)
1368                               end
1369                           end
1370                       end
1371                   end,
1372
1373   layer_update = function(self, oper, layer, mask)
1374                       if verbose > 0 then
1375                           print("### LAYER UPDATE:" ..
1376                                 layer_operation_name(oper) ..
1377                                 " mask: " .. tostring(mask))
1378                           if verbose > 1 then
1379                               print(layer)
1380                           end
1381                       end
1382                       if oper == 3 then -- visible
1383                          local command = 0x10008 -- change_layer
1384                          local msg = m:JSON({
1385                                          command = command,
1386                                          appid = "",
1387                                          arg = m:JSON({layer = layer.id,
1388                                                        visible = layer.visible
1389                                          })
1390                                 })
1391                          if verbose > 0 then
1392                             print("### <== sending "..command_name(command)..
1393                                   " layer message")
1394                             if verbose > 1 then
1395                                 print(msg)
1396                             end
1397                          end
1398                          sc:send_message(homescreen, msg)
1399                       else
1400                            if verbose > 0 then
1401                                print("### nothing to do")
1402                            end
1403                       end
1404                  end,
1405
1406   output_update = function(self, oper, out, mask)
1407                       local idx = out.index
1408                       local defidx = self.output_order[idx+1]
1409                       if verbose > 0 then
1410                           print("### OUTPUT UPDATE:" .. oper ..
1411                                 " mask: "..tostring(mask))
1412                       end
1413                       if not defidx then
1414                           return
1415                       end
1416                       print(out)
1417                       local outdef = self.outputs[defidx+1]
1418                       if (oper == 1) then -- create
1419                           if outdef then
1420                               self:output_request(m:JSON({index = idx,
1421                                                           id    = outdef.id,
1422                                                           name  = outdef.name
1423                                                           }))
1424                           end
1425                       elseif (oper == 5) then -- done
1426                           local ads = outdef.areas
1427                           local on = outdef.name
1428                           if ads then
1429                               for name,ad in pairs(ads) do
1430                                   local can = wmgr:canonical_name(on.."."..name)
1431                                   local a = m:JSON({name   = name,
1432                                                     output = out.index})
1433                                   for fld,val in pairs(ad) do
1434                                       a[fld] = self:geometry(out.width,
1435                                                              out.height,
1436                                                              val)
1437                                    end
1438                                    self:area_create(a)
1439                                    resmgr:area_create(area[can], outdef.zone)
1440                               end
1441                           end
1442                       end
1443                   end
1444 }
1445
1446
1447 imgr = input_manager {
1448   inputs = {{ name = "G27 Racing Wheel",
1449               id = 0,
1450               switch = { [2] = {appid="org.tizen.ico.app-soundsample"      },
1451                          [3] = {appid="org.tizen.ico.homescreen", keycode=1},
1452                          [4] = {appid="org.tizen.ico.app-soundsample"      },
1453                          [5] = {appid="org.tizen.ico.homescreen", keycode=2}
1454              }}
1455   },
1456
1457   manager_update = function(self, oper)
1458                        if verbose > 0 then
1459                            print("### <== INPUT MANAGER UPDATE:" ..
1460                                  input_manager_operation_name(oper))
1461                        end
1462                    end,
1463
1464   input_update = function(self, oper, inp, mask)
1465                      if verbose > 0 then
1466                          print("### INPUT UPDATE:" ..
1467                                 input_operation_name(oper) ..
1468                                 " mask: " .. tostring(mask))
1469                           if verbose > 1 then
1470                               print(inp)
1471                           end
1472                       end
1473                  end,
1474   code_update  = function(self, oper, code, mask)
1475                      if verbose > 0 then
1476                          print("### CODE UPDATE: mask: " .. tostring(mask))
1477                          if verbose > 1 then
1478                              print(code)
1479                          end
1480                      end
1481                      local msg = m:JSON({ command = 1,
1482                                           appid = "org.tizen.ico.homescreen",
1483                                           arg = m:JSON({ device = code.device,
1484                                                          time = code.time,
1485                                                          input = code.input,
1486                                                          code = code.id,
1487                                                          state = code.state
1488                                            })
1489                      })
1490                      if verbose > 0 then
1491                          print("### <== sending " ..
1492                                command_name(msg.command) ..
1493                                " input message")
1494                          if verbose > 1 then
1495                              print(msg)
1496                          end
1497                      end
1498                      sc:send_message(homescreen, msg)
1499                  end
1500 }
1501
1502 sc = m:get_system_controller()
1503
1504 -- resource sets
1505 sets = {}
1506
1507 -- special screen resource sets
1508 -- TODO: just rewrite screen resource handling to use regular resource API
1509
1510 special_screen_sets = {}
1511
1512 -- user manager
1513 um = m:UserManager()
1514
1515 connected = false
1516 homescreen = ""
1517 onscreen = ""
1518
1519 cids = {}
1520
1521 -- these shoud be before wmgr:connect() is called
1522 if verbose > 0 then
1523    print("====== creating applications ======")
1524 end
1525 application {
1526     appid          = "default",
1527     area           = "Center.Full",
1528     privileges     = { screen = "none", audio = "none" },
1529     resource_class = "player",
1530     screen_priority = 0
1531 }
1532
1533 application {
1534     appid           = "weston",
1535     area            = "Center.Full",
1536     privileges      = { screen = "system", audio = "none" },
1537     resource_class  = "implicit",
1538     screen_priority = 30
1539 }
1540
1541 application {
1542     appid           = "org.tizen.ico.homescreen",
1543     area            = "Center.Full",
1544     windows         = { {'ico_hs_controlbarwindow', 'Center.Control'} },
1545     privileges      = { screen = "system", audio = "system" },
1546     resource_class  = "player",
1547     screen_priority = 20
1548 }
1549
1550 application {
1551     appid           = "org.tizen.ico.statusbar",
1552     area            = "Center.Status",
1553     privileges      = { screen = "system", audio = "none" },
1554     resource_class  = "player",
1555     screen_priority = 20
1556 }
1557
1558 application {
1559     appid           = "org.tizen.ico.onscreen",
1560     area            = "Center.Full",
1561     privileges      = { screen = "system", audio = "system" },
1562     resource_class  = "player",
1563     screen_priority = 20
1564 }
1565
1566 application {
1567     appid           = "org.tizen.ico.login",
1568     area            = "Center.Full",
1569     privileges      = { screen = "system", audio = "system" },
1570     resource_class  = "player",
1571     screen_priority = 20
1572 }
1573
1574 application {
1575     appid           = "org.tizen.ico.camera_left",
1576     area            = "Center.SysApp.Left",
1577     privileges      = { screen = "system", audio = "none" },
1578     requisites      = { screen = "blinker_left", audio = "none" },
1579     resource_class  = "player",
1580     screen_priority = 30
1581 }
1582
1583 application {
1584     appid           = "org.tizen.ico.camera_right",
1585     area            = "Center.SysApp.Right",
1586     privileges      = { screen = "system", audio = "none" },
1587     requisites      = { screen = "blinker_right", audio = "none" },
1588     resource_class  = "player",
1589     screen_priority = 30
1590 }
1591
1592 application {
1593     appid           = "net.zmap.navi",
1594     area            = "Center.Full",
1595     privileges      = { screen = "none", audio = "none" },
1596     resource_class  = "navigator",
1597     screen_priority = 30
1598 }
1599
1600 application {
1601     appid           = "GV3ySIINq7.GhostCluster",
1602     area            = "Center.Full",
1603     privileges      = { screen = "none", audio = "none" },
1604     resource_class  = "system",
1605     requisites      = { screen = "driving", audio = "none" },
1606     screen_priority = 30
1607 }
1608
1609 application {
1610     appid           = "MediaPlayer",
1611     area            = "Center.Full",
1612     privileges      = { screen = "none", audio = "none" },
1613     requisites      = { screen = "driving", audio = "none" },
1614     resource_class  = "player",
1615     screen_priority = 0
1616 }
1617
1618 application {
1619     appid           = "MyMediaPlayer",
1620     area            = "Center.Full",
1621     privileges      = { screen = "none", audio = "none" },
1622     requisites      = { screen = "driving", audio = "none" },
1623     resource_class  = "player",
1624     screen_priority = 0
1625 }
1626
1627 application {
1628     appid           = "MeterWidget",
1629     area            = "Center.Full",
1630     privileges      = { screen = "none", audio = "none" },
1631     requisites      = { screen = "driving", audio = "none" },
1632     resource_class  = "player",
1633     screen_priority = 0
1634 }
1635
1636 application {
1637     appid           = "org.tizen.ico.app-soundsample",
1638     area            = "Center.Full",
1639     privileges      = { screen = "none", audio = "none" },
1640     -- uncomment the next line to make the app exempt from regulation
1641     -- requisites      = { screen = "driving", audio = "none" },
1642     resource_class  = "player",
1643     screen_priority = 0
1644 }
1645
1646
1647 if sc then
1648     sc.client_handler = function (self, cid, msg)
1649         local command = msg.command
1650         local appid = msg.appid
1651         if verbose > 0 then
1652             print('### ==> client handler:')
1653             if verbose > 1 then
1654                 print(msg)
1655             end
1656         end
1657
1658         -- known commands: 1 for SEND_APPID, synthetic command 0xFFFF for
1659         -- disconnection
1660
1661         if command == 0xFFFF then
1662             if verbose > 1 then
1663                 print('client ' .. cid .. ' disconnected')
1664             end
1665             if msg.appid == homescreen then
1666                 homescreen = ""
1667                 for i,v in pairs(special_screen_sets) do
1668                     resclnt:resource_set_destroy("screen", i)
1669                     special_screen_sets[i] = nil
1670                 end
1671             end
1672             return
1673         end
1674
1675         -- handle the connection to weston
1676
1677         if appid then
1678             if appid == "org.tizen.ico.homescreen" then
1679                 print('Setting homescreen='..appid)
1680                 homescreen = appid
1681                 if command and command == 1 then
1682                     send_driving_mode_to(homescreen)
1683                     send_night_mode_to(homescreen)
1684                 end
1685             elseif appid == "org.tizen.ico.onscreen" then
1686                 onscreen = appid
1687                 if command and command == 1 then
1688                     send_driving_mode_to(onscreen)
1689                     send_night_mode_to(onscreen)
1690                 end
1691             end
1692
1693         if not connected and appid == "org.tizen.ico.homescreen" then
1694                 print('Trying to connect to weston...')
1695                 connected = wmgr:connect()
1696             end
1697             cids[cid] = appid
1698         end
1699     end
1700
1701     sc.generic_handler = function (self, cid, msg)
1702         if verbose > 0 then
1703             print('### ==> generic handler:')
1704             if verbose > 1 then
1705                print(msg)
1706             end
1707         end
1708     end
1709
1710     sc.window_handler = function (self, cid, msg)
1711         if verbose > 0 then
1712             print('### ==> received ' ..
1713                    command_name(msg.command) .. ' message from ' .. cids[cid])
1714             if verbose > 1 then
1715                 print(tostring(msg))
1716             end
1717         end
1718
1719         local a = animation({})
1720         local nores = false
1721         if msg.command == 0x10003 then       -- ico SHOW command
1722             local raise_mask = 0x01000000
1723             local lower_mask = 0x02000000
1724             local nores_mask = 0x40000000
1725             local time_mask  = 0x00ffffff
1726
1727             local surface        = msg.arg.surface
1728             local system_surface = false
1729             local appdb          = wmgr:application(msg.appid)
1730             system_surface       = appdb.privileges.screen == "system"
1731
1732             msg.arg.visible = 1
1733
1734             if msg.arg then
1735                 local time = 200
1736                 if  msg.arg.anim_time then
1737                     local t = msg.arg.anim_time
1738                     -- the actual time for the animation
1739                     time = m:AND(t, time_mask)
1740                     -- flag for ignoring resource control
1741                     nores = m:AND(t, nores_mask)
1742                     if m:AND(t, raise_mask) then
1743                         msg.arg.raise = 1
1744                     elseif m:AND(t, lower_mask) then
1745                         msg.arg.raise = 0
1746                     end
1747                 end
1748                 if msg.arg.anim_name then
1749                     a.show = { msg.arg.anim_name, time }
1750                     print('time: ' .. tostring(time))
1751                 end
1752             end
1753
1754             -- all show messages from system surfaces are forced
1755             if not nores and system_surface then
1756                 nores = true
1757                 if not msg.arg.raise then
1758                     msg.arg.raise = 1
1759                 end
1760             end
1761
1762             if verbose > 2 then
1763                 print('### ==> SHOW')
1764                 print(tostring(msg.arg) .. ", system_surface=" .. tostring(system_surface))
1765             end
1766
1767             if nores then
1768                 wmgr:window_request(msg.arg, a, 0)
1769
1770                 -- only non-system surfaces have resource sets
1771                 if not system_surface then
1772                     resclnt:resource_set_acquire("screen", surface)
1773                 end
1774             else
1775                 resclnt:resource_set_acquire("screen", surface)
1776                 resmgr:window_raise(msg.appid, surface, 1)
1777             end
1778         elseif msg.command == 0x10004 then   -- ico HIDE command
1779             local raise_mask = 0x01000000
1780             local lower_mask = 0x02000000
1781             local nores_mask = 0x40000000
1782             local time_mask  = 0x00ffffff
1783             msg.arg.visible = 0
1784             if msg.arg then
1785                 local time = 200
1786                 if msg.arg.anim_time then
1787                     local t = msg.arg.anim_time
1788                     -- the actual time for the animation
1789                     time = m:AND(t, time_mask)
1790                     -- flag for ignoring resource control
1791                     nores = m:AND(t, nores_mask)
1792                 end
1793                 if msg.arg.anim_name then
1794                     a.hide = { msg.arg.anim_name, time }
1795                     print('hide animation time: ' .. tostring(a.hide[2]))
1796                 end
1797             end
1798             if not nores then
1799                 local p = wmgr:application(msg.appid)
1800                 local s = p.privileges.screen
1801                 if s == "system" then
1802                     nores = true
1803                     msg.arg.raise = 0
1804                 end
1805             end
1806             if verbose > 2 then
1807                 print('### ==> HIDE REQUEST')
1808                 print(tostring(msg.arg))
1809             end
1810             if nores then
1811                 wmgr:window_request(msg.arg, a, 0)
1812             else
1813                 resmgr:window_raise(msg.appid, msg.arg.surface, -1)
1814             end
1815         elseif msg.command == 0x10005 then   -- ico MOVE
1816             if verbose > 2 then
1817                 print('### ==> MOVE REQUEST')
1818                 print(tostring(msg.arg))
1819             end
1820             if msg.arg.zone then
1821                 msg.arg.area = msg.arg.zone
1822             end
1823             wmgr:window_request(msg.arg, a, 0)
1824             -- TODO: handle if area changed
1825         elseif msg.command == 0x10007 then   -- ico CHANGE_ACTIVE
1826             if not msg.arg.active then
1827                 msg.arg.active = 3 -- pointer + keyboard
1828             end
1829             if verbose > 2 then
1830                 print('### ==> CHANGE_ACTIVE REQUEST')
1831                 print(tostring(msg.arg))
1832             end
1833             wmgr:window_request(msg.arg, a, 0)
1834         elseif msg.command == 0x10008 then   -- ico CHANGE_LAYER
1835             if verbose > 2 then
1836                 print('### ==> CHANGE_LAYER REQUEST')
1837                 print(tostring(msg.arg))
1838             end
1839             --[[
1840             if msg.arg.layer ~= 4 or msg.arg.layer ~= 5 then
1841                 print("do not change layer for other than cursor or touch")
1842                 return
1843             end
1844             --]]
1845             wmgr:window_request(msg.arg, a, 0)
1846         elseif msg.command == 0x10020 then   -- ico MAP_THUMB
1847             local framerate = msg.arg.framerate
1848             local animname  = msg.arg.anim_name
1849             if animname then
1850                a.map = { animname, 1 }
1851                if not framerate or framerate < 0 then
1852                   framerate = 5
1853                end
1854                msg.arg.mapped = 1
1855                if verbose > 2 then
1856                   print('### ==> MAP_THUMB REQUEST')
1857                   print(msg.arg)
1858                   print('framerate: '..framerate)
1859                end
1860                wmgr:window_request(msg.arg, a, framerate)
1861             end
1862         elseif msg.command == 0x10021 then   -- ico UNMAP_THUMB
1863             msg.arg.mapped = 0
1864             if verbose > 2 then
1865                 print('### ==> UNMAP_THUMB REQUEST')
1866                 print(msg.arg)
1867             end
1868             wmgr:window_request(msg.arg, a, 0)
1869 --[[
1870         elseif msg.command == 0x10013 then -- ico MAP_BUFFER command
1871             local shmname = msg.arg.anim_name
1872             local bufsize = msg.arg.width
1873             local bufnum  = msg.arg.height
1874             if shmname and bufsize and bufnum then
1875                 if verbose > 2 then
1876                     print('### ==> MAP_BUFFER REQUEST')
1877                     print("shmaname='" .. shmname ..
1878                           "' bufsize='" .. bufsize ..
1879                           " bufnum=" .. bufnum)
1880                 end
1881                 wmgr:buffer_request(shmname, bufsize, bufnum)
1882             end
1883 --]]
1884         elseif msg.command == 0x10030 then   -- ico SHOW_LAYER command
1885             msg.arg.visible = 1
1886             if verbose > 2 then
1887                 print('### ==> SHOW_LAYER REQUEST')
1888                 print(msg.arg)
1889             end
1890             wmgr:layer_request(msg.arg)
1891         elseif msg.command == 0x10031 then   -- ico HIDE_LAYER command
1892             msg.arg.visible = 0
1893             if verbose > 2 then
1894                 print('### ==> HIDE_LAYER REQUEST')
1895                 print(msg.arg)
1896             end
1897             wmgr:layer_request(msg.arg)
1898         end
1899     end
1900
1901     sc.input_handler = function (self, cid, msg)
1902         if verbose > 0 then
1903             print('### ==> input handler: ' .. command_name(msg.command))
1904             if verbose > 1 then
1905                 print(msg)
1906             end
1907         end
1908         if msg.command == 0x20001 then -- add_input
1909             msg.arg.appid = msg.appid
1910             if verbose > 2 then
1911                 print('### ==> ADD_INPUT REQUEST')
1912                 print(tostring(msg.arg))
1913             end
1914             imgr:input_request(msg.arg)
1915         elseif msg.command == 0x20002 then -- del_input
1916             msg.arg.appid = ''
1917             if verbose > 2 then
1918                 print('### ==> DEL_INPUT REQUEST')
1919                 print(tostring(msg.arg))
1920             end
1921             imgr:input_request(msg.arg)
1922         -- elseif msg.command == 0x20003 then -- send_input
1923         end
1924     end
1925
1926     sc.user_handler = function (self, cid, msg)
1927         if verbose > 0 then
1928             print('### ==> user handler: ' .. command_name(msg.command))
1929             if verbose > 1 then
1930                 print(msg)
1931             end
1932         end
1933
1934         if not um then
1935             print("User Manager not initialized")
1936             return
1937         end
1938
1939         if msg.command == 0x30001 then -- change_user
1940             print("command CHANGE_USER")
1941             if not msg.arg then
1942                 print("invalid message")
1943                 return
1944             end
1945
1946             username = msg.arg.user
1947             passwd = msg.arg.pass
1948
1949             if not username then
1950                 username = ""
1951             end
1952
1953             if not passwd then
1954                 passwd = ""
1955             end
1956
1957             success = um:changeUser(username, passwd)
1958
1959             if not success then
1960                 reply = m.JSON({
1961                     appid = msg.appid,
1962                     command = cmd
1963                 })
1964                 if sc:send_message(msg.appid, reply) then
1965                     print('*** sent authentication failed message')
1966                 else
1967                     print('*** failed to send authentication failed message')
1968                 end
1969             end
1970
1971         elseif msg.command == 0x30002 then -- get_userlist
1972             print("command GET_USERLIST")
1973             if not msg.appid then
1974                 print("invalid message")
1975                 return
1976             end
1977
1978             users, currentUser = um:getUserList()
1979
1980             if not users then
1981                 print("failed to get user list")
1982                 return
1983             end
1984
1985             nUsers = 0
1986
1987             for i,v in pairs(users) do
1988                 nUsers = nUsers + 1
1989             end
1990
1991             if not currentUser then
1992                 currentUser = ""
1993             end
1994
1995             if verbose > 1 then
1996                 print("current user: " .. currentUser)
1997                 print("user list:")
1998                 for i,v in pairs(users) do
1999                     print(v)
2000                 end
2001             end
2002
2003             reply = m.JSON({
2004                 appid = msg.appid,
2005                 command = cmd,
2006                 arg = m.JSON({
2007                     user_num = nUsers,
2008                     user_list = users,
2009                     user_login = currentUser
2010                 })
2011             })
2012
2013             if verbose > 1 then
2014                 print("### <== GetUserList reply: " .. tostring(reply))
2015             end
2016
2017             if sc:send_message(msg.appid, reply) then
2018                 print('*** reply OK')
2019             else
2020                 print('*** reply FAILED')
2021             end
2022
2023         elseif msg.command == 0x30003 then -- get_lastinfo
2024             print("command GET_LASTINFO")
2025             if not msg.appid then
2026                 print("invalid message")
2027                 return
2028             end
2029
2030             lastInfo = um:getLastInfo(msg.appid)
2031
2032             if not lastInfo then
2033                 print("failed to get last info for app" .. msg.appid)
2034                 return
2035             end
2036
2037             reply = m.JSON({
2038                 appid = msg.appid,
2039                 command = cmd,
2040                 arg = m.JSON({
2041                     lastinfo = lastinfo
2042                 })
2043             })
2044
2045             if sc:send_message(msg.appid, reply) then
2046                 print('*** reply OK')
2047             else
2048                 print('*** reply FAILED')
2049             end
2050
2051         elseif msg.command == 0x30004 then -- set_lastinfo
2052             print("command SET_LASTINFO")
2053             if not msg.arg or not msg.appid then
2054                 print("invalid message")
2055                 return
2056             end
2057
2058             lastInfo = um:setLastInfo(msg.appid, msg.arg.lastinfo)
2059         end
2060     end
2061
2062     sc.resource_handler = function (self, cid, msg)
2063         if verbose > 0 then
2064             print('### ==> resource handler: ' .. command_name(msg.command))
2065             if verbose > 1 then
2066                 print(msg)
2067             end
2068         end
2069
2070         getKey = function (msg)
2071             -- Field rset.key is an id for distinguishing between rsets. All
2072             -- resource types appear to contain a different key. Just pick one
2073             -- based on what we have on the message.
2074
2075             key = nil
2076
2077             if msg and msg.res then
2078                 if msg.res.sound then
2079                     key = msg.res.sound.id
2080                 elseif msg.res.input then
2081                     key = msg.res.input.name
2082                 elseif msg.res.window then
2083                     -- alarm! this appars to be non-unique?
2084                     key = msg.res.window.resourceId
2085                 end
2086             end
2087
2088             return key
2089         end
2090
2091         createResourceSet = function (ctl, client, msg)
2092             cb = function(rset)
2093
2094                 -- m:info("*** resource_cb: client = '" .. msg.appid .. "'")
2095
2096                 -- type is either basic (0) or interrupt (1)
2097                 requestType = 0
2098                 if msg.res.type then
2099                     requestType = msg.res.type
2100                 end
2101
2102                 if rset.data.filter_first then
2103                     rset.data.filter_first = false
2104                     return
2105                 end
2106
2107                 if rset.acquired then
2108                     cmd = 0x00040001 -- acquire
2109
2110                     if msg.appid == onscreen then
2111                         -- notifications are valid only for a number of seconds
2112                         rset.timer = m:Timer({
2113                             interval = 5000,
2114                             oneshot = true,
2115                             callback = function (t)
2116                                 m:info("notification timer expired")
2117
2118                                 if rset.data then
2119                                     reply.res.window = rset.data.window
2120                                 end
2121
2122                                 rset:release()
2123                                 rset.timer = nil
2124
2125                                 -- Send a "RELEASE" message to client.
2126                                 -- This triggers the resource deletion
2127                                 -- cycle in OnScreen.
2128
2129                                 reply = m.JSON({
2130                                     appid = msg.appid,
2131                                     command = cmd,
2132                                     res = {
2133                                         type = requestType
2134                                     }
2135                                 })
2136
2137                                 sc:send_message(client, reply)
2138                             end
2139                         })
2140                     end
2141                 else
2142                     cmd = 0x00040002 -- release
2143                     if rset.timer then
2144                        rset.timer.callback = nil
2145                        rset.timer = nil
2146                     end
2147                 end
2148
2149                 reply = m.JSON({
2150                         appid = msg.appid,
2151                         command = cmd,
2152                         res = {
2153                             type = requestType
2154                         }
2155                     })
2156
2157                 if rset.data.sound then
2158                     reply.res.sound = rset.data.sound
2159                 end
2160
2161                 if rset.data.window then
2162                     reply.res.window = rset.data.window
2163                 end
2164
2165                 if rset.data.input then
2166                     reply.res.input = rset.data.input
2167                 end
2168
2169                 if rset.acquired then
2170                     m:info("resource cb: 'acquire' reply to client " .. client)
2171                 else
2172                     m:info("resource cb: 'release' reply to client " .. client)
2173                 end
2174
2175                 if not sc:send_message(client, reply) then
2176                     m:info('*** reply FAILED')
2177                 end
2178             end
2179
2180             local rset = m:ResourceSet({
2181                     application_class = "player",
2182                     zone = "driver", -- msg.zone ("full")
2183                     callback = cb
2184                 })
2185
2186             rset.data = {
2187                 cid = cid,
2188                 ctl = ctl,
2189                 filter_first = true
2190             }
2191
2192             if msg.res.sound then
2193                 rset:addResource({
2194                         resource_name = "audio_playback"
2195                     })
2196                 rset.resources.audio_playback.attributes.pid = tostring(msg.pid)
2197                 rset.resources.audio_playback.attributes.appid = msg.appid
2198                 print("sound name: " .. msg.res.sound.name)
2199                 print("sound zone:" .. msg.res.sound.zone)
2200                 print("sound adjust: " .. tostring(msg.res.sound.adjust))
2201
2202                 rset.data.sound = msg.res.sound
2203             end
2204
2205             if msg.res.input then
2206                 rset:addResource({
2207                         resource_name = "input"
2208                     })
2209                 rset.resources.input.attributes.pid = tostring(msg.pid)
2210                 rset.resources.input.attributes.appid = msg.appid
2211                 print("input name: " .. msg.res.input.name)
2212                 print("input event:" .. tostring(msg.res.input.event))
2213
2214                 rset.data.input = msg.res.input
2215             end
2216
2217             if msg.res.window then
2218                 rset:addResource({
2219                         resource_name = "screen",
2220                         shared = true
2221                     })
2222                 rset.resources.screen.attributes.pid = tostring(msg.pid)
2223                 rset.resources.screen.attributes.appid = msg.appid
2224                 rset.resources.screen.attributes.surface = msg.res.window.resourceId
2225                 complete_area = msg.res.window.display .. '.' .. msg.res.window.area
2226                 rset.resources.screen.attributes.area = complete_area
2227                 if msg.appid == onscreen then
2228                     rset.resources.screen.attributes.classpri = 1
2229                 else
2230                     rset.resources.screen.attributes.classpri = 0
2231                 end
2232
2233                 rset.data.window = msg.res.window
2234             end
2235
2236             rset.key = getKey(msg)
2237
2238             return rset
2239         end
2240
2241         -- parse the message
2242
2243         -- fields common to all messages:
2244         --      msg.command
2245         --      msg.appid
2246         --      msg.pid
2247
2248         if msg.command == 0x40011 then -- create_res
2249             print("command CREATE_RES")
2250             key = getKey(msg)
2251
2252             if key then
2253                 if not sets.cid then
2254                     sets.cid = {}
2255                 end
2256                 sets.cid[key] = createResourceSet(self, cid, msg)
2257             end
2258
2259         elseif msg.command == 0x40012 then -- destroy_res
2260             print("command DESTROY_RES")
2261             key = getKey(msg)
2262
2263             if key then
2264                 if sets.cid and sets.cid[key] then
2265                     sets.cid[key]:release()
2266                     sets.cid[key].timer = nil
2267                     sets.cid[key] = nil -- garbage collecting
2268                 end
2269             end
2270
2271         elseif msg.command == 0x40001 then -- acquire_res
2272             print("command ACQUIRE_RES")
2273             key = getKey(msg)
2274
2275             if key then
2276                 if not sets.cid then
2277                     sets.cid = {}
2278                 end
2279                 if not sets.cid[key] then
2280                     sets.cid[key] = createResourceSet(self, cid, msg)
2281                 end
2282                 print("acquiring the resource set")
2283                 sets.cid[key]:acquire()
2284             end
2285
2286         elseif msg.command == 0x40002 then -- release_res
2287             print("command RELEASE_RES")
2288
2289             key = getKey(msg)
2290
2291             if key then
2292                 if sets.cid and sets.cid[key] then
2293                     sets.cid[key]:release()
2294
2295                     if msg.appid == onscreen then
2296                         -- in case of OnScreen, this actually means that the
2297                         -- resource set is never used again; let gc do its job
2298                         sets.cid[key].timer = nil
2299                         sets.cid[key] = nil -- garbage collecting
2300                     end
2301                 end
2302             end
2303
2304         elseif msg.command == 0x40003 then -- deprive_res
2305             print("command DEPRIVE_RES")
2306
2307         elseif msg.command == 0x40004 then -- waiting_res
2308             print("command WAITING_RES")
2309
2310         elseif msg.command == 0x40005 then -- revert_res
2311             print("command REVERT_RES")
2312         end
2313     end
2314
2315     sc.inputdev_handler = function (self, cid, msg)
2316         if verbose > 0 then
2317             print('*** inputdev handler: ' .. command_name(msg.command))
2318             if verbose > 1 then
2319                 print(msg)
2320             end
2321         end
2322     end
2323
2324     sc.notify_handler = function (self, cid, msg)
2325         if verbose > 0 then
2326             print('### notify handler: ' .. command_name(msg.command))
2327             if verbose > 1 then
2328                 print(msg)
2329             end
2330         end
2331     end
2332 end
2333
2334 function send_driving_mode_to(client)
2335     if client == "" then
2336         return
2337     end
2338
2339     local driving_mode = mdb.select.select_driving_mode.single_value
2340
2341     if not driving_mode then driving_mode = 0 end
2342
2343     local reply = m:JSON({ command = 0x60001,
2344                            arg     = m:JSON({ stateid = 1,
2345                                               state   = driving_mode
2346                                      })
2347                   })
2348
2349     if verbose > 0 then
2350         print("### <== sending " .. command_name(reply.command) .. " message")
2351         if verbose > 1 then
2352             print(reply)
2353         end
2354     end
2355
2356     sc:send_message(client, reply)
2357 end
2358
2359 function send_night_mode_to(client)
2360     if client == "" then
2361         return
2362     end
2363
2364     local night_mode = mdb.select.select_night_mode.single_value
2365
2366     if not night_mode then night_mode = 0 end
2367
2368     local reply = m:JSON({ command = 0x60001,
2369                            arg     = m:JSON({ stateid = 2,
2370                                               state   = night_mode
2371                                      })
2372                   })
2373
2374     if verbose > 0 then
2375         print("### <== sending " .. command_name(reply.command) .. " message")
2376         if verbose > 1 then
2377             print(reply)
2378         end
2379      end
2380
2381      sc:send_message(client, reply)
2382 end
2383
2384 -- we should have 'audio_playback' defined by now
2385 m:try_load_plugin('telephony')