mirror of
https://github.com/johrpan/musicus_mobile.git
synced 2025-10-26 02:37:25 +01:00
common: Remove platform interface
This commit is contained in:
parent
8987735797
commit
b14dcd67f2
16 changed files with 44 additions and 204 deletions
|
|
@ -1,5 +1,4 @@
|
||||||
export 'src/app.dart';
|
export 'src/app.dart';
|
||||||
export 'src/library.dart';
|
export 'src/library.dart';
|
||||||
export 'src/platform.dart';
|
|
||||||
export 'src/playback.dart';
|
export 'src/playback.dart';
|
||||||
export 'src/settings.dart';
|
export 'src/settings.dart';
|
||||||
|
|
@ -1,12 +1,11 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:file_picker/file_picker.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
|
||||||
|
|
||||||
import 'backend.dart';
|
import 'backend.dart';
|
||||||
import 'screens/home.dart';
|
import 'screens/home.dart';
|
||||||
import 'settings.dart';
|
import 'settings.dart';
|
||||||
import 'platform.dart';
|
|
||||||
import 'playback.dart';
|
import 'playback.dart';
|
||||||
import 'widgets/player_bar.dart';
|
import 'widgets/player_bar.dart';
|
||||||
|
|
||||||
|
|
@ -24,14 +23,10 @@ class MusicusApp extends StatelessWidget {
|
||||||
/// An object handling playback.
|
/// An object handling playback.
|
||||||
final MusicusPlayback playback;
|
final MusicusPlayback playback;
|
||||||
|
|
||||||
/// An object handling platform dependent functionality.
|
|
||||||
final MusicusPlatform platform;
|
|
||||||
|
|
||||||
MusicusApp({
|
MusicusApp({
|
||||||
@required this.dbPath,
|
@required this.dbPath,
|
||||||
@required this.settingsStorage,
|
@required this.settingsStorage,
|
||||||
@required this.playback,
|
@required this.playback,
|
||||||
@required this.platform,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
@ -39,7 +34,6 @@ class MusicusApp extends StatelessWidget {
|
||||||
return MusicusBackend(
|
return MusicusBackend(
|
||||||
settingsStorage: settingsStorage,
|
settingsStorage: settingsStorage,
|
||||||
playback: playback,
|
playback: playback,
|
||||||
platform: platform,
|
|
||||||
child: Builder(
|
child: Builder(
|
||||||
builder: (context) {
|
builder: (context) {
|
||||||
final backend = MusicusBackend.of(context);
|
final backend = MusicusBackend.of(context);
|
||||||
|
|
@ -91,7 +85,7 @@ class MusicusApp extends StatelessWidget {
|
||||||
leading: const Icon(Icons.folder_open),
|
leading: const Icon(Icons.folder_open),
|
||||||
title: Text('Choose path'),
|
title: Text('Choose path'),
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
final uri = await platform.chooseBasePath();
|
final uri = await FilePicker.platform.getDirectoryPath();
|
||||||
if (uri != null) {
|
if (uri != null) {
|
||||||
backend.settings.setMusicLibraryPath(uri);
|
backend.settings.setMusicLibraryPath(uri);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@ import 'package:flutter/widgets.dart';
|
||||||
import 'package:musicus_database/musicus_database.dart';
|
import 'package:musicus_database/musicus_database.dart';
|
||||||
|
|
||||||
import 'library.dart';
|
import 'library.dart';
|
||||||
import 'platform.dart';
|
|
||||||
import 'playback.dart';
|
import 'playback.dart';
|
||||||
import 'settings.dart';
|
import 'settings.dart';
|
||||||
|
|
||||||
|
|
@ -43,9 +42,6 @@ class MusicusBackend extends StatefulWidget {
|
||||||
/// An object handling playback.
|
/// An object handling playback.
|
||||||
final MusicusPlayback playback;
|
final MusicusPlayback playback;
|
||||||
|
|
||||||
/// An object handling platform dependent functionality.
|
|
||||||
final MusicusPlatform platform;
|
|
||||||
|
|
||||||
/// The first child below the backend widget.
|
/// The first child below the backend widget.
|
||||||
///
|
///
|
||||||
/// This widget should keep track of the current backend status and block
|
/// This widget should keep track of the current backend status and block
|
||||||
|
|
@ -56,7 +52,6 @@ class MusicusBackend extends StatefulWidget {
|
||||||
MusicusBackend({
|
MusicusBackend({
|
||||||
@required this.settingsStorage,
|
@required this.settingsStorage,
|
||||||
@required this.playback,
|
@required this.playback,
|
||||||
@required this.platform,
|
|
||||||
@required this.child,
|
@required this.child,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -76,7 +71,6 @@ class MusicusBackendState extends State<MusicusBackend> {
|
||||||
|
|
||||||
MusicusPlayback playback;
|
MusicusPlayback playback;
|
||||||
MusicusSettings settings;
|
MusicusSettings settings;
|
||||||
MusicusPlatform platform;
|
|
||||||
MusicusLibrary library;
|
MusicusLibrary library;
|
||||||
|
|
||||||
MusicusClientDatabase get db => library.db;
|
MusicusClientDatabase get db => library.db;
|
||||||
|
|
@ -90,7 +84,6 @@ class MusicusBackendState extends State<MusicusBackend> {
|
||||||
/// Initialize resources.
|
/// Initialize resources.
|
||||||
Future<void> _load() async {
|
Future<void> _load() async {
|
||||||
playback = widget.playback;
|
playback = widget.playback;
|
||||||
await playback.setup();
|
|
||||||
|
|
||||||
settings = MusicusSettings(widget.settingsStorage);
|
settings = MusicusSettings(widget.settingsStorage);
|
||||||
await settings.load();
|
await settings.load();
|
||||||
|
|
@ -104,9 +97,6 @@ class MusicusBackendState extends State<MusicusBackend> {
|
||||||
|
|
||||||
final path = settings.musicLibraryPath.valueOrNull;
|
final path = settings.musicLibraryPath.valueOrNull;
|
||||||
|
|
||||||
platform = widget.platform;
|
|
||||||
platform.setBasePath(path);
|
|
||||||
|
|
||||||
// This will change the status for us.
|
// This will change the status for us.
|
||||||
_updateMusicLibrary(path);
|
_updateMusicLibrary(path);
|
||||||
}
|
}
|
||||||
|
|
@ -118,9 +108,11 @@ class MusicusBackendState extends State<MusicusBackend> {
|
||||||
status = MusicusBackendStatus.setup;
|
status = MusicusBackendStatus.setup;
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
platform.setBasePath(path);
|
library = MusicusLibrary(path);
|
||||||
library = MusicusLibrary(path, platform);
|
|
||||||
await library.load();
|
await library.load();
|
||||||
|
await playback.setup(library);
|
||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
status = MusicusBackendStatus.ready;
|
status = MusicusBackendStatus.ready;
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,6 @@ import 'package:drift/isolate.dart';
|
||||||
import 'package:drift/native.dart';
|
import 'package:drift/native.dart';
|
||||||
import 'package:musicus_database/musicus_database.dart';
|
import 'package:musicus_database/musicus_database.dart';
|
||||||
|
|
||||||
import 'platform.dart';
|
|
||||||
|
|
||||||
/// Manager for all available tracks and their representation on disk.
|
/// Manager for all available tracks and their representation on disk.
|
||||||
class MusicusLibrary {
|
class MusicusLibrary {
|
||||||
/// Starts the database isolate.
|
/// Starts the database isolate.
|
||||||
|
|
@ -19,6 +17,7 @@ class MusicusLibrary {
|
||||||
static void _dbIsolateEntrypoint(_IsolateStartRequest request) {
|
static void _dbIsolateEntrypoint(_IsolateStartRequest request) {
|
||||||
final executor = NativeDatabase(File(request.path));
|
final executor = NativeDatabase(File(request.path));
|
||||||
|
|
||||||
|
|
||||||
final driftIsolate =
|
final driftIsolate =
|
||||||
DriftIsolate.inCurrent(() => DatabaseConnection.fromExecutor(executor));
|
DriftIsolate.inCurrent(() => DatabaseConnection.fromExecutor(executor));
|
||||||
|
|
||||||
|
|
@ -31,10 +30,7 @@ class MusicusLibrary {
|
||||||
/// The actual music library database.
|
/// The actual music library database.
|
||||||
MusicusClientDatabase db;
|
MusicusClientDatabase db;
|
||||||
|
|
||||||
/// Access to platform dependent functionality.
|
MusicusLibrary(this.basePath);
|
||||||
final MusicusPlatform platform;
|
|
||||||
|
|
||||||
MusicusLibrary(this.basePath, this.platform);
|
|
||||||
|
|
||||||
/// Load all available tracks.
|
/// Load all available tracks.
|
||||||
///
|
///
|
||||||
|
|
|
||||||
|
|
@ -1,82 +0,0 @@
|
||||||
/// Object representing a document in Storage Access Framework terms.
|
|
||||||
class Document {
|
|
||||||
/// Unique ID for the document.
|
|
||||||
///
|
|
||||||
/// The platform implementation thould be able to get the content of the
|
|
||||||
/// document based on this value.
|
|
||||||
final String id;
|
|
||||||
|
|
||||||
/// Name of the document (i.e. file name).
|
|
||||||
final String name;
|
|
||||||
|
|
||||||
/// Document ID of the parent document.
|
|
||||||
final String parent;
|
|
||||||
|
|
||||||
/// Whether this document represents a directory.
|
|
||||||
final bool isDirectory;
|
|
||||||
|
|
||||||
Document({
|
|
||||||
this.id,
|
|
||||||
this.name,
|
|
||||||
this.parent,
|
|
||||||
this.isDirectory,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Use Map<dynamic, dynamic> here, as we get casting errors otherwise. This
|
|
||||||
// won't be typesafe anyway.
|
|
||||||
Document.fromJson(Map<dynamic, dynamic> json)
|
|
||||||
: id = json['id'],
|
|
||||||
name = json['name'],
|
|
||||||
parent = json['parent'],
|
|
||||||
isDirectory = json['isDirectory'];
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Platform dependent code for the Musicus backend.
|
|
||||||
abstract class MusicusPlatform {
|
|
||||||
/// An identifier for the root directory of the music library.
|
|
||||||
///
|
|
||||||
/// This will be the string, that is stored as musicLibraryPath in the
|
|
||||||
/// settings object.
|
|
||||||
String basePath;
|
|
||||||
|
|
||||||
MusicusPlatform();
|
|
||||||
|
|
||||||
/// This will be called, when the music library path was changed.
|
|
||||||
void setBasePath(String path) {
|
|
||||||
basePath = path;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Choose a root level directory for the music library.
|
|
||||||
///
|
|
||||||
/// This should return a string representation of the chosen directory
|
|
||||||
/// suitable for storage as [basePath].
|
|
||||||
Future<String> chooseBasePath();
|
|
||||||
|
|
||||||
/// Get all documents in a directory.
|
|
||||||
///
|
|
||||||
/// [parentId] will be the ID of the directory document. If [parentId] is
|
|
||||||
/// null, the children of the root directory will be returned.
|
|
||||||
Future<List<Document>> getChildren(String parentId);
|
|
||||||
|
|
||||||
/// Read the contents of a document by ID.
|
|
||||||
Future<String> readDocument(String id);
|
|
||||||
|
|
||||||
/// Read from a document by name.
|
|
||||||
///
|
|
||||||
/// [parentId] is the document ID of the parent directory.
|
|
||||||
Future<String> readDocumentByName(String parentId, String fileName);
|
|
||||||
|
|
||||||
/// Get a string identifying a document.
|
|
||||||
///
|
|
||||||
/// [parentId] is the document ID of the parent directory. The return value
|
|
||||||
/// should be a string, that the playback object can use to find and play the
|
|
||||||
/// file. It will be included in [InternalTrack] objects by the music
|
|
||||||
/// library.
|
|
||||||
Future<String> getIdentifier(String parentId, String fileName);
|
|
||||||
|
|
||||||
/// Write to a document by name.
|
|
||||||
///
|
|
||||||
/// [parentId] is the document ID of the parent directory.
|
|
||||||
Future<void> writeDocumentByName(
|
|
||||||
String parentId, String fileName, String contents);
|
|
||||||
}
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import 'package:meta/meta.dart';
|
import 'package:meta/meta.dart';
|
||||||
import 'package:musicus_database/musicus_database.dart';
|
import 'package:musicus_common/musicus_common.dart';
|
||||||
import 'package:rxdart/rxdart.dart';
|
import 'package:rxdart/rxdart.dart';
|
||||||
|
|
||||||
/// Base class for Musicus playback.
|
/// Base class for Musicus playback.
|
||||||
|
|
@ -13,7 +13,7 @@ abstract class MusicusPlayback {
|
||||||
/// The current playlist.
|
/// The current playlist.
|
||||||
///
|
///
|
||||||
/// If the player is not active, this will be an empty list.
|
/// If the player is not active, this will be an empty list.
|
||||||
final playlist = BehaviorSubject.seeded(<Track>[]);
|
final playlist = BehaviorSubject.seeded(<String>[]);
|
||||||
|
|
||||||
/// Index of the currently played (or paused) track within the playlist.
|
/// Index of the currently played (or paused) track within the playlist.
|
||||||
///
|
///
|
||||||
|
|
@ -23,7 +23,7 @@ abstract class MusicusPlayback {
|
||||||
/// The currently played track.
|
/// The currently played track.
|
||||||
///
|
///
|
||||||
/// This will be null, if there is no current track.
|
/// This will be null, if there is no current track.
|
||||||
final currentTrack = BehaviorSubject<Track>.seeded(null);
|
final currentTrack = BehaviorSubject<String>.seeded(null);
|
||||||
|
|
||||||
/// Whether we are currently playing or not.
|
/// Whether we are currently playing or not.
|
||||||
///
|
///
|
||||||
|
|
@ -46,10 +46,10 @@ abstract class MusicusPlayback {
|
||||||
/// Initialize the player.
|
/// Initialize the player.
|
||||||
///
|
///
|
||||||
/// This will be called after the database was initialized.
|
/// This will be called after the database was initialized.
|
||||||
Future<void> setup();
|
Future<void> setup(MusicusLibrary library);
|
||||||
|
|
||||||
/// Add a list of tracks to the players playlist.
|
/// Add a list of tracks to the players playlist.
|
||||||
Future<void> addTracks(List<Track> tracks);
|
Future<void> addTracks(List<String> tracks);
|
||||||
|
|
||||||
/// Remove the track at [index] from the playlist.
|
/// Remove the track at [index] from the playlist.
|
||||||
Future<void> removeTrack(int index);
|
Future<void> removeTrack(int index);
|
||||||
|
|
@ -96,16 +96,15 @@ abstract class MusicusPlayback {
|
||||||
/// Update [position] and [normalizedPosition].
|
/// Update [position] and [normalizedPosition].
|
||||||
///
|
///
|
||||||
/// Requires [duration] to be up to date
|
/// Requires [duration] to be up to date
|
||||||
void updatePosition(int positionMs) {
|
void updatePosition(Duration pos) {
|
||||||
position.add(Duration(milliseconds: positionMs));
|
position.add(pos);
|
||||||
_setNormalizedPosition(positionMs / duration.value.inMilliseconds);
|
_setNormalizedPosition(pos.inMilliseconds / duration.value.inMilliseconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Update [position], [duration] and [normalizedPosition].
|
/// Update [position], [duration] and [normalizedPosition].
|
||||||
void updateDuration(int positionMs, int durationMs) {
|
void updateDuration(Duration dur) {
|
||||||
position.add(Duration(milliseconds: positionMs));
|
duration.add(dur);
|
||||||
duration.add(Duration(milliseconds: durationMs));
|
_setNormalizedPosition(position.value.inMilliseconds / dur.inMilliseconds);
|
||||||
_setNormalizedPosition(positionMs / durationMs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Update [normalizedPosition] ensuring its value is between 0.0 and 1.0.
|
/// Update [normalizedPosition] ensuring its value is between 0.0 and 1.0.
|
||||||
|
|
@ -124,6 +123,9 @@ abstract class MusicusPlayback {
|
||||||
/// Requires [playlist] to be up to date.
|
/// Requires [playlist] to be up to date.
|
||||||
void updateCurrentTrack(int index) {
|
void updateCurrentTrack(int index) {
|
||||||
currentIndex.add(index);
|
currentIndex.add(index);
|
||||||
|
|
||||||
|
if (playlist.value != null && index >= 0 && index < playlist.value.length) {
|
||||||
currentTrack.add(playlist.value[index]);
|
currentTrack.add(playlist.value[index]);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ class _ProgramScreenState extends State<ProgramScreen> {
|
||||||
|
|
||||||
StreamSubscription<bool> playerActiveSubscription;
|
StreamSubscription<bool> playerActiveSubscription;
|
||||||
|
|
||||||
StreamSubscription<List<Track>> playlistSubscription;
|
StreamSubscription<List<String>> playlistSubscription;
|
||||||
List<Widget> widgets = [];
|
List<Widget> widgets = [];
|
||||||
|
|
||||||
StreamSubscription<double> positionSubscription;
|
StreamSubscription<double> positionSubscription;
|
||||||
|
|
@ -63,7 +63,7 @@ class _ProgramScreenState extends State<ProgramScreen> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Go through the tracks of [playlist] and preprocess them for displaying.
|
/// Go through the tracks of [playlist] and preprocess them for displaying.
|
||||||
Future<void> updateProgram(List<Track> playlist) async {
|
Future<void> updateProgram(List<String> playlist) async {
|
||||||
List<Widget> newWidgets = [];
|
List<Widget> newWidgets = [];
|
||||||
|
|
||||||
// The following variables exist to adapt the resulting ProgramItem to its
|
// The following variables exist to adapt the resulting ProgramItem to its
|
||||||
|
|
@ -84,7 +84,7 @@ class _ProgramScreenState extends State<ProgramScreen> {
|
||||||
// The widgets displayed for this track.
|
// The widgets displayed for this track.
|
||||||
List<Widget> children = [];
|
List<Widget> children = [];
|
||||||
|
|
||||||
final track = playlist[i];
|
final track = await backend.db.tracksById(playlist[i]).getSingle();
|
||||||
final recordingId = track.recording;
|
final recordingId = track.recording;
|
||||||
final partIds = track.workParts;
|
final partIds = track.workParts;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,9 @@
|
||||||
|
import 'package:file_picker/file_picker.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
|
||||||
|
|
||||||
import '../backend.dart';
|
import '../backend.dart';
|
||||||
|
|
||||||
class SettingsScreen extends StatelessWidget {
|
class SettingsScreen extends StatelessWidget {
|
||||||
static const _platform = MethodChannel('de.johrpan.musicus/platform');
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final backend = MusicusBackend.of(context);
|
final backend = MusicusBackend.of(context);
|
||||||
|
|
@ -25,7 +23,7 @@ class SettingsScreen extends StatelessWidget {
|
||||||
subtitle: Text(snapshot.data ?? 'Choose folder'),
|
subtitle: Text(snapshot.data ?? 'Choose folder'),
|
||||||
isThreeLine: snapshot.hasData,
|
isThreeLine: snapshot.hasData,
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
final uri = await backend.platform.chooseBasePath();
|
final uri = await FilePicker.platform.getDirectoryPath();
|
||||||
|
|
||||||
if (uri != null) {
|
if (uri != null) {
|
||||||
settings.setMusicLibraryPath(uri);
|
settings.setMusicLibraryPath(uri);
|
||||||
|
|
|
||||||
|
|
@ -32,8 +32,9 @@ class WorkScreen extends StatelessWidget {
|
||||||
performanceInfos: recordingInfo.performances,
|
performanceInfos: recordingInfo.performances,
|
||||||
),
|
),
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
final tracks = await backend.db.tracksByRecording(recordingId).get();
|
final tracks =
|
||||||
backend.playback.addTracks(tracks);
|
await backend.db.tracksByRecording(recordingId).get();
|
||||||
|
backend.playback.addTracks(tracks.map((t) => t.id).toList());
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,6 @@ import 'dart:async';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import '../backend.dart';
|
|
||||||
import '../widgets/texts.dart';
|
|
||||||
|
|
||||||
/// A list view supporting pagination and searching.
|
/// A list view supporting pagination and searching.
|
||||||
///
|
///
|
||||||
/// The [fetch] function will be called, when the user has scrolled to the end
|
/// The [fetch] function will be called, when the user has scrolled to the end
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ class PlayerBar extends StatefulWidget {
|
||||||
|
|
||||||
class _PlayerBarState extends State<PlayerBar> {
|
class _PlayerBarState extends State<PlayerBar> {
|
||||||
MusicusBackendState _backend;
|
MusicusBackendState _backend;
|
||||||
StreamSubscription<Track> _currentTrackSubscribtion;
|
StreamSubscription<String> _currentTrackSubscribtion;
|
||||||
WorkInfo _workInfo;
|
WorkInfo _workInfo;
|
||||||
List<int> _partIds;
|
List<int> _partIds;
|
||||||
|
|
||||||
|
|
@ -26,9 +26,10 @@ class _PlayerBarState extends State<PlayerBar> {
|
||||||
_backend = MusicusBackend.of(context);
|
_backend = MusicusBackend.of(context);
|
||||||
|
|
||||||
_currentTrackSubscribtion?.cancel();
|
_currentTrackSubscribtion?.cancel();
|
||||||
_currentTrackSubscribtion = _backend.playback.currentTrack.listen((track) {
|
_currentTrackSubscribtion =
|
||||||
|
_backend.playback.currentTrack.listen((track) async {
|
||||||
if (track != null) {
|
if (track != null) {
|
||||||
_setTrack(track);
|
_setTrack(await _backend.db.tracksById(track).getSingle());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,14 @@
|
||||||
name: musicus_common
|
name: musicus_common
|
||||||
version: 0.1.0
|
version: 0.1.0
|
||||||
description: Common building blocks for Musicus client apps.
|
description: Common building blocks for Musicus client apps.
|
||||||
|
publish_to: none
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=2.3.0 <3.0.0"
|
sdk: ">=2.3.0 <3.0.0"
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
drift: ^1.0.0
|
drift: ^1.0.0
|
||||||
|
file_picker: ^4.5.1
|
||||||
flutter:
|
flutter:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
flutter_markdown:
|
flutter_markdown:
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ import 'package:path/path.dart' as p;
|
||||||
import 'package:path_provider/path_provider.dart' as pp;
|
import 'package:path_provider/path_provider.dart' as pp;
|
||||||
|
|
||||||
import 'settings.dart';
|
import 'settings.dart';
|
||||||
import 'platform.dart';
|
|
||||||
import 'playback.dart';
|
import 'playback.dart';
|
||||||
|
|
||||||
Future<void> main() async {
|
Future<void> main() async {
|
||||||
|
|
@ -16,7 +15,6 @@ Future<void> main() async {
|
||||||
runApp(MusicusApp(
|
runApp(MusicusApp(
|
||||||
dbPath: dbPath,
|
dbPath: dbPath,
|
||||||
settingsStorage: SettingsStorage(),
|
settingsStorage: SettingsStorage(),
|
||||||
platform: MusicusDesktopPlatform(),
|
|
||||||
playback: MusicusDesktopPlayback(),
|
playback: MusicusDesktopPlayback(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,58 +0,0 @@
|
||||||
import 'dart:io';
|
|
||||||
|
|
||||||
import 'package:file_picker/file_picker.dart';
|
|
||||||
import 'package:musicus_common/musicus_common.dart';
|
|
||||||
import 'package:path/path.dart' as p;
|
|
||||||
|
|
||||||
class MusicusDesktopPlatform extends MusicusPlatform {
|
|
||||||
@override
|
|
||||||
Future<String> chooseBasePath() async {
|
|
||||||
return await FilePicker.platform.getDirectoryPath();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<List<Document>> getChildren(String parentId) async {
|
|
||||||
final List<Document> result = [];
|
|
||||||
|
|
||||||
final parent = Directory(parentId ?? basePath);
|
|
||||||
await for (final fse in parent.list()) {
|
|
||||||
result.add(Document(
|
|
||||||
id: fse.path,
|
|
||||||
name: p.basename(fse.path),
|
|
||||||
parent: parentId,
|
|
||||||
isDirectory: fse is Directory,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<String> getIdentifier(String parentId, String fileName) async {
|
|
||||||
return p.absolute(parentId, fileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<String> readDocument(String id) async {
|
|
||||||
try {
|
|
||||||
return await File(id).readAsString();
|
|
||||||
} on FileSystemException {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<String> readDocumentByName(String parentId, String fileName) async {
|
|
||||||
try {
|
|
||||||
return await File(p.absolute(parentId, fileName)).readAsString();
|
|
||||||
} on FileSystemException {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> writeDocumentByName(
|
|
||||||
String parentId, String fileName, String contents) async {
|
|
||||||
await File(p.absolute(parentId, fileName)).writeAsString(contents);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,13 +1,12 @@
|
||||||
import 'package:musicus_common/musicus_common.dart';
|
import 'package:musicus_common/musicus_common.dart';
|
||||||
import 'package:musicus_database/musicus_database.dart';
|
|
||||||
|
|
||||||
class MusicusDesktopPlayback extends MusicusPlayback {
|
class MusicusDesktopPlayback extends MusicusPlayback {
|
||||||
@override
|
@override
|
||||||
Future<void> setup() async {}
|
Future<void> setup(MusicusLibrary library) async {}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> addTracks(List<Track> tracks) async {
|
Future<void> addTracks(List<String> tracks) async {
|
||||||
final List<Track> newPlaylist = List.from(playlist.value);
|
final List<String> newPlaylist = List.from(playlist.value);
|
||||||
newPlaylist.addAll(tracks);
|
newPlaylist.addAll(tracks);
|
||||||
playlist.add(newPlaylist);
|
playlist.add(newPlaylist);
|
||||||
active.add(true);
|
active.add(true);
|
||||||
|
|
@ -20,7 +19,7 @@ class MusicusDesktopPlayback extends MusicusPlayback {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> removeTrack(int index) async {
|
Future<void> removeTrack(int index) async {
|
||||||
final List<Track> tracks = List.from(playlist.value);
|
final List<String> tracks = List.from(playlist.value);
|
||||||
tracks.removeAt(index);
|
tracks.removeAt(index);
|
||||||
playlist.add(tracks);
|
playlist.add(tracks);
|
||||||
}
|
}
|
||||||
|
|
@ -29,7 +28,7 @@ class MusicusDesktopPlayback extends MusicusPlayback {
|
||||||
Future<void> seekTo(double pos) async {
|
Future<void> seekTo(double pos) async {
|
||||||
if (active.value && pos >= 0.0 && pos <= 1.0) {
|
if (active.value && pos >= 0.0 && pos <= 1.0) {
|
||||||
final durationMs = duration.value.inMilliseconds;
|
final durationMs = duration.value.inMilliseconds;
|
||||||
updatePosition((pos * durationMs).floor());
|
updatePosition(Duration(milliseconds: (pos * durationMs).floor()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
name: musicus_desktop
|
name: musicus_desktop
|
||||||
version: 0.1.0
|
version: 0.1.0
|
||||||
description: Desktop version of the classical music player and organizer.
|
description: Desktop version of the classical music player and organizer.
|
||||||
|
publish_to: none
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=2.3.0 <3.0.0"
|
sdk: ">=2.3.0 <3.0.0"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue