first commit
David Blume

David Blume commited on 2020-03-06 23:03:37
Showing 16 changed files, with 549 additions and 0 deletions.

... ...
@@ -0,0 +1,2 @@
1
+test.zip
2
+.DS_Store
... ...
@@ -0,0 +1,21 @@
1
+The MIT License (MIT)
2
+
3
+Copyright (c) 2016 David Blume
4
+
5
+Permission is hereby granted, free of charge, to any person obtaining a copy 
6
+of this software and associated documentation files (the "Software"), to deal 
7
+in the Software without restriction, including without limitation the rights
8
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
9
+copies of the Software, and to permit persons to whom the Software is 
10
+furnished to do so, subject to the following conditions:
11
+
12
+The above copyright notice and this permission notice shall be included in all 
13
+copies or substantial portions of the Software.
14
+
15
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
16
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
17
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
18
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
19
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+SOFTWARE.
... ...
@@ -0,0 +1,13 @@
1
+.PHONY: clean
2
+ZIPFILE=test.zip
3
+
4
+all: $(ZIPFILE)
5
+	curl -s -S --user rokudev:$(DEVPASSWORD) --digest -F "archive=@$(ZIPFILE)" \
6
+	-F "mysubmit=Install" --output /dev/null --write-out "%{http_code}" \
7
+	http://$(ROKU_DEV_TARGET)/plugin_install
8
+
9
+$(ZIPFILE):  manifest source/*.brs components/*.xml components/*.brs images/*.png
10
+	zip $@ manifest source/*.brs components/*.xml components/*.brs images/*.png
11
+
12
+clean:
13
+	rm $(ZIPFILE)
... ...
@@ -0,0 +1,28 @@
1
+# dxb Channel
2
+
3
+dxb Channel is a test [channel for Roku devices](https://sdkdocs.roku.com/display/sdkdoc/SceneGraph+Samples).
4
+It uses SceneGraph and the BrightScript language.
5
+
6
+# Getting the project
7
+
8
+You can get a copy of this project by clicking on the
9
+[ZIP](http://git.dlma.com/dxb_channel.git/zipball/master)
10
+or [TAR](http://git.dlma.com/dxb_channel.git/tarball/master) buttons
11
+near the top right of the GitList web page.
12
+
13
+If you're me, and you want to contribute to the repo, then you can clone it like so:
14
+
15
+    git clone ssh://USERNAME@dlma.com/~/git/dxb_channel.git
16
+
17
+# Building it
18
+
19
+[Ensure you can sideload a dev channel](https://sdkdocs.roku.com/display/sdkdoc/Loading+and+Running+Your+Application).
20
+Then see the "build\_systems" command in dxb\_channel.sublime-project to see how the channel is zipped and deployed.
21
+
22
+# Is it any good?
23
+
24
+[Yes](https://news.ycombinator.com/item?id=3067434).
25
+
26
+# Licence
27
+
28
+This software uses the [MIT license](http://git.dlma.com/dxb_channel.git/blob/master/LICENSE.txt).
... ...
@@ -0,0 +1,170 @@
1
+function init()
2
+  m.title = m.top.findNode("title")
3
+  m.title.font.size=248
4
+  m.title.color="0x62C7FF18"
5
+
6
+  title_font_size = 34
7
+  font_size = 32
8
+  m.updates = m.top.findNode("updates")
9
+  m.updates.font.size=font_size
10
+  m.updates.color="0x52C7F8FF"
11
+  m.updates.lineSpacing = 8
12
+
13
+  m.updates_title = m.top.findNode("updates_title")
14
+  m.updates_title.font.size=title_font_size
15
+  m.updates_title.color="0x62E7FFFF"
16
+  m.updates_title.text = "Launch Parameters"
17
+
18
+  m.updates_lower = m.top.findNode("updates_lower")
19
+  m.updates_lower.font.size=font_size
20
+  m.updates_lower.color="0x52C7F8FF"
21
+  m.updates_lower.text = ""
22
+  m.updates_lower.lineSpacing = 8
23
+
24
+  m.updates_lower_title = m.top.findNode("updates_lower_title")
25
+  m.updates_lower_title.font.size=title_font_size
26
+  m.updates_lower_title.color="0x62E7FFFF"
27
+  m.updates_lower_title.text = "Events"
28
+
29
+  m.updates_right = m.top.findNode("updates_right")
30
+  m.updates_right.font.size=font_size
31
+  m.updates_right.color="0x52C7F8FF"
32
+  m.updates_right.lineSpacing = 8
33
+
34
+  m.updates_right_title = m.top.findNode("updates_right_title")
35
+  m.updates_right_title.font.size=title_font_size
36
+  m.updates_right_title.color="0x62E7FFFF"
37
+  m.updates_right_title.text = "Test Output"
38
+
39
+  m.title_color = "0x20204080"
40
+  m.title_focus_color = "0x4060B0A0"
41
+  m.tl_rect = m.top.findNode("updates_title_rect")
42
+  m.tl_rect.color = m.title_color
43
+  m.bl_rect = m.top.findNode("updates_lower_title_rect")
44
+  m.bl_rect.color = m.title_color
45
+  m.r_rect = m.top.findNode("updates_right_title_rect")
46
+  m.r_rect.color = m.title_color
47
+  label_color = "0x00002080"
48
+  r = m.top.findNode("updates_rect")
49
+  r.color = label_color
50
+  r = m.top.findNode("updates_lower_rect")
51
+  r.color = label_color
52
+  r = m.top.findNode("updates_right_rect")
53
+  r.color = label_color
54
+
55
+  m.myTask = CreateObject("roSGNode", "MyTask")
56
+  m.myTask.ObserveField("updateText", "onUpdateText")
57
+  m.myTask.ObserveField("updateTextLower", "onUpdateTextLower")
58
+  m.myTask.ObserveField("updateTextRight", "onUpdateTextRight")
59
+  m.myTask.control = "RUN"
60
+
61
+  texttimer = m.top.findNode("textTimer")
62
+  texttimer.observeField("fire", "timerUpdate")
63
+  texttimer.control = "start"
64
+
65
+  m.updates_lower_array = CreateObject("roArray", 10, true)
66
+
67
+  m.focus_rect = 3
68
+  doUpdateFocus()
69
+
70
+  m.top.setFocus(true)
71
+end function
72
+
73
+function onUpdateText() as void
74
+   if m.updates.text.Len() = 0
75
+       m.updates.text = m.myTask.updateText
76
+   else
77
+       m.updates.text = m.updates.text + chr(10) + m.myTask.updateText
78
+   end if
79
+end function
80
+
81
+function onUpdateTextLower() as void
82
+   updateTextLower(m.myTask.updateTextLower)
83
+end function
84
+
85
+function updateTextLower(s as String) as void
86
+    while m.updates_lower_array.Count() > 9
87
+        m.updates_lower_array.Shift()
88
+    end while
89
+    m.updates_lower_array.Push(s)
90
+
91
+    m.updates_lower.text = m.updates_lower_array.Join(chr(10))
92
+end function
93
+
94
+function onUpdateTextRight() as void
95
+   if m.updates_right.text.Len() = 0
96
+       m.updates_right.text = m.myTask.updateTextRight
97
+   else
98
+       m.updates_right.text = m.updates_right.text + chr(10) + m.myTask.updateTextRight
99
+   end if
100
+end function
101
+
102
+function onKeyEvent(key as String, press as Boolean) as Boolean
103
+    handled = false
104
+    if press then
105
+        if (key = "back") then
106
+            handled = false
107
+        else
108
+            update_ui = false
109
+            if key = "up"
110
+                if m.focus_rect = 2:
111
+                    m.focus_rect = 1
112
+                elseif m.focus_rect = 3
113
+                    m.focus_rect = 0
114
+                    update_ui = true
115
+                endif
116
+            elseif key = "right"
117
+                if m.focus_rect = 0:
118
+                    m.focus_rect = 1
119
+                    update_ui = true
120
+                elseif m.focus_rect = 3
121
+                    m.focus_rect = 2
122
+                    update_ui = true
123
+                endif
124
+            elseif key = "down"
125
+                if m.focus_rect = 0:
126
+                    m.focus_rect = 3
127
+                    update_ui = true
128
+                elseif m.focus_rect = 1
129
+                    m.focus_rect = 2
130
+                endif
131
+            elseif key = "left"
132
+                if m.focus_rect = 1:
133
+                    m.focus_rect = 0
134
+                    update_ui = true
135
+                elseif m.focus_rect = 2
136
+                    m.focus_rect = 3
137
+                    update_ui = true
138
+                endif
139
+            end if
140
+            if update_ui
141
+                doUpdateFocus()
142
+            endif
143
+            dt = Mid(CreateObject("roDateTime").ToISOString(), 15, 5)
144
+            updateTextLower(dt + " " + key)
145
+            handled = true
146
+        end if
147
+    end if
148
+    return handled
149
+end function
150
+
151
+sub doUpdateFocus()
152
+    if m.focus_rect = 0
153
+        m.tl_rect.color = m.title_focus_color
154
+        m.bl_rect.color = m.title_color
155
+        m.r_rect.color = m.title_color
156
+    elseif m.focus_rect = 1 or m.focus_rect = 2
157
+        m.tl_rect.color = m.title_color
158
+        m.bl_rect.color = m.title_color
159
+        m.r_rect.color = m.title_focus_color
160
+    elseif m.focus_rect = 3
161
+        m.tl_rect.color = m.title_color
162
+        m.bl_rect.color = m.title_focus_color
163
+        m.r_rect.color = m.title_color
164
+    end if
165
+end sub
166
+
167
+sub timerUpdate()
168
+  ' Not needed, but nice to have as an example.
169
+  ' print "timerUpdate called."
170
+end sub
... ...
@@ -0,0 +1,108 @@
1
+<?xml version="1.0" encoding="utf-8" ?>
2
+<component name="dxb" extends="Scene">
3
+  <children>
4
+    <Label id="title"
5
+      text="dxb"
6
+      font = "font:LargeBoldSystemFont"
7
+      width="1000"
8
+      height="100"
9
+      translation = "[860, 40]"
10
+      horizAlign="right"
11
+      vertAlign="top" />
12
+
13
+    <Rectangle id="updates_title_rect"
14
+      width="900"
15
+      height="51"
16
+      translation = "[50,40]"
17
+      color = "0x20600040" >
18
+      <Label id="updates_title"
19
+        text=""
20
+        font = "font:SmallBoldSystemFont"
21
+        width="880"
22
+        height="40"
23
+        translation = "[10,10]"
24
+        horizAlign="left"
25
+        vertAlign="top"
26
+        wrap="true" />
27
+    </Rectangle>
28
+    <Rectangle id="updates_rect"
29
+      width="900"
30
+      height="440"
31
+      translation = "[50,90]"
32
+      color = "0x00800040" >
33
+      <Label id="updates"
34
+        text=""
35
+        width="880"
36
+        height="420"
37
+        translation = "[10,10]"
38
+        horizAlign="left"
39
+        vertAlign="top"
40
+        wrap="true" />
41
+    </Rectangle>
42
+
43
+    <Rectangle id="updates_lower_title_rect"
44
+      width="900"
45
+      height="50"
46
+      translation = "[50,540]"
47
+      color = "0x40203040" >
48
+      <Label id="updates_lower_title"
49
+        text="updates_lower_title text"
50
+        font = "font:SmallBoldSystemFont"
51
+        width="880"
52
+        height="40"
53
+        translation = "[10,10]"
54
+        horizAlign="left"
55
+        vertAlign="top"
56
+        wrap="true" />
57
+    </Rectangle>
58
+    <Rectangle id="updates_lower_rect"
59
+      width="900"
60
+      height="440"
61
+      translation = "[50,590]"
62
+      color = "0x60202040" >
63
+      <Label id="updates_lower"
64
+        text="updates_lower text"
65
+        width="880"
66
+        height="420"
67
+        translation = "[10,10]"
68
+        horizAlign="left"
69
+        vertAlign="top"
70
+        wrap="true" />
71
+    </Rectangle>
72
+
73
+    <Rectangle id="updates_right_title_rect"
74
+      width="900"
75
+      height="51"
76
+      translation = "[960,40]"
77
+      color = "0x20004040" >
78
+      <Label id="updates_right_title"
79
+        text=""
80
+        font = "font:SmallBoldSystemFont"
81
+        width="880"
82
+        height="40"
83
+        translation = "[10,10]"
84
+        horizAlign="left"
85
+        vertAlign="top"
86
+        wrap="true" />
87
+    </Rectangle>
88
+    <Rectangle id="updates_right_rect"
89
+      width="900"
90
+      height="940"
91
+      translation = "[960,90]"
92
+      color = "0x00002040" >
93
+      <Label id="updates_right"
94
+        width="880"
95
+        height="920"
96
+        translation = "[10,10]"
97
+        horizAlign="left"
98
+        vertAlign="top"
99
+        wrap="true" />
100
+    </Rectangle>
101
+
102
+    <Timer
103
+      id = "textTimer"
104
+      repeat = "true"
105
+      duration = "4" />
106
+  </children>
107
+<script type="text/brightscript" uri="pkg:/components/dxb.brs" />
108
+</component>
... ...
@@ -0,0 +1,117 @@
1
+sub init()
2
+    m.top.functionName = "executeTask"
3
+end sub
4
+
5
+function getDeviceId(deviceInfo as object) as String
6
+    ' Try to get the Serial Number for an ECP call
7
+    request = CreateObject("roUrlTransfer")
8
+    request.SetUrl("http://localhost:8060/query/device-info")
9
+    root = CreateObject("roXMLElement")
10
+    if root.Parse(request.GetToString()) then
11
+        serialnums = root.GetNamedElements("serial-number")
12
+        if serialnums.Count() > 0
13
+            model = root.GetNamedElements("model-number")
14
+            if model.Count() > 0
15
+                return serialnums[0].GetText() + ":" + model[0].GetText()
16
+            end if
17
+        end if
18
+    end if
19
+    ' That did not work, so make a custom one.
20
+    clientID = Right(deviceInfo.GetChannelClientId(), 6)
21
+    modelID = deviceInfo.GetModel()
22
+    return clientID + "-" + modelID
23
+end function
24
+
25
+function executeTask() as void
26
+
27
+    am = CreateObject("roAppManager")
28
+    aaRunParams = am.GetRunParams()
29
+    for each key in aaRunParams
30
+        val = aaRunParams[key]
31
+        m.top.updateText = key + " = " + val.ToStr()
32
+        print "roAppManager.runParams " key " = " val
33
+    end for 
34
+
35
+    deviceInfo = CreateObject("roDeviceInfo")
36
+    port = CreateObject("roMessagePort")
37
+    deviceInfo.SetMessagePort(port)
38
+
39
+    success = deviceInfo.EnableLinkStatusEvent(true)
40
+    if not success m.top.updateTextLower = "EnableLinkStatusEvent failure"
41
+    success = deviceInfo.EnableAudioDestinationEvent(true)
42
+    if not success then m.top.updateTextLower = "EnableAudioDestinationEvent failure"
43
+    success = deviceInfo.EnableAudioGuideChangedEvent(true)
44
+    if not success then m.top.updateTextLower = "EnableAudioGuideChangedEvent failure"
45
+    success = deviceInfo.EnableAppFocusEvent(true)
46
+    if not success then m.top.updateTextLower = "EnableAppFocusEvent failure"
47
+    success = deviceInfo.EnableCodecCapChangedEvent(true)
48
+    if not success then m.top.updateTextLower = "EnableCodecCapChangedEvent failure"
49
+
50
+
51
+    aaConnectionInfo = deviceInfo.GetConnectionInfo()
52
+    for each key in aaConnectionInfo
53
+        val = aaConnectionInfo[key]
54
+        m.top.updateTextRight = key + " = " + val.ToStr()
55
+        print "roDeviceInfo.ConnectionInfo " key " = " val
56
+    end for
57
+
58
+    while(true)
59
+        msg = wait(0, port)
60
+        msgType = type(msg)
61
+
62
+        dt = Mid(CreateObject("roDateTime").ToISOString(), 15, 5)
63
+
64
+        if msgType = "roHdmiStatusEvent"
65
+            aa = msg.GetInfo()
66
+            v = aa.LookupCI("Plugged")
67
+            if v <> invalid
68
+                m.top.updateTextLower = dt + " HDMI plugged " + v.toStr()
69
+                print "HDMI plugged " v.toStr()
70
+            end if
71
+        elseif msgType = "roCECStatusEvent"
72
+            aa = msg.GetInfo()
73
+            v = aa.LookupCI("Active")
74
+            if v <> invalid
75
+                m.top.updateTextLower = dt + " CEC Status " + v.toStr()
76
+                print "CEC Status " v.toStr()
77
+            end if
78
+        elseif msgType = "roDeviceInfoEvent"
79
+            aa = msg.GetInfo()
80
+            v = aa.LookupCI("Mute")
81
+            if v <> invalid
82
+                m.top.updateTextLower = dt + " Mute " + v.toStr()
83
+                print "Mute " v.toStr()
84
+            end if
85
+            v = aa.LookupCI("Mode")
86
+            if v <> invalid
87
+                m.top.updateTextLower = dt + " Mode " + v.toStr()
88
+                print "Mode " v.toStr()
89
+            end if
90
+            v = aa.LookupCI("linkStatus")
91
+            if v <> invalid
92
+                m.top.updateTextLower = dt + " LinkStatus " + v.toStr()
93
+                print "LinkStatus " v.toStr()
94
+            end if
95
+            v = aa.LookupCI("audioGuideEnabled")
96
+            if v <> invalid
97
+                m.top.updateTextLower = dt + " AudioGuide " + v.toStr()
98
+                print "AudioGuide " v.toStr()
99
+            end if
100
+            v = aa.LookupCI("appFocused")
101
+            if v <> invalid
102
+                m.top.updateTextLower = dt + " appFocused " + v.toStr()
103
+                print "appFocused " v.toStr()
104
+            end if
105
+            v = aa.LookupCI("audioCodecCapabilityChanged")
106
+            if v <> invalid
107
+                m.top.updateTextLower = dt + " audioCodecCapabilityChanged " + v.toStr()
108
+                print "audioCodecCapabilityChanged " v.toStr()
109
+            end if
110
+        else
111
+            m.top.updateTextLower = dt + " msgType " + msgType
112
+            print "Unknown event msgType " v.toStr()
113
+        end if
114
+
115
+    end while
116
+
117
+end function
... ...
@@ -0,0 +1,12 @@
1
+<?xml version="1.0" encoding="utf-8" ?>
2
+
3
+<component name="MyTask" extends="Task">
4
+
5
+<interface>
6
+  <field id="updateText" type="string" value=""/>
7
+  <field id="updateTextRight" type="string" value=""/>
8
+  <field id="updateTextLower" type="string" value=""/>
9
+</interface>
10
+
11
+<script type="text/brightscript" uri="pkg:/components/mytask.brs"/>
12
+</component>
... ...
@@ -0,0 +1,41 @@
1
+{
2
+	"build_systems":
3
+	[
4
+		{
5
+			"name": "Run",
6
+			"linux": {
7
+				"shell_cmd": "make all",
8
+			},
9
+			"working_dir": "$project_path"
10
+		},
11
+		{
12
+			"name": "Zip",
13
+			"working_dir": "$project_path",
14
+			"windows": {
15
+				"cmd": "\"C:\\Program Files\\7-Zip\\7z.exe\" a -tzip \"$project_base_name.zip\" manifest source/*.* images"
16
+			},
17
+			"osx": {
18
+				"shell_cmd": "zip \"$project_base_name.zip\" manifest source/*.* images/*.*"
19
+			},
20
+			"linux": {
21
+				"shell_cmd": "zip \"$project_base_name.zip\" manifest source/*.* images/*.*"
22
+			}
23
+		}
24
+	],
25
+	"folders":
26
+	[
27
+		{
28
+			"path": ".",
29
+			"file_exclude_patterns":
30
+			[
31
+				"tags",
32
+				"*.zip",
33
+				"*.sublime-project"
34
+			],
35
+			"folder_exclude_patterns":
36
+			[
37
+				"obj"
38
+			],
39
+		}
40
+	]
41
+}
... ...
@@ -0,0 +1,10 @@
1
+title=dxb
2
+major_version=0
3
+minor_version=0
4
+build_version=2
5
+ui_resolutions=fhd
6
+mm_icon_focus_hd=pkg:/images/mm_icon_focus_hd.png
7
+mm_icon_focus_sd=pkg:/images/mm_icon_focus_sd.png
8
+splash_screen_hd=pkg:/images/splash_screen_hd.png
9
+splash_screen_sd=pkg:/images/splash_screen_sd.png
10
+splash_min_time=0
... ...
@@ -0,0 +1,27 @@
1
+sub Main(launchParams)
2
+    ' Just to test various ECP params
3
+    print "Launch parameters:"
4
+    for each key in launchParams
5
+        print "  " key "=" launchParams[key]
6
+    end for
7
+
8
+    ' Indicate this is a Roku SceneGraph application'
9
+    screen = CreateObject("roSGScreen")
10
+    port = CreateObject("roMessagePort")
11
+    screen.SetMessagePort(port)
12
+
13
+    ' Create a scene and load /components/dxb.xml'
14
+    m.scene = screen.CreateScene("dxb")
15
+    screen.show()
16
+
17
+    while(true)
18
+        msg = wait(0, port)
19
+        msgType = type(msg)
20
+        print "dxb Main loop msgType = " msgType
21
+        if msgType = "roSGScreenEvent"
22
+            if msg.isScreenClosed() then return
23
+        end if
24
+    end while
25
+
26
+end sub
27
+
0 28