Skip to content

Commit 91b761c

Browse files
committed
feat: MediaStream Image Capture API (#32)
Basic support only, more to come.
1 parent cb6a59e commit 91b761c

11 files changed

Lines changed: 971 additions & 391 deletions

AppSrc/Dashboard.wo

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,24 @@ Object oDashboard is a cWebView
147147
End_Procedure
148148
End_Object
149149

150+
Object oTileMediaStreamImageCapture is a cWebHtmlBox
151+
Set pbServerOnClick to True
152+
Set psCSSClass to "Tile"
153+
Set psHtml to """
154+
<div class="WebCon_Sizer" data-ServerOnClick="openview">
155+
<div Class="Tile_Title">MediaStream Image Capture API</div>
156+
<div class="Tile_Subtitle">capture images from photographic device</div>
157+
<span class="material-icons-outlined">https</span>
158+
</div>
159+
"""
160+
161+
WebRegisterPath ntNavigateForward oMediaStreamImageCaptureDemo
162+
163+
Procedure OnClick
164+
Send NavigatePath
165+
End_Procedure
166+
End_Object
167+
150168
Object oTileMediaStreamRecording is a cWebHtmlBox
151169
Set pbServerOnClick to True
152170
Set psCSSClass to "Tile"
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
Use cWebView.pkg
2+
Use cWebPanel.pkg
3+
Use cWebLabel.pkg
4+
Use cWebHtmlBox.pkg
5+
Use cLogger.pkg
6+
7+
Use cMediaStreamImageCaptureAPI.pkg
8+
Use cMediaStreamAPI.pkg
9+
Use cWebImage.pkg
10+
Use cWebButton.pkg
11+
12+
Object oMediaStreamImageCaptureDemo is a cWebView
13+
Set peWebViewStyle to wvsDrillDown
14+
Set peViewType to vtUndefined
15+
Set pbShowCaption to False
16+
17+
Set psCaption to "MediaStream Image Capture Demo"
18+
19+
Set piMaxWidth to 1024
20+
Set piColumnCount to 6
21+
Set pbServerOnShow to True
22+
23+
Object oMediaStreamImageCaptureAPI is a cMediaStreamImageCaptureAPI
24+
Set pbWithDimension to True // to include width/height in OnPhoto event
25+
Set pbServerOnConnect to True
26+
Set pbServerOnDisconnect to True
27+
Set pbServerOnError to True
28+
Set pbServerOnPhoto to True
29+
30+
// This can be any cMediaStream object with a video track
31+
Object oUserMediaStreamAPI is a cUserMediaStreamAPI
32+
Set pbVideo to True
33+
Set peFacingMode to MSAPI_FACING_MODE_ENVIRONMENT
34+
End_Object
35+
36+
Procedure OnConnect tMediaStreamTrackInfo stInfo
37+
Send Log of oLogger (SFormat("Connected to camera"))
38+
WebSet pbEnabled of oBtnConnect to False
39+
WebSet pbEnabled of oBtnTakePhoto to True
40+
WebSet pbEnabled of oBtnDisconnect to True
41+
End_Procedure
42+
43+
Procedure OnDisconnect
44+
Send Log of oLogger "Disconnected"
45+
WebSet pbEnabled of oBtnConnect to True
46+
WebSet pbEnabled of oBtnTakePhoto to False
47+
WebSet pbEnabled of oBtnDisconnect to False
48+
End_Procedure
49+
50+
Procedure OnError String sErrorName String sErrorMessage
51+
Send Log of oLogger (SFormat("%1: %2", sErrorName, sErrorMessage))
52+
End_Procedure
53+
54+
// ucData and sDataURL both contain the image, in different formats
55+
Procedure OnPhoto String sMimeType UChar[] ucData String sDataURL Integer iWidth Integer iHeight
56+
Send Log of oLogger (SFormat("Received %1 bytes, mime: %2, width: %3, height: %4", SizeOfArray(ucData), sMimeType, iWidth, iHeight))
57+
WebSet psURL of oWebImage to sDataURL
58+
End_Procedure
59+
End_Object
60+
61+
Object oWebMainPanel is a cWebPanel
62+
Set piColumnCount to 12
63+
WebSetResponsive piColumnCount rmMobile to 6
64+
65+
Object oWebLabel is a cWebLabel
66+
Set piColumnSpan to 0
67+
Set psCaption to "Supported?"
68+
End_Object
69+
70+
Object oWebHtmlBox is a cWebHtmlBox
71+
Set piColumnSpan to 0
72+
Set psHtml to '<div class="as-label"><a href="https://developer.mozilla.org/en-US/docs/Web/API/MediaStream_Image_Capture_API#browser_compatibility" target="_blank">See browser compatibility</a></div>'
73+
End_Object
74+
75+
Object oWebLabel2 is a cWebLabel
76+
Set piColumnSpan to 0
77+
Set psCaption to "The MediaStream Image Capture API lets you capture images from a photographic device."
78+
End_Object
79+
80+
Object oVideo is a cWebHtmlBox
81+
Set piColumnIndex to 0
82+
Set piColumnSpan to 6
83+
Set psHtml to '<video style="width: 100%" id="my-video-element"></video>'
84+
End_Object
85+
86+
Object oWebImage is a cWebImage
87+
Set piColumnIndex to 6
88+
Set piColumnSpan to 6
89+
Set pePosition to wiFit
90+
End_Object
91+
92+
Object oBtnConnect is a cWebButton
93+
Set piColumnSpan to 2
94+
Set psCaption to "Connect"
95+
96+
Procedure OnClick
97+
Send Connect of oMediaStreamImageCaptureAPI "my-video-element"
98+
End_Procedure
99+
End_Object
100+
101+
Object oBtnTakePhoto is a cWebButton
102+
Set piColumnIndex to 2
103+
Set piColumnSpan to 2
104+
Set psCaption to "Take photo"
105+
Set pbEnabled to False
106+
107+
Procedure OnClick
108+
Send TakePhoto of oMediaStreamImageCaptureAPI
109+
End_Procedure
110+
End_Object
111+
112+
Object oBtnDisconnect is a cWebButton
113+
Set piColumnSpan to 2
114+
Set piColumnIndex to 4
115+
Set psCaption to "Disconnect"
116+
Set pbEnabled to False
117+
118+
Procedure OnClick
119+
Send Disconnect of oMediaStreamImageCaptureAPI
120+
End_Procedure
121+
End_Object
122+
123+
Object oLogger is a cLogger
124+
End_Object
125+
End_Object
126+
127+
Procedure OnShow
128+
Boolean bIsSupported
129+
130+
Forward Send OnShow
131+
132+
WebGet pbIsSupported of oMediaStreamImageCaptureAPI to bIsSupported
133+
If (bIsSupported) Begin
134+
WebSet psCaption of oWebLabel to "MediaStream Image Capture API is supported"
135+
WebSet psTextColor of oWebLabel to "green"
136+
End
137+
Else Begin
138+
WebSet psCaption of oWebLabel to "MediaStream Image Capture API is NOT supported (try on anything but Firefox)"
139+
WebSet psTextColor of oWebLabel to "red"
140+
End
141+
End_Procedure
142+
End_Object

AppSrc/WebApp.src

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,15 @@ Object oWebApp is a cWebApp
117117
End_Procedure
118118
End_Object
119119

120+
Object oWebMenuItemMediaStreamImageCapture is a cWebMenuItem
121+
Set psCaption to "MediaStream Image Capture Demo"
122+
WebRegisterPath ntNavigateBegin oMediaStreamImageCaptureDemo
123+
124+
Procedure OnClick
125+
Send NavigatePath
126+
End_Procedure
127+
End_Object
128+
120129
Object oWebMenuItemMediaStreamRecording is a cWebMenuItem
121130
Set psCaption to "MediaStream Recording Demo"
122131
WebRegisterPath ntNavigateBegin oMediaStreamRecordingDemo
@@ -295,6 +304,7 @@ Object oWebApp is a cWebApp
295304
Use WebStorageDemo.wo
296305
Use MediaStreamRecordingDemo.wo
297306
Use BatteryStatusDemo.wo
307+
Use MediaStreamImageCaptureDemo.wo
298308
Set phoDefaultView to oDashboard
299309

300310
End_Object

AppSrc/cMediaStreamAPI.pkg

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,36 @@ Struct tInputDeviceInfo
1010
String label
1111
End_Struct
1212

13+
Struct tMediaTrackSettings
14+
String deviceId
15+
String groupId
16+
17+
String autoGainControl
18+
String channelCount
19+
String echoCancellation
20+
String latency
21+
String noiseSuppression
22+
String sampleRate
23+
String sampleSize
24+
25+
String aspectRatio
26+
String facingMode
27+
String frameRate
28+
String height
29+
String width
30+
String resizeMode
31+
32+
String cursor
33+
String displaySurface
34+
String logicalSurface
35+
End_Struct
36+
37+
Struct tMediaStreamTrackInfo
38+
String kind
39+
String label
40+
tMediaTrackSettings settings
41+
End_Struct
42+
1343
Define MSAPI_DEFAULT for -1
1444

1545
Enum_List
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
Use cWebObject.pkg
2+
Use cMediaStreamAPI.pkg
3+
4+
Class cMediaStreamImageCaptureAPI is a cWebObject
5+
6+
Procedure Construct_Object
7+
Forward Send Construct_Object
8+
9+
{ WebProperty=Client DesignTime=False }
10+
Property Boolean pbIsSupported False
11+
{ WebProperty=Client Visibility=Private }
12+
Property String psMediaStream
13+
{ WebProperty=Client Description="Set to True to include width and height in OnPhoto event" }
14+
Property Boolean pbWithDimension False
15+
16+
{ WebProperty=Client Category="Server events" }
17+
Property Boolean pbServerOnConnect False
18+
{ WebProperty=Client Category="Client events" }
19+
Property String psClientOnConnect ""
20+
{ WebProperty=Client Category="Server events" }
21+
Property Boolean pbServerOnDisconnect False
22+
{ WebProperty=Client Category="Client events" }
23+
Property String psClientOnDisconnect ""
24+
{ WebProperty=Client Category="Server events" }
25+
Property Boolean pbServerOnError False
26+
{ WebProperty=Client Category="Client events" }
27+
Property String psClientOnError ""
28+
{ WebProperty=Client Category="Server events" }
29+
Property Boolean pbServerOnPhoto False
30+
{ WebProperty=Client Category="Client events" }
31+
Property String psClientOnPhoto ""
32+
33+
Object oCharTranslate is a cCharTranslate
34+
End_Object
35+
36+
Set psJSClass to "WebAPIs.MediaStreamImageCapture"
37+
End_Procedure
38+
39+
Procedure End_Construct_Object
40+
Forward Send End_Construct_Object
41+
42+
WebPublishProcedure OnConnectProxy
43+
WebPublishProcedure OnDisconnect
44+
WebPublishProcedure OnError
45+
WebPublishProcedure OnPhotoProxy
46+
End_Procedure
47+
48+
{ Visibility=Private }
49+
Function SerializeObject Returns tWebObjectDef
50+
Handle hoStream
51+
String sMediaStreamName
52+
tWebObjectDef tResult
53+
54+
If (Child_Count(Self) = 2) Begin
55+
Get ChildByIndex 1 to hoStream
56+
If (IsObjectOfClass(hoStream, RefClass(cMediaStream))) Begin
57+
Get WebObjectName of hoStream to sMediaStreamName
58+
Set psMediaStream to sMediaStreamName
59+
End
60+
End
61+
62+
Forward Get SerializeObject to tResult
63+
64+
Function_Return tResult
65+
End_Function
66+
67+
// Connect to the media stream to prepare for image capture
68+
// If you pass the id of a <video> element, the stream will start playing on that element
69+
Procedure Connect String sOptionalElementId
70+
String[] aParams
71+
If (num_arguments > 0) Begin
72+
Move sOptionalElementId to aParams[0]
73+
End
74+
Send ClientAction "connect" aParams
75+
End_Procedure
76+
77+
// Capture an image from the media stream, triggering OnPhoto with the result
78+
Procedure TakePhoto
79+
Send ClientAction "takePhoto"
80+
End_Procedure
81+
82+
// Disconnect from the media stream and release any media device resources held
83+
Procedure Disconnect
84+
Send ClientAction "disconnect"
85+
End_Procedure
86+
87+
{ Visibility=Private }
88+
Procedure OnConnectProxy
89+
Handle hoJson
90+
tMediaStreamTrackInfo stInfo
91+
92+
Get phoActionJsonData to hoJson
93+
If (hoJson <> C_WebUnresolvedObject) Begin
94+
If (IsOfJsonType(hoJson, jsonTypeObject)) Begin
95+
Set pbRequireAllMembers of hoJson to False
96+
Get JsonToDataType of hoJson to stInfo
97+
Send OnConnect stInfo
98+
End
99+
End
100+
End_Procedure
101+
102+
{ MethodType=Event }
103+
Procedure OnConnect tMediaStreamTrackInfo stInfo
104+
End_Procedure
105+
106+
{ MethodType=Event }
107+
Procedure OnDisconnect
108+
End_Procedure
109+
110+
{ MethodType=Event }
111+
Procedure OnError String sErrorName String sErrorMessage
112+
End_Procedure
113+
114+
{ Visibility=Private }
115+
Procedure OnPhotoProxy String sDataURL Integer iWidth Integer iHeight
116+
Integer iPos
117+
String sMimeType
118+
UChar[] ucBase64 ucBinary
119+
120+
Move (Pos(";base64,", sDataURL, 1, 100)) to iPos
121+
Move (Mid(sDataURL, iPos - 6, 6)) to sMimeType
122+
Move (StringToUCharArray(Mid(sDataURL, Length(sDataURL), iPos + 8))) to ucBase64
123+
Get Base64DecodeUCharArray of oCharTranslate ucBase64 to ucBinary
124+
125+
Send OnPhoto sMimeType ucBinary sDataURL iWidth iHeight
126+
End_Procedure
127+
128+
{ MethodType=Event }
129+
Procedure OnPhoto String sMimeType UChar[] ucData String sDataURL Integer iWidth Integer iHeight
130+
// Note that the client-side version of this event receives a single Blob argument instead
131+
// iWidth and iHeight will be 0 unless pbWithDimension is True (will reduce performance)
132+
End_Procedure
133+
134+
End_Class

0 commit comments

Comments
 (0)