Added support for reading chapters from streams
This commit is contained in:
parent
7bbbeb0382
commit
142f3cb9db
|
@ -81,7 +81,13 @@ public class AudioplayerActivity extends MediaplayerActivity {
|
|||
@Override
|
||||
protected void loadMediaInfo() {
|
||||
super.loadMediaInfo();
|
||||
if (controller.getMedia() != null) {
|
||||
final FeedMedia media = controller.getMedia();
|
||||
if (media != null) {
|
||||
if (media.getItem().getChapters() != null
|
||||
&& pagerAdapter.getCount() < MediaPlayerPagerAdapter.NUM_ITEMS_WITH_CHAPTERS) {
|
||||
pagerAdapter
|
||||
.setNumItems(MediaPlayerPagerAdapter.NUM_ITEMS_WITH_CHAPTERS);
|
||||
}
|
||||
pagerAdapter.notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
|
@ -96,6 +102,9 @@ public class AudioplayerActivity extends MediaplayerActivity {
|
|||
private static final int POS_DESCR = 1;
|
||||
private static final int POS_CHAPTERS = 2;
|
||||
|
||||
public static final int NUM_ITEMS_WITH_CHAPTERS = 3;
|
||||
public static final int NUM_ITMEMS_WITHOUT_CHAPTERS = 2;
|
||||
|
||||
public MediaPlayerPagerAdapter(FragmentManager fm, int numItems,
|
||||
AudioplayerActivity activity) {
|
||||
super(fm);
|
||||
|
@ -123,8 +132,8 @@ public class AudioplayerActivity extends MediaplayerActivity {
|
|||
public void onListItemClick(ListView l, View v,
|
||||
int position, long id) {
|
||||
super.onListItemClick(l, v, position, id);
|
||||
Chapter chapter = (Chapter) this.getListAdapter().getItem(
|
||||
position);
|
||||
Chapter chapter = (Chapter) this.getListAdapter()
|
||||
.getItem(position);
|
||||
controller.seekToChapter(chapter);
|
||||
}
|
||||
|
||||
|
@ -161,6 +170,10 @@ public class AudioplayerActivity extends MediaplayerActivity {
|
|||
return numItems;
|
||||
}
|
||||
|
||||
public void setNumItems(int numItems) {
|
||||
this.numItems = numItems;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemPosition(Object object) {
|
||||
return POSITION_UNCHANGED;
|
||||
|
|
|
@ -46,6 +46,7 @@ import de.danoeh.antennapod.feed.FeedMedia;
|
|||
import de.danoeh.antennapod.feed.SimpleChapter;
|
||||
import de.danoeh.antennapod.receiver.MediaButtonReceiver;
|
||||
import de.danoeh.antennapod.receiver.PlayerWidget;
|
||||
import de.danoeh.antennapod.util.ChapterUtils;
|
||||
|
||||
/** Controls the MediaPlayer that plays a FeedMedia-file */
|
||||
public class PlaybackService extends Service {
|
||||
|
@ -505,6 +506,23 @@ public class PlaybackService extends Service {
|
|||
if (startWhenPrepared) {
|
||||
play();
|
||||
}
|
||||
if (shouldStream && media.getItem().getChapters() == null) {
|
||||
// load chapters if available
|
||||
Thread chapterLoader = new Thread() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (AppConfig.DEBUG) Log.d(TAG, "Starting chapterLoader thread");
|
||||
ChapterUtils.readID3ChaptersFromFeedMediaDownloadUrl(media.getItem());
|
||||
if (media.getItem().getChapters() != null) {
|
||||
sendNotificationBroadcast(NOTIFICATION_TYPE_RELOAD, 0);
|
||||
}
|
||||
if (AppConfig.DEBUG) Log.d(TAG, "ChapterLoaderThread has finished");
|
||||
}
|
||||
|
||||
};
|
||||
chapterLoader.start();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -961,7 +979,7 @@ public class PlaybackService extends Service {
|
|||
try {
|
||||
Thread.sleep(UPDATE_INTERVALL);
|
||||
waitingTime -= UPDATE_INTERVALL;
|
||||
|
||||
|
||||
if (waitingTime <= 0) {
|
||||
if (AppConfig.DEBUG)
|
||||
Log.d(TAG, "Waiting completed");
|
||||
|
|
|
@ -695,7 +695,7 @@ public class DownloadService extends Service {
|
|||
}
|
||||
|
||||
if (media.getItem().getChapters() == null) {
|
||||
ChapterUtils.readID3ChaptersFromFeedItem(media.getItem());
|
||||
ChapterUtils.readID3ChaptersFromFeedMediaFileUrl(media.getItem());
|
||||
if (media.getItem().getChapters() != null) {
|
||||
chaptersRead = true;
|
||||
}
|
||||
|
|
|
@ -5,6 +5,9 @@ import java.io.File;
|
|||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
@ -25,7 +28,63 @@ public class ChapterUtils {
|
|||
private ChapterUtils() {
|
||||
}
|
||||
|
||||
public static void readID3ChaptersFromFeedItem(FeedItem item) {
|
||||
/**
|
||||
* Uses the download URL of a media object of a feeditem to read its ID3
|
||||
* chapters.
|
||||
*/
|
||||
public static void readID3ChaptersFromFeedMediaDownloadUrl(FeedItem item) {
|
||||
if (AppConfig.DEBUG)
|
||||
Log.d(TAG, "Reading id3 chapters from item " + item.getTitle());
|
||||
final FeedMedia media = item.getMedia();
|
||||
if (media != null && media.getDownload_url() != null) {
|
||||
InputStream in = null;
|
||||
try {
|
||||
URL url = new URL(media.getDownload_url());
|
||||
ChapterReader reader = new ChapterReader();
|
||||
|
||||
in = url.openStream();
|
||||
reader.readInputStream(in);
|
||||
List<Chapter> chapters = reader.getChapters();
|
||||
|
||||
if (chapters != null) {
|
||||
Collections
|
||||
.sort(chapters, new ChapterStartTimeComparator());
|
||||
processChapters(chapters, item);
|
||||
if (chaptersValid(chapters)) {
|
||||
item.setChapters(chapters);
|
||||
Log.i(TAG, "Chapters loaded");
|
||||
} else {
|
||||
Log.e(TAG, "Chapter data was invalid");
|
||||
}
|
||||
} else {
|
||||
Log.i(TAG, "ChapterReader could not find any ID3 chapters");
|
||||
}
|
||||
} catch (MalformedURLException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} catch (ID3ReaderException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (in != null) {
|
||||
try {
|
||||
in.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Log.e(TAG,
|
||||
"Unable to read ID3 chapters: media or download URL was null");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses the file URL of a media object of a feeditem to read its ID3
|
||||
* chapters.
|
||||
*/
|
||||
public static void readID3ChaptersFromFeedMediaFileUrl(FeedItem item) {
|
||||
if (AppConfig.DEBUG)
|
||||
Log.d(TAG, "Reading id3 chapters from item " + item.getTitle());
|
||||
final FeedMedia media = item.getMedia();
|
||||
|
@ -40,17 +99,20 @@ public class ChapterUtils {
|
|||
in = new BufferedInputStream(new FileInputStream(source));
|
||||
reader.readInputStream(in);
|
||||
List<Chapter> chapters = reader.getChapters();
|
||||
|
||||
|
||||
if (chapters != null) {
|
||||
Collections.sort(chapters, new ChapterStartTimeComparator());
|
||||
Collections.sort(chapters,
|
||||
new ChapterStartTimeComparator());
|
||||
processChapters(chapters, item);
|
||||
if (chaptersValid(chapters)) {
|
||||
item.setChapters(chapters);
|
||||
Log.i(TAG, "Chapters loaded");
|
||||
} else {
|
||||
Log.e(TAG, "Chapter data was invalid");
|
||||
}
|
||||
} else {
|
||||
Log.i(TAG, "ChapterReader could not find any ID3 chapters");
|
||||
Log.i(TAG,
|
||||
"ChapterReader could not find any ID3 chapters");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
|
@ -93,5 +155,5 @@ public class ChapterUtils {
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -43,9 +43,13 @@ public class ID3Reader {
|
|||
while (readerPosition < tagHeader.getSize()) {
|
||||
FrameHeader frameHeader = createFrameHeader(readBytes(
|
||||
input, HEADER_LENGTH));
|
||||
rc = onStartFrameHeader(frameHeader, input);
|
||||
if (rc == ACTION_SKIP) {
|
||||
skipBytes(input, frameHeader.getSize());
|
||||
if (checkForNullString(frameHeader.getId())) {
|
||||
break;
|
||||
} else {
|
||||
rc = onStartFrameHeader(frameHeader, input);
|
||||
if (rc == ACTION_SKIP) {
|
||||
skipBytes(input, frameHeader.getSize());
|
||||
}
|
||||
}
|
||||
}
|
||||
onEndTag();
|
||||
|
@ -53,6 +57,25 @@ public class ID3Reader {
|
|||
}
|
||||
}
|
||||
|
||||
/** Returns true if string only contains null-bytes. */
|
||||
private boolean checkForNullString(String s) {
|
||||
if (!s.isEmpty()) {
|
||||
int i = 0;
|
||||
if (s.charAt(i) == 0) {
|
||||
for (i = 1; i < s.length(); i++) {
|
||||
if (s.charAt(i) != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a certain number of bytes from the given input stream. This method
|
||||
* changes the readerPosition-attribute.
|
||||
|
@ -80,7 +103,6 @@ public class ID3Reader {
|
|||
int skipped = 0;
|
||||
while (skipped < number) {
|
||||
skipped += input.skip(number - skipped);
|
||||
System.out.println("Skipped = " + skipped);
|
||||
}
|
||||
|
||||
readerPosition += number;
|
||||
|
|
Loading…
Reference in New Issue