config: check for nil system controller variable.
[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
1114 if sc then
1115     sc.client_handler = function (self, cid, msg)
1116         local command = msg.command
1117         if verbose > 0 then
1118             print('### ==> client handler:')
1119             if verbose > 1 then
1120                 print(msg)
1121             end
1122         end
1123         if not connected then
1124             print('Setting homescreen='..msg.appid)
1125             homescreen = msg.appid
1126             print('Trying to connect to wayland...')
1127             connected = wmgr:connect()
1128         end
1129         if connected and command then
1130             if command == 1 then -- send_appid
1131                 local driving_mode = mdb.select.select_driving_mode.single_value
1132                 local night_mode = mdb.select.select_night_mode.single_value
1133
1134                 if not driving_mode then driving_mode = 0 end
1135                 if not night_mode then night_mode = 0 end
1136
1137                 local reply = m:JSON({ command = 0x60001,
1138                                        arg     = m:JSON({ stateid = 1,
1139                                                           state   = driving_mode})
1140                                      })
1141                  if verbose > 0 then
1142                      print("### <== sending " ..
1143                            command_name(command) .. " message")
1144                      if verbose > 1 then
1145                          print(reply)
1146                      end
1147                  end
1148                  sc:send_message(homescreen, reply)
1149
1150                  reply = m:JSON({ command = 0x60001,
1151                                   arg     = m:JSON({ stateid = 2,
1152                                                      state   = night_mode})
1153                                 })
1154                  if verbose > 0 then
1155                      print("### <== sending " ..
1156                            command_name(command) .. " message")
1157                      if verbose > 1 then
1158                          print(reply)
1159                      end
1160                  end
1161                  sc:send_message(homescreen, reply)
1162             end
1163         end
1164     end
1165
1166     sc.generic_handler = function (self, cid, msg)
1167         if verbose > 0 then
1168             print('### ==> generic handler:')
1169             if verbose > 1 then
1170                print(msg)
1171             end
1172         end
1173     end
1174
1175     sc.window_handler = function (self, cid, msg)
1176         if verbose > 0 then
1177             print('### ==> received ' ..
1178                    command_name(msg.command) .. ' message')
1179             if verbose > 1 then
1180                 print(tostring(msg))
1181             end
1182         end
1183
1184         local a = animation({})
1185         local nores = false
1186         if msg.command == 0x10003 then       -- ico SHOW command
1187             local raise_mask = 0x01000000
1188             local lower_mask = 0x02000000
1189             local nores_mask = 0x40000000
1190             local time_mask  = 0x00ffffff
1191             msg.arg.visible = 1
1192             if msg.arg then
1193                 local time = 200
1194                 if  msg.arg.anim_time then
1195                     local t = msg.arg.anim_time
1196                     time = m:AND(t, time_mask)
1197                     nores = m:AND(t, nores_mask)
1198                     if m:AND(t, raise_mask) then
1199                         msg.arg.raise = 1
1200                     elseif m:AND(t, lower_mask) then
1201                         msg.arg.raise = 0
1202                     end
1203                 end
1204                 if msg.arg.anim_name then
1205                     a.show = { msg.arg.anim_name, time }
1206                     print('time: ' .. tostring(a.show[2]))
1207                 end
1208             end
1209             if not nores then
1210                 local p = wmgr:application(msg.appid)
1211                 local s = p.privileges.screen
1212                 if s == "system" then
1213                     nores = true
1214                 end
1215             end
1216             if verbose > 2 then
1217                 print('### ==> SHOW')
1218                 print(tostring(msg.arg))
1219             end
1220             if nores then
1221                 wmgr:window_request(msg.arg, a, 0)
1222             else
1223                 local surface = msg.arg.surface
1224                 resclnt:resource_set_acquire("screen", surface)
1225                 resmgr:window_raise(msg.appid, surface, 1)
1226             end
1227         elseif msg.command == 0x10004 then   -- ico HIDE command
1228             local raise_mask = 0x01000000
1229             local lower_mask = 0x02000000
1230             local nores_mask = 0x40000000
1231             local time_mask  = 0x00ffffff
1232             msg.arg.visible = 0
1233             if msg.arg then
1234                 local time = 200
1235                 if msg.arg.anim_time then
1236                     local t = msg.arg.anim_time
1237                     time = m:AND(t, time_mask)
1238                     nores = m:AND(t, nores_mask)
1239                 end
1240                 if msg.arg.anim_name then
1241                     a.hide = { msg.arg.anim_name, time }
1242                     print('hide animation time: ' .. tostring(a.hide[2]))
1243                 end
1244             end
1245             if not nores then
1246                 local p = wmgr:application(msg.appid)
1247                 local s = p.privileges.screen
1248                 if s == "system" then
1249                     nores = true
1250                 end
1251             end
1252             if verbose > 2 then
1253                 print('### ==> HIDE REQUEST')
1254                 print(tostring(msg.arg))
1255             end
1256             if nores then
1257                 wmgr:window_request(msg.arg, a, 0)
1258             else
1259                 resmgr:window_raise(msg.appid, msg.arg.surface, -1)
1260             end
1261         elseif msg.command == 0x10005 then   -- ico MOVE
1262             if verbose > 2 then
1263                 print('### ==> MOVE REQUEST')
1264                 print(tostring(msg.arg))
1265             end
1266             wmgr:window_request(msg.arg, a, 0)
1267             -- TODO: handle if area changed
1268         elseif msg.command == 0x10006 then   -- ico ACTIVE
1269             if not msg.arg.active then
1270                 msg.arg.active = 3 -- pointer + keyboard
1271             end
1272             if verbose > 2 then
1273                 print('### ==> ACTIVE REQUEST')
1274                 print(tostring(msg.arg))
1275             end
1276             wmgr:window_request(msg.arg, a, 0)
1277         elseif msg.command == 0x10007 then   -- ico CHANGE_LAYER
1278             if verbose > 2 then
1279                 print('### ==> CHANGE_LAYER REQUEST')
1280                 print(tostring(msg.arg))
1281             end
1282             --[[
1283             if msg.arg.layer ~= 4 or msg.arg.layer ~= 5 then
1284                 print("do not change layer for other than cursor or touch")
1285                 return
1286             end
1287             --]]
1288             wmgr:window_request(msg.arg, a, 0)
1289         elseif msg.command == 0x10011 then   -- ico MAP_THUMB
1290             local framerate = msg.arg.framerate
1291             if not framerate or framerate < 0 then
1292                 framerate = 0
1293             end
1294             msg.arg.map = 1
1295             if verbose > 2 then
1296                 print('### ==> MAP_THUMB REQUEST')
1297                 print(msg.arg)
1298                 print('framerate: '..framerate)
1299             end
1300             wmgr:window_request(msg.arg, a, framerate)
1301         elseif msg.command == 0x10012 then   -- ico UNMAP_THUMB
1302             msg.arg.map = 0
1303             if verbose > 2 then
1304                 print('### ==> UNMAP_THUMB REQUEST')
1305                 print(msg.arg)
1306             end
1307             wmgr:window_request(msg.arg, a, 0)
1308         elseif msg.command == 0x10020 then   -- ico SHOW_LAYER command
1309             msg.arg.visible = 1
1310             if verbose > 2 then
1311                 print('### ==> SHOW_LAYER REQUEST')
1312                 print(msg.arg)
1313             end
1314             wmgr:layer_request(msg.arg)
1315         elseif msg.command == 0x10021 then   -- ico HIDE_LAYER command
1316             msg.arg.visible = 0
1317             if verbose > 2 then
1318                 print('### ==> HIDE_LAYER REQUEST')
1319                 print(msg.arg)
1320             end
1321             wmgr:layer_request(msg.arg)
1322         end
1323     end
1324
1325     sc.input_handler = function (self, cid, msg)
1326         if verbose > 0 then
1327             print('### ==> input handler: ' .. command_name(msg.command))
1328             if verbose > 1 then
1329                 print(msg)
1330             end
1331         end
1332         if msg.command == 0x20001 then -- add_input
1333             msg.arg.appid = msg.appid
1334             if verbose > 2 then
1335                 print('### ==> ADD_INPUT REQUEST')
1336                 print(tostring(msg.arg))
1337             end
1338             imgr:input_request(msg.arg)
1339         elseif msg.command == 0x20002 then -- del_input
1340             msg.arg.appid = ''
1341             if verbose > 2 then
1342                 print('### ==> DEL_INPUT REQUEST')
1343                 print(tostring(msg.arg))
1344             end
1345             imgr:input_request(msg.arg)
1346         elseif msg.command == 0x20003 then -- send_input
1347         end
1348     end
1349
1350     sc.user_handler = function (self, cid, msg)
1351         if verbose > 0 then
1352             print('### ==> user handler: ' .. command_name(msg.command))
1353             if verbose > 1 then
1354                 print(msg)
1355             end
1356         end
1357
1358         if not um then
1359             print("User Manager not initialized")
1360             return
1361         end
1362
1363         if msg.command == 0x00030001 then -- MSG_CMD_CHANGE_USER
1364             print("command CHANGE_USER")
1365             if not msg.arg then
1366                 print("invalid message")
1367                 return
1368             end
1369
1370             username = msg.arg.user
1371             passwd = msg.arg.pass
1372
1373             if not username then
1374                 username = ""
1375             end
1376
1377             if not passwd then
1378                 passwd = ""
1379             end
1380
1381             success = um:changeUser(username, passwd)
1382
1383             if not success then
1384                 reply = m.JSON({
1385                     appid = msg.appid,
1386                     command = cmd
1387                 })
1388                 if sc:send_message(msg.appid, reply) then
1389                     print('*** sent authentication failed message')
1390                 else
1391                     print('*** failed to send authentication failed message')
1392                 end
1393             end
1394
1395         elseif msg.command == 0x00030002 then -- MSG_CMD_GET_USERLIST
1396             print("command GET_USERLIST")
1397             if not msg.appid then
1398                 print("invalid message")
1399                 return
1400             end
1401
1402             users, currentUser = um:getUserList()
1403
1404             if not users then
1405                 print("failed to get user list")
1406                 return
1407             end
1408
1409             nUsers = 0
1410
1411             for i,v in pairs(users) do
1412                 nUsers = nUsers + 1
1413             end
1414
1415             if not currentUser then
1416                 currentUser = ""
1417             end
1418
1419             if verbose > 1 then
1420                 print("current user: " .. currentUser)
1421                 print("user list:")
1422                 for i,v in pairs(users) do
1423                     print(v)
1424                 end
1425             end
1426
1427             reply = m.JSON({
1428                 appid = msg.appid,
1429                 command = cmd,
1430                 arg = m.JSON({
1431                     user_num = nUsers,
1432                     user_list = users,
1433                     user_login = currentUser
1434                 })
1435             })
1436
1437             if verbose > 1 then
1438                 print("### <== GetUserList reply: " .. tostring(reply))
1439             end
1440
1441             if sc:send_message(msg.appid, reply) then
1442                 print('*** reply OK')
1443             else
1444                 print('*** reply FAILED')
1445             end
1446
1447         elseif msg.command == 0x00030003 then -- MSG_CMD_GET_LASTINFO
1448             print("command GET_LASTINFO")
1449             if not msg.appid then
1450                 print("invalid message")
1451                 return
1452             end
1453
1454             lastInfo = um:getLastInfo(msg.appid)
1455
1456             if not lastInfo then
1457                 print("failed to get last info for app" .. msg.appid)
1458                 return
1459             end
1460
1461             reply = m.JSON({
1462                 appid = msg.appid,
1463                 command = cmd,
1464                 arg = m.JSON({
1465                     lastinfo = lastinfo
1466                 })
1467             })
1468
1469             if sc:send_message(msg.appid, reply) then
1470                 print('*** reply OK')
1471             else
1472                 print('*** reply FAILED')
1473             end
1474
1475         elseif msg.command == 0x00030004 then -- MSG_CMD_SET_LASTINFO
1476             print("command SET_LASTINFO")
1477             if not msg.arg or not msg.appid then
1478                 print("invalid message")
1479                 return
1480             end
1481
1482             lastInfo = um:setLastInfo(msg.appid, msg.arg.lastinfo)
1483         end
1484     end
1485
1486     sc.resource_handler = function (self, cid, msg)
1487         if verbose > 0 then
1488             print('### ==> resource handler: ' .. command_name(msg.command))
1489             if verbose > 1 then
1490                 print(msg)
1491             end
1492         end
1493
1494         createResourceSet = function (ctl, client, msg)
1495             cb = function(rset, data)
1496                 print("> resource callback")
1497
1498                 -- type is either basic (0) or interrupt (1)
1499                 requestType = 0
1500                 if msg.res.type then
1501                     requestType = msg.res.type
1502                 end
1503
1504                 if rset.acquired then
1505                     cmd = 0x00040001 -- acquire
1506                 else
1507                     cmd = 0x00040002 -- release
1508                 end
1509
1510                 reply = m.JSON({
1511                         appid = data.client,
1512                         command = cmd,
1513                         res = {
1514                             type = requestType
1515                         }
1516                     })
1517
1518                 if rset.resources.audio_playback then
1519                     reply.res.sound = {
1520                         zone = "driver",
1521                         name = msg.appid,
1522                         adjust = 0,
1523                         -- id = "0"
1524                     }
1525                 end
1526
1527                 if rset.resources.display then
1528                     reply.res.window = {
1529                         zone = "driver",
1530                         name = msg.appid,
1531                         -- id = "0"
1532                     }
1533                 end
1534
1535                 if rset.resources.input then
1536                     reply.res.input = {
1537                         name = msg.appid,
1538                         event = 0
1539                     }
1540                 end
1541                 print("sending message to client: " .. data.client)
1542
1543                 if sc:send_message(data.client, reply) then
1544                     print('*** reply OK')
1545                 else
1546                     print('*** reply FAILED')
1547                 end
1548             end
1549
1550             rset = m:ResourceSet({
1551                     application_class = "player",
1552                     zone = "driver", -- msg.zone ("full")
1553                     callback = cb
1554                 })
1555
1556             rset.data = {
1557                 cid = cid,
1558                 ctl = ctl
1559             }
1560
1561             if msg.res.sound then
1562                 rset:addResource({
1563                         resource_name = "audio_playback"
1564                     })
1565                 rset.resources.audio_playback.attributes.pid = tostring(msg.pid)
1566                 rset.resources.audio_playback.attributes.appid = msg.appid
1567                 print("sound name: " .. msg.res.sound.name)
1568                 print("sound zone:" .. msg.res.sound.zone)
1569                 print("sound adjust: " .. tostring(msg.res.sound.adjust))
1570                 if msg.res.sound.id then
1571                     print("sound id: " .. msg.res.sound.id)
1572                 end
1573             end
1574
1575             if msg.res.input then
1576                 rset:addResource({
1577                         resource_name = "input"
1578                     })
1579                 rset.resources.input.attributes.pid = tostring(msg.pid)
1580                 rset.resources.input.attributes.appid = msg.appid
1581                 print("input name: " .. msg.res.sound.name)
1582                 print("input event:" .. tostring(msg.res.input.event))
1583             end
1584
1585             if msg.res.window then
1586                 rset:addResource({
1587                         resource_name = "display"
1588                     })
1589                 rset.resources.display.attributes.pid = tostring(msg.pid)
1590                 rset.resources.display.attributes.appid = msg.appid
1591                 print("display name: " .. msg.res.display.name)
1592                 print("display zone:" .. msg.res.display.zone)
1593                 if msg.res.display.id then
1594                     print("display id: " .. msg.res.display.id)
1595                 end
1596             end
1597
1598             return rset
1599         end
1600
1601         -- parse the message
1602
1603         -- fields common to all messages:
1604         --      msg.command
1605         --      msg.appid
1606         --      msg.pid
1607
1608         if msg.command == 0x00040011 then -- MSG_CMD_CREATE_RES
1609             print("command CREATE")
1610
1611             if not sets.cid then
1612                 sets.cid = createResourceSet(self, cid, msg)
1613             end
1614
1615         elseif msg.command == 0x00040012 then -- MSG_CMD_DESTORY_RES
1616             print("command DESTROY")
1617
1618             if sets.cid then
1619                 sets.cid:release()
1620             end
1621
1622             sets.cid = nil -- garbage collecting
1623
1624         elseif msg.command == 0x00040001 then -- MSG_CMD_ACQUIRE_RES
1625             print("command ACQUIRE")
1626
1627             if not sets.cid then
1628                 sets.cid = createResourceSet(self, cid, msg)
1629             end
1630
1631             sets.cid:acquire()
1632
1633         elseif msg.command == 0x00040002 then -- MSG_CMD_RELEASE_RES
1634             print("command RELEASE")
1635
1636             if sets.cid then
1637                 sets.cid:release()
1638             end
1639
1640         elseif msg.command == 0x00040003 then -- MSG_CMD_DEPRIVE_RES
1641             print("command DEPRIVE")
1642
1643         elseif msg.command == 0x00040004 then -- MSG_CMD_WAITING_RES
1644             print("command WAITING")
1645
1646         elseif msg.command == 0x00040005 then -- MSG_CMD_REVERT_RES
1647             print("command REVERT")
1648         end
1649     end
1650
1651     sc.inputdev_handler = function (self, cid, msg)
1652         if verbose > 0 then
1653             print('*** inputdev handler: ' .. command_name(msg.command))
1654             if verbose > 1 then
1655                 print(msg)
1656             end
1657         end
1658     end
1659 end