Skip to content

Commit fd07f72

Browse files
author
Chris Bellew
committed
Added voice patterns for audio/subtitle stream manipulation.
1 parent ff117cc commit fd07f72

File tree

14 files changed

+170
-80
lines changed

14 files changed

+170
-80
lines changed

mobile/src/main/java/com/atomjack/vcfp/CastPlayerManager.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -455,11 +455,10 @@ public String getTranscodeUrl(PlexMedia media, Connection connection, int offset
455455
qs.add("videoQuality", "60");
456456
qs.add("maxVideoBitrate", VoiceControlForPlexApplication.chromecastVideoOptions.get(VoiceControlForPlexApplication.getInstance().prefs.getString(connection.local ? Preferences.CHROMECAST_VIDEO_QUALITY_LOCAL : Preferences.CHROMECAST_VIDEO_QUALITY_REMOTE))[0]);
457457
qs.add("videoResolution", VoiceControlForPlexApplication.chromecastVideoOptions.get(VoiceControlForPlexApplication.getInstance().prefs.getString(connection.local ? Preferences.CHROMECAST_VIDEO_QUALITY_LOCAL : Preferences.CHROMECAST_VIDEO_QUALITY_REMOTE))[1]);
458-
qs.add("subtitleSize", "100");
459458
qs.add("audioBoost", "100");
460459
qs.add("session", mSessionId);
461460
qs.add(PlexHeaders.XPlexClientIdentifier, VoiceControlForPlexApplication.getInstance().prefs.getUUID());
462-
qs.add(PlexHeaders.XPlexProduct, String.format("%s Chromecast", mContext.getString(R.string.app_name)));
461+
qs.add(PlexHeaders.XPlexProduct, String.format("%s Chromecast", VoiceControlForPlexApplication.getInstance().getString(R.string.app_name)));
463462
qs.add(PlexHeaders.XPlexDevice, mClient.castDevice.getModelName());
464463
qs.add(PlexHeaders.XPlexDeviceName, mClient.castDevice.getModelName());
465464
qs.add(PlexHeaders.XPlexPlatform, mClient.castDevice.getModelName());

mobile/src/main/java/com/atomjack/vcfp/VoiceControlForPlexApplication.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,7 @@
1010
import android.content.Context;
1111
import android.content.DialogInterface;
1212
import android.content.pm.PackageInfo;
13-
import android.content.res.Resources.NotFoundException;
1413
import android.graphics.Bitmap;
15-
import android.net.ConnectivityManager;
16-
import android.net.NetworkInfo;
1714
import android.net.Uri;
1815
import android.os.AsyncTask;
1916
import android.os.Build;

mobile/src/main/java/com/atomjack/vcfp/activities/CastActivity.java

Lines changed: 21 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import com.atomjack.vcfp.VoiceControlForPlexApplication;
2020
import com.atomjack.vcfp.model.PlexClient;
2121
import com.atomjack.vcfp.model.PlexMedia;
22+
import com.atomjack.vcfp.model.Stream;
2223
import com.google.android.libraries.cast.companionlibrary.cast.VideoCastManager;
2324

2425
import java.util.ArrayList;
@@ -101,63 +102,6 @@ protected void onCreate(Bundle savedInstanceState) {
101102

102103
start(true);
103104

104-
/*
105-
106-
boolean mediaChange = false;
107-
PlexMedia newMedia = getIntent().getParcelableExtra(Intent.EXTRA_MEDIA);
108-
if(castPlayerManager.isSubscribed()) {
109-
if(newMedia != null && castPlayerManager.getNowPlayingMedia() != null && !newMedia.key.equals(castPlayerManager.getNowPlayingMedia().key))
110-
mediaChange = true;
111-
}
112-
113-
114-
nowPlayingMedia = newMedia;
115-
nowPlayingAlbum = getIntent().getParcelableArrayListExtra(Intent.EXTRA_ALBUM);
116-
resumePlayback = getIntent().getBooleanExtra("resume", false);
117-
castManager = castPlayerManager.getCastManager();
118-
119-
if(getIntent().getBooleanExtra(WearConstants.FROM_WEAR, false)) {
120-
new SendToDataLayerThread(WearConstants.FINISH, this).start();
121-
}
122-
// If just playing a single track, put the media into an array
123-
if(nowPlayingAlbum == null) {
124-
nowPlayingAlbum = new ArrayList<>();
125-
nowPlayingAlbum.add(nowPlayingMedia);
126-
}
127-
128-
Logger.d("[CastActivity] starting up, action: %s, current state: %s", getIntent().getAction(), castPlayerManager.getCurrentState());
129-
Logger.d("client: %s", mClient);
130-
if(getIntent().getAction() != null && getIntent().getAction().equals(Intent.CAST_MEDIA)) {
131-
132-
/*
133-
Logger.d("Casting %s (%s)", nowPlayingMedia.title, nowPlayingMedia.viewOffset);
134-
135-
// TODO: only show now playing if stopped?
136-
// if(castPlayerManager.getCurrentState().equals(PlayerState.STOPPED))
137-
138-
if(mediaChange) {
139-
Logger.d("[CastActivity] MEDIA CHANGED!");
140-
141-
init(true); // tell the chromecast to load the new media. The cast player activity will receive a notification of the new media and will update accordingly
142-
} else {
143-
144-
showNowPlaying(castPlayerManager.getCurrentState().equals(PlayerState.STOPPED) || !mediaChange ? true : false);
145-
if (castPlayerManager.isSubscribed()) {
146-
init();
147-
} else {
148-
showInfoDialog(getResources().getString(R.string.connecting));
149-
castPlayerManager.subscribe(mClient);
150-
}
151-
}
152-
} else {
153-
Logger.d("[CastActivity] No action found.");
154-
if(castPlayerManager.getCurrentState().equals(PlayerState.STOPPED))
155-
finish();
156-
else {
157-
showNowPlaying(true);
158-
}
159-
}
160-
*/
161105
}
162106

163107
@Override
@@ -423,4 +367,24 @@ public void onCastSeek() {
423367
if(!nowPlayingMedia.getType().equals("music"))
424368
showInfoDialog(getString(R.string.please_wait));
425369
}
370+
371+
@Override
372+
public void setStream(Stream stream) {
373+
374+
}
375+
376+
@Override
377+
public void cycleStreams(int streamType) {
378+
379+
}
380+
381+
@Override
382+
public void subtitlesOn() {
383+
384+
}
385+
386+
@Override
387+
public void subtitlesOff() {
388+
389+
}
426390
}

mobile/src/main/java/com/atomjack/vcfp/activities/NowPlayingActivity.java

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,15 @@
2929
import com.atomjack.vcfp.model.PlexResponse;
3030
import com.atomjack.shared.model.Timeline;
3131
import com.atomjack.vcfp.model.PlexTrack;
32+
import com.atomjack.vcfp.model.Stream;
3233
import com.atomjack.vcfp.net.PlexHttpResponseHandler;
3334
import com.bugsense.trace.BugSenseHandler;
3435
import com.google.android.gms.wearable.DataMap;
3536

3637
import org.codechimp.apprater.AppRater;
3738

39+
import java.util.List;
40+
3841
public class NowPlayingActivity extends PlayerActivity {
3942
private boolean subscribed = false;
4043
private boolean fromWear = false;
@@ -369,4 +372,55 @@ public void onUnsubscribed() {
369372
super.onUnsubscribed();
370373
finish();
371374
}
375+
376+
@Override
377+
public void setStream(Stream stream) {
378+
mClient.setStream(stream);
379+
}
380+
381+
@Override
382+
public void cycleStreams(int streamType) {
383+
List<Stream> streams = nowPlayingMedia.getStreams(streamType);
384+
385+
if(streams.size() == 0) {
386+
387+
} else {
388+
int activeIndex = 0;
389+
for(int i=0;i<streams.size();i++) {
390+
if(streams.get(i).isActive())
391+
activeIndex = i;
392+
}
393+
Logger.d("Active %s stream: %d", (streamType == Stream.SUBTITLE ? "subtitle" : "audio"), activeIndex);
394+
int newI = activeIndex+1 >= streams.size() ? 0 : activeIndex+1;
395+
Stream newStream = streams.get(newI);
396+
mClient.setStream(newStream);
397+
nowPlayingMedia.setActiveStream(newStream);
398+
if(streamType == Stream.SUBTITLE) {
399+
if(activeIndex+1 >= streams.size()) {
400+
feedback.m(R.string.subtitles_off);
401+
} else {
402+
feedback.m(String.format(getString(R.string.subtitle_active), newStream.getTitle()));
403+
}
404+
} else {
405+
feedback.m(String.format(getString(R.string.audio_track_active), newStream.getTitle()));
406+
}
407+
408+
}
409+
}
410+
411+
@Override
412+
public void subtitlesOn() {
413+
if(nowPlayingMedia.getStreams(Stream.SUBTITLE).size() > 0) {
414+
mClient.setStream(nowPlayingMedia.getStreams(Stream.SUBTITLE).get(1));
415+
feedback.m(String.format(getString(R.string.subtitle_active), nowPlayingMedia.getStreams(Stream.SUBTITLE).get(1).getTitle()));
416+
}
417+
}
418+
419+
@Override
420+
public void subtitlesOff() {
421+
if(nowPlayingMedia.getStreams(Stream.SUBTITLE).size() > 0) {
422+
mClient.setStream(nowPlayingMedia.getStreams(Stream.SUBTITLE).get(0));
423+
feedback.m(R.string.subtitles_off);
424+
}
425+
}
372426
}

mobile/src/main/java/com/atomjack/vcfp/activities/PlayerActivity.java

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,11 @@ public void doMic(View v) {
8383
}
8484
}
8585

86+
public abstract void setStream(Stream stream);
87+
public abstract void cycleStreams(int streamType);
88+
public abstract void subtitlesOff();
89+
public abstract void subtitlesOn();
90+
8691
// Open an alert to allow selection of currently playing media's audio and/or subtitle options
8792
public void doMediaOptions(View v) {
8893
if(nowPlayingMedia == null) {
@@ -107,7 +112,7 @@ public void doMediaOptions(View v) {
107112
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
108113
Stream stream = subtitleStreams.get(position);
109114
if (!stream.isActive()) {
110-
mClient.setStream(stream);
115+
setStream(stream);
111116
nowPlayingMedia.setActiveStream(stream);
112117
}
113118
}
@@ -131,7 +136,7 @@ public void onNothingSelected(AdapterView<?> parent) {
131136
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
132137
Stream stream = audioStreams.get(position);
133138
if (!stream.isActive()) {
134-
mClient.setStream(stream);
139+
setStream(stream);
135140
nowPlayingMedia.setActiveStream(stream);
136141
}
137142
}
@@ -266,8 +271,15 @@ public void showNowPlaying(boolean setView) {
266271
TextView nowPlayingOnClient = (TextView)findViewById(R.id.nowPlayingOnClient);
267272
nowPlayingOnClient.setText(getResources().getString(R.string.now_playing_on) + " " + mClient.name);
268273

269-
if(findViewById(R.id.mediaOptionsButton) != null && nowPlayingMedia.getStreams(Stream.SUBTITLE).size() == 0 && nowPlayingMedia.getStreams(Stream.AUDIO).size() == 0) {
270-
findViewById(R.id.mediaOptionsButton).setVisibility(View.GONE);
274+
// Hide stream options on chromecast, for now
275+
if(mClient.isCastClient) {
276+
if(findViewById(R.id.mediaOptionsButton) != null) {
277+
findViewById(R.id.mediaOptionsButton).setVisibility(View.GONE);
278+
}
279+
} else {
280+
if (findViewById(R.id.mediaOptionsButton) != null && nowPlayingMedia.getStreams(Stream.SUBTITLE).size() == 0 && nowPlayingMedia.getStreams(Stream.AUDIO).size() == 0) {
281+
findViewById(R.id.mediaOptionsButton).setVisibility(View.GONE);
282+
}
271283
}
272284

273285
Logger.d("[PlayerActivity] Setting thumb in showNowPlaying");

mobile/src/main/java/com/atomjack/vcfp/model/PlexMedia.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -170,10 +170,10 @@ public int describeContents() {
170170
private List<Stream> streams;
171171

172172
public List<Stream> getStreams() {
173-
// The list of streams needs to have a "none" subtitle stream added to it. Subsequent calls
174-
// to get the list of streams should get this list, since any manipulation of which (audio/video)
175-
// stream is active will need to be saved to it - the list of streams in media/parts will not reflect
176-
// the updating of active streams.
173+
// The list of streams needs to have a "none" subtitle stream added to it (if there is at least
174+
// one subtitle stream). Subsequent calls to get the list of streams should get this list, since any
175+
// manipulation of which (audio/video) stream is active will need to be saved to it - the list of
176+
// streams in media/parts will not reflect the updating of active streams.
177177
if (streams == null) {
178178
streams = new ArrayList<>();
179179
Media m = media.get(0);

mobile/src/main/java/com/atomjack/vcfp/net/PlexHttpClient.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -397,9 +397,6 @@ public static void createPlayQueue(Connection connection, final PlexMedia media,
397397
if (media.server.accessToken != null)
398398
qs.put(PlexHeaders.XPlexToken, media.server.accessToken);
399399

400-
for(Object name:qs.keySet()) {
401-
Logger.d("QS %s:%s", name, qs.get(name));
402-
}
403400
PlexHttpService service = getService(String.format("http://%s:%s", connection.address, connection.port));
404401
Call<MediaContainer> call = service.createPlayQueue(qs, VoiceControlForPlexApplication.getUUID());
405402
call.enqueue(new Callback<MediaContainer>() {

mobile/src/main/java/com/atomjack/vcfp/services/PlexSearchService.java

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,13 @@
1515
import com.atomjack.shared.WearConstants;
1616
import com.atomjack.shared.model.Timeline;
1717
import com.atomjack.vcfp.Utils;
18+
import com.atomjack.vcfp.activities.PlayerActivity;
1819
import com.atomjack.vcfp.interfaces.ActiveConnectionHandler;
1920
import com.atomjack.vcfp.interfaces.AfterTransientTokenRequest;
2021
import com.atomjack.vcfp.BuildConfig;
2122
import com.atomjack.vcfp.CastPlayerManager;
2223
import com.atomjack.vcfp.Feedback;
2324
import com.atomjack.shared.Logger;
24-
import com.atomjack.vcfp.PlexHeaders;
2525
import com.atomjack.vcfp.PlexSubscription;
2626
import com.atomjack.shared.Preferences;
2727
import com.atomjack.vcfp.QueryString;
@@ -42,6 +42,7 @@
4242
import com.atomjack.vcfp.model.PlexServer;
4343
import com.atomjack.vcfp.model.PlexTrack;
4444
import com.atomjack.vcfp.model.PlexVideo;
45+
import com.atomjack.vcfp.model.Stream;
4546
import com.atomjack.vcfp.net.PlexHttpClient;
4647
import com.atomjack.vcfp.net.PlexHttpMediaContainerHandler;
4748
import com.atomjack.vcfp.net.PlexHttpResponseHandler;
@@ -851,6 +852,63 @@ public void run() {
851852
}
852853

853854

855+
p = Pattern.compile(getString(R.string.pattern_cycle_subtitles), Pattern.DOTALL);
856+
matcher = p.matcher(queryText);
857+
if(matcher.find()) {
858+
return new StopRunnable() {
859+
@Override
860+
public void run() {
861+
if(VoiceControlForPlexApplication.getInstance().plexSubscription.getListener() != null) {
862+
PlayerActivity act = (PlayerActivity)VoiceControlForPlexApplication.getInstance().plexSubscription.getListener();
863+
act.cycleStreams(Stream.SUBTITLE);
864+
}
865+
}
866+
};
867+
}
868+
869+
p = Pattern.compile(getString(R.string.pattern_cycle_audio), Pattern.DOTALL);
870+
matcher = p.matcher(queryText);
871+
if(matcher.find()) {
872+
return new StopRunnable() {
873+
@Override
874+
public void run() {
875+
if(VoiceControlForPlexApplication.getInstance().plexSubscription.getListener() != null) {
876+
PlayerActivity act = (PlayerActivity)VoiceControlForPlexApplication.getInstance().plexSubscription.getListener();
877+
act.cycleStreams(Stream.AUDIO);
878+
}
879+
}
880+
};
881+
}
882+
883+
p = Pattern.compile(getString(R.string.pattern_subtitles_off), Pattern.DOTALL);
884+
matcher = p.matcher(queryText);
885+
if(matcher.find()) {
886+
return new StopRunnable() {
887+
@Override
888+
public void run() {
889+
if(VoiceControlForPlexApplication.getInstance().plexSubscription.getListener() != null) {
890+
PlayerActivity act = (PlayerActivity)VoiceControlForPlexApplication.getInstance().plexSubscription.getListener();
891+
act.subtitlesOff();
892+
}
893+
}
894+
};
895+
}
896+
897+
p = Pattern.compile(getString(R.string.pattern_subtitles_on), Pattern.DOTALL);
898+
matcher = p.matcher(queryText);
899+
if(matcher.find()) {
900+
return new StopRunnable() {
901+
@Override
902+
public void run() {
903+
if(VoiceControlForPlexApplication.getInstance().plexSubscription.getListener() != null) {
904+
PlayerActivity act = (PlayerActivity)VoiceControlForPlexApplication.getInstance().plexSubscription.getListener();
905+
act.subtitlesOn();
906+
}
907+
}
908+
};
909+
}
910+
911+
854912

855913

856914

mobile/src/main/res/values-de/patterns.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ Wenn du eine Übersetzung hinzufügst bitte modifiziere nicht die Muster (.*), $
99
complexen regulären Ausdruck. Der Dienst https://www.debuggex.com/ kann zur Visualisierung des Musters verwendet werden.
1010
-->
1111

12-
<item name="pattern_recognition" type="string">^(((schaue|spiele|weiterschauen|höre|schaue film|spiele film) (.+)( auf (.+))?( mit zufallswiedergabe)?)|((springe) (.+)( auf (.+))?)|((forward|rewind|back) (.+)( on (.+))?)|(( wiedergabe)?(pausieren|anhalten|fortsetzen)( auf (.+))?))|(verbinde mit (.+)|trenne)$</item>
12+
<item name="pattern_recognition" type="string">^(((schaue|spiele|weiterschauen|höre|schaue film|spiele film) (.+)( auf (.+))?( mit zufallswiedergabe)?)|((springe) (.+)( auf (.+))?)|((forward|rewind|back) (.+)( on (.+))?)|(( wiedergabe)?(pausieren|anhalten|fortsetzen)( auf (.+))?))|(verbinde mit (.+)|trenne)|(cycle (subtitles|audio))|(.*subtitle.*(off|on))$</item>
1313

1414
<item name="pattern_on_client" type="string">(.+) auf (.+)$</item>
1515
<item name="pattern_resume_watching" type="string">^weiterschauen (.+)</item>

mobile/src/main/res/values-es/patterns.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ adding translations, please do not modify (.*), $1, ([0-9]+), etc.
99
a quite complicated regular expression. Plugging it into https://www.debuggex.com/ should help you figure out how
1010
it is constructed.
1111
-->
12-
<item name="pattern_recognition" type="string">^(((ver|continuar viendo|escuchar|ver película) (.+)( en (.+))?( en modo aleatorio)?)|((posición) (.+)( en (.+))?)|((forward|rewind|back) (.+)( on (.+))?)|((pausar|detener|continuar)( reproducción)?( en (.+))?))|(conectar a (.+)|desconectar)$</item>
12+
<item name="pattern_recognition" type="string">^(((ver|continuar viendo|escuchar|ver película) (.+)( en (.+))?( en modo aleatorio)?)|((posición) (.+)( en (.+))?)|((forward|rewind|back) (.+)( on (.+))?)|((pausar|detener|continuar)( reproducción)?( en (.+))?))|(conectar a (.+)|desconectar)|(cycle (subtitles|audio))|(.*subtitle.*(off|on))$</item>
1313

1414
<item name="pattern_on_client" type="string">(.+) en (.+)$</item>
1515
<item name="pattern_resume_watching" type="string">^continuar (viendo) (.+)</item>

0 commit comments

Comments
 (0)