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