Skip to content

Commit 31b7d27

Browse files
committed
feat: MediaStream Image Capture API (#32)
Capabilities and settings
1 parent 91b761c commit 31b7d27

11 files changed

Lines changed: 586 additions & 88 deletions

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,4 @@ WebApp.log
4141
AppHtml/Custom/
4242
dist/
4343
/.idea/
44+
/Programs/temp/

AppSrc/MediaStreamImageCaptureDemo.wo

Lines changed: 330 additions & 65 deletions
Large diffs are not rendered by default.

AppSrc/MediaStreamRecordingDemo.wo

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1021,7 +1021,7 @@ Object oMediaStreamRecordingDemo is a cWebView
10211021

10221022
Procedure OnShow
10231023
Boolean bIsSupported
1024-
String sPermMic sPermCam
1024+
String sPermMic sPermCam sPermPanTiltZoom
10251025

10261026
Forward Send OnShow
10271027

@@ -1034,6 +1034,8 @@ Object oMediaStreamRecordingDemo is a cWebView
10341034
Send Log of oLogger (SFormat("Microphone permission is '%1'", sPermMic))
10351035
WebGet psCameraPermission of oUserMediaStream to sPermCam
10361036
Send Log of oLogger (SFormat("Camera permission is '%1'", sPermCam))
1037+
WebGet psPanTiltZoomPermission of oUserMediaStream to sPermPanTiltZoom
1038+
Send Log of oLogger (SFormat("Camera pan/tilt/zoom permission is '%1'", sPermPanTiltZoom))
10371039

10381040
If ((sPermMic = "granted") and (sPermCam = "granted")) Begin
10391041
WebSet pbEnabled of oBtnRequestPermission to False

AppSrc/WebApp.src

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,22 @@ Object oWebApp is a cWebApp
306306
Use BatteryStatusDemo.wo
307307
Use MediaStreamImageCaptureDemo.wo
308308
Set phoDefaultView to oDashboard
309+
310+
Procedure End_Construct_Object
311+
String sPath sLine
312+
Boolean bTempExists
313+
314+
Forward Send End_Construct_Object
315+
316+
Get GetApplicationPath of ghoApplication to sPath
317+
Move (sPath + "\temp") to sPath
318+
File_Exist sPath bTempExists
319+
If (not(bTempExists)) Begin
320+
Make_Directory sPath
321+
End
322+
Send RegisterDownloadFolder of ghoWebResourceManager sPath
323+
Set_Directory sPath
324+
End_Procedure
309325

310326
End_Object
311327

AppSrc/cMediaStreamAPI.pkg

Lines changed: 90 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,32 +3,105 @@
33
Define MS_KIND_VIDEO for "videoinput"
44
Define MS_KIND_AUDIO for "audioinput"
55

6+
Define MS_MODE_NONE for "none"
7+
Define MS_MODE_MANUAL for "manual"
8+
Define MS_MODE_SINGLE_SHOT for "single-shot"
9+
Define MS_MODE_CONTINUOUS for "continuous"
10+
11+
Define MS_RESIZE_MODE_NONE for "none"
12+
Define MS_RESIZE_MODE_CROP_AND_SCALE for "crop-and-scale"
13+
614
Struct tInputDeviceInfo
715
String deviceId
816
String groupId
9-
String kind // MS_KIND_VIDEO or MS_KIND_AUDIO
17+
String kind // MS_KIND_*
1018
String label
1119
End_Struct
1220

21+
Struct tMediaSettingsRange
22+
Number min
23+
Number max
24+
Number step
25+
End_Struct
26+
27+
Struct tMediaTrackCapabilities
28+
String deviceId
29+
String groupId
30+
31+
// Audio
32+
Boolean[] autoGainControl
33+
tMediaSettingsRange channelCount
34+
Boolean[] echoCancellation
35+
tMediaSettingsRange latency
36+
Boolean[] noiseSuppression
37+
tMediaSettingsRange sampleRate
38+
tMediaSettingsRange sampleSize
39+
Boolean[] voiceIsolation
40+
41+
// Video
42+
tMediaSettingsRange aspectRatio
43+
tMediaSettingsRange brightness
44+
tMediaSettingsRange colorTemperature
45+
tMediaSettingsRange contrast
46+
tMediaSettingsRange exposureCompensation
47+
String[] exposureMode // MS_MODE_*
48+
tMediaSettingsRange exposureTime
49+
String[] facingMode
50+
tMediaSettingsRange focusDistance
51+
String[] focusMode // MS_MODE_*
52+
tMediaSettingsRange frameRate
53+
tMediaSettingsRange height
54+
tMediaSettingsRange iso
55+
tMediaSettingsRange pan
56+
String[] resizeMode // MS_RESIZE_MODE_*
57+
tMediaSettingsRange saturation
58+
tMediaSettingsRange sharpness
59+
tMediaSettingsRange tilt
60+
Boolean torch
61+
String[] whiteBalanceMode // MS_MODE_*
62+
tMediaSettingsRange width
63+
tMediaSettingsRange zoom
64+
End_Struct
65+
1366
Struct tMediaTrackSettings
1467
String deviceId
1568
String groupId
1669

70+
// Audio
1771
String autoGainControl
1872
String channelCount
1973
String echoCancellation
2074
String latency
2175
String noiseSuppression
2276
String sampleRate
2377
String sampleSize
78+
String voiceIsolation
2479

80+
// Video
2581
String aspectRatio
82+
String brightness
83+
String colorTemperature
84+
String contrast
85+
String exposureCompensation
86+
String exposureMode
87+
String exposureTime
2688
String facingMode
89+
String focusDistance
90+
String focusMode
2791
String frameRate
2892
String height
29-
String width
93+
String iso
94+
String pan
3095
String resizeMode
96+
String saturation
97+
String sharpness
98+
String tilt
99+
String torch
100+
String whiteBalanceMode
101+
String width
102+
String zoom
31103

104+
// Display
32105
String cursor
33106
String displaySurface
34107
String logicalSurface
@@ -37,6 +110,7 @@ End_Struct
37110
Struct tMediaStreamTrackInfo
38111
String kind
39112
String label
113+
tMediaTrackCapabilities capabilities
40114
tMediaTrackSettings settings
41115
End_Struct
42116

@@ -97,6 +171,8 @@ Class cUserMediaStreamAPI is a cMediaStream
97171
Property String psMicrophonePermission ""
98172
{ WebProperty=Client DesignTime=False }
99173
Property String psCameraPermission ""
174+
{ WebProperty=Client DesignTime=False }
175+
Property String psPanTiltZoomPermission ""
100176

101177
// Set to True to include an audio stream
102178
{ WebProperty=Client Category=Audio }
@@ -129,6 +205,9 @@ Class cUserMediaStreamAPI is a cMediaStream
129205
// Set to True to include a video stream
130206
{ WebProperty=Client Category=Video }
131207
Property Boolean pbVideo False
208+
// Set to True to enable pan/tilt/zoom features if available (will ask for extended permissions)
209+
{ WebProperty=Client Category=Video }
210+
Property Boolean pbWithPanTiltZoom False
132211
// Set to a deviceId from OnEnumerateDevices to request a specific device
133212
{ WebProperty=Client Category=Video }
134213
Property String psVideoDeviceId ""
@@ -160,6 +239,10 @@ Class cUserMediaStreamAPI is a cMediaStream
160239
{ WebProperty=Client Category="Client events" }
161240
Property String psClientOnCameraPermissionChange ""
162241
{ WebProperty=Client Category="Server events" }
242+
Property Boolean pbServerOnPanTiltZoomPermissionChange False
243+
{ WebProperty=Client Category="Client events" }
244+
Property String psClientOnPanTiltZoomPermissionChange ""
245+
{ WebProperty=Client Category="Server events" }
163246
Property Boolean pbServerOnEnumerateDevices False
164247
{ WebProperty=Client Category="Client events" }
165248
Property String psClientOnEnumerateDevices ""
@@ -172,6 +255,7 @@ Class cUserMediaStreamAPI is a cMediaStream
172255

173256
WebPublishProcedure OnMicrophonePermissionChange
174257
WebPublishProcedure OnCameraPermissionChange
258+
WebPublishProcedure OnPanTiltZoomPermissionChange
175259
WebPublishProcedure OnEnumerateDevicesProxy
176260
End_Procedure
177261

@@ -202,6 +286,10 @@ Class cUserMediaStreamAPI is a cMediaStream
202286
Procedure OnCameraPermissionChange
203287
End_Procedure
204288

289+
{ MethodType=Event }
290+
Procedure OnPanTiltZoomPermissionChange
291+
End_Procedure
292+
205293
{ MethodType=Event }
206294
Procedure OnEnumerateDevices tInputDeviceInfo[] stDevices
207295
End_Procedure

AppSrc/cMediaStreamImageCaptureAPI.pkg

Lines changed: 67 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,32 @@
11
Use cWebObject.pkg
22
Use cMediaStreamAPI.pkg
33

4+
Struct tMediaStreamPhotoCapabilities
5+
String[] fillLightMode // Zero or more of "auto", "off", "flash"
6+
tMediaSettingsRange imageHeight
7+
tMediaSettingsRange imageWidth
8+
String redEyeReduction // "never", "always" or "controllable"
9+
End_Struct
10+
11+
Struct tMediaStreamPhotoSettings
12+
String fillLightMode // numerous bugs concerning this, do not expect it to work
13+
Integer imageHeight
14+
Integer imageWidth
15+
Boolean redEyeReduction
16+
End_Struct
17+
18+
Struct tMediaStreamImageCaptureInfo
19+
tMediaStreamPhotoCapabilities capabilities
20+
tMediaStreamPhotoSettings settings
21+
tMediaStreamTrackInfo track
22+
End_Struct
23+
24+
Enum_List
25+
Define MSIC_FILL_LIGHT_MODE_AUTO
26+
Define MSIC_FILL_LIGHT_MODE_OFF
27+
Define MSIC_FILL_LIGHT_MODE_FLASH
28+
End_Enum_List
29+
430
Class cMediaStreamImageCaptureAPI is a cWebObject
531

632
Procedure Construct_Object
@@ -10,7 +36,8 @@ Class cMediaStreamImageCaptureAPI is a cWebObject
1036
Property Boolean pbIsSupported False
1137
{ WebProperty=Client Visibility=Private }
1238
Property String psMediaStream
13-
{ WebProperty=Client Description="Set to True to include width and height in OnPhoto event" }
39+
// Set to True to include width and height in OnPhoto event
40+
{ WebProperty=Client }
1441
Property Boolean pbWithDimension False
1542

1643
{ WebProperty=Client Category="Server events" }
@@ -47,17 +74,22 @@ Class cMediaStreamImageCaptureAPI is a cWebObject
4774

4875
{ Visibility=Private }
4976
Function SerializeObject Returns tWebObjectDef
50-
Handle hoStream
77+
Integer iCount i
78+
Handle hoChild
5179
String sMediaStreamName
80+
Boolean bFound
5281
tWebObjectDef tResult
5382

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
83+
Get Child_Count to iCount
84+
For i from 0 to (iCount - 1)
85+
Get ChildByIndex i to hoChild
86+
If (IsObjectOfClass(hoChild, RefClass(cMediaStream))) Begin
87+
Get WebObjectName of hoChild to sMediaStreamName
5888
Set psMediaStream to sMediaStreamName
89+
Move True to bFound
5990
End
60-
End
91+
If (bFound) Break
92+
Loop
6193

6294
Forward Get SerializeObject to tResult
6395

@@ -74,9 +106,33 @@ Class cMediaStreamImageCaptureAPI is a cWebObject
74106
Send ClientAction "connect" aParams
75107
End_Procedure
76108

109+
// Change a setting on a video stream
110+
// sName should be the name of a property from the Video section of tMediaTrackSettings
111+
// Valid settings will be reported under stInfo.track.capabilities in OnConnect event
112+
Procedure ApplyConstraint String sName String sValue
113+
String[] aParams
114+
Move sName to aParams[0]
115+
Move sValue to aParams[1]
116+
Send ClientAction "applyConstraint" aParams
117+
End_Procedure
118+
77119
// Capture an image from the media stream, triggering OnPhoto with the result
78-
Procedure TakePhoto
79-
Send ClientAction "takePhoto"
120+
// All arguments are optional
121+
Procedure TakePhoto Integer eFillLightMode Integer iImageHeight Integer iImageWidth Boolean bRedEyeReduction
122+
String[] aParams
123+
If (num_arguments > 0) Begin
124+
Move eFillLightMode to aParams[0]
125+
End
126+
If (num_arguments > 1) Begin
127+
Move iImageHeight to aParams[1]
128+
End
129+
If (num_arguments > 2) Begin
130+
Move iImageWidth to aParams[2]
131+
End
132+
If (num_arguments > 3) Begin
133+
Move bRedEyeReduction to aParams[3]
134+
End
135+
Send ClientAction "takePhoto" aParams
80136
End_Procedure
81137

82138
// Disconnect from the media stream and release any media device resources held
@@ -87,7 +143,7 @@ Class cMediaStreamImageCaptureAPI is a cWebObject
87143
{ Visibility=Private }
88144
Procedure OnConnectProxy
89145
Handle hoJson
90-
tMediaStreamTrackInfo stInfo
146+
tMediaStreamImageCaptureInfo stInfo
91147

92148
Get phoActionJsonData to hoJson
93149
If (hoJson <> C_WebUnresolvedObject) Begin
@@ -100,7 +156,7 @@ Class cMediaStreamImageCaptureAPI is a cWebObject
100156
End_Procedure
101157

102158
{ MethodType=Event }
103-
Procedure OnConnect tMediaStreamTrackInfo stInfo
159+
Procedure OnConnect tMediaStreamImageCaptureInfo stInfo
104160
End_Procedure
105161

106162
{ MethodType=Event }

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
"scripts": {
1616
"watch": "webpack --watch --config webpack.dev.js",
1717
"build": "webpack --config webpack.prod.js",
18-
"dist": "rimraf dist && copyfiles -f \"%ProgramFiles%/DataFlex 24.0/Lib/WebAppMaster/Data/[Ww]eb[Aa]pp[Ss]erver[Pp]rops.*\" Data && npm run build && 7z a dist/WebAPIsDemo.zip * -r -x!.git -x!.github -x!.vscode -x!CssThemes -x!DfEngine -x!*.dep -x!*.prn -x!IdeSrc/* -x!node_modules -x!*.dbg -x!*.exe -x!*.log && 7z a dist/WebAPIsComponents.zip AppHtml/Custom/* AppSrc/*API.pkg LICENSE.txt"
18+
"dist": "rimraf dist && copyfiles -f \"%ProgramFiles%/DataFlex 24.0/Lib/WebAppMaster/Data/[Ww]eb[Aa]pp[Ss]erver[Pp]rops.*\" Data && npm run build && 7z a dist/WebAPIsDemo.zip * -r -x!.git -x!.github -x!.vscode -x!CssThemes -x!DfEngine -x!*.dep -x!*.prn -x!IdeSrc/* -x!node_modules -x!temp -x!*.dbg -x!*.exe -x!*.log && 7z a dist/WebAPIsComponents.zip AppHtml/Custom/* AppSrc/*API.pkg LICENSE.txt"
1919
},
2020
"devDependencies": {
2121
"@babel/core": "^7.26.7",

0 commit comments

Comments
 (0)