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: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<SBCall> callStream =
StreamController<SBCall>.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:

View file

@ -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<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;
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<LCD> {
));
}
void lcdOn() {
setState(() {
_lcdColor = _lcdOnColor;
});
}
void lcdOff() {
setState(() {
_lcdColor = _lcdOffColor;
});
}
Widget lcdContents() {
return Consumer<Stillbox>(builder: (context, sb, child) {
if (sb.currentCall != null) {
lcdOn();
return FutureBuilder(
future: sb.currentCall?.tg,
builder: (BuildContext context, AsyncSnapshot<TalkgroupInfo> 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<TalkgroupInfo> 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<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> {
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) {

View file

@ -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<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
Widget build(BuildContext context) {
return const SafeArea(
return SafeArea(
child: Scaffold(
body: Center(
child: SizedBox(
@ -22,12 +82,23 @@ class _MainRadioState extends State<MainRadio> {
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
ScannerLabel(),
LCD(),
Keypad(),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
const ScannerLabel('Stillbox'),
LED(_ledColor),
]),
LCD(_call, _lcdColor),
const Keypad(),
],
)),
),
));
}
Widget lcdContents() {
return Consumer<Stillbox>(builder: (context, sb, child) {
return Container();
});
}
}