merge: reject a local track as a recording source
This commit is contained in:
@@ -18,6 +18,23 @@ import '../servicios/servicio_grabacion_radio.dart';
|
||||
/// `EstadoRadio` consumers (S4-R5). Playback orchestration (stop recording on
|
||||
/// pause/stop/station switch) stays in `EstadoRadio`, which keeps a reference
|
||||
/// to this notifier.
|
||||
/// Whether [emisora] is something the recorder can actually capture: a live
|
||||
/// network stream.
|
||||
///
|
||||
/// The recorder opens the URL as an HTTP stream and writes the bytes to disk,
|
||||
/// so anything else fails inside the HTTP client with a message no user can
|
||||
/// act on ("Unsupported scheme 'content' in URI content://...").
|
||||
///
|
||||
/// This is not hypothetical tidiness. `PluriWaveAudioHandler._cambiarFuente`
|
||||
/// sets `emisoraActual` for EVERY source it plays, so a local MP3 shows up
|
||||
/// here as an `Emisora` whose `url` is the `content://` document URI it was
|
||||
/// opened from. Recording a local file makes no sense anyway — it is already
|
||||
/// on the device.
|
||||
bool esEmisoraGrabable(Emisora emisora) {
|
||||
final esquema = Uri.tryParse(emisora.url)?.scheme.toLowerCase();
|
||||
return esquema == 'http' || esquema == 'https';
|
||||
}
|
||||
|
||||
class EstadoGrabacion extends ChangeNotifier {
|
||||
EstadoGrabacion({
|
||||
ServicioGrabacionRadio? servicio,
|
||||
@@ -72,7 +89,13 @@ class EstadoGrabacion extends ChangeNotifier {
|
||||
|
||||
Future<void> iniciar({Duration? duracion}) async {
|
||||
final actual = _emisoraActual();
|
||||
if (actual == null) {
|
||||
// `emisoraActual` is set by `_cambiarFuente` for EVERY source, local
|
||||
// tracks included -- a local file becomes an `Emisora` whose `url` is the
|
||||
// SAF `content://` URI it was opened from. Handing that to the recorder
|
||||
// produced "Unsupported scheme 'content' in URI content://..." on screen,
|
||||
// and it started happening only once local music playback existed: before
|
||||
// that, whatever was playing was always a real station.
|
||||
if (actual == null || !esEmisoraGrabable(actual)) {
|
||||
_alError?.call(_textos.recordingSelectStationFirst);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:pluriwave/estado/estado_grabacion.dart';
|
||||
import 'package:pluriwave/modelos/emisora.dart';
|
||||
|
||||
/// Reported: recording a station stopped working, with this on screen —
|
||||
///
|
||||
/// No se pudo iniciar la grabación: Invalid argument(s): Unsupported scheme
|
||||
/// 'content' in URI content://com.android.externalstorage.documents/tree/
|
||||
/// primary%3AMusic/document/primary%3AMusic%2F...%2FNew Limit - Smile.mp3
|
||||
///
|
||||
/// The URI in the message is a LOCAL MP3, not a station.
|
||||
/// `PluriWaveAudioHandler._cambiarFuente` sets `emisoraActual` for every
|
||||
/// source it plays, so a local track becomes an `Emisora` whose `url` is the
|
||||
/// SAF `content://` document URI it was opened from. The recorder then tried
|
||||
/// to open that as an HTTP stream.
|
||||
///
|
||||
/// "It used to work" is accurate: before local music playback existed,
|
||||
/// whatever was playing was always a real station, so this could not happen.
|
||||
void main() {
|
||||
Emisora conUrl(String url) => Emisora(uuid: 'u', nombre: 'n', url: url);
|
||||
|
||||
test('un stream de red es grabable', () {
|
||||
expect(esEmisoraGrabable(conUrl('http://stream.example.com/live')), isTrue);
|
||||
expect(
|
||||
esEmisoraGrabable(conUrl('https://stream.example.com/live')),
|
||||
isTrue,
|
||||
);
|
||||
expect(
|
||||
esEmisoraGrabable(conUrl('HTTPS://STREAM.EXAMPLE.COM/live')),
|
||||
isTrue,
|
||||
reason: 'el esquema no distingue mayúsculas',
|
||||
);
|
||||
});
|
||||
|
||||
test('la URI content:// de una pista local NO es grabable — el caso '
|
||||
'exacto del reporte', () {
|
||||
expect(
|
||||
esEmisoraGrabable(
|
||||
conUrl(
|
||||
'content://com.android.externalstorage.documents/tree/'
|
||||
'primary%3AMusic/document/primary%3AMusic%2FNew%20Limit%20-%20'
|
||||
'Smile.mp3',
|
||||
),
|
||||
),
|
||||
isFalse,
|
||||
);
|
||||
});
|
||||
|
||||
test('ni un fichero local, ni una url vacía o rota', () {
|
||||
expect(
|
||||
esEmisoraGrabable(conUrl('file:///storage/emulated/0/a.mp3')),
|
||||
isFalse,
|
||||
);
|
||||
expect(esEmisoraGrabable(conUrl('')), isFalse);
|
||||
expect(esEmisoraGrabable(conUrl('no es una uri')), isFalse);
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user