Skip to content

Commit

Permalink
Add a popup menu for selecting subtitle and audio tracks, and togglin…
Browse files Browse the repository at this point in the history
…g fullscreen

#1 #4
  • Loading branch information
insin committed Jul 8, 2019
1 parent 222026a commit d21082a
Show file tree
Hide file tree
Showing 2 changed files with 161 additions and 16 deletions.
49 changes: 48 additions & 1 deletion lib/models.dart
Expand Up @@ -292,8 +292,21 @@ class Settings {
}
}

class LanguageTrack {
String language;
int streamNumber;

LanguageTrack(this.language, this.streamNumber);

String toString() {
return '$language ($streamNumber)';
}
}

class VlcStatusResponse {
xml.XmlDocument document;
List<LanguageTrack> _audioTracks;
List<LanguageTrack> _subtitleTracks;

VlcStatusResponse(this.document);

Expand All @@ -315,12 +328,46 @@ class VlcStatusResponse {
return titles['title'] ?? titles['filename'] ?? '';
}

bool get fullscreen =>
document.findAllElements('fullscreen').first.text == 'true';

List<LanguageTrack> get audioTracks {
if (_audioTracks == null) {
_audioTracks = _getLanguageTracks('Audio');
}
return _audioTracks;
}

List<LanguageTrack> get subtitleTracks {
if (_subtitleTracks == null) {
_subtitleTracks = _getLanguageTracks('Subtitle');
}
return _subtitleTracks;
}

List<LanguageTrack> _getLanguageTracks(String type) {
List<LanguageTrack> tracks = [];
document.findAllElements('category').forEach((category) {
Map<String, String> info = Map.fromIterable(category.findElements('info'),
key: (info) => info.getAttribute('name'), value: (info) => info.text);
if (info['Type'] == type) {
tracks.add(new LanguageTrack(info['Language'],
int.parse(category.getAttribute('name').split(' ').last)));
}
});
tracks.sort((a, b) => a.streamNumber - b.streamNumber);
return tracks;
}

String toString() {
return 'VlcResponse(${{
'state': state,
'time': time,
'length': length,
'title': title
'title': title,
'fullscreen': fullscreen,
'audioTracks': audioTracks,
'subtitleTracks': subtitleTracks,
}})';
}
}
128 changes: 113 additions & 15 deletions lib/remote_control.dart
Expand Up @@ -14,6 +14,8 @@ import 'utils.dart';

var headerFooterBgColor = Colors.grey.shade200.withOpacity(0.75);

enum PopupMenuChoice { AUDIO_TRACK, FULLSCREEN, SUBTITLE_TRACK }

class RemoteControl extends StatefulWidget {
final SharedPreferences prefs;
final Settings settings;
Expand All @@ -30,6 +32,7 @@ class RemoteControl extends StatefulWidget {
class _RemoteControlState extends State<RemoteControl> {
http.Client client = http.Client();
int lastStatusCode;
VlcStatusResponse lastStatusResponse;
String state = 'stopped';
String title = '';
Duration time = Duration.zero;
Expand Down Expand Up @@ -151,6 +154,7 @@ class _RemoteControlState extends State<RemoteControl> {
var response = await _statusRequest();

if (response == null) {
lastStatusResponse = response;
return;
}

Expand All @@ -162,6 +166,7 @@ class _RemoteControlState extends State<RemoteControl> {
if (!sliding) {
time = response.time;
}
lastStatusResponse = response;
});
}

Expand Down Expand Up @@ -263,6 +268,66 @@ class _RemoteControlState extends State<RemoteControl> {
return (time.inSeconds / length.inSeconds * 100);
}

Future<LanguageTrack> _chooseLanguageTrack(List<LanguageTrack> options) {
return showDialog<LanguageTrack>(
context: context,
builder: (BuildContext context) {
return SimpleDialog(
children: options
.map((option) => SimpleDialogOption(
onPressed: () {
Navigator.pop(context, option);
},
child: Text(option.language),
))
.toList(),
);
},
);
}

void _chooseSubtitleTrack() async {
LanguageTrack subtitleTrack =
await _chooseLanguageTrack(lastStatusResponse.subtitleTracks);
if (subtitleTrack != null) {
_statusRequest({
'command': 'subtitle_track',
'val': subtitleTrack.streamNumber.toString(),
});
}
}

void _chooseAudioTrack() async {
LanguageTrack audioTrack =
await _chooseLanguageTrack(lastStatusResponse.audioTracks);
if (audioTrack != null) {
_statusRequest({
'command': 'audio_track',
'val': audioTrack.streamNumber.toString(),
});
}
}

void _toggleFullScreen() {
_statusRequest({
'command': 'fullscreen',
});
}

void _onPopupMenuChoice(PopupMenuChoice choice) {
switch (choice) {
case PopupMenuChoice.AUDIO_TRACK:
_chooseAudioTrack();
break;
case PopupMenuChoice.FULLSCREEN:
_toggleFullScreen();
break;
case PopupMenuChoice.SUBTITLE_TRACK:
_chooseSubtitleTrack();
break;
}
}

@override
Widget build(BuildContext context) {
return Scaffold(
Expand All @@ -282,23 +347,56 @@ class _RemoteControlState extends State<RemoteControl> {
overflow: TextOverflow.ellipsis,
style: TextStyle(fontWeight: FontWeight.bold),
),
trailing: IconButton(
icon: Icon(Icons.settings),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => SettingsScreen(
settings: widget.settings,
onSettingsChanged: () {
setState(() {
widget.settings.save();
});
},
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
IconButton(
icon: Icon(Icons.settings),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => SettingsScreen(
settings: widget.settings,
onSettingsChanged: () {
setState(() {
widget.settings.save();
});
},
),
),
);
},
),
Visibility(
visible: lastStatusCode == 200,
child: PopupMenuButton<PopupMenuChoice>(
onSelected: _onPopupMenuChoice,
itemBuilder: (context) {
return [
PopupMenuItem(
child: Text('Select subtitle track'),
value: PopupMenuChoice.SUBTITLE_TRACK,
enabled:
(lastStatusResponse?.subtitleTracks ?? [])
.isNotEmpty,
),
PopupMenuItem(
child: Text('Select audio track'),
value: PopupMenuChoice.AUDIO_TRACK,
enabled: (lastStatusResponse?.audioTracks ?? [])
.isNotEmpty,
),
PopupMenuItem(
child: Text('Toggle fullscreen'),
value: PopupMenuChoice.FULLSCREEN,
enabled: lastStatusResponse != null,
),
];
},
),
);
},
)
],
),
),
),
Expand Down

0 comments on commit d21082a

Please sign in to comment.