1 with_system_controller = false
5 -- try loading the various logging plugins
6 m:try_load_plugin('systemd')
7 m:try_load_plugin('dlog')
9 -- load the console plugin
10 m:try_load_plugin('console')
12 m:try_load_plugin('console.disabled', 'webconsole', {
13 address = 'wsck:127.0.0.1:3000/murphy',
14 httpdir = '/usr/share/murphy/webconsole' });
16 -- load the dbus plugin
17 if m:plugin_exists('dbus') then
21 -- load the native resource plugin
22 if m:plugin_exists('resource-native') then
23 m:load_plugin('resource-native')
24 m:info("native resource plugin loaded")
26 m:info("No native resource plugin found...")
29 -- load the dbus resource plugin
30 m:try_load_plugin('resource-dbus', {
32 dbus_service = "org.Murphy",
34 default_zone = "driver",
35 default_class = "implicit"
38 -- load the domain control plugin
39 if m:plugin_exists('domain-control') then
40 m:load_plugin('domain-control')
42 m:info("No domain-control plugin found...")
45 -- load the AMB plugin
46 if m:plugin_exists('amb') then
49 m:info("No amb plugin found...")
52 -- load the ASM resource plugin
53 if m:plugin_exists('resource-asm') then
54 m:load_plugin('resource-asm', {
56 share_mmplayer = "player:AVP,mandatory,exclusive,strict",
57 ignored_argv0 = "WebProcess"
60 m:info("No audio session manager plugin found...")
63 if m:plugin_exists('ivi-resource-manager') and not with_system_controller then
64 m:load_plugin('ivi-resource-manager')
67 -- define application classes
114 application_class { name="event" , priority=4 , modal=false, share=true , order="fifo" }
115 application_class { name="game" , priority=3 , modal=false, share=false, order="lifo" }
116 --# doesn't need to be created here, ivi-resource-manager creates it if loaded
117 --#application_class { name="basic" , priority=2 , modal=false, share=false, order="lifo" }
118 application_class { name="player" , priority=1 , modal=false, share=true , order="lifo" }
119 application_class { name="implicit" , priority=0 , modal=false, share=false, order="lifo" }
121 -- define zone attributes
123 type = {mdb.string, "common", "rw"},
124 location = {mdb.string, "anywhere", "rw"}
132 location = "front-left"
140 location = "front-right"
148 location = "back-left"
156 location = "back-right"
164 location = "back-left"
169 -- define resource classes
170 if not m:plugin_exists('ivi-resource-manager') and
171 not with_system_controller
174 name = "audio_playback",
177 role = { mdb.string, "music", "rw" },
178 pid = { mdb.string, "<unknown>", "rw" },
179 policy = { mdb.string, "relaxed", "rw" }
185 name = "audio_recording",
188 role = { mdb.string, "music" , "rw" },
189 pid = { mdb.string, "<unknown>", "rw" },
190 policy = { mdb.string, "relaxed" , "rw" }
195 name = "video_playback",
200 name = "video_recording",
204 if not m:plugin_exists('ivi-resource-manager') then
205 resource.method.veto = {
206 function(zone, rset, grant, owners)
207 rset_priority = application_class[rset.application_class].priority
209 owner_id = owners.audio_playback.resource_set
212 if (rset_priority >= 50 and owner_id ~= rset_id) then
213 print("*** resource-set "..rset_id.." - veto")
222 -- test for creating selections
224 name = "audio_owner",
225 table = "audio_playback_owner",
226 columns = {"application_class"},
227 condition = "zone_name = 'driver'"
231 name = "vehicle_speed",
232 table = "amb_vehicle_speed",
234 condition = "key = 'VehicleSpeed'"
238 name = "speed2volume",
239 inputs = { speed = mdb.select.vehicle_speed, param = 9 },
240 outputs = { mdb.table { name = "speedvol",
241 index = {"zone", "device"},
242 columns = {{"zone", mdb.string, 16},
243 {"device", mdb.string, 16},
244 {"value", mdb.floating}},
249 update = function(self)
250 speed = self.inputs.speed.single_value
252 volume = (speed - 144.0) / 7.0
256 diff = volume - self.oldvolume
257 if (diff*diff > self.inputs.param) then
258 print("*** element "..self.name.." update "..volume)
259 self.oldvolume = volume
260 mdb.table.speedvol:replace({zone = "driver", device = "speakers", value = volume})
265 -- Night mode processing chain
268 name = "exterior_brightness",
269 table = "amb_exterior_brightness",
270 columns = { "value" },
271 condition = "key = 'ExteriorBrightness'"
276 inputs = { brightness = mdb.select.exterior_brightness },
280 name = "amb_nightmode",
284 { "id", mdb.unsigned },
285 { "night_mode", mdb.unsigned }
289 update = function(self)
290 -- This is a trivial function to calculate night mode. Later, we will
291 -- need a better threshold value and hysteresis to prevent oscillation.
293 brightness = self.inputs.brightness.single_value
295 if not brightness then
299 print("*** element "..self.name.." update brightness: "..brightness)
301 if brightness > 300 then
307 print("*** resulting mode: ".. mode)
309 if not (mode == self.oldmode) then
310 mdb.table.amb_nightmode:replace({ id = 0, night_mode = mode })
318 name = "select_night_mode",
319 table = "amb_nightmode",
320 columns = { "night_mode" },
326 inputs = { owner = mdb.select.select_night_mode },
327 property = "NightMode",
329 initiate = builtin.method.amb_initiate,
330 update = builtin.method.amb_update
334 -- Driving mode processing chain
338 name = "drivingmode",
339 inputs = { speed = mdb.select.vehicle_speed },
343 name = "amb_drivingmode",
347 { "id", mdb.unsigned },
348 { "driving_mode", mdb.unsigned }
352 update = function(self)
354 speed = self.inputs.speed.single_value
366 if not (mode == self.oldmode) then
367 mdb.table.amb_drivingmode:replace({ id = 0, driving_mode = mode })
375 name = "select_driving_mode",
376 table = "amb_drivingmode",
377 columns = { "driving_mode" },
382 name = "driving_mode",
383 inputs = { owner = mdb.select.select_driving_mode },
384 property = "DrivingMode",
386 initiate = builtin.method.amb_initiate,
387 update = builtin.method.amb_update
390 -- turn signals (left, right)
394 table = "amb_turn_signal",
395 columns = { "value" },
396 condition = "key = 'TurnSignal'"
399 -- regulation (on), use "select_driving_mode"
401 -- shift position (parking, reverse, other)
404 name = "gear_position",
405 table = "amb_gear_position",
406 columns = { "value" },
407 condition = "key = 'GearPosition'"
410 -- cameras (back, front, left, right)
413 name = "camera_state",
414 inputs = { winker = mdb.select.winker, gear = mdb.select.gear_position },
418 name = "target_camera_state",
422 { "id", mdb.unsigned },
423 { "front_camera", mdb.unsigned },
424 { "back_camera", mdb.unsigned },
425 { "right_camera", mdb.unsigned },
426 { "left_camera", mdb.unsigned }
430 update = function(self)
437 if self.inputs.gear == 128 then
439 elseif self.inputs.winker == 1 then
441 elseif self.inputs.winker == 2 then
445 mdb.table.target_camera_state:replace({ id = 0, front_camera = front_camera, back_camera = back_camera, right_camera = right_camera, left_camera = left_camera })
450 -- load the telephony plugin
451 m:try_load_plugin('telephony')
454 -- system controller test setup
456 if not with_system_controller then
460 window_operation_names = {
469 function window_operation_name(oper)
470 local name = window_operation_names[oper]
471 if name then return name end
472 return "<unknown " .. tostring(oper) .. ">"
476 [0x00001] = "send_appid",
477 [0x10001] = "create",
478 [0x10002] = "destroy",
482 [0x10006] = "change_active",
483 [0x10007] = "change_layer",
484 [0x10008] = "change_attr",
486 [0x10011] = "map_thumb",
487 [0x10012] = "unmap_thumb",
488 [0x10020] = "show layer",
489 [0x10021] = "hide_layer",
490 [0x10022] = "change_layer_attr",
491 [0x20001] = "add_input",
492 [0x20002] = "del_input",
493 [0x20003] = "send_input"
496 function command_name(command)
497 local name = command_names[command]
498 if name then return name end
499 return "<unknown " .. tostring(command) .. ">"
502 wmgr = window_manager({
503 geometry = function(self, w,h, v)
504 if type(v) == "function" then
510 outputs = { { name = "Center",
516 width = function(w,h) return w end,
523 width = function(w,h) return w end,
524 height = function(w,h) return h-64-128 end
530 width = function(w,h) return w end,
531 height = function(w,h) return (h-64-128)/2 end
536 pos_y = function(w,h) return (h-64-128)/2+64 end,
537 width = function(w,h) return w end,
538 height = function(w,h) return (h-64-128)/2 end
544 width = function(w,h) return w/2 end,
545 height = function(w,h) return (h-64-128)/2 end
549 pos_x = function(w,h) return w/2 end,
551 width = function(w,h) return w/2 end,
552 height = function(w,h) return (h-64-128)/2 end
557 pos_y = function(w,h) return (h-64-128/2)+64 end,
558 width = function(w,h) return w/2 end,
559 height = function(w,h) return (h-64-128)/2 end
563 pos_x = function(w,h) return w/2 end,
564 pos_y = function(w,h) return (h-64-128/2)+64 end,
565 width = function(w,h) return w/2 end,
566 height = function(w,h) return (h-64-128)/2 end
572 width = function(w,h) return w end,
573 height = function(w,h) return h-64-128 end
579 width = function(w,h) return w/2-181 end,
580 height = function(w,h) return h-64-128 end
584 pos_x = function(w,h) return w/2+181 end,
586 width = function(w,h) return w/2-181 end,
587 height = function(w,h) return h-64-128 end
596 layers = { { 0, "Background" , 1 },
597 { 1, "Application" , 2 },
598 { 2, "Softkeyboard" , 4 },
599 { 3, "HomeScreen" , 2 },
600 { 4, "ControlBar" , 2 },
601 { 5, "InterruptApp" , 2 },
602 { 6, "OnScreen" , 2 },
603 { 101, "Input" , 3 },
604 { 102, "Touch" , 4 },
605 { 103, "Cursor" , 5 },
606 { 0x1000, "Background" , 1 },
607 { 0x2000, "Normal" , 2 },
608 { 0x3000, "Fullscreen" , 2 },
609 { 0x4000, "InputPanel" , 3 },
610 { 0xA000, "Touch" , 4 },
611 { 0xB000, "Cursor" , 5 },
612 { 0xC000, "Startup" , 6 }
616 window_update = function(self, oper, win, mask)
618 print("*** WINDOW UPDATE oper:"..window_operation_name(oper).." mask: "..tostring(mask))
622 local arg = m:JSON({ surface = win.surface,
627 if oper == 1 then -- create
628 if win.layertype and win.layertype == 3 then
629 print("ignoring input panel window creation")
633 elseif oper == 2 then -- destroy
635 elseif oper == 3 then -- namechange
637 elseif oper == 4 or oper == 5 then --visible or configure
641 arg.layer = win.layer
642 arg.pos_x = win.pos_x
643 arg.pos_y = win.pos_y
644 arg.width = win.width
645 arg.height = win.height
646 arg.raise = win.raise
647 arg.visible = win.visible
648 arg.active = win.active
649 elseif oper == 6 then -- active
650 if false and win.active ~= 0 then
651 print("### already active")
656 print("### nothing to do")
660 local msg = m:JSON({ command = command,
665 print("### sending window message: " .. command_name(msg.command))
667 sc:send_message(msg.appid, msg)
669 if (oper == 1) then -- create
670 local a = animation({})
671 local r = m:JSON({surface = win.surface,
674 self:window_request(r,a,0)
678 layer_update = function(self, oper, j, mask)
680 print("*** LAYER UPDATE oper:"..oper.." mask: "..tostring(mask))
684 output_update = function(self, oper, out, mask)
685 local idx = out.index
687 print("*** OUTPUT UPDATE oper:"..oper.." mask: "..tostring(mask))
690 if (oper == 1) then -- create
691 local outdef = self.outputs[idx+1]
693 self:output_request(m:JSON({index = idx,
698 elseif (oper == 5) then -- done
699 local ads = self.outputs[idx+1].areas
701 for name,area in pairs(ads) do
702 local a = m:JSON({name=name,output=out.index})
703 for fld,val in pairs(area) do
704 a[fld] = self:geometry(out.width,out.height,val)
714 sc = m:get_system_controller()
721 -- these shoud be before wmgr:connect() is called
722 print("====== creating applications")
725 area = "Center.Full",
726 privileges = { screen = "none", audio = "none" }
730 appid = "org.tizen.ico.homescreen",
731 area = "Center.Full",
732 privileges = { screen = "system", audio = "system" }
736 appid = "org.tizen.ico.statusbar",
737 area = "Center.Status",
738 privileges = { screen = "system", audio = "none" }
743 sc.client_handler = function (self, cid, msg)
744 print('*** client handler: ' .. tostring(msg))
745 if not connected then
746 print('Trying to connect to wayland...')
747 connected = wmgr:connect()
749 print('Window manager already connected...')
753 sc.generic_handler = function (self, cid, msg)
754 print('*** generic handler: ' .. tostring(msg))
757 sc.window_handler = function (self, cid, msg)
758 print('*** window handler: ' .. command_name(msg.command) .. ' ' .. tostring(msg))
760 local a = animation({})
761 if msg.command == 0x10003 then -- ico SHOW command
762 local raise_mask = 0x01000000
763 local lower_mask = 0x02000000
765 if msg.arg and msg.arg.anim_name then
766 local time = msg.arg.time
767 time = m:AND(time, m:NEG(m:OR(raise_mask, lower_mask)))
769 if m:AND(msg.arg.anim_time, raise_mask) then
771 elseif m:AND(msg.arg.anim_time, lower_mask) then
774 a.show = { msg.arg.anim_name, time }
775 print('time: ' .. tostring(a.show[2]))
778 print(tostring(msg.arg))
779 wmgr:window_request(msg.arg, a, 0)
780 elseif msg.command == 0x10004 then -- ico HIDE command
781 local raise_mask = 0x01000000
782 local lower_mask = 0x02000000
784 if msg.arg and msg.arg.anim_name then
785 local time = msg.arg.time
786 time = m:AND(time, m:NEG(m:OR(raise_mask, lower_mask)))
788 if m:AND(msg.arg.anim_time, raise_mask) then
791 if m:AND(msg.arg.anim_time, lower_mask) then
794 a.hide = { msg.arg.anim_name, time }
795 print('hide animation time: ' .. tostring(a.hide[2]))
798 print(tostring(msg.arg))
799 wmgr:window_request(msg.arg, a, 0)
800 elseif msg.command == 0x10005 then -- ico MOVE
802 print(tostring(msg.arg))
803 wmgr:window_request(msg.arg, a, 0)
804 elseif msg.command == 0x10006 then -- ico ACTIVE
805 print('##### ACTIVE')
806 if not msg.arg.active then
809 print(tostring(msg.arg))
810 wmgr:window_request(msg.arg, a, 0)
811 elseif msg.command == 0x10007 then -- ico CHANGE_LAYER
812 print('##### CHANGE_LAYER')
813 print(tostring(msg.arg))
815 if msg.arg.layer ~= 4 or msg.arg.layer ~= 5 then
816 print("do not change layer for other than cursor or touch")
820 wmgr:window_request(msg.arg, a, 0)
821 elseif msg.command == 0x10011 then -- ico MAP_THUMB
822 local framerate = msg.arg.framerate
823 print('##### MAP_THUMB')
825 if not framerate or framerate < 0 then
828 wmgr:window_request(msg.arg, a, framerate)
829 elseif msg.command == 0x10012 then -- ico UNMAP_THUMB
830 print('##### UNMAP_THUMB')
832 wmgr:window_request(msg.arg, a, 0)
833 elseif msg.command == 0x10020 then -- ico SHOW_LAYER command
835 print('##### SHOW_LAYER')
836 wmgr:layer_request(msg.arg)
839 sc.input_handler = function (self, cid, msg)
840 print('*** input handler: ' .. tostring(msg))
842 sc.user_handler = function (self, cid, msg)
843 print('*** user handler: ' .. tostring(msg))
845 sc.resource_handler = function (self, cid, msg)
846 print('*** resource handler: ' .. tostring(msg))
848 createResourceSet = function (ctl, client, msg)
849 cb = function(rset, data)
850 print("> resource callback")
852 -- type is either basic (0) or interrupt (1)
855 requestType = msg.res.type
858 if rset.acquired then
859 cmd = 0x00040001 -- acquire
861 cmd = 0x00040002 -- release
872 if rset.resources.audio_playback then
881 if rset.resources.display then
889 if rset.resources.input then
895 print("sending message to client: " .. data.client)
897 if sc:send_message(data.client, reply) then
898 print('*** reply OK')
900 print('*** reply FAILED')
904 rset = m:ResourceSet({
905 application_class = "player",
906 zone = "driver", -- msg.zone ("full")
915 if msg.res.sound then
917 resource_name = "audio_playback"
919 rset.resources.audio_playback.attributes.pid = tostring(msg.pid)
920 rset.resources.audio_playback.attributes.appid = msg.appid
921 print("sound name: " .. msg.res.sound.name)
922 print("sound zone:" .. msg.res.sound.zone)
923 print("sound adjust: " .. tostring(msg.res.sound.adjust))
924 if msg.res.sound.id then
925 print("sound id: " .. msg.res.sound.id)
929 if msg.res.input then
931 resource_name = "input"
933 rset.resources.input.attributes.pid = tostring(msg.pid)
934 rset.resources.input.attributes.appid = msg.appid
935 print("input name: " .. msg.res.sound.name)
936 print("input event:" .. tostring(msg.res.input.event))
939 if msg.res.window then
941 resource_name = "display"
943 rset.resources.display.attributes.pid = tostring(msg.pid)
944 rset.resources.display.attributes.appid = msg.appid
945 print("display name: " .. msg.res.display.name)
946 print("display zone:" .. msg.res.display.zone)
947 if msg.res.display.id then
948 print("display id: " .. msg.res.display.id)
957 -- fields common to all messages:
962 if msg.command == 0x00040011 then -- MSG_CMD_CREATE_RES
963 print("command CREATE")
966 sets.cid = createResourceSet(self, cid, msg)
969 elseif msg.command == 0x00040012 then -- MSG_CMD_DESTORY_RES
970 print("command DESTROY")
976 sets.cid = nil -- garbage collecting
978 elseif msg.command == 0x00040001 then -- MSG_CMD_ACQUIRE_RES
979 print("command ACQUIRE")
982 sets.cid = createResourceSet(self, cid, msg)
987 elseif msg.command == 0x00040002 then -- MSG_CMD_RELEASE_RES
988 print("command RELEASE")
994 elseif msg.command == 0x00040003 then -- MSG_CMD_DEPRIVE_RES
995 print("command DEPRIVE")
997 elseif msg.command == 0x00040004 then -- MSG_CMD_WAITING_RES
998 print("command WAITING")
1000 elseif msg.command == 0x00040005 then -- MSG_CMD_REVERT_RES
1001 print("command REVERT")
1004 sc.inputdev_handler = function (self, cid, msg)
1005 print('*** inputdev handler: ' .. tostring(msg))