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