This commit is contained in:
Daniel 2024-08-17 16:51:47 -04:00
parent c7e42d08d0
commit ce3523fbd1
7 changed files with 107 additions and 164 deletions

View file

@ -1,7 +0,0 @@
import 'package:just_audio_media_kit/just_audio_media_kit.dart';
class AudioInitializer {
void audioInit() {
JustAudioMediaKit.ensureInitialized();
}
}

View file

@ -1,3 +0,0 @@
class AudioInitializer {
void audioInit() {}
}

View file

@ -1,3 +0,0 @@
class AudioInitializer {
void audioInit() {}
}

View file

@ -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<void> play(Call call);
Stream<justaudio.PlayerState> get playerStateStream;
}
class Player {
late AudioDriver driver;
Player() {
// if (Platform.isMacOS || Platform.isIOS) {
driver = JustAudioDriver();
// } else {
// driver = AudioPlayersDriver();
// }
}
Future<void> play(Call call) {
return driver.play(call);
}
// TODO make a queue
}
/*
class AudioPlayersDriver implements AudioDriver {
final player = auplay.AudioPlayer();
@override
Future<void> 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<justaudio.PlayerState> get playerStateStream {
return player.playerStateStream;
}
@override
Future<void> 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<justaudio.StreamAudioResponse> 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,
);
}
}

View file

@ -1,8 +1,7 @@
import 'dart:async';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:http/http.dart' as http; import 'package:http/http.dart' as http;
import 'package:just_audio/just_audio.dart';
import '../pb/stillbox.pb.dart'; import '../pb/stillbox.pb.dart';
import 'play.dart';
import 'stillbox_none.dart' import 'stillbox_none.dart'
if (dart.library.io) 'stillbox_io.dart' if (dart.library.io) 'stillbox_io.dart'
if (dart.library.html) 'stillbox_web.dart'; if (dart.library.html) 'stillbox_web.dart';
@ -13,7 +12,6 @@ class BadAuthException implements Exception {}
class Stillbox extends ChangeNotifier { class Stillbox extends ChangeNotifier {
final storage = Storer(); final storage = Storer();
Player player = Player();
final channel = Socketer(); final channel = Socketer();
late TalkgroupCache tgCache; late TalkgroupCache tgCache;
bool connected = false; bool connected = false;
@ -22,6 +20,8 @@ class Stillbox extends ChangeNotifier {
Filter? currentFilter; Filter? currentFilter;
SBCall? _currentCall; SBCall? _currentCall;
Uri? baseUri = Uri.base; Uri? baseUri = Uri.base;
final StreamController<SBCall> callStream =
StreamController<SBCall>.broadcast();
set state(LiveState newState) { set state(LiveState newState) {
channel.sink.add(Live(state: newState, filter: currentFilter)); channel.sink.add(Live(state: newState, filter: currentFilter));
@ -34,22 +34,9 @@ class Stillbox extends ChangeNotifier {
} }
SBCall? get currentCall => _currentCall; SBCall? get currentCall => _currentCall;
set currentCall(SBCall? call) {
_currentCall = call;
if (_currentCall != null) {
player.play(_currentCall!.call);
}
notifyListeners();
}
Stillbox() { Stillbox() {
setUris(); setUris();
player.driver.playerStateStream.listen((event) async {
if ((!event.playing && _currentCall != null) &&
event.processingState == ProcessingState.completed) {
currentCall = null;
}
});
} }
void setUris() { void setUris() {
@ -83,7 +70,6 @@ class Stillbox extends ChangeNotifier {
); );
if (response.statusCode == 200) { if (response.statusCode == 200) {
String? token = channel.updateCookie(response); String? token = channel.updateCookie(response);
print('token is $token');
storage.setKey('baseURL', uri); storage.setKey('baseURL', uri);
if (!kIsWeb && token != null) { if (!kIsWeb && token != null) {
storage.setKey('token', token); storage.setKey('token', token);
@ -127,8 +113,8 @@ class Stillbox extends ChangeNotifier {
final msg = Message.fromBuffer(event); final msg = Message.fromBuffer(event);
switch (msg.whichToClientMessage()) { switch (msg.whichToClientMessage()) {
case Message_ToClientMessage.call: case Message_ToClientMessage.call:
currentCall = SBCall( callStream.add(SBCall(
msg.call, tgCache.getTg(msg.call.system, msg.call.talkgroup)); msg.call, tgCache.getTg(msg.call.system, msg.call.talkgroup)));
case Message_ToClientMessage.notification: case Message_ToClientMessage.notification:
case Message_ToClientMessage.popup: case Message_ToClientMessage.popup:
case Message_ToClientMessage.error: case Message_ToClientMessage.error:

View file

@ -3,17 +3,10 @@ import 'package:flutter/material.dart';
import '../controller/stillbox.dart'; import '../controller/stillbox.dart';
import '../pb/stillbox.pb.dart'; import '../pb/stillbox.pb.dart';
class LCD extends StatefulWidget { class LCD extends StatelessWidget {
const LCD({super.key}); final Color _lcdColor;
final SBCall? _call;
@override const LCD(this._call, this._lcdColor, {super.key});
State<LCD> createState() => _LCDState();
}
class _LCDState extends State<LCD> {
static const _lcdOnColor = Colors.amber;
static const _lcdOffColor = Color.fromARGB(255, 255, 219, 110);
Color _lcdColor = _lcdOffColor;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -45,48 +38,38 @@ class _LCDState extends State<LCD> {
)); ));
} }
void lcdOn() {
setState(() {
_lcdColor = _lcdOnColor;
});
}
void lcdOff() {
setState(() {
_lcdColor = _lcdOffColor;
});
}
Widget lcdContents() { Widget lcdContents() {
return Consumer<Stillbox>(builder: (context, sb, child) {
if (sb.currentCall != null) {
lcdOn();
return FutureBuilder( return FutureBuilder(
future: sb.currentCall?.tg, future: _call?.tg,
builder: (BuildContext context, AsyncSnapshot<TalkgroupInfo> tgi) { builder: (BuildContext context, AsyncSnapshot<TalkgroupInfo> tgi) {
return Text( return Text(
'${tgi.data?.name ?? sb.currentCall!.call.talkgroup}${tgi.data?.learned ?? false ? ' 📓' : ''}'); '${tgi.data?.name ?? (_call?.call.talkgroup ?? '')}${tgi.data?.learned ?? false ? ' 📓' : ''}');
});
}
return const Text('');
}); });
} }
} }
class ScannerLabel extends StatefulWidget { class LED extends StatelessWidget {
const ScannerLabel({super.key}); final Color _ledColor;
LED(this._ledColor);
@override @override
State<ScannerLabel> 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<ScannerLabel> { class ScannerLabel extends StatelessWidget {
String _label = "Stillbox"; final String _label;
void setLabel(String s) { const ScannerLabel(this._label, {super.key});
_label = s;
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {

View file

@ -1,6 +1,11 @@
import 'dart:async';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:just_audio/just_audio.dart';
import '../../views/lcd.dart'; import '../../views/lcd.dart';
import '../../views/keypad.dart'; import '../../views/keypad.dart';
import '../controller/stillbox.dart';
import 'play.dart';
class MainRadio extends StatefulWidget { class MainRadio extends StatefulWidget {
const MainRadio({super.key, required this.title}); const MainRadio({super.key, required this.title});
@ -12,9 +17,64 @@ class MainRadio extends StatefulWidget {
} }
class _MainRadioState extends State<MainRadio> { class _MainRadioState extends State<MainRadio> {
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<Stillbox>(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 @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return const SafeArea( return SafeArea(
child: Scaffold( child: Scaffold(
body: Center( body: Center(
child: SizedBox( child: SizedBox(
@ -22,12 +82,23 @@ class _MainRadioState extends State<MainRadio> {
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[ children: <Widget>[
ScannerLabel(), Row(
LCD(), mainAxisAlignment: MainAxisAlignment.spaceBetween,
Keypad(), children: <Widget>[
const ScannerLabel('Stillbox'),
LED(_ledColor),
]),
LCD(_call, _lcdColor),
const Keypad(),
], ],
)), )),
), ),
)); ));
} }
Widget lcdContents() {
return Consumer<Stillbox>(builder: (context, sb, child) {
return Container();
});
}
} }