mirror of
https://github.com/amigan/calls.git
synced 2024-11-21 20:39:47 -05:00
fix
This commit is contained in:
parent
c7e42d08d0
commit
ce3523fbd1
7 changed files with 107 additions and 164 deletions
|
@ -1,7 +0,0 @@
|
||||||
import 'package:just_audio_media_kit/just_audio_media_kit.dart';
|
|
||||||
|
|
||||||
class AudioInitializer {
|
|
||||||
void audioInit() {
|
|
||||||
JustAudioMediaKit.ensureInitialized();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,3 +0,0 @@
|
||||||
class AudioInitializer {
|
|
||||||
void audioInit() {}
|
|
||||||
}
|
|
|
@ -1,3 +0,0 @@
|
||||||
class AudioInitializer {
|
|
||||||
void audioInit() {}
|
|
||||||
}
|
|
|
@ -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,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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:
|
||||||
|
|
|
@ -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) {
|
return FutureBuilder(
|
||||||
if (sb.currentCall != null) {
|
future: _call?.tg,
|
||||||
lcdOn();
|
builder: (BuildContext context, AsyncSnapshot<TalkgroupInfo> tgi) {
|
||||||
return FutureBuilder(
|
return Text(
|
||||||
future: sb.currentCall?.tg,
|
'${tgi.data?.name ?? (_call?.call.talkgroup ?? '')}${tgi.data?.learned ?? false ? ' 📓' : ''}');
|
||||||
builder: (BuildContext context, AsyncSnapshot<TalkgroupInfo> tgi) {
|
});
|
||||||
return Text(
|
|
||||||
'${tgi.data?.name ?? sb.currentCall!.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) {
|
||||||
|
|
|
@ -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();
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue