summaryrefslogtreecommitdiff
path: root/packaging.in/murphy.lua
diff options
context:
space:
mode:
Diffstat (limited to 'packaging.in/murphy.lua')
-rw-r--r--packaging.in/murphy.lua2385
1 files changed, 2385 insertions, 0 deletions
diff --git a/packaging.in/murphy.lua b/packaging.in/murphy.lua
new file mode 100644
index 0000000..b625d1f
--- /dev/null
+++ b/packaging.in/murphy.lua
@@ -0,0 +1,2385 @@
+with_system_controller = false
+with_amb = false
+verbose = 0
+
+m = murphy.get()
+
+-- try loading the various logging plugins
+m:try_load_plugin('systemd')
+m:try_load_plugin('dlog')
+
+-- load the console plugin
+m:try_load_plugin('console')
+
+m:try_load_plugin('console.disabled', 'webconsole', {
+ address = 'wsck:127.0.0.1:3000/murphy',
+ httpdir = '/usr/share/murphy/webconsole' });
+
+-- load the dbus plugin
+if m:plugin_exists('dbus') then
+ m:load_plugin('dbus')
+end
+
+-- load the native resource plugin
+if m:plugin_exists('resource-native') then
+ m:load_plugin('resource-native')
+ m:info("native resource plugin loaded")
+else
+ m:info("No native resource plugin found...")
+end
+
+-- load the dbus resource plugin
+m:try_load_plugin('resource-dbus', {
+ dbus_bus = "system",
+ dbus_service = "org.Murphy",
+ dbus_track = true,
+ default_zone = "driver",
+ default_class = "implicit"
+})
+
+-- load the domain control plugin
+if m:plugin_exists('domain-control') then
+ m:load_plugin('domain-control')
+else
+ m:info("No domain-control plugin found...")
+end
+
+if m:plugin_exists('glib') then
+ m:load_plugin('glib')
+else
+ m:info("No glib plugin found...")
+end
+
+if m:plugin_exists("gam-resource-manager") then
+
+function get_general_priorities(self)
+ print("*** get_general_priorities\n")
+ return { "USB Headset", "wiredHeadset", "speakers" }
+end
+
+function get_phone_priorities(self)
+ print("*** get_phone_priorities\n")
+ return { "wiredHeadset", "USB Headset" }
+end
+
+m:load_plugin('gam-resource-manager', {
+ config_dir = '/etc/murphy/gam',
+ decision_names = 'gam-wrtApplication-4',
+ max_active = 4,
+ app_mapping = {
+ ['t8j6HTRpuz.MediaPlayer'] = 'wrtApplication',
+ ['pacat'] = 'icoApplication'
+ },
+ app_default = 'icoApplication'
+})
+
+routing_sink_priority {
+ application_class = "player",
+ priority_queue = get_general_priorities
+}
+
+routing_sink_priority {
+ application_class = "game",
+ priority_queue = get_general_priorities
+}
+
+routing_sink_priority {
+ application_class = "implicit",
+ priority_queue = get_general_priorities
+}
+
+routing_sink_priority {
+ application_class = "phone",
+ priority_queue = get_phone_priorities
+}
+
+routing_sink_priority {
+ application_class = "basic",
+ priority_queue = get_phone_priorities
+}
+
+routing_sink_priority {
+ application_class = "event",
+ priority_queue = get_phone_priorities
+}
+end
+
+-- load the AMB plugin
+if m:plugin_exists('amb') then
+ m:try_load_plugin('amb')
+
+ if builtin.method.amb_initiate and
+ builtin.method.amb_update
+ then
+ with_amb = true
+ end
+else
+ m:info("No amb plugin found...")
+end
+
+-- load the ASM resource plugin
+if m:plugin_exists('resource-asm') then
+ m:try_load_plugin('resource-asm', {
+ zone = "driver",
+ share_mmplayer = "player:AVP,mandatory,exclusive,strict",
+ ignored_argv0 = "WebProcess"
+ })
+else
+ m:info("No audio session manager plugin found...")
+end
+
+if m:plugin_exists('system-controller') then
+ with_system_controller = true
+elseif m:plugin_exists('ivi-resource-manager') then
+ m:load_plugin('ivi-resource-manager')
+ with_system_controller = false
+end
+
+-- define application classes
+application_class {
+ name = "interrupt",
+ priority = 99,
+ modal = true ,
+ share = false,
+ order = "fifo"
+}
+
+application_class {
+ name = "emergency",
+ priority = 80,
+ modal = false,
+ share = false,
+ order = "fifo"
+}
+application_class {
+ name = "system",
+ priority = 52,
+ modal = false,
+ share = true,
+ order = "lifo"
+}
+application_class {
+ name = "alert",
+ priority = 51,
+ modal = false,
+ share = false,
+ order = "fifo"
+}
+
+application_class {
+ name = "navigator",
+ priority = 50,
+ modal = false,
+ share = true,
+ order = "fifo"
+}
+
+application_class {
+ name = "phone",
+ priority = 6 ,
+ modal = false,
+ share = false,
+ order = "lifo"
+}
+application_class {
+ name = "camera",
+ priority = 5,
+ modal = false,
+ share = false,
+ order = "lifo"
+}
+
+application_class { name="event" , priority=4 , modal=false, share=true , order="fifo" }
+application_class { name="game" , priority=3 , modal=false, share=false, order="lifo" }
+--# doesn't need to be created here, ivi-resource-manager creates it if loaded
+--#application_class { name="basic" , priority=2 , modal=false, share=false, order="lifo" }
+application_class { name="player" , priority=1 , modal=false, share=true , order="lifo" }
+application_class { name="implicit" , priority=0 , modal=false, share=false, order="lifo" }
+
+-- define zone attributes
+zone.attributes {
+ type = {mdb.string, "common", "rw"},
+ location = {mdb.string, "anywhere", "rw"}
+}
+
+-- define zones
+zone {
+ name = "driver",
+ attributes = {
+ type = "common",
+ location = "front-left"
+ }
+}
+
+zone {
+ name = "passanger1",
+ attributes = {
+ type = "private",
+ location = "front-right"
+ }
+}
+
+zone {
+ name = "passanger2",
+ attributes = {
+ type = "private",
+ location = "back-left"
+ }
+}
+
+zone {
+ name = "passanger3",
+ attributes = {
+ type = "private",
+ location = "back-right"
+ }
+}
+
+zone {
+ name = "passanger4",
+ attributes = {
+ type = "private",
+ location = "back-left"
+ }
+}
+
+
+-- define resource classes
+if not m:plugin_exists('ivi-resource-manager') and
+ not with_system_controller and
+ not m:plugin_exists('gam-resource-manager')
+then
+ resource.class {
+ name = "audio_playback",
+ shareable = true,
+ attributes = {
+ role = { mdb.string, "music", "rw" },
+ pid = { mdb.string, "<unknown>", "rw" },
+ policy = { mdb.string, "relaxed", "rw" },
+ source = { mdb.string, "webkit", "rw" },
+ conn_id = { mdb.unsigned, 0, "rw" },
+ name = { mdb.string, "<unknown>", "rw" },
+ }
+ }
+end
+
+if not m:plugin_exists('gam-resource-manager') then
+ resource.class {
+ name = "audio_recording",
+ shareable = true,
+ attributes = {
+ role = { mdb.string, "music" , "rw" },
+ pid = { mdb.string, "<unknown>", "rw" },
+ policy = { mdb.string, "relaxed" , "rw" },
+ name = { mdb.string, "<unknown>", "rw" },
+ }
+ }
+end
+
+resource.class {
+ name = "video_playback",
+ shareable = false,
+}
+
+resource.class {
+ name = "video_recording",
+ shareable = false
+}
+
+resource.class {
+ name = "speech_recognition",
+ shareable = true
+}
+
+resource.class {
+ name = "speech_synthesis",
+ shareable = true
+}
+
+-- PulseAudio volume context
+mdb.table {
+ name = "volume_context",
+ index = { "id" },
+ create = true,
+ columns = {
+ { "id", mdb.unsigned },
+ { "value", mdb.string, 64 },
+ }
+}
+
+-- put default volume context to the table
+mdb.table.volume_context:insert({ id = 1, value = "default" })
+
+if not m:plugin_exists('ivi-resource-manager') and
+ not with_system_controller
+then
+ resource.method.veto = {
+ function(zone, rset, grant, owners, req_set)
+ return true
+ end
+ }
+end
+
+-- test for creating selections
+mdb.select {
+ name = "audio_owner",
+ table = "audio_playback_owner",
+ columns = {"application_class"},
+ condition = "zone_name = 'driver'"
+}
+
+mdb.select {
+ name = "vehicle_speed",
+ table = "amb_vehicle_speed",
+ columns = {"value"},
+ condition = "key = 'VehicleSpeed'"
+}
+
+element.lua {
+ name = "speed2volume",
+ inputs = { speed = mdb.select.vehicle_speed, param = 9 },
+ outputs = { mdb.table { name = "speedvol",
+ index = {"zone", "device"},
+ columns = {{"zone", mdb.string, 16},
+ {"device", mdb.string, 16},
+ {"value", mdb.floating}},
+ create = true
+ }
+ },
+ oldvolume = 0.0,
+ update = function(self)
+ speed = self.inputs.speed.single_value
+ if (speed) then
+ volume = (speed - 144.0) / 7.0
+ else
+ volume = 0.0
+ end
+ diff = volume - self.oldvolume
+ if (diff*diff > self.inputs.param) then
+ print("*** element "..self.name.." update "..volume)
+ self.oldvolume = volume
+ mdb.table.speedvol:replace({zone = "driver", device = "speakers", value = volume})
+ end
+ end
+}
+
+mdb.select {
+ name = "amb_state",
+ table = "amb_state",
+ columns = { "state" },
+ condition = "id = 0"
+}
+
+-- Night mode processing chain
+
+mdb.select {
+ name = "exterior_brightness",
+ table = "amb_exterior_brightness",
+ columns = { "value" },
+ condition = "key = 'ExteriorBrightness'"
+}
+
+element.lua {
+ name = "nightmode",
+ inputs = { brightness = mdb.select.exterior_brightness },
+ oldmode = -1;
+ outputs = {
+ mdb.table {
+ name = "amb_nightmode",
+ index = { "id" },
+ create = true,
+ columns = {
+ { "id", mdb.unsigned },
+ { "night_mode", mdb.unsigned }
+ }
+ }
+ },
+ update = function(self)
+ -- This is a trivial function to calculate night mode. Later, we will
+ -- need a better threshold value and hysteresis to prevent oscillation.
+
+ brightness = self.inputs.brightness.single_value
+
+ if not brightness then
+ return
+ end
+
+ print("*** element "..self.name.." update brightness: "..brightness)
+
+ if brightness > 300 then
+ mode = 0
+ else
+ mode = 1
+ end
+
+ print("*** resulting mode: ".. mode)
+
+ if not (mode == self.oldmode) then
+ mdb.table.amb_nightmode:replace({ id = 0, night_mode = mode })
+ end
+
+ self.oldmode = mode
+ end
+}
+
+mdb.select {
+ name = "select_night_mode",
+ table = "amb_nightmode",
+ columns = { "night_mode" },
+ condition = "id = 0"
+}
+
+if with_amb then
+ sink.lua {
+ name = "night_mode",
+ inputs = { NightMode = mdb.select.select_night_mode,
+ amb_state = mdb.select.amb_state },
+ property = "NightMode",
+ type = "b",
+ initiate = builtin.method.amb_initiate,
+ update = builtin.method.amb_update
+ }
+end
+
+-- Night mode general handlers
+
+if with_system_controller then
+ sink.lua {
+ name = "nightmode_homescreen",
+ inputs = { owner = mdb.select.select_night_mode },
+ initiate = function(self)
+ -- data = mdb.select.select_night_mode.single_value
+ return true
+ end,
+ update = function(self)
+ send_night_mode_to(homescreen)
+ end
+ }
+end
+
+-- Driving mode processing chain
+
+element.lua {
+ name = "drivingmode",
+ inputs = { speed = mdb.select.vehicle_speed },
+ oldmode = -1;
+ outputs = {
+ mdb.table {
+ name = "amb_drivingmode",
+ index = { "id" },
+ create = true,
+ columns = {
+ { "id", mdb.unsigned },
+ { "driving_mode", mdb.unsigned }
+ }
+ }
+ },
+ update = function(self)
+
+ speed = self.inputs.speed.single_value
+
+ if not speed then
+ return
+ end
+
+ if speed == 0 then
+ mode = 0
+ else
+ mode = 1
+ end
+
+ if not (mode == self.oldmode) then
+ mdb.table.amb_drivingmode:replace({ id = 0, driving_mode = mode })
+ end
+
+ self.oldmode = mode
+ end
+}
+
+mdb.select {
+ name = "select_driving_mode",
+ table = "amb_drivingmode",
+ columns = { "driving_mode" },
+ condition = "id = 0"
+}
+
+if with_amb then
+ sink.lua {
+ name = "driving_mode",
+ inputs = { DrivingMode = mdb.select.select_driving_mode,
+ amb_state = mdb.select.amb_state },
+ property = "DrivingMode",
+ type = "u",
+ initiate = builtin.method.amb_initiate,
+ update = builtin.method.amb_update
+ }
+end
+
+-- turn signals (left, right)
+
+mdb.select {
+ name = "winker",
+ table = "amb_turn_signal",
+ columns = { "value" },
+ condition = "key = 'TurnSignal'"
+}
+
+-- define three categories
+
+mdb.select {
+ name = "undefined_applications",
+ table = "aul_applications",
+ columns = { "appid" },
+ condition = "category = '<undefined>'"
+}
+
+mdb.select {
+ name = "basic_applications",
+ table = "aul_applications",
+ columns = { "appid" },
+ condition = "category = 'basic'"
+}
+
+mdb.select {
+ name = "entertainment_applications",
+ table = "aul_applications",
+ columns = { "appid" },
+ condition = "category = 'entertainment'"
+}
+
+function ft(t)
+ -- filter the object garbage out of the tables
+ ret = {}
+
+ for k,v in pairs(t) do
+ if k ~= "userdata" and k ~= "new" then
+ ret[k] = v
+ end
+ end
+
+ return ret
+end
+
+function getApplication(appid)
+ local conf = nil
+
+ -- find the correct local application definition
+
+ for k,v in pairs(ft(application)) do
+ if appid == v.appid then
+ conf = v
+ break
+ end
+ end
+
+ return conf
+end
+
+function regulateApplications(t, regulation)
+ for k,v in pairs(ft(t)) do
+
+ whitelisted = false
+
+ -- our local application config, which takes precedence
+ local conf = getApplication(v.appid)
+
+ if conf then
+ if conf.resource_class ~= "player" then
+ whitelisted = true
+ end
+
+ if conf.requisites and conf.requisites.screen then
+ if conf.requisites.screen.driving then
+ whitelisted = true
+ end
+ end
+ end
+
+ if whitelisted then
+ -- override, don't disable
+ resmgr:disable_screen_by_appid("*", "*", v.appid, false, false)
+ else
+ resmgr:disable_screen_by_appid("*", "*", v.appid, regulation == 1, false)
+ end
+ end
+ resource.method.recalc("driver")
+end
+
+-- regulation (on), use "select_driving_mode"
+
+sink.lua {
+ name = "driving_regulation",
+ inputs = { owner = mdb.select.select_driving_mode },
+ initiate = function(self)
+ -- local data = mdb.select.select_driving_mode.single_value
+ return true
+ end,
+ update = function(self)
+ local data = mdb.select.select_driving_mode.single_value
+
+ if verbose > 1 then
+ print("Driving mode updated: " .. tostring(data))
+ end
+
+ if not sc then
+ return true
+ end
+
+ -- tell homescreen that driving mode was updated
+ send_driving_mode_to(homescreen)
+
+ regulateApplications(ft(mdb.select.entertainment_applications), data)
+ regulateApplications(ft(mdb.select.undefined_applications), data)
+
+ return true
+ end
+}
+--[[
+sink.lua {
+ name = "regulated_app_change",
+ inputs = { undef = mdb.select.undefined_applications,
+ entertainment = mdb.select.entertainment_applications },
+ initiate = function(self)
+ return true
+ end,
+ update = function(self)
+ local data = mdb.select.select_driving_mode.single_value
+
+ if not sc then
+ return
+ end
+
+ if verbose > 1 then
+ print("regulated application list was changed")
+ end
+
+ regulateApplications(ft(mdb.select.entertainment_applications), data)
+ regulateApplications(ft(mdb.select.undefined_applications), data)
+
+ return true
+ end
+}
+--]]
+
+-- shift position (parking, reverse, other)
+
+mdb.select {
+ name = "gear_position",
+ table = "amb_gear_position",
+ columns = { "value" },
+ condition = "key = 'GearPosition'"
+}
+
+-- cameras (back, front, left, right)
+
+element.lua {
+ name = "camera_state",
+ inputs = { winker = mdb.select.winker, gear = mdb.select.gear_position },
+ oldmode = -1;
+ outputs = {
+ mdb.table {
+ name = "target_camera_state",
+ index = { "id" },
+ create = true,
+ columns = {
+ { "id", mdb.unsigned },
+ { "front_camera", mdb.unsigned },
+ { "back_camera", mdb.unsigned },
+ { "right_camera", mdb.unsigned },
+ { "left_camera", mdb.unsigned }
+ }
+ }
+ },
+ update = function(self)
+
+ front_camera = 0
+ back_camera = 0
+ right_camera = 0
+ left_camera = 0
+
+ if self.inputs.gear == 128 then
+ back_camera = 1
+ elseif self.inputs.winker == 1 then
+ right_camera = 1
+ elseif self.inputs.winker == 2 then
+ left_camera = 1
+ end
+
+ mdb.table.target_camera_state:replace({ id = 0, front_camera = front_camera, back_camera = back_camera, right_camera = right_camera, left_camera = left_camera })
+
+ end
+}
+
+-- system controller test setup
+
+if not with_system_controller then
+ -- ok, we should have 'audio_playback' defined by now
+ m:try_load_plugin('telephony')
+ return
+end
+
+m:load_plugin('system-controller')
+
+onscreen_counter = 0
+
+window_manager_operation_names = {
+ [1] = "create",
+ [2] = "destroy"
+}
+
+function window_manager_operation_name(oper)
+ local name = window_manager_operation_names[oper]
+ if name then return name end
+ return "<unknown " .. tostring(oper) .. ">"
+end
+
+window_operation_names = {
+ [1] = "create",
+ [2] = "destroy",
+ [3] = "name_change",
+ [4] = "visible",
+ [5] = "configure",
+ [6] = "active",
+ [7] = "map",
+ [8] = "hint"
+}
+
+function window_operation_name(oper)
+ local name = window_operation_names[oper]
+ if name then return name end
+ return "<unknown " .. tostring(oper) .. ">"
+end
+
+layer_operation_names = {
+ [1] = "create",
+ [2] = "destroy",
+ [3] = "visible"
+}
+
+function layer_operation_name(oper)
+ local name = layer_operation_names[oper]
+ if name then return name end
+ return "<unknown " .. tostring(oper) .. ">"
+end
+
+input_manager_operation_names = {
+ [1] = "create",
+ [2] = "destroy",
+ [3] = "ready"
+}
+
+function input_manager_operation_name(oper)
+ local name = input_manager_operation_names[oper]
+ if name then return name end
+ return "<unknown " .. tostring(oper) .. ">"
+end
+
+input_operation_names = {
+ [1] = "create",
+ [2] = "destroy",
+ [3] = "update"
+}
+
+function input_operation_name(oper)
+ local name = input_operation_names[oper]
+ if name then return name end
+ return "<unknown " .. tostring(oper) .. ">"
+end
+
+code_operation_names = {
+ [1] = "create",
+ [2] = "destroy",
+ [3] = "state_change"
+}
+
+function code_operation_name(oper)
+ local name = code_operation_names[oper]
+ if name then return name end
+ return "<unknown " .. tostring(oper) .. ">"
+end
+
+command_names = {
+ [0x00001] = "send_appid",
+ [0x10001] = "create",
+ [0x10002] = "destroy",
+ [0x10003] = "show",
+ [0x10004] = "hide",
+ [0x10005] = "move",
+ [0x10006] = "animation",
+ [0x10007] = "change_active",
+ [0x10008] = "change_layer",
+ [0x10009] = "change_attr",
+ [0x10010] = "name",
+ [0x10020] = "map_thumb",
+ [0x10021] = "unmap_thumb",
+ [0x10022] = "map_get",
+ [0x10030] = "show layer",
+ [0x10031] = "hide_layer",
+ [0x10032] = "change_layer_attr",
+ [0x20001] = "add_input",
+ [0x20002] = "del_input",
+ [0x30001] = "change_user",
+ [0x30002] = "get_userlist",
+ [0x30003] = "get_lastinfo",
+ [0x30004] = "set_lastinfo",
+ [0x40001] = "acquire_res",
+ [0x40002] = "release_res",
+ [0x40003] = "deprive_res",
+ [0x40004] = "waiting_res",
+ [0x40005] = "revert_res",
+ [0x40006] = "window_id_res",
+ [0x40011] = "create_res",
+ [0x40012] = "destroy_res",
+ [0x50001] = "set_region",
+ [0x50002] = "unset_region",
+ [0x60001] = "change_state"
+}
+
+function command_name(command)
+ local name = command_names[command]
+ if name then return name end
+ return "<unknown " .. tostring(command) .. ">"
+end
+
+input_layer = {
+ [101] = true, -- input
+ [102] = true, -- touch
+ [103] = true -- cursor
+}
+
+-- some day this should be merged with wmgr.layers
+ico_layer_type = {
+ [1] = 0x1000, -- background
+ [2] = 0x2000, -- application
+ [3] = 0x2000, -- homescreen
+ [4] = 0x2000, -- interrupt application
+ [5] = 0x2000, -- onscreen application
+ [6] = 0xc000, -- startup
+ [7] = 0x3000, -- fullscreen
+ [101] = 0x4000, -- input
+ [102] = 0xa000, -- touch
+ [103] = 0xb000 -- cursor
+}
+
+resmgr = resource_manager {
+ screen_event_handler = function(self, ev)
+ local event = ev.event
+ local surface = ev.surface
+
+ if event == "init" then
+ if verbose > 0 then
+ print("*** init screen resource allocation -- disable all 'player'")
+ end
+ resmgr:disable_audio_by_appid("*", "player", "*", true, false)
+ elseif event == "preallocate" then
+ if verbose > 0 then
+ print("*** preallocate screen resource "..
+ "for '" .. ev.appid .. "' -- enable 'player', if any")
+ end
+ resmgr:disable_audio_by_appid("*", "player", ev.appid, false, false)
+ elseif event == "grant" then
+ if verbose > 0 then
+ print("*** make visible surface "..surface)
+ end
+ local a = animation({})
+ local r = m:JSON({surface = surface,
+ visible = 1,
+ raise = 1})
+ if ev.appid == onscreen then
+ onscreen_counter = onscreen_counter + 1
+ wmgr:layer_request(m:JSON({layer = 5, visible = 1}))
+ end
+
+ wmgr:window_request(r,a,0)
+ elseif event == "revoke" then
+ if verbose > 0 then
+ print("*** hide surface "..surface)
+ end
+ local a = animation({})
+ local r = m:JSON({surface = ev.surface,
+ visible = 0})
+ if ev.appid == onscreen then
+ onscreen_counter = onscreen_counter - 1
+ if onscreen_counter <= 0 then
+ onscreen_counter = 0
+ wmgr:layer_request(m:JSON({layer = 5, visible = 0}))
+ end
+ end
+ wmgr:window_request(r,a,0)
+
+ elseif event == "create" then
+
+ if verbose > 0 then
+ print("*** screen resource event: " ..
+ tostring(ev))
+ end
+
+ local regulation = mdb.select.select_driving_mode.single_value
+
+ if regulation == 1 then
+
+ local blacklisted = false
+
+ -- applications which have their category set to "entertainment"
+ -- or "undefined" are blacklisted, meaning they should be regulated
+
+ for i,v in pairs(ft(mdb.select.undefined_applications)) do
+ if v.appid == ev.appid then
+ if verbose > 0 then
+ print(ev.appid .. " was blacklisted (undefined)")
+ end
+ blacklisted = true
+ break
+ end
+ end
+
+ if not blacklisted then
+ for i,v in pairs(ft(mdb.select.entertainment_applications)) do
+ if v.appid == ev.appid then
+ if verbose > 0 then
+ print(ev.appid .. " was blacklisted (entertainment)")
+ end
+ blacklisted = true
+ break
+ end
+ end
+ end
+
+ -- our local application config, which takes precedence
+ local conf = getApplication(ev.appid)
+
+ if not conf then
+ blacklisted = true
+ else
+ if conf.resource_class == "player" then
+ blacklisted = true
+ end
+
+ -- check the exceptions
+ if conf.requisites and conf.requisites.screen then
+ if conf.requisites.screen.driving then
+ blacklisted = false
+ end
+ end
+ end
+
+ -- disable only non-whitelisted applications
+ if blacklisted then
+ if verbose > 0 then
+ print("disabling screen for " .. ev.appid)
+ end
+ resmgr:disable_screen_by_appid("*", "*", ev.appid, true, true)
+ end
+ end
+
+ elseif event == "destroy" then
+ if verbose > 0 then
+ print("*** screen resource event: " ..
+ tostring(ev))
+ end
+ else
+ if verbose > 0 then
+ print("*** screen resource event: " ..
+ tostring(ev))
+ end
+ end
+ end,
+ audio_event_handler = function(self, ev)
+ local event = ev.event
+ local appid = ev.appid
+ local audioid = ev.audioid
+
+ if event == "grant" then
+ if verbose > 0 then
+ print("*** grant audio to "..appid..
+ " ("..audioid..") in '" ..
+ ev.zone .. "' zone")
+ end
+ elseif event == "revoke" then
+ if verbose > 0 then
+ print("*** revoke audio from "..appid..
+ " ("..audioid..") in '" ..
+ ev.zone .. "' zone")
+ end
+ else
+ if verbose > 0 then
+ print("*** audio resource event: " ..
+ tostring(ev))
+ end
+ end
+ end
+}
+
+resclnt = resource_client {}
+
+wmgr = window_manager {
+ geometry = function(self, w,h, v)
+ if type(v) == "function" then
+ return v(w,h)
+ end
+ return v
+ end,
+
+ application = function(self, appid)
+ if appid then
+ local app = application_lookup(appid)
+ if not app then
+ app = application_lookup("default")
+ end
+ return app
+ end
+ return { privileges = {screen="none", audio="none"} }
+ end,
+
+ output_order = { 1, 0 },
+
+ outputs = { { name = "Mid",
+ id = 1,
+ zone = "driver",
+ areas = { Full = {
+ id = 20,
+ pos_x = 0,
+ pos_y = 0,
+ width = function(w,h) return w end,
+ height = function(w,h) return h end
+ },
+ Left = {
+ id = 21,
+ pos_x = 0,
+ pos_y = 0,
+ width = 320,
+ height = function(w,h) return h end
+ },
+ Right = {
+ id = 22,
+ pos_x = function(w,h) return w-320 end,
+ pos_y = 0,
+ width = 320,
+ height = function(w,h) return h end
+ }
+ }
+ },
+ { name = "Center",
+ id = 4,
+ zone = "driver",
+ areas = { Status = {
+ id = 0,
+ pos_x = 0,
+ pos_y = 0,
+ width = function(w,h) return w end,
+ height = 64
+ },
+ Full = {
+ id = 1,
+ pos_x = 0,
+ pos_y = 64,
+ width = function(w,h) return w end,
+ height = function(w,h) return h-64-128 end
+ },
+ Upper = {
+ id = 2,
+ pos_x = 0,
+ pos_y = 64,
+ width = function(w,h) return w end,
+ height = function(w,h) return (h-64-128)/2 end
+ },
+ Lower = {
+ id = 3,
+ pos_x = 0,
+ pos_y = function(w,h) return (h-64-128)/2+64 end,
+ width = function(w,h) return w end,
+ height = function(w,h) return (h-64-128)/2 end
+ },
+ UpperLeft = {
+ id = 4,
+ pos_x = 0,
+ pos_y = 64,
+ width = function(w,h) return w/2 end,
+ height = function(w,h) return (h-64-128)/2 end
+ },
+ UpperRight = {
+ id = 5,
+ pos_x = function(w,h) return w/2 end,
+ pos_y = 64,
+ width = function(w,h) return w/2 end,
+ height = function(w,h) return (h-64-128)/2 end
+ },
+ LowerLeft = {
+ id = 6,
+ pos_x = 0,
+ pos_y = function(w,h) return (h-64-128/2)+64 end,
+ width = function(w,h) return w/2 end,
+ height = function(w,h) return (h-64-128)/2 end
+ },
+ LowerRight = {
+ id = 7,
+ pos_x = function(w,h) return w/2 end,
+ pos_y = function(w,h) return (h-64-128/2)+64 end,
+ width = function(w,h) return w/2 end,
+ height = function(w,h) return (h-64-128)/2 end
+ },
+ SysApp = {
+ id = 8,
+ pos_x = 0,
+ pos_y = 64,
+ width = function(w,h) return w end,
+ height = function(w,h) return h-64-128 end
+ },
+ ["SysApp.Left"] = {
+ id = 9,
+ pos_x = 0,
+ pos_y = 64,
+ width = function(w,h) return w/2-181 end,
+ height = function(w,h) return h-64-128 end
+ },
+ ["SysApp.Right"] = {
+ id = 10,
+ pos_x = function(w,h) return w/2+181 end,
+ pos_y = 64,
+ width = function(w,h) return w/2-181 end,
+ height = function(w,h) return h-64-128 end
+ },
+ MobileFull = {
+ id = 11,
+ pos_x = 0,
+ pos_y = 64,
+ width = function(w,h) return w end,
+ height = function(w,h) return h-64-128 end
+ },
+ MobileUpper = {
+ id = 12,
+ pos_x = 0,
+ pos_y = 64,
+ width = function(w,h) return w end,
+ height = function(w,h) return (h-64-128)/2 end
+ },
+ MobileLower = {
+ id = 13,
+ pos_x = 0,
+ pos_y = function(w,h) return (h-64-128)/2+64 end,
+ width = function(w,h) return w end,
+ height = function(w,h) return (h-64-128)/2 end
+ },
+ Control = {
+ id = 14,
+ pos_x = 0,
+ pos_y = function(w,h) return h-128 end,
+ width = function(w,h) return w end,
+ height = 128
+ },
+ }
+ }
+ },
+ -- id name type output
+ layers = { { 0, "BackGround" , 1, "Center" },
+ { 1, "Application" , 2, "Center" },
+ { 2, "HomeScreen" , 3, "Center" },
+ { 3, "ControlBar" , 3, "Center" },
+ { 4, "InterruptApp" , 4, "Center" },
+ { 5, "OnScreen" , 5, "Center" },
+ { 6, "Touch" , 102, "Center" },
+ { 7, "Cursor" , 103, "Center" }
+ },
+
+
+ manager_update = function(self, oper)
+ if verbose > 0 then
+ print("### <== WINDOW MANAGER UPDATE:" ..
+ window_manager_operation_name(oper))
+ end
+ if oper == 1 then
+ local wumask = window_mask { --raise = true,
+ visible = true,
+ active = true }
+ local wrmask = window_mask { raise = true,
+ active = true,
+ layer = true }
+ local lumask = layer_mask { visible = true }
+ local lrmask = layer_mask { visible = true }
+ local req = m:JSON({
+ passthrough_window_update = wumask:tointeger(),
+ passthrough_window_request = wrmask:tointeger(),
+ passthrough_layer_update = lumask:tointeger(),
+ passthrough_layer_request = lrmask:tointeger()
+ })
+ self:manager_request(req)
+ end
+ end,
+
+ window_update = function(self, oper, win, mask)
+ if verbose > 0 then
+ print("### <== WINDOW UPDATE oper:" ..
+ window_operation_name(oper) ..
+ " mask: " .. tostring(mask))
+ if verbose > 1 then
+ print(win)
+ end
+ end
+
+ local arg = m:JSON({ surface = win.surface,
+ winname = win.name
+ })
+ local command = 0
+
+ if oper == 1 then -- create
+ local layertype = win.layertype
+ if layertype and input_layer[layertype] then
+ if verbose > 0 then
+ print("ignoring input panel creation")
+ end
+ return
+ end
+ command = 0x10001
+ elseif oper == 2 then -- destroy
+ command = 0x10002
+ elseif oper == 3 then -- namechange
+ command = 0x10010
+ elseif oper == 4 or oper == 5 then -- visible/configure
+ command = 0x10009
+ arg.zone = win.area
+ arg.node = win.node
+ if win.layertype then
+ arg.layertype = win.layertype
+ end
+ arg.layer = win.layer
+ arg.pos_x = win.pos_x
+ arg.pos_y = win.pos_y
+ arg.width = win.width
+ arg.height = win.height
+ arg.raise = win.raise
+ arg.visible = win.visible
+ if win.active == 0 then
+ arg.active = 0
+ else
+ arg.active = 1
+ end
+ elseif oper == 6 then -- active
+ if win.active == 0 then
+ if verbose > 0 then
+ print("ignoring inactive event")
+ end
+ return
+ end
+ command = 0x10007
+ elseif oper == 7 then -- map
+ local map = win.map
+ if not map then
+ return
+ end
+ if win.mapped == 0 then
+ command = 0x10021
+ else
+ command = 0x10020
+ end
+ arg.attr = map.type
+ --arg.name = map.target
+ arg.width = map.width
+ arg.height = map.height
+ arg.stride = map.stride
+ arg.format = map.format
+ else
+ if verbose > 0 then
+ print("### nothing to do")
+ end
+ return
+ end
+
+ local msg = m:JSON({ command = command,
+ appid = win.appid,
+ pid = win.pid,
+ arg = arg
+ })
+ if verbose > 0 then
+ print("### <== sending " ..
+ command_name(msg.command) ..
+ " window message to '" .. homescreen .. "'")
+ if verbose > 1 then
+ print(msg)
+ end
+ end
+ sc:send_message(homescreen, msg)
+
+ if oper == 1 then -- create
+ local i = input_layer[win.layertype]
+ local p = self:application(win.appid)
+ local s = p.privileges.screen
+
+ if s == "system" then
+ local a = animation({})
+ local r = m:JSON({surface = win.surface,
+ visible = 0,
+ raise = 1})
+ self:window_request(r,a,0)
+ else
+ if i then
+ if verbose > 0 then
+ print("do not make resource for " ..
+ "input window")
+ end
+ else
+ resclnt:resource_set_create("screen",
+ "driver",
+ win.appid,
+ win.surface)
+ special_screen_sets[win.surface] = true
+ end
+ end
+
+ if onscreen and win.appid == onscreen then
+ local resmsg = m:JSON({
+ command = 0x40006, -- window_id_res
+ appid = win.appid,
+ pid = win.pid,
+ res = m:JSON({
+ window = m:JSON({
+ ECU = "",
+ display = "",
+ layer = "",
+ layout = "",
+ area = "",
+ dispatchApp = "",
+ role = win.name,
+ resourceId = win.surface
+ })
+ })
+ })
+ if verbose > 0 then
+ print("### <== sending " ..
+ command_name(resmsg.command) ..
+ " message to '" .. onscreen .. "'")
+ if verbose > 1 then
+ print(resmsg)
+ end
+ end
+ sc:send_message(onscreen, resmsg);
+ end
+ elseif oper == 2 then -- destroy
+ resclnt:resource_set_destroy("screen", win.surface)
+ special_screen_sets[win.surface] = nil
+ elseif oper == 6 then -- active
+ if win.active then
+ local i = input_layer[win.layertype]
+ local p = self:application(win.appid)
+ local s = p.privileges.screen
+ local surface = win.surface
+ if not i and s ~= "system" then
+ resclnt:resource_set_acquire("screen",surface)
+ resmgr:window_raise(win.appid, surface, 1)
+ end
+ end
+ end
+ end,
+
+ layer_update = function(self, oper, layer, mask)
+ if verbose > 0 then
+ print("### LAYER UPDATE:" ..
+ layer_operation_name(oper) ..
+ " mask: " .. tostring(mask))
+ if verbose > 1 then
+ print(layer)
+ end
+ end
+ if oper == 3 then -- visible
+ local command = 0x10008 -- change_layer
+ local msg = m:JSON({
+ command = command,
+ appid = "",
+ arg = m:JSON({layer = layer.id,
+ visible = layer.visible
+ })
+ })
+ if verbose > 0 then
+ print("### <== sending "..command_name(command)..
+ " layer message")
+ if verbose > 1 then
+ print(msg)
+ end
+ end
+ sc:send_message(homescreen, msg)
+ else
+ if verbose > 0 then
+ print("### nothing to do")
+ end
+ end
+ end,
+
+ output_update = function(self, oper, out, mask)
+ local idx = out.index
+ local defidx = self.output_order[idx+1]
+ if verbose > 0 then
+ print("### OUTPUT UPDATE:" .. oper ..
+ " mask: "..tostring(mask))
+ end
+ if not defidx then
+ return
+ end
+ print(out)
+ local outdef = self.outputs[defidx+1]
+ if (oper == 1) then -- create
+ if outdef then
+ self:output_request(m:JSON({index = idx,
+ id = outdef.id,
+ name = outdef.name
+ }))
+ end
+ elseif (oper == 5) then -- done
+ local ads = outdef.areas
+ local on = outdef.name
+ if ads then
+ for name,ad in pairs(ads) do
+ local can = wmgr:canonical_name(on.."."..name)
+ local a = m:JSON({name = name,
+ output = out.index})
+ for fld,val in pairs(ad) do
+ a[fld] = self:geometry(out.width,
+ out.height,
+ val)
+ end
+ self:area_create(a)
+ resmgr:area_create(area[can], outdef.zone)
+ end
+ end
+ end
+ end
+}
+
+
+imgr = input_manager {
+ inputs = {{ name = "G27 Racing Wheel",
+ id = 0,
+ switch = { [2] = {appid="org.tizen.ico.app-soundsample" },
+ [3] = {appid="org.tizen.ico.homescreen", keycode=1},
+ [4] = {appid="org.tizen.ico.app-soundsample" },
+ [5] = {appid="org.tizen.ico.homescreen", keycode=2}
+ }}
+ },
+
+ manager_update = function(self, oper)
+ if verbose > 0 then
+ print("### <== INPUT MANAGER UPDATE:" ..
+ input_manager_operation_name(oper))
+ end
+ end,
+
+ input_update = function(self, oper, inp, mask)
+ if verbose > 0 then
+ print("### INPUT UPDATE:" ..
+ input_operation_name(oper) ..
+ " mask: " .. tostring(mask))
+ if verbose > 1 then
+ print(inp)
+ end
+ end
+ end,
+ code_update = function(self, oper, code, mask)
+ if verbose > 0 then
+ print("### CODE UPDATE: mask: " .. tostring(mask))
+ if verbose > 1 then
+ print(code)
+ end
+ end
+ local msg = m:JSON({ command = 1,
+ appid = "org.tizen.ico.homescreen",
+ arg = m:JSON({ device = code.device,
+ time = code.time,
+ input = code.input,
+ code = code.id,
+ state = code.state
+ })
+ })
+ if verbose > 0 then
+ print("### <== sending " ..
+ command_name(msg.command) ..
+ " input message")
+ if verbose > 1 then
+ print(msg)
+ end
+ end
+ sc:send_message(homescreen, msg)
+ end
+}
+
+sc = m:get_system_controller()
+
+-- resource sets
+sets = {}
+
+-- special screen resource sets
+-- TODO: just rewrite screen resource handling to use regular resource API
+
+special_screen_sets = {}
+
+-- user manager
+um = m:UserManager()
+
+connected = false
+homescreen = ""
+onscreen = ""
+
+cids = {}
+
+-- these shoud be before wmgr:connect() is called
+if verbose > 0 then
+ print("====== creating applications ======")
+end
+application {
+ appid = "default",
+ area = "Center.Full",
+ privileges = { screen = "none", audio = "none" },
+ resource_class = "player",
+ screen_priority = 0
+}
+
+application {
+ appid = "weston",
+ area = "Center.Full",
+ privileges = { screen = "system", audio = "none" },
+ resource_class = "implicit",
+ screen_priority = 30
+}
+
+application {
+ appid = "org.tizen.ico.homescreen",
+ area = "Center.Full",
+ windows = { {'ico_hs_controlbarwindow', 'Center.Control'} },
+ privileges = { screen = "system", audio = "system" },
+ resource_class = "player",
+ screen_priority = 20
+}
+
+application {
+ appid = "org.tizen.ico.statusbar",
+ area = "Center.Status",
+ privileges = { screen = "system", audio = "none" },
+ resource_class = "player",
+ screen_priority = 20
+}
+
+application {
+ appid = "org.tizen.ico.onscreen",
+ area = "Center.Full",
+ privileges = { screen = "system", audio = "system" },
+ resource_class = "player",
+ screen_priority = 20
+}
+
+application {
+ appid = "org.tizen.ico.login",
+ area = "Center.Full",
+ privileges = { screen = "system", audio = "system" },
+ resource_class = "player",
+ screen_priority = 20
+}
+
+application {
+ appid = "org.tizen.ico.camera_left",
+ area = "Center.SysApp.Left",
+ privileges = { screen = "system", audio = "none" },
+ requisites = { screen = "blinker_left", audio = "none" },
+ resource_class = "player",
+ screen_priority = 30
+}
+
+application {
+ appid = "org.tizen.ico.camera_right",
+ area = "Center.SysApp.Right",
+ privileges = { screen = "system", audio = "none" },
+ requisites = { screen = "blinker_right", audio = "none" },
+ resource_class = "player",
+ screen_priority = 30
+}
+
+application {
+ appid = "net.zmap.navi",
+ area = "Center.Full",
+ privileges = { screen = "none", audio = "none" },
+ resource_class = "navigator",
+ screen_priority = 30
+}
+
+application {
+ appid = "GV3ySIINq7.GhostCluster",
+ area = "Center.Full",
+ privileges = { screen = "none", audio = "none" },
+ resource_class = "system",
+ requisites = { screen = "driving", audio = "none" },
+ screen_priority = 30
+}
+
+application {
+ appid = "MediaPlayer",
+ area = "Center.Full",
+ privileges = { screen = "none", audio = "none" },
+ requisites = { screen = "driving", audio = "none" },
+ resource_class = "player",
+ screen_priority = 0
+}
+
+application {
+ appid = "MyMediaPlayer",
+ area = "Center.Full",
+ privileges = { screen = "none", audio = "none" },
+ requisites = { screen = "driving", audio = "none" },
+ resource_class = "player",
+ screen_priority = 0
+}
+
+application {
+ appid = "MeterWidget",
+ area = "Center.Full",
+ privileges = { screen = "none", audio = "none" },
+ requisites = { screen = "driving", audio = "none" },
+ resource_class = "player",
+ screen_priority = 0
+}
+
+application {
+ appid = "org.tizen.ico.app-soundsample",
+ area = "Center.Full",
+ privileges = { screen = "none", audio = "none" },
+ -- uncomment the next line to make the app exempt from regulation
+ -- requisites = { screen = "driving", audio = "none" },
+ resource_class = "player",
+ screen_priority = 0
+}
+
+
+if sc then
+ sc.client_handler = function (self, cid, msg)
+ local command = msg.command
+ local appid = msg.appid
+ if verbose > 0 then
+ print('### ==> client handler:')
+ if verbose > 1 then
+ print(msg)
+ end
+ end
+
+ -- known commands: 1 for SEND_APPID, synthetic command 0xFFFF for
+ -- disconnection
+
+ if command == 0xFFFF then
+ if verbose > 1 then
+ print('client ' .. cid .. ' disconnected')
+ end
+ if msg.appid == homescreen then
+ homescreen = ""
+ for i,v in pairs(special_screen_sets) do
+ resclnt:resource_set_destroy("screen", i)
+ special_screen_sets[i] = nil
+ end
+ end
+ return
+ end
+
+ -- handle the connection to weston
+
+ if appid then
+ if appid == "org.tizen.ico.homescreen" then
+ print('Setting homescreen='..appid)
+ homescreen = appid
+ if command and command == 1 then
+ send_driving_mode_to(homescreen)
+ send_night_mode_to(homescreen)
+ end
+ elseif appid == "org.tizen.ico.onscreen" then
+ onscreen = appid
+ if command and command == 1 then
+ send_driving_mode_to(onscreen)
+ send_night_mode_to(onscreen)
+ end
+ end
+
+ if not connected and appid == "org.tizen.ico.homescreen" then
+ print('Trying to connect to weston...')
+ connected = wmgr:connect()
+ end
+ cids[cid] = appid
+ end
+ end
+
+ sc.generic_handler = function (self, cid, msg)
+ if verbose > 0 then
+ print('### ==> generic handler:')
+ if verbose > 1 then
+ print(msg)
+ end
+ end
+ end
+
+ sc.window_handler = function (self, cid, msg)
+ if verbose > 0 then
+ print('### ==> received ' ..
+ command_name(msg.command) .. ' message from ' .. cids[cid])
+ if verbose > 1 then
+ print(tostring(msg))
+ end
+ end
+
+ local a = animation({})
+ local nores = false
+ if msg.command == 0x10003 then -- ico SHOW command
+ local raise_mask = 0x01000000
+ local lower_mask = 0x02000000
+ local nores_mask = 0x40000000
+ local time_mask = 0x00ffffff
+
+ local surface = msg.arg.surface
+ local system_surface = false
+ local appdb = wmgr:application(msg.appid)
+ system_surface = appdb.privileges.screen == "system"
+
+ msg.arg.visible = 1
+
+ if msg.arg then
+ local time = 200
+ if msg.arg.anim_time then
+ local t = msg.arg.anim_time
+ -- the actual time for the animation
+ time = m:AND(t, time_mask)
+ -- flag for ignoring resource control
+ nores = m:AND(t, nores_mask)
+ if m:AND(t, raise_mask) then
+ msg.arg.raise = 1
+ elseif m:AND(t, lower_mask) then
+ msg.arg.raise = 0
+ end
+ end
+ if msg.arg.anim_name then
+ a.show = { msg.arg.anim_name, time }
+ print('time: ' .. tostring(time))
+ end
+ end
+
+ -- all show messages from system surfaces are forced
+ if not nores and system_surface then
+ nores = true
+ if not msg.arg.raise then
+ msg.arg.raise = 1
+ end
+ end
+
+ if verbose > 2 then
+ print('### ==> SHOW')
+ print(tostring(msg.arg) .. ", system_surface=" .. tostring(system_surface))
+ end
+
+ if nores then
+ wmgr:window_request(msg.arg, a, 0)
+
+ -- only non-system surfaces have resource sets
+ if not system_surface then
+ resclnt:resource_set_acquire("screen", surface)
+ end
+ else
+ resclnt:resource_set_acquire("screen", surface)
+ resmgr:window_raise(msg.appid, surface, 1)
+ end
+ elseif msg.command == 0x10004 then -- ico HIDE command
+ local raise_mask = 0x01000000
+ local lower_mask = 0x02000000
+ local nores_mask = 0x40000000
+ local time_mask = 0x00ffffff
+ msg.arg.visible = 0
+ if msg.arg then
+ local time = 200
+ if msg.arg.anim_time then
+ local t = msg.arg.anim_time
+ -- the actual time for the animation
+ time = m:AND(t, time_mask)
+ -- flag for ignoring resource control
+ nores = m:AND(t, nores_mask)
+ end
+ if msg.arg.anim_name then
+ a.hide = { msg.arg.anim_name, time }
+ print('hide animation time: ' .. tostring(a.hide[2]))
+ end
+ end
+ if not nores then
+ local p = wmgr:application(msg.appid)
+ local s = p.privileges.screen
+ if s == "system" then
+ nores = true
+ msg.arg.raise = 0
+ end
+ end
+ if verbose > 2 then
+ print('### ==> HIDE REQUEST')
+ print(tostring(msg.arg))
+ end
+ if nores then
+ wmgr:window_request(msg.arg, a, 0)
+ else
+ resmgr:window_raise(msg.appid, msg.arg.surface, -1)
+ end
+ elseif msg.command == 0x10005 then -- ico MOVE
+ if verbose > 2 then
+ print('### ==> MOVE REQUEST')
+ print(tostring(msg.arg))
+ end
+ if msg.arg.zone then
+ msg.arg.area = msg.arg.zone
+ end
+ wmgr:window_request(msg.arg, a, 0)
+ -- TODO: handle if area changed
+ elseif msg.command == 0x10007 then -- ico CHANGE_ACTIVE
+ if not msg.arg.active then
+ msg.arg.active = 3 -- pointer + keyboard
+ end
+ if verbose > 2 then
+ print('### ==> CHANGE_ACTIVE REQUEST')
+ print(tostring(msg.arg))
+ end
+ wmgr:window_request(msg.arg, a, 0)
+ elseif msg.command == 0x10008 then -- ico CHANGE_LAYER
+ if verbose > 2 then
+ print('### ==> CHANGE_LAYER REQUEST')
+ print(tostring(msg.arg))
+ end
+ --[[
+ if msg.arg.layer ~= 4 or msg.arg.layer ~= 5 then
+ print("do not change layer for other than cursor or touch")
+ return
+ end
+ --]]
+ wmgr:window_request(msg.arg, a, 0)
+ elseif msg.command == 0x10020 then -- ico MAP_THUMB
+ local framerate = msg.arg.framerate
+ local animname = msg.arg.anim_name
+ if animname then
+ a.map = { animname, 1 }
+ if not framerate or framerate < 0 then
+ framerate = 5
+ end
+ msg.arg.mapped = 1
+ if verbose > 2 then
+ print('### ==> MAP_THUMB REQUEST')
+ print(msg.arg)
+ print('framerate: '..framerate)
+ end
+ wmgr:window_request(msg.arg, a, framerate)
+ end
+ elseif msg.command == 0x10021 then -- ico UNMAP_THUMB
+ msg.arg.mapped = 0
+ if verbose > 2 then
+ print('### ==> UNMAP_THUMB REQUEST')
+ print(msg.arg)
+ end
+ wmgr:window_request(msg.arg, a, 0)
+--[[
+ elseif msg.command == 0x10013 then -- ico MAP_BUFFER command
+ local shmname = msg.arg.anim_name
+ local bufsize = msg.arg.width
+ local bufnum = msg.arg.height
+ if shmname and bufsize and bufnum then
+ if verbose > 2 then
+ print('### ==> MAP_BUFFER REQUEST')
+ print("shmaname='" .. shmname ..
+ "' bufsize='" .. bufsize ..
+ " bufnum=" .. bufnum)
+ end
+ wmgr:buffer_request(shmname, bufsize, bufnum)
+ end
+--]]
+ elseif msg.command == 0x10030 then -- ico SHOW_LAYER command
+ msg.arg.visible = 1
+ if verbose > 2 then
+ print('### ==> SHOW_LAYER REQUEST')
+ print(msg.arg)
+ end
+ wmgr:layer_request(msg.arg)
+ elseif msg.command == 0x10031 then -- ico HIDE_LAYER command
+ msg.arg.visible = 0
+ if verbose > 2 then
+ print('### ==> HIDE_LAYER REQUEST')
+ print(msg.arg)
+ end
+ wmgr:layer_request(msg.arg)
+ end
+ end
+
+ sc.input_handler = function (self, cid, msg)
+ if verbose > 0 then
+ print('### ==> input handler: ' .. command_name(msg.command))
+ if verbose > 1 then
+ print(msg)
+ end
+ end
+ if msg.command == 0x20001 then -- add_input
+ msg.arg.appid = msg.appid
+ if verbose > 2 then
+ print('### ==> ADD_INPUT REQUEST')
+ print(tostring(msg.arg))
+ end
+ imgr:input_request(msg.arg)
+ elseif msg.command == 0x20002 then -- del_input
+ msg.arg.appid = ''
+ if verbose > 2 then
+ print('### ==> DEL_INPUT REQUEST')
+ print(tostring(msg.arg))
+ end
+ imgr:input_request(msg.arg)
+ -- elseif msg.command == 0x20003 then -- send_input
+ end
+ end
+
+ sc.user_handler = function (self, cid, msg)
+ if verbose > 0 then
+ print('### ==> user handler: ' .. command_name(msg.command))
+ if verbose > 1 then
+ print(msg)
+ end
+ end
+
+ if not um then
+ print("User Manager not initialized")
+ return
+ end
+
+ if msg.command == 0x30001 then -- change_user
+ print("command CHANGE_USER")
+ if not msg.arg then
+ print("invalid message")
+ return
+ end
+
+ username = msg.arg.user
+ passwd = msg.arg.pass
+
+ if not username then
+ username = ""
+ end
+
+ if not passwd then
+ passwd = ""
+ end
+
+ success = um:changeUser(username, passwd)
+
+ if not success then
+ reply = m.JSON({
+ appid = msg.appid,
+ command = cmd
+ })
+ if sc:send_message(msg.appid, reply) then
+ print('*** sent authentication failed message')
+ else
+ print('*** failed to send authentication failed message')
+ end
+ end
+
+ elseif msg.command == 0x30002 then -- get_userlist
+ print("command GET_USERLIST")
+ if not msg.appid then
+ print("invalid message")
+ return
+ end
+
+ users, currentUser = um:getUserList()
+
+ if not users then
+ print("failed to get user list")
+ return
+ end
+
+ nUsers = 0
+
+ for i,v in pairs(users) do
+ nUsers = nUsers + 1
+ end
+
+ if not currentUser then
+ currentUser = ""
+ end
+
+ if verbose > 1 then
+ print("current user: " .. currentUser)
+ print("user list:")
+ for i,v in pairs(users) do
+ print(v)
+ end
+ end
+
+ reply = m.JSON({
+ appid = msg.appid,
+ command = cmd,
+ arg = m.JSON({
+ user_num = nUsers,
+ user_list = users,
+ user_login = currentUser
+ })
+ })
+
+ if verbose > 1 then
+ print("### <== GetUserList reply: " .. tostring(reply))
+ end
+
+ if sc:send_message(msg.appid, reply) then
+ print('*** reply OK')
+ else
+ print('*** reply FAILED')
+ end
+
+ elseif msg.command == 0x30003 then -- get_lastinfo
+ print("command GET_LASTINFO")
+ if not msg.appid then
+ print("invalid message")
+ return
+ end
+
+ lastInfo = um:getLastInfo(msg.appid)
+
+ if not lastInfo then
+ print("failed to get last info for app" .. msg.appid)
+ return
+ end
+
+ reply = m.JSON({
+ appid = msg.appid,
+ command = cmd,
+ arg = m.JSON({
+ lastinfo = lastinfo
+ })
+ })
+
+ if sc:send_message(msg.appid, reply) then
+ print('*** reply OK')
+ else
+ print('*** reply FAILED')
+ end
+
+ elseif msg.command == 0x30004 then -- set_lastinfo
+ print("command SET_LASTINFO")
+ if not msg.arg or not msg.appid then
+ print("invalid message")
+ return
+ end
+
+ lastInfo = um:setLastInfo(msg.appid, msg.arg.lastinfo)
+ end
+ end
+
+ sc.resource_handler = function (self, cid, msg)
+ if verbose > 0 then
+ print('### ==> resource handler: ' .. command_name(msg.command))
+ if verbose > 1 then
+ print(msg)
+ end
+ end
+
+ getKey = function (msg)
+ -- Field rset.key is an id for distinguishing between rsets. All
+ -- resource types appear to contain a different key. Just pick one
+ -- based on what we have on the message.
+
+ key = nil
+
+ if msg and msg.res then
+ if msg.res.sound then
+ key = msg.res.sound.id
+ elseif msg.res.input then
+ key = msg.res.input.name
+ elseif msg.res.window then
+ -- alarm! this appars to be non-unique?
+ key = msg.res.window.resourceId
+ end
+ end
+
+ return key
+ end
+
+ createResourceSet = function (ctl, client, msg)
+ cb = function(rset)
+
+ -- m:info("*** resource_cb: client = '" .. msg.appid .. "'")
+
+ -- type is either basic (0) or interrupt (1)
+ requestType = 0
+ if msg.res.type then
+ requestType = msg.res.type
+ end
+
+ if rset.data.filter_first then
+ rset.data.filter_first = false
+ return
+ end
+
+ if rset.acquired then
+ cmd = 0x00040001 -- acquire
+
+ if msg.appid == onscreen then
+ -- notifications are valid only for a number of seconds
+ rset.timer = m:Timer({
+ interval = 5000,
+ oneshot = true,
+ callback = function (t)
+ m:info("notification timer expired")
+
+ if rset.data then
+ reply.res.window = rset.data.window
+ end
+
+ rset:release()
+ rset.timer = nil
+
+ -- Send a "RELEASE" message to client.
+ -- This triggers the resource deletion
+ -- cycle in OnScreen.
+
+ reply = m.JSON({
+ appid = msg.appid,
+ command = cmd,
+ res = {
+ type = requestType
+ }
+ })
+
+ sc:send_message(client, reply)
+ end
+ })
+ end
+ else
+ cmd = 0x00040002 -- release
+ if rset.timer then
+ rset.timer.callback = nil
+ rset.timer = nil
+ end
+ end
+
+ reply = m.JSON({
+ appid = msg.appid,
+ command = cmd,
+ res = {
+ type = requestType
+ }
+ })
+
+ if rset.data.sound then
+ reply.res.sound = rset.data.sound
+ end
+
+ if rset.data.window then
+ reply.res.window = rset.data.window
+ end
+
+ if rset.data.input then
+ reply.res.input = rset.data.input
+ end
+
+ if rset.acquired then
+ m:info("resource cb: 'acquire' reply to client " .. client)
+ else
+ m:info("resource cb: 'release' reply to client " .. client)
+ end
+
+ if not sc:send_message(client, reply) then
+ m:info('*** reply FAILED')
+ end
+ end
+
+ local rset = m:ResourceSet({
+ application_class = "player",
+ zone = "driver", -- msg.zone ("full")
+ callback = cb
+ })
+
+ rset.data = {
+ cid = cid,
+ ctl = ctl,
+ filter_first = true
+ }
+
+ if msg.res.sound then
+ rset:addResource({
+ resource_name = "audio_playback"
+ })
+ rset.resources.audio_playback.attributes.pid = tostring(msg.pid)
+ rset.resources.audio_playback.attributes.appid = msg.appid
+ print("sound name: " .. msg.res.sound.name)
+ print("sound zone:" .. msg.res.sound.zone)
+ print("sound adjust: " .. tostring(msg.res.sound.adjust))
+
+ rset.data.sound = msg.res.sound
+ end
+
+ if msg.res.input then
+ rset:addResource({
+ resource_name = "input"
+ })
+ rset.resources.input.attributes.pid = tostring(msg.pid)
+ rset.resources.input.attributes.appid = msg.appid
+ print("input name: " .. msg.res.input.name)
+ print("input event:" .. tostring(msg.res.input.event))
+
+ rset.data.input = msg.res.input
+ end
+
+ if msg.res.window then
+ rset:addResource({
+ resource_name = "screen",
+ shared = true
+ })
+ rset.resources.screen.attributes.pid = tostring(msg.pid)
+ rset.resources.screen.attributes.appid = msg.appid
+ rset.resources.screen.attributes.surface = msg.res.window.resourceId
+ complete_area = msg.res.window.display .. '.' .. msg.res.window.area
+ rset.resources.screen.attributes.area = complete_area
+ if msg.appid == onscreen then
+ rset.resources.screen.attributes.classpri = 1
+ else
+ rset.resources.screen.attributes.classpri = 0
+ end
+
+ rset.data.window = msg.res.window
+ end
+
+ rset.key = getKey(msg)
+
+ return rset
+ end
+
+ -- parse the message
+
+ -- fields common to all messages:
+ -- msg.command
+ -- msg.appid
+ -- msg.pid
+
+ if msg.command == 0x40011 then -- create_res
+ print("command CREATE_RES")
+ key = getKey(msg)
+
+ if key then
+ if not sets.cid then
+ sets.cid = {}
+ end
+ sets.cid[key] = createResourceSet(self, cid, msg)
+ end
+
+ elseif msg.command == 0x40012 then -- destroy_res
+ print("command DESTROY_RES")
+ key = getKey(msg)
+
+ if key then
+ if sets.cid and sets.cid[key] then
+ sets.cid[key]:release()
+ sets.cid[key].timer = nil
+ sets.cid[key] = nil -- garbage collecting
+ end
+ end
+
+ elseif msg.command == 0x40001 then -- acquire_res
+ print("command ACQUIRE_RES")
+ key = getKey(msg)
+
+ if key then
+ if not sets.cid then
+ sets.cid = {}
+ end
+ if not sets.cid[key] then
+ sets.cid[key] = createResourceSet(self, cid, msg)
+ end
+ print("acquiring the resource set")
+ sets.cid[key]:acquire()
+ end
+
+ elseif msg.command == 0x40002 then -- release_res
+ print("command RELEASE_RES")
+
+ key = getKey(msg)
+
+ if key then
+ if sets.cid and sets.cid[key] then
+ sets.cid[key]:release()
+
+ if msg.appid == onscreen then
+ -- in case of OnScreen, this actually means that the
+ -- resource set is never used again; let gc do its job
+ sets.cid[key].timer = nil
+ sets.cid[key] = nil -- garbage collecting
+ end
+ end
+ end
+
+ elseif msg.command == 0x40003 then -- deprive_res
+ print("command DEPRIVE_RES")
+
+ elseif msg.command == 0x40004 then -- waiting_res
+ print("command WAITING_RES")
+
+ elseif msg.command == 0x40005 then -- revert_res
+ print("command REVERT_RES")
+ end
+ end
+
+ sc.inputdev_handler = function (self, cid, msg)
+ if verbose > 0 then
+ print('*** inputdev handler: ' .. command_name(msg.command))
+ if verbose > 1 then
+ print(msg)
+ end
+ end
+ end
+
+ sc.notify_handler = function (self, cid, msg)
+ if verbose > 0 then
+ print('### notify handler: ' .. command_name(msg.command))
+ if verbose > 1 then
+ print(msg)
+ end
+ end
+ end
+end
+
+function send_driving_mode_to(client)
+ if client == "" then
+ return
+ end
+
+ local driving_mode = mdb.select.select_driving_mode.single_value
+
+ if not driving_mode then driving_mode = 0 end
+
+ local reply = m:JSON({ command = 0x60001,
+ arg = m:JSON({ stateid = 1,
+ state = driving_mode
+ })
+ })
+
+ if verbose > 0 then
+ print("### <== sending " .. command_name(reply.command) .. " message")
+ if verbose > 1 then
+ print(reply)
+ end
+ end
+
+ sc:send_message(client, reply)
+end
+
+function send_night_mode_to(client)
+ if client == "" then
+ return
+ end
+
+ local night_mode = mdb.select.select_night_mode.single_value
+
+ if not night_mode then night_mode = 0 end
+
+ local reply = m:JSON({ command = 0x60001,
+ arg = m:JSON({ stateid = 2,
+ state = night_mode
+ })
+ })
+
+ if verbose > 0 then
+ print("### <== sending " .. command_name(reply.command) .. " message")
+ if verbose > 1 then
+ print(reply)
+ end
+ end
+
+ sc:send_message(client, reply)
+end
+
+-- we should have 'audio_playback' defined by now
+m:try_load_plugin('telephony')