Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit fa20afe

Browse files
chore: more changes.
1 parent 1db68ab commit fa20afe

File tree

6 files changed

+261
-120
lines changed

6 files changed

+261
-120
lines changed

‎example/lib/main.dart‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import 'package:flutter_webrtc/flutter_webrtc.dart';
66
import 'route_item.dart';
77
import 'pages/publish_sample.dart';
88
import 'pages/subscribe_sample.dart';
9-
import 'pages/qr_scanner.dart';
109

1110
void main() {
1211
if (!WebRTC.platformIsWeb) {

‎example/lib/pages/publish_sample.dart‎

Lines changed: 111 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import 'package:flutter/foundation.dart';
44
import 'package:flutter/material.dart';
55
import 'package:flutter_webrtc/flutter_webrtc.dart';
66
import 'package:flutter_whip/flutter_whip.dart';
7+
import 'package:shared_preferences/shared_preferences.dart';
78

89
import 'qr_scanner.dart';
910

@@ -17,21 +18,37 @@ class WhipPublishSample extends StatefulWidget {
1718
class _WhipPublishSampleState extends State<WhipPublishSample> {
1819
MediaStream? _localStream;
1920
final _localRenderer = RTCVideoRenderer();
20-
List<MediaDeviceInfo>? _mediaDevicesList;
21+
String stateStr ='init';
2122
bool _connecting = false;
2223
late WHIP _whip;
23-
String? url;
24+
25+
TextEditingController _serverController = TextEditingController();
26+
late SharedPreferences _preferences;
2427

2528
@override
2629
void initState() {
2730
super.initState();
2831
initRenderers();
32+
_loadSettings();
33+
}
34+
35+
void _loadSettings() async {
36+
_preferences = await SharedPreferences.getInstance();
37+
this.setState(() {
38+
_serverController.text = _preferences.getString('pushserver') ??
39+
'http://localhost:8080/whip/live/stream1';
40+
});
2941
}
3042

3143
@override
3244
void deactivate() {
3345
super.deactivate();
3446
_localRenderer.dispose();
47+
_saveSettings();
48+
}
49+
50+
void _saveSettings() {
51+
_preferences.setString('pushserver', _serverController.text);
3552
}
3653

3754
void initRenderers() async {
@@ -40,17 +57,45 @@ class _WhipPublishSampleState extends State<WhipPublishSample> {
4057

4158
// Platform messages are asynchronous, so we initialize in an async method.
4259
void _connect() async {
43-
if (url == null) {
60+
final url = _serverController.text;
61+
62+
if (url.isEmpty) {
4463
return;
4564
}
4665

47-
_whip = WHIP(url: url!);
66+
_whip = WHIP(url: url);
67+
68+
_whip.onState = (WhipState state) {
69+
setState(() {
70+
switch (state) {
71+
case WhipState.kNew:
72+
stateStr = 'New';
73+
break;
74+
case WhipState.kInitialized:
75+
stateStr = 'Initialized';
76+
break;
77+
case WhipState.kConnecting:
78+
stateStr = 'Connecting';
79+
break;
80+
case WhipState.kConnected:
81+
stateStr = 'Connected';
82+
break;
83+
case WhipState.kDisconnected:
84+
stateStr = 'Closed';
85+
break;
86+
case WhipState.kFailure:
87+
stateStr = 'Failure: \n${_whip.lastError.toString()}';
88+
break;
89+
}
90+
});
91+
};
92+
4893
final mediaConstraints = <String, dynamic>{
4994
'audio': true,
5095
'video': {
5196
'mandatory': {
52-
'minWidth': '640',
53-
'minHeight': '480',
97+
'minWidth': '1280',
98+
'minHeight': '720',
5499
'minFrameRate': '30',
55100
},
56101
'facingMode': 'user',
@@ -60,13 +105,14 @@ class _WhipPublishSampleState extends State<WhipPublishSample> {
60105

61106
try {
62107
var stream = await navigator.mediaDevices.getUserMedia(mediaConstraints);
63-
_mediaDevicesList = await navigator.mediaDevices.enumerateDevices();
64108
_localStream = stream;
65109
_localRenderer.srcObject = _localStream;
66110
await _whip.initlize(mode: WhipMode.kSend, stream: _localStream);
67111
await _whip.connect();
68112
} catch (e) {
69-
print(e.toString());
113+
print('connect: error => ' + e.toString());
114+
_localRenderer.srcObject = null;
115+
_localStream?.dispose();
70116
return;
71117
}
72118
if (!mounted) return;
@@ -108,75 +154,79 @@ class _WhipPublishSampleState extends State<WhipPublishSample> {
108154
IconButton(
109155
icon: Icon(Icons.qr_code_scanner_sharp),
110156
onPressed: () async {
111-
Future future = Navigator.of(context).push(
112-
MaterialPageRoute(builder: (context) => QRViewExample()));
113-
114-
future.then((value) {
115-
print('QR code result: $value');
116-
this.setState(() {
117-
url = value;
157+
if (!WebRTC.platformIsDesktop) {
158+
/// only support mobile for now
159+
Future future = Navigator.of(context).push(
160+
MaterialPageRoute(builder: (context) => QRViewExample()));
161+
future.then((value) {
162+
print('QR code result: $value');
163+
this.setState(() {
164+
_serverController.text = value;
165+
});
118166
});
119-
});
167+
}
120168
},
121169
),
122170
if (_connecting)
123171
IconButton(
124172
icon: Icon(Icons.switch_video),
125173
onPressed: _toggleCamera,
126174
),
127-
if (_connecting)
128-
PopupMenuButton<String>(
129-
onSelected: _selectAudioOutput,
130-
itemBuilder: (BuildContext context) {
131-
if (_mediaDevicesList != null) {
132-
return _mediaDevicesList!
133-
.where((device) => device.kind == 'audiooutput')
134-
.map((device) {
135-
return PopupMenuItem<String>(
136-
value: device.deviceId,
137-
child: Text(device.label),
138-
);
139-
}).toList();
140-
}
141-
return [];
142-
},
143-
),
144175
]),
145176
body: OrientationBuilder(
146177
builder: (context, orientation) {
147178
return Column(children: <Widget>[
148-
FittedBox(
149-
child: Text(
150-
'URL: ${url ?? 'Not set, Please scan the QR code ...'}',
151-
textAlign: TextAlign.left,
152-
),
153-
),
154-
Center(
155-
child: Container(
156-
margin: EdgeInsets.fromLTRB(0.0, 0.0, 0.0, 0.0),
157-
width: MediaQuery.of(context).size.width,
158-
height: MediaQuery.of(context).size.height - 110,
159-
decoration: BoxDecoration(color: Colors.black54),
160-
child: RTCVideoView(_localRenderer,
161-
mirror: true,
162-
objectFit:
163-
RTCVideoViewObjectFit.RTCVideoViewObjectFitCover),
179+
Column(children: <Widget>[
180+
FittedBox(
181+
child: Text(
182+
'${stateStr}',
183+
textAlign: TextAlign.left,
184+
),
164185
),
165-
)
186+
if (!_connecting)
187+
Padding(
188+
padding: const EdgeInsets.fromLTRB(10.0, 18.0, 10.0, 0),
189+
child: Align(
190+
child: Text('WHIP URI:'),
191+
alignment: Alignment.centerLeft,
192+
),
193+
),
194+
if (!_connecting)
195+
Padding(
196+
padding: const EdgeInsets.fromLTRB(10.0, 0.0, 10.0, 0),
197+
child: TextFormField(
198+
controller: _serverController,
199+
keyboardType: TextInputType.text,
200+
textAlign: TextAlign.center,
201+
decoration: InputDecoration(
202+
contentPadding: EdgeInsets.all(10.0),
203+
border: UnderlineInputBorder(
204+
borderSide: BorderSide(color: Colors.black12)),
205+
),
206+
),
207+
)
208+
]),
209+
if (_connecting)
210+
Center(
211+
child: Container(
212+
margin: EdgeInsets.fromLTRB(0.0, 0.0, 0.0, 0.0),
213+
width: MediaQuery.of(context).size.width,
214+
height: MediaQuery.of(context).size.height - 110,
215+
decoration: BoxDecoration(color: Colors.black54),
216+
child: RTCVideoView(_localRenderer,
217+
mirror: true,
218+
objectFit:
219+
RTCVideoViewObjectFit.RTCVideoViewObjectFitCover),
220+
),
221+
)
166222
]);
167223
},
168224
),
169-
floatingActionButton: url != null
170-
? FloatingActionButton(
171-
onPressed: _connecting ? _disconnect : _connect,
172-
tooltip: _connecting ? 'Hangup' : 'Call',
173-
child: Icon(_connecting ? Icons.call_end : Icons.phone),
174-
)
175-
: Container(),
225+
floatingActionButton: FloatingActionButton(
226+
onPressed: _connecting ? _disconnect : _connect,
227+
tooltip: _connecting ? 'Hangup' : 'Call',
228+
child: Icon(_connecting ? Icons.call_end : Icons.phone),
229+
),
176230
);
177231
}
178-
179-
void _selectAudioOutput(String deviceId) {
180-
_localRenderer.audioOutput(deviceId);
181-
}
182232
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /