diff --git a/lib/controller/audio_mediakit.dart b/lib/controller/audio_mediakit.dart deleted file mode 100644 index a7f2476..0000000 --- a/lib/controller/audio_mediakit.dart +++ /dev/null @@ -1,7 +0,0 @@ -import 'package:just_audio_media_kit/just_audio_media_kit.dart'; - -class AudioInitializer { - void audioInit() { - JustAudioMediaKit.ensureInitialized(); - } -} diff --git a/lib/controller/audio_none.dart b/lib/controller/audio_none.dart deleted file mode 100644 index 6c6f840..0000000 --- a/lib/controller/audio_none.dart +++ /dev/null @@ -1,3 +0,0 @@ -class AudioInitializer { - void audioInit() {} -} diff --git a/lib/controller/audio_web.dart b/lib/controller/audio_web.dart deleted file mode 100644 index 6c6f840..0000000 --- a/lib/controller/audio_web.dart +++ /dev/null @@ -1,3 +0,0 @@ -class AudioInitializer { - void audioInit() {} -} diff --git a/lib/controller/play.dart b/lib/controller/play.dart deleted file mode 100644 index cd1c606..0000000 --- a/lib/controller/play.dart +++ /dev/null @@ -1,84 +0,0 @@ -import 'package:flutter/services.dart'; -import 'package:just_audio/just_audio.dart' as justaudio; -import 'audio_none.dart' - if (dart.library.io) 'audio_mediakit.dart' - if (dart.library.html) 'audio_web.dart'; -//import 'package:audioplayers/audioplayers.dart' as auplay; -//import 'dart:io' show Platform; - -import '../pb/stillbox.pb.dart'; - -abstract class AudioDriver { - Future play(Call call); - Stream get playerStateStream; -} - -class Player { - late AudioDriver driver; - Player() { -// if (Platform.isMacOS || Platform.isIOS) { - driver = JustAudioDriver(); -// } else { -// driver = AudioPlayersDriver(); -// } - } - - Future play(Call call) { - return driver.play(call); - } - // TODO make a queue -} - -/* -class AudioPlayersDriver implements AudioDriver { - final player = auplay.AudioPlayer(); - - @override - Future play(Call call) { - return player.play(auplay.BytesSource(Uint8List.fromList(call.audio))); - } -} -*/ - -class JustAudioDriver implements AudioDriver { - final player = justaudio.AudioPlayer(); - final initializer = AudioInitializer(); - - JustAudioDriver() { - initializer.audioInit(); - } - - @override - Stream get playerStateStream { - return player.playerStateStream; - } - - @override - Future play(Call call) async { - player.setAudioSource(CallBytesSource(call)); - return player.play(); - } -} - -class CallBytesSource extends justaudio.StreamAudioSource { - late Uint8List _buffer; - final Call _call; - - factory CallBytesSource(Call call) { - return CallBytesSource._(call, Uint8List.fromList(call.audio)); - } - - CallBytesSource._(this._call, this._buffer) : super(tag: 'CallBytesSource'); - - @override - Future request([int? start, int? end]) async { - // Returning the stream audio response with the parameters - return justaudio.StreamAudioResponse( - sourceLength: _buffer.length, - contentLength: (end ?? _buffer.length) - (start ?? 0), - offset: start ?? 0, - stream: Stream.fromIterable([_buffer.sublist(start ?? 0, end)]), - contentType: _call.audioType, - ); - } -} diff --git a/lib/controller/stillbox.dart b/lib/controller/stillbox.dart index cb05962..612e5b2 100644 --- a/lib/controller/stillbox.dart +++ b/lib/controller/stillbox.dart @@ -1,8 +1,7 @@ +import 'dart:async'; import 'package:flutter/foundation.dart'; import 'package:http/http.dart' as http; -import 'package:just_audio/just_audio.dart'; import '../pb/stillbox.pb.dart'; -import 'play.dart'; import 'stillbox_none.dart' if (dart.library.io) 'stillbox_io.dart' if (dart.library.html) 'stillbox_web.dart'; @@ -13,7 +12,6 @@ class BadAuthException implements Exception {} class Stillbox extends ChangeNotifier { final storage = Storer(); - Player player = Player(); final channel = Socketer(); late TalkgroupCache tgCache; bool connected = false; @@ -22,6 +20,8 @@ class Stillbox extends ChangeNotifier { Filter? currentFilter; SBCall? _currentCall; Uri? baseUri = Uri.base; + final StreamController callStream = + StreamController.broadcast(); set state(LiveState newState) { channel.sink.add(Live(state: newState, filter: currentFilter)); @@ -34,22 +34,9 @@ class Stillbox extends ChangeNotifier { } SBCall? get currentCall => _currentCall; - set currentCall(SBCall? call) { - _currentCall = call; - if (_currentCall != null) { - player.play(_currentCall!.call); - } - notifyListeners(); - } Stillbox() { setUris(); - player.driver.playerStateStream.listen((event) async { - if ((!event.playing && _currentCall != null) && - event.processingState == ProcessingState.completed) { - currentCall = null; - } - }); } void setUris() { @@ -83,7 +70,6 @@ class Stillbox extends ChangeNotifier { ); if (response.statusCode == 200) { String? token = channel.updateCookie(response); - print('token is $token'); storage.setKey('baseURL', uri); if (!kIsWeb && token != null) { storage.setKey('token', token); @@ -127,8 +113,8 @@ class Stillbox extends ChangeNotifier { final msg = Message.fromBuffer(event); switch (msg.whichToClientMessage()) { case Message_ToClientMessage.call: - currentCall = SBCall( - msg.call, tgCache.getTg(msg.call.system, msg.call.talkgroup)); + callStream.add(SBCall( + msg.call, tgCache.getTg(msg.call.system, msg.call.talkgroup))); case Message_ToClientMessage.notification: case Message_ToClientMessage.popup: case Message_ToClientMessage.error: diff --git a/lib/views/lcd.dart b/lib/views/lcd.dart index b32f1cf..0767536 100644 --- a/lib/views/lcd.dart +++ b/lib/views/lcd.dart @@ -3,17 +3,10 @@ import 'package:flutter/material.dart'; import '../controller/stillbox.dart'; import '../pb/stillbox.pb.dart'; -class LCD extends StatefulWidget { - const LCD({super.key}); - - @override - State createState() => _LCDState(); -} - -class _LCDState extends State { - static const _lcdOnColor = Colors.amber; - static const _lcdOffColor = Color.fromARGB(255, 255, 219, 110); - Color _lcdColor = _lcdOffColor; +class LCD extends StatelessWidget { + final Color _lcdColor; + final SBCall? _call; + const LCD(this._call, this._lcdColor, {super.key}); @override Widget build(BuildContext context) { @@ -45,48 +38,38 @@ class _LCDState extends State { )); } - void lcdOn() { - setState(() { - _lcdColor = _lcdOnColor; - }); - } - - void lcdOff() { - setState(() { - _lcdColor = _lcdOffColor; - }); - } - Widget lcdContents() { - return Consumer(builder: (context, sb, child) { - if (sb.currentCall != null) { - lcdOn(); - return FutureBuilder( - future: sb.currentCall?.tg, - builder: (BuildContext context, AsyncSnapshot tgi) { - return Text( - '${tgi.data?.name ?? sb.currentCall!.call.talkgroup}${tgi.data?.learned ?? false ? ' 📓' : ''}'); - }); - } - - return const Text(''); - }); + return FutureBuilder( + future: _call?.tg, + builder: (BuildContext context, AsyncSnapshot tgi) { + return Text( + '${tgi.data?.name ?? (_call?.call.talkgroup ?? '')}${tgi.data?.learned ?? false ? ' 📓' : ''}'); + }); } } -class ScannerLabel extends StatefulWidget { - const ScannerLabel({super.key}); +class LED extends StatelessWidget { + final Color _ledColor; + + LED(this._ledColor); @override - State createState() => _ScannerLabelState(); + Widget build(BuildContext context) { + return Container( + width: 20.0, + height: 20.0, + decoration: BoxDecoration( + color: _ledColor, + shape: BoxShape.circle, + ), + ); + } } -class _ScannerLabelState extends State { - String _label = "Stillbox"; +class ScannerLabel extends StatelessWidget { + final String _label; - void setLabel(String s) { - _label = s; - } + const ScannerLabel(this._label, {super.key}); @override Widget build(BuildContext context) { diff --git a/lib/views/radio.dart b/lib/views/radio.dart index 070dcbb..be9cabc 100644 --- a/lib/views/radio.dart +++ b/lib/views/radio.dart @@ -1,6 +1,11 @@ +import 'dart:async'; import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:just_audio/just_audio.dart'; import '../../views/lcd.dart'; import '../../views/keypad.dart'; +import '../controller/stillbox.dart'; +import 'play.dart'; class MainRadio extends StatefulWidget { const MainRadio({super.key, required this.title}); @@ -12,9 +17,64 @@ class MainRadio extends StatefulWidget { } class _MainRadioState extends State { + Player player = Player(); + bool lcdState = false; + static const _lcdTimeout = 3; + static const _lcdOnColor = Colors.amber; + static const _lcdOffColor = Color.fromARGB(255, 255, 219, 110); + Color _lcdColor = _lcdOffColor; + Color _ledColor = Colors.black; + Timer? _lcdTimer; + SBCall? _call; + + @override + void initState() { + super.initState(); + final sb = Provider.of(context, listen: false); + player.driver.playerStateStream.listen((event) async { + if (!event.playing && + event.processingState == ProcessingState.completed) { + setState(() { + _ledColor = Colors.black; + }); + } + }); + sb.callStream.stream.listen((call) async { + lcdOn(); + setState(() { + _call = call; + }); + await player.play(call.call); + lcdOff(); + }); + } + + void lcdOn() { + if (_lcdTimer != null) { + _lcdTimer!.cancel(); + _lcdTimer = null; + } + setState(() { + _ledColor = Colors.purple; + _lcdColor = _lcdOnColor; + }); + } + + void lcdOff() { + if (_lcdTimer != null) { + _lcdTimer!.cancel(); + } + _lcdTimer = Timer(const Duration(seconds: _lcdTimeout), () { + setState(() { + _lcdColor = _lcdOffColor; + }); + _lcdTimer = null; + }); + } + @override Widget build(BuildContext context) { - return const SafeArea( + return SafeArea( child: Scaffold( body: Center( child: SizedBox( @@ -22,12 +82,23 @@ class _MainRadioState extends State { child: Column( mainAxisAlignment: MainAxisAlignment.start, children: [ - ScannerLabel(), - LCD(), - Keypad(), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + const ScannerLabel('Stillbox'), + LED(_ledColor), + ]), + LCD(_call, _lcdColor), + const Keypad(), ], )), ), )); } + + Widget lcdContents() { + return Consumer(builder: (context, sb, child) { + return Container(); + }); + } }