Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/news-android.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/services')
-rw-r--r--News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/services/OwnCloudSyncService.java1
-rw-r--r--News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/services/PodcastPlaybackService.java351
-rw-r--r--News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/services/podcast/MediaPlayerPlaybackService.java185
-rw-r--r--News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/services/podcast/PlaybackService.java63
-rw-r--r--News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/services/podcast/TTSPlaybackService.java89
-rw-r--r--News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/services/podcast/YoutubePlaybackService.java163
6 files changed, 577 insertions, 275 deletions
diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/services/OwnCloudSyncService.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/services/OwnCloudSyncService.java
index 681e2f33..7c89cdfd 100644
--- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/services/OwnCloudSyncService.java
+++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/services/OwnCloudSyncService.java
@@ -42,7 +42,6 @@ import org.greenrobot.eventbus.EventBus;
import java.util.List;
import java.util.concurrent.CountDownLatch;
-import de.luhmer.owncloudnewsreader.Constants;
import de.luhmer.owncloudnewsreader.ListView.SubscriptionExpandableListAdapter;
import de.luhmer.owncloudnewsreader.R;
import de.luhmer.owncloudnewsreader.SettingsActivity;
diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/services/PodcastPlaybackService.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/services/PodcastPlaybackService.java
index 4bbc45f3..7476d19d 100644
--- a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/services/PodcastPlaybackService.java
+++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/services/PodcastPlaybackService.java
@@ -2,47 +2,47 @@ package de.luhmer.owncloudnewsreader.services;
import android.app.Service;
import android.content.Intent;
-import android.media.MediaPlayer;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
-import android.speech.tts.TextToSpeech;
-import android.speech.tts.UtteranceProgressListener;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.util.Log;
-import android.view.SurfaceHolder;
import android.view.View;
-import android.widget.Toast;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
-import java.io.IOException;
-import java.util.HashMap;
-
-import de.luhmer.owncloudnewsreader.R;
import de.luhmer.owncloudnewsreader.events.podcast.NewPodcastPlaybackListener;
import de.luhmer.owncloudnewsreader.events.podcast.PodcastCompletedEvent;
import de.luhmer.owncloudnewsreader.events.podcast.RegisterVideoOutput;
+import de.luhmer.owncloudnewsreader.events.podcast.RegisterYoutubeOutput;
import de.luhmer.owncloudnewsreader.events.podcast.TogglePlayerStateEvent;
import de.luhmer.owncloudnewsreader.events.podcast.UpdatePodcastStatusEvent;
import de.luhmer.owncloudnewsreader.events.podcast.WindPodcast;
+import de.luhmer.owncloudnewsreader.model.MediaItem;
import de.luhmer.owncloudnewsreader.model.PodcastItem;
import de.luhmer.owncloudnewsreader.model.TTSItem;
+import de.luhmer.owncloudnewsreader.services.podcast.MediaPlayerPlaybackService;
+import de.luhmer.owncloudnewsreader.services.podcast.PlaybackService;
+import de.luhmer.owncloudnewsreader.services.podcast.TTSPlaybackService;
+import de.luhmer.owncloudnewsreader.services.podcast.YoutubePlaybackService;
import de.luhmer.owncloudnewsreader.view.PodcastNotification;
-public class PodcastPlaybackService extends Service implements TextToSpeech.OnInitListener {
+public class PodcastPlaybackService extends Service {
// Binder given to clients
private final IBinder mBinder = new LocalBinder();
- public PodcastItem getCurrentlyPlayingPodcast() {
- return mCurrentlyPlayingPodcast;
+ public MediaItem getCurrentlyPlayingPodcast() {
+ if(mPlaybackService != null) {
+ return mPlaybackService.getMediaItem();
+ }
+ return null;
}
public boolean isActive() {
- return mCurrentlyPlayingPodcast != null || mCurrentlyPlayingTTS != null;
+ return mPlaybackService != null;
}
/**
@@ -75,72 +75,33 @@ public class PodcastPlaybackService extends Service implements TextToSpeech.OnIn
return super.onUnbind(intent);
}
- public static final String PODCAST_ITEM = "PODCAST_ITEM";
- public static final String TTS_ITEM = "TTS_ITEM";
-
- private PodcastItem mCurrentlyPlayingPodcast;
- private TTSItem mCurrentlyPlayingTTS;
+ public static final String MEDIA_ITEM = "MediaItem";
private static final String TAG = "PodcastPlaybackService";
private PodcastNotification podcastNotification;
private EventBus eventBus;
private Handler mHandler;
- private MediaPlayer mMediaPlayer;
-
- private TextToSpeech ttsController;
- private String mediaTitle;
- private PlaybackType mPlaybackType;
+ private PlaybackService mPlaybackService;
private View parentResizableView;
- private enum PlaybackType { PODCAST, TTS }
+
@Override
public void onCreate() {
Log.v(TAG, "onCreate PodcastPlaybackService");
- mediaTitle = getString(R.string.no_podcast_selected);
-
TelephonyManager mgr = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
if(mgr != null) {
mgr.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
}
- mMediaPlayer = new MediaPlayer();
+
podcastNotification = new PodcastNotification(this);
mHandler = new Handler();
eventBus = EventBus.getDefault();
-
eventBus.register(this);
-
- mMediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
- @Override
- public boolean onError(MediaPlayer mediaPlayer, int i, int i2) {
- isPreparing = false;
- Toast.makeText(PodcastPlaybackService.this, "Failed to open podcast", Toast.LENGTH_LONG).show();
- return false;
- }
- });
-
- mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
- @Override
- public void onPrepared(MediaPlayer mediaPlayer) {
- play();
- isPreparing = false;
- canCallGetDuration = true;
- }
- });
-
- mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
- @Override
- public void onCompletion(MediaPlayer mediaPlayer) {
- pause();//Send the over signal
- podcastCompleted();
- }
- });
-
-
eventBus.post(new PodcastPlaybackServiceStarted());
mHandler.postDelayed(mUpdateTimeTask, 0);
@@ -166,118 +127,51 @@ public class PodcastPlaybackService extends Service implements TextToSpeech.OnIn
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent != null) {
- if (intent.hasExtra(PODCAST_ITEM)) {
- openFile((PodcastItem) intent.getSerializableExtra(PODCAST_ITEM));
- } else if(intent.hasExtra(TTS_ITEM)) {
- openTtsFeed((TTSItem) intent.getSerializableExtra(TTS_ITEM));
+ if(mPlaybackService != null) {
+ mPlaybackService.destroy();
+ mPlaybackService = null;
}
- }
-
- return Service.START_STICKY;
- }
-
-
- public static final int delay = 500; //In milliseconds
-
- private boolean canCallGetDuration = false;//Otherwise the player would call getDuration all the time without loading a media file
- private boolean isPreparing = false;
- private boolean isVideoFile = false;
-
- public void openTtsFeed(TTSItem textToSpeechItem) {
- this.mCurrentlyPlayingTTS = textToSpeechItem;
- this.mCurrentlyPlayingPodcast = null;
- this.mPlaybackType = PlaybackType.TTS;
- this.isVideoFile = false;
+ MediaItem mediaItem = (MediaItem) intent.getSerializableExtra(MEDIA_ITEM);
- try {
- if(mMediaPlayer.isPlaying())
- pause();
-
- this.mediaTitle = textToSpeechItem.title;
-
- isPreparing = true;
- mHandler.postDelayed(mUpdateTimeTask, 0);
-
- if(ttsController == null) {
- ttsController = new TextToSpeech(this, this);
- ttsController.setOnUtteranceProgressListener(new UtteranceProgressListener() {
- @Override
- public void onDone(String utteranceId) {
- podcastCompleted();
- }
-
- @Override public void onStart(String utteranceId) {}
- @Override public void onError(String utteranceId) {}
- });
+ if (mediaItem instanceof PodcastItem) {
+ if(((PodcastItem)mediaItem).isYoutubeVideo()) {
+ mPlaybackService = new YoutubePlaybackService(this, podcastStatusListener, mediaItem);
+ } else {
+ mPlaybackService = new MediaPlayerPlaybackService(this, podcastStatusListener, mediaItem);
+ }
+ } else if(mediaItem instanceof TTSItem) {
+ mPlaybackService = new TTSPlaybackService(this, podcastStatusListener, mediaItem);
}
- else
- onInit(TextToSpeech.SUCCESS);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- private void podcastCompleted() {
- Log.d(TAG, "Podcast completed, cleaning up");
- mHandler.removeCallbacks(mUpdateTimeTask);
- podcastNotification.cancel();
- mCurrentlyPlayingPodcast = null;
- mCurrentlyPlayingTTS = null;
+ sendMediaStatus();
+ podcastNotification.podcastChanged();
+ }
- EventBus.getDefault().post(new PodcastCompletedEvent());
+ return Service.START_STICKY;
}
- @Override
- public void onInit(int status) {
- if (status == TextToSpeech.SUCCESS) {
- /*
- int result = ttsController.setLanguage(Locale.US);
-
- if (result == TextToSpeech.LANG_MISSING_DATA
- || result == TextToSpeech.LANG_NOT_SUPPORTED) {
- Log.e("TTS", "This Language is not supported");
- } else {
- ttsController.speak(text, TextToSpeech.QUEUE_FLUSH, null);
- }*/
-
- HashMap<String,String> ttsParams = new HashMap<>();
- ttsParams.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID,"dummyId");
- ttsController.speak(mCurrentlyPlayingTTS.text, TextToSpeech.QUEUE_FLUSH, ttsParams);
-
- isPreparing = false;
-
- } else {
- Log.e("TTS", "Initilization Failed!");
- ttsController = null;
+ private PlaybackService.PodcastStatusListener podcastStatusListener = new PlaybackService.PodcastStatusListener() {
+ @Override
+ public void podcastStatusUpdated() {
+ sendMediaStatus();
}
- }
-
- public void openFile(PodcastItem podcastItem) {
- this.mPlaybackType = PlaybackType.PODCAST;
- this.mCurrentlyPlayingPodcast = podcastItem;
- this.mCurrentlyPlayingTTS = null;
-
- this.isVideoFile = podcastItem.isVideoPodcast;
- try {
- if(mMediaPlayer.isPlaying())
- pause();
- this.mediaTitle = podcastItem.title;
+ @Override
+ public void podcastCompleted() {
+ Log.d(TAG, "Podcast completed, cleaning up");
+ mHandler.removeCallbacks(mUpdateTimeTask);
+ podcastNotification.cancel();
- isPreparing = true;
- mHandler.postDelayed(mUpdateTimeTask, 0);
+ mPlaybackService.destroy();
+ mPlaybackService = null;
- mMediaPlayer.reset();
- mMediaPlayer.setDataSource(podcastItem.link);
- mMediaPlayer.prepareAsync();
- } catch (IOException e) {
- e.printStackTrace();
- isPreparing = false;
+ EventBus.getDefault().post(new PodcastCompletedEvent());
}
+ };
+
+ public static final int delay = 500; //In milliseconds
- podcastNotification.podcastChanged();
- }
/**
* Background Runnable thread
@@ -302,45 +196,30 @@ public class PodcastPlaybackService extends Service implements TextToSpeech.OnIn
}
private boolean isPlaying() {
- return (mPlaybackType == PlaybackType.PODCAST && mMediaPlayer.isPlaying()) || //If podcast is running
- mPlaybackType == PlaybackType.TTS && ttsController.isSpeaking(); // or if tts is running
+ return (mPlaybackService != null && mPlaybackService.getStatus() == PlaybackService.Status.PLAYING);
}
@Subscribe
public void onEvent(WindPodcast event) {
- if(mMediaPlayer != null) {
- double totalDuration = mMediaPlayer.getDuration();
- int position = (int)((totalDuration / 100d) * event.toPositionInPercent);
- mMediaPlayer.seekTo(position);
+ if(mPlaybackService != null) {
+ mPlaybackService.seekTo(event.toPositionInPercent);
}
}
- /*
- public void onEventBackgroundThread(OpenPodcastEvent event) {
- this.isVideoFile = event.isVideoFile;
- openFile(event.pathToFile, event.mediaTitle);
- }
- */
-
@Subscribe
public void onEvent(RegisterVideoOutput videoOutput) {
- if(mMediaPlayer != null) {
- if(videoOutput.surfaceView == null) {
- mMediaPlayer.setDisplay(null);
- Log.d(TAG, "Disable Screen output!");
+ if(mPlaybackService != null && mPlaybackService instanceof MediaPlayerPlaybackService) {
+ ((MediaPlayerPlaybackService) mPlaybackService).setVideoView(videoOutput.surfaceView, videoOutput.parentResizableView);
+ }
+ }
- mMediaPlayer.setScreenOnWhilePlaying(false);
+ @Subscribe
+ public void onEvent(RegisterYoutubeOutput videoOutput) {
+ if(mPlaybackService != null && mPlaybackService instanceof YoutubePlaybackService) {
+ if(videoOutput.youTubePlayer == null) {
+ mPlaybackService.destroy();
} else {
- if(videoOutput.surfaceView.getHolder() != mSurfaceHolder) {
- parentResizableView = videoOutput.parentResizableView;
-
- videoOutput.surfaceView.getHolder().addCallback(mSHCallback);
- //videoOutput.surfaceView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); //holder.setType(SurfaceHolder.SURFACE_TYPE_GPU);
-
- populateVideo();
-
- Log.d(TAG, "Enable Screen output!");
- }
+ ((YoutubePlaybackService) mPlaybackService).setYoutubePlayer(videoOutput.youTubePlayer, videoOutput.wasRestored);
}
}
}
@@ -351,59 +230,18 @@ public class PodcastPlaybackService extends Service implements TextToSpeech.OnIn
}
-
-
public void play() {
- if(mPlaybackType == PlaybackType.PODCAST) {
- try {
- int progress = mMediaPlayer.getCurrentPosition() / mMediaPlayer.getDuration();
- if (progress >= 1) {
- mMediaPlayer.seekTo(0);
- }
- } catch (Exception ex) {
- ex.printStackTrace();
- }
-
- mMediaPlayer.start();
- } else {
- onInit(TextToSpeech.SUCCESS);//restart last tts
+ if(mPlaybackService != null) {
+ mPlaybackService.play();
}
mHandler.removeCallbacks(mUpdateTimeTask);
mHandler.postDelayed(mUpdateTimeTask, 0);
-
- populateVideo();
- }
-
- private void populateVideo() {
- double videoHeightRel = (double) mSurfaceWidth / (double) mMediaPlayer.getVideoWidth();
- int videoHeight = (int) (mMediaPlayer.getVideoHeight() * videoHeightRel);
-
- if (mSurfaceWidth != 0 && videoHeight != 0 && mSurfaceHolder != null) {
- //mSurfaceHolder.setFixedSize(mSurfaceWidth, videoHeight);
-
- parentResizableView.getLayoutParams().height = videoHeight;
- parentResizableView.setLayoutParams(parentResizableView.getLayoutParams());
- }
}
public void pause() {
- if(mPlaybackType == PlaybackType.PODCAST) {
- if (mMediaPlayer.isPlaying())
- mMediaPlayer.pause();
- }
-
- if(mPlaybackType == PlaybackType.TTS) {
- if (ttsController.isSpeaking()) {
- ttsController.stop();
-
- //The tts service needs a few ms's to end playing. So wait 100ms
- try {
- Thread.sleep(100);
- } catch (Exception ex) {
- ex.printStackTrace();
- }
- }
+ if(mPlaybackService != null) {
+ mPlaybackService.pause();
}
mHandler.removeCallbacks(mUpdateTimeTask);
@@ -411,25 +249,20 @@ public class PodcastPlaybackService extends Service implements TextToSpeech.OnIn
}
public void sendMediaStatus() {
- long totalDuration = 0;
- long currentDuration = 0;
-
- if(mPlaybackType == PlaybackType.PODCAST) {
- if (!isPreparing && canCallGetDuration) {
- totalDuration = mMediaPlayer.getDuration();
- currentDuration = mMediaPlayer.getCurrentPosition();
- }
-
- long currentRssItemId = -1;
- if (mCurrentlyPlayingPodcast != null)
- currentRssItemId = mCurrentlyPlayingPodcast.itemId;
+ UpdatePodcastStatusEvent audioPodcastEvent;
- UpdatePodcastStatusEvent audioPodcastEvent = new UpdatePodcastStatusEvent(currentDuration, totalDuration, mMediaPlayer.isPlaying(), mediaTitle, isPreparing, canCallGetDuration, isVideoFile, currentRssItemId);
- eventBus.post(audioPodcastEvent);
- } else if(mPlaybackType == PlaybackType.TTS) {
- UpdatePodcastStatusEvent audioPodcastEvent = new UpdatePodcastStatusEvent(0, 0, ttsController.isSpeaking(), mediaTitle, isPreparing, true, false, mCurrentlyPlayingTTS.itemId);
- eventBus.post(audioPodcastEvent);
+ if(mPlaybackService == null) {
+ audioPodcastEvent = new UpdatePodcastStatusEvent(0, 0, PlaybackService.Status.NOT_INITIALIZED, "", PlaybackService.VideoType.None, -1);
+ } else {
+ audioPodcastEvent = new UpdatePodcastStatusEvent(
+ mPlaybackService.getCurrentDuration(),
+ mPlaybackService.getTotalDuration(),
+ mPlaybackService.getStatus(),
+ mPlaybackService.getMediaItem().title,
+ mPlaybackService.getVideoType(),
+ mPlaybackService.getMediaItem().itemId);
}
+ eventBus.post(audioPodcastEvent);
}
@@ -451,34 +284,4 @@ public class PodcastPlaybackService extends Service implements TextToSpeech.OnIn
super.onCallStateChanged(state, incomingNumber);
}
};
-
-
-
-
- int mSurfaceWidth;
- int mSurfaceHeight;
- SurfaceHolder mSurfaceHolder;
- SurfaceHolder.Callback mSHCallback = new SurfaceHolder.Callback()
- {
- public void surfaceChanged(SurfaceHolder holder, int format, int surfaceWidth, int surfaceHeight)
- {
- mSurfaceWidth = surfaceWidth;
- mSurfaceHeight = surfaceHeight;
- }
-
- public void surfaceCreated(SurfaceHolder holder)
- {
- mSurfaceHolder = holder;
- mMediaPlayer.setDisplay(mSurfaceHolder);
-
- mMediaPlayer.setScreenOnWhilePlaying(true);
-
- Log.d(TAG, "surfaceCreated");
- }
-
- public void surfaceDestroyed(SurfaceHolder holder)
- {
- Log.d(TAG, "surfaceDestroyed");
- }
- };
}
diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/services/podcast/MediaPlayerPlaybackService.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/services/podcast/MediaPlayerPlaybackService.java
new file mode 100644
index 00000000..63c3a46e
--- /dev/null
+++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/services/podcast/MediaPlayerPlaybackService.java
@@ -0,0 +1,185 @@
+package de.luhmer.owncloudnewsreader.services.podcast;
+
+import android.content.Context;
+import android.media.MediaPlayer;
+import android.util.Log;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import android.view.View;
+import android.widget.Toast;
+
+import java.io.IOException;
+
+import de.luhmer.owncloudnewsreader.model.MediaItem;
+import de.luhmer.owncloudnewsreader.model.PodcastItem;
+
+/**
+ * Created by david on 31.01.17.
+ */
+
+public class MediaPlayerPlaybackService extends PlaybackService {
+ private static final String TAG = MediaPlayerPlaybackService.class.getCanonicalName();
+ private MediaPlayer mMediaPlayer;
+ private View parentResizableView;
+
+ public MediaPlayerPlaybackService(final Context context, PodcastStatusListener podcastStatusListener, MediaItem mediaItem) {
+ super(context, podcastStatusListener, mediaItem);
+
+ mMediaPlayer = new MediaPlayer();
+ mMediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
+ @Override
+ public boolean onError(MediaPlayer mediaPlayer, int i, int i2) {
+ setStatus(Status.FAILED);
+ Toast.makeText(context, "Failed to open podcast", Toast.LENGTH_LONG).show();
+ return false;
+ }
+ });
+
+ mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
+ @Override
+ public void onPrepared(MediaPlayer mediaPlayer) {
+ setStatus(Status.PAUSED);
+ play();
+ }
+ });
+
+ mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
+ @Override
+ public void onCompletion(MediaPlayer mediaPlayer) {
+ pause();//Send the over signal
+ podcastCompleted();
+ }
+ });
+
+
+ try {
+ setStatus(Status.PREPARING);
+
+ mMediaPlayer.setDataSource(((PodcastItem) mediaItem).link);
+ mMediaPlayer.prepareAsync();
+ } catch (IOException e) {
+ e.printStackTrace();
+ setStatus(Status.FAILED);
+ }
+ }
+
+ @Override
+ public void destroy() {
+ mMediaPlayer.stop();
+ mMediaPlayer.reset();
+ mMediaPlayer.release();
+ }
+
+ @Override
+ public void play() {
+ try {
+ int progress = mMediaPlayer.getCurrentPosition() / mMediaPlayer.getDuration();
+ if (progress >= 1) {
+ mMediaPlayer.seekTo(0);
+ }
+ setStatus(Status.PLAYING);
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+
+ mMediaPlayer.start();
+
+ populateVideo();
+ }
+
+ @Override
+ public void pause() {
+ if (mMediaPlayer.isPlaying()) {
+ mMediaPlayer.pause();
+ }
+ setStatus(Status.PAUSED);
+ }
+
+ @Override
+ public void seekTo(double percent) {
+ double totalDuration = mMediaPlayer.getDuration();
+ int position = (int) ((totalDuration / 100d) * percent);
+ mMediaPlayer.seekTo(position);
+ }
+
+ @Override
+ public int getCurrentDuration() {
+ if (mMediaPlayer != null && isMediaLoaded()) {
+ return mMediaPlayer.getCurrentPosition();
+ }
+ return 0;
+ }
+
+ @Override
+ public int getTotalDuration() {
+ if (mMediaPlayer != null && isMediaLoaded()) {
+ return mMediaPlayer.getDuration();
+ }
+ return 0;
+ }
+
+ @Override
+ public VideoType getVideoType() {
+ return ((PodcastItem) getMediaItem()).isVideoPodcast ? VideoType.Video : VideoType.None;
+ }
+
+
+ private void populateVideo() {
+ double videoHeightRel = (double) mSurfaceWidth / (double) mMediaPlayer.getVideoWidth();
+ int videoHeight = (int) (mMediaPlayer.getVideoHeight() * videoHeightRel);
+
+ if (mSurfaceWidth != 0 && videoHeight != 0 && mSurfaceHolder != null) {
+ //mSurfaceHolder.setFixedSize(mSurfaceWidth, videoHeight);
+
+ parentResizableView.getLayoutParams().height = videoHeight;
+ parentResizableView.setLayoutParams(parentResizableView.getLayoutParams());
+ }
+ }
+
+ public void setVideoView(SurfaceView surfaceView, View parentResizableView) {
+ if (surfaceView == null) {
+ mMediaPlayer.setDisplay(null);
+ Log.d(TAG, "Disable Screen output!");
+
+ mMediaPlayer.setScreenOnWhilePlaying(false);
+ } else {
+ if (surfaceView.getHolder() != mSurfaceHolder) {
+ this.parentResizableView = parentResizableView;
+
+ surfaceView.getHolder().addCallback(mSHCallback);
+ //videoOutput.surfaceView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); //holder.setType(SurfaceHolder.SURFACE_TYPE_GPU);
+
+ populateVideo();
+
+ Log.d(TAG, "Enable Screen output!");
+ }
+ }
+ }
+
+
+ private int mSurfaceWidth;
+ private int mSurfaceHeight;
+ private SurfaceHolder mSurfaceHolder;
+ SurfaceHolder.Callback mSHCallback = new SurfaceHolder.Callback()
+ {
+ public void surfaceChanged(SurfaceHolder holder, int format, int surfaceWidth, int surfaceHeight)
+ {
+ mSurfaceWidth = surfaceWidth;
+ mSurfaceHeight = surfaceHeight;
+ }
+
+ public void surfaceCreated(SurfaceHolder holder)
+ {
+ mSurfaceHolder = holder;
+ mMediaPlayer.setDisplay(mSurfaceHolder); //TODO required
+ mMediaPlayer.setScreenOnWhilePlaying(true); //TODO required
+
+ Log.d(TAG, "surfaceCreated");
+ }
+
+ public void surfaceDestroyed(SurfaceHolder holder)
+ {
+ Log.d(TAG, "surfaceDestroyed");
+ }
+ };
+}
diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/services/podcast/PlaybackService.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/services/podcast/PlaybackService.java
new file mode 100644
index 00000000..15fdc19f
--- /dev/null
+++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/services/podcast/PlaybackService.java
@@ -0,0 +1,63 @@
+package de.luhmer.owncloudnewsreader.services.podcast;
+
+import android.content.Context;
+
+import de.luhmer.owncloudnewsreader.model.MediaItem;
+
+/**
+ * Created by david on 31.01.17.
+ */
+
+public abstract class PlaybackService {
+
+ public interface PodcastStatusListener {
+ void podcastStatusUpdated();
+ void podcastCompleted();
+ }
+
+ public enum Status { NOT_INITIALIZED, FAILED, PREPARING, PLAYING, PAUSED, STOPPED };
+ public enum VideoType { None, Video, VideoType, YouTube }
+
+ private Status mStatus = Status.NOT_INITIALIZED;
+ private PodcastStatusListener podcastStatusListener;
+ private MediaItem mediaItem;
+
+ public PlaybackService(Context context, PodcastStatusListener podcastStatusListener, MediaItem mediaItem) {
+ this.podcastStatusListener = podcastStatusListener;
+ this.mediaItem = mediaItem;
+ }
+
+ public abstract void destroy();
+ public abstract void play();
+ public abstract void pause();
+
+
+ public void seekTo(double percent) { }
+ public int getCurrentDuration() { return 0; }
+ public int getTotalDuration() { return 0; }
+ public VideoType getVideoType() { return VideoType.None; }
+
+ public MediaItem getMediaItem() {
+ return mediaItem;
+ }
+
+ public Status getStatus() {
+ return mStatus;
+ }
+
+ protected void setStatus(Status status) {
+ this.mStatus = status;
+ podcastStatusListener.podcastStatusUpdated();
+ }
+
+ protected void podcastCompleted() {
+ podcastStatusListener.podcastCompleted();
+ }
+
+ public boolean isMediaLoaded() {
+ return getStatus() != Status.NOT_INITIALIZED
+ && getStatus() != Status.PREPARING
+ && getStatus() != Status.FAILED;
+ }
+
+}
diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/services/podcast/TTSPlaybackService.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/services/podcast/TTSPlaybackService.java
new file mode 100644
index 00000000..430109f6
--- /dev/null
+++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/services/podcast/TTSPlaybackService.java
@@ -0,0 +1,89 @@
+package de.luhmer.owncloudnewsreader.services.podcast;
+
+import android.content.Context;
+import android.speech.tts.TextToSpeech;
+import android.speech.tts.UtteranceProgressListener;
+import android.util.Log;
+
+import java.util.HashMap;
+
+import de.luhmer.owncloudnewsreader.model.MediaItem;
+import de.luhmer.owncloudnewsreader.model.TTSItem;
+
+/**
+ * Created by david on 31.01.17.
+ */
+
+public class TTSPlaybackService extends PlaybackService implements TextToSpeech.OnInitListener {
+ private TextToSpeech ttsController;
+
+ public TTSPlaybackService(Context context, PodcastStatusListener podcastStatusListener, MediaItem mediaItem) {
+ super(context, podcastStatusListener, mediaItem);
+
+ try {
+ ttsController = new TextToSpeech(context, this);
+ setStatus(Status.PREPARING);
+
+ if(ttsController == null) {
+
+ ttsController.setOnUtteranceProgressListener(new UtteranceProgressListener() {
+ @Override
+ public void onDone(String utteranceId) {
+ podcastCompleted();
+ }
+
+ @Override public void onStart(String utteranceId) {}
+ @Override public void onError(String utteranceId) {}
+ });
+ }
+ else
+ onInit(TextToSpeech.SUCCESS);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void destroy() {
+ pause();
+ ttsController.shutdown();
+ ttsController = null;
+ }
+
+ @Override
+ public void play() {
+ onInit(TextToSpeech.SUCCESS);//restart last tts
+ }
+
+ @Override
+ public void pause() {
+ if (ttsController.isSpeaking()) {
+ ttsController.stop();
+ setStatus(Status.PAUSED);
+ }
+ }
+
+ @Override
+ public void onInit(int status) {
+ if (status == TextToSpeech.SUCCESS) {
+ /*
+ int result = ttsController.setLanguage(Locale.US);
+
+ if (result == TextToSpeech.LANG_MISSING_DATA
+ || result == TextToSpeech.LANG_NOT_SUPPORTED) {
+ Log.e("TTS", "This Language is not supported");
+ } else {
+ ttsController.speak(text, TextToSpeech.QUEUE_FLUSH, null);
+ }*/
+
+ HashMap<String,String> ttsParams = new HashMap<>();
+ ttsParams.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID,"dummyId");
+ ttsController.speak(((TTSItem)getMediaItem()).text, TextToSpeech.QUEUE_FLUSH, ttsParams);
+ setStatus(Status.PLAYING);
+ } else {
+ Log.e("TTS", "Initilization Failed!");
+ ttsController = null;
+ }
+ }
+
+}
diff --git a/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/services/podcast/YoutubePlaybackService.java b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/services/podcast/YoutubePlaybackService.java
new file mode 100644
index 00000000..29e3c87f
--- /dev/null
+++ b/News-Android-App/src/main/java/de/luhmer/owncloudnewsreader/services/podcast/YoutubePlaybackService.java
@@ -0,0 +1,163 @@
+package de.luhmer.owncloudnewsreader.services.podcast;
+
+import android.content.Context;
+import android.util.Log;
+import android.widget.Toast;
+
+import com.google.android.youtube.player.YouTubePlayer;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import de.luhmer.owncloudnewsreader.model.MediaItem;
+
+/**
+ * Created by david on 31.01.17.
+ */
+
+public class YoutubePlaybackService extends PlaybackService {
+
+ private static final String TAG = YoutubePlaybackService.class.getCanonicalName();
+ YouTubePlayer youTubePlayer;
+ Context context;
+
+ public YoutubePlaybackService(Context context, PodcastStatusListener podcastStatusListener, MediaItem mediaItem) {
+ super(context, podcastStatusListener, mediaItem);
+ this.context = context;
+ setStatus(Status.PREPARING);
+ }
+
+ @Override
+ public void destroy() {
+ if(youTubePlayer != null) {
+ youTubePlayer.pause();
+ youTubePlayer = null;
+ }
+ }
+
+ @Override
+ public void play() {
+ if(youTubePlayer != null) {
+ youTubePlayer.play();
+ }
+ }
+
+ @Override
+ public void pause() {
+ if(youTubePlayer != null) {
+ youTubePlayer.pause();
+ }
+ }
+
+ public void seekTo(double percent) {
+ if(youTubePlayer != null) {
+ double totalDuration = getTotalDuration();
+ int position = (int) ((totalDuration / 100d) * percent);
+ youTubePlayer.seekToMillis(position);
+ }
+ }
+ public int getCurrentDuration() {
+ if(youTubePlayer != null) {
+ return youTubePlayer.getCurrentTimeMillis();
+ }
+ return 0;
+ }
+
+ public int getTotalDuration() {
+ if(youTubePlayer != null) {
+ return youTubePlayer.getDurationMillis();
+ }
+ return 0;
+ }
+
+ @Override
+ public VideoType getVideoType() {
+ return VideoType.YouTube;
+ }
+
+ public void setYoutubePlayer(YouTubePlayer youTubePlayer, boolean wasRestored) {
+ this.youTubePlayer = youTubePlayer;
+ youTubePlayer.setPlaybackEventListener(youtubePlaybackEventListener);
+ youTubePlayer.setPlayerStateChangeListener(youtubePlayerStateChangeListener);
+
+ youTubePlayer.setPlayerStyle(YouTubePlayer.PlayerStyle.MINIMAL);
+
+ // Start buffering
+ if (!wasRestored) {
+ Pattern youtubeIdPattern = Pattern.compile(".*?v=([^&]*)");
+ Matcher matcher = youtubeIdPattern.matcher(getMediaItem().link);
+ if(matcher.matches()) {
+ String youtubeId = matcher.group(1);
+ youTubePlayer.cueVideo(youtubeId);
+ } else {
+ Toast.makeText(context, "Cannot find youtube video id", Toast.LENGTH_LONG).show();
+ setStatus(Status.FAILED);
+ }
+ }
+ }
+
+
+ YouTubePlayer.PlayerStateChangeListener youtubePlayerStateChangeListener = new YouTubePlayer.PlayerStateChangeListener() {
+ @Override
+ public void onLoading() {
+ Log.d(TAG, "onLoading() called");
+ }
+
+ @Override
+ public void onLoaded(String s) {
+ Log.d(TAG, "onLoaded() called with: s = [" + s + "]");
+ youTubePlayer.play();
+ }
+
+ @Override
+ public void onAdStarted() {
+ Log.d(TAG, "onAdStarted() called");
+ }
+
+ @Override
+ public void onVideoStarted() {
+ Log.d(TAG, "onVideoStarted() called");
+ }
+
+ @Override
+ public void onVideoEnded() {
+ Log.d(TAG, "onVideoEnded() called");
+ }
+
+ @Override
+ public void onError(YouTubePlayer.ErrorReason errorReason) {
+ Log.d(TAG, "onError() called with: errorReason = [" + errorReason + "]");
+ }
+ };
+
+
+ YouTubePlayer.PlaybackEventListener youtubePlaybackEventListener = new YouTubePlayer.PlaybackEventListener() {
+ @Override
+ public void onPlaying() {
+ Log.d(TAG, "onPlaying() called");
+ setStatus(Status.PLAYING);
+ }
+
+ @Override
+ public void onPaused() {
+ Log.d(TAG, "onPaused() called");
+ setStatus(Status.PAUSED);
+ }
+
+ @Override
+ public void onStopped() {
+ Log.d(TAG, "onStopped() called");
+ setStatus(Status.PAUSED);
+ }
+
+ @Override
+ public void onBuffering(boolean b) {
+ Log.d(TAG, "onBuffering() called with: b = [" + b + "]");
+ }
+
+ @Override
+ public void onSeekTo(int i) {
+ Log.d(TAG, "onSeekTo() called with: i = [" + i + "]");
+ }
+ };
+}