Added support for reading chapters from streams

This commit is contained in:
daniel oeh 2012-09-22 11:56:50 +02:00
parent 7bbbeb0382
commit 142f3cb9db
5 changed files with 129 additions and 14 deletions

View File

@ -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;

View File

@ -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");

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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;