Skip to content

Commit fa20afe

Browse files
committed
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)