ad service_id field, and pulled video/audio stream out of streaminfo

This commit is contained in:
Christian Schabesberger 2016-03-04 13:36:06 +01:00
parent d9cd928100
commit b1d2e64450
23 changed files with 230 additions and 126 deletions

View File

@ -4,10 +4,12 @@ import android.test.AndroidTestCase;
import org.apache.commons.lang.exception.ExceptionUtils; import org.apache.commons.lang.exception.ExceptionUtils;
import org.schabi.newpipe.extractor.SearchResult; import org.schabi.newpipe.extractor.SearchResult;
import org.schabi.newpipe.extractor.ServiceList;
import org.schabi.newpipe.extractor.StreamPreviewInfo; import org.schabi.newpipe.extractor.StreamPreviewInfo;
import org.schabi.newpipe.extractor.SearchEngine; import org.schabi.newpipe.extractor.SearchEngine;
import org.schabi.newpipe.extractor.services.youtube.YoutubeSearchEngine; import org.schabi.newpipe.extractor.services.youtube.YoutubeSearchEngine;
import org.schabi.newpipe.Downloader; import org.schabi.newpipe.Downloader;
import org.schabi.newpipe.extractor.services.youtube.YoutubeService;
import java.util.ArrayList; import java.util.ArrayList;
@ -38,7 +40,8 @@ public class YoutubeSearchEngineTest extends AndroidTestCase {
@Override @Override
public void setUp() throws Exception{ public void setUp() throws Exception{
super.setUp(); super.setUp();
SearchEngine engine = new YoutubeSearchEngine(); SearchEngine engine = ServiceList.getService("Youtube")
.getSearchEngineInstance(new Downloader());
result = engine.search("bla", result = engine.search("bla",
0, "de", new Downloader()).getSearchResult(); 0, "de", new Downloader()).getSearchResult();

View File

@ -5,6 +5,9 @@ import android.test.AndroidTestCase;
import org.schabi.newpipe.Downloader; import org.schabi.newpipe.Downloader;
import org.schabi.newpipe.extractor.ExtractionException; import org.schabi.newpipe.extractor.ExtractionException;
import org.schabi.newpipe.extractor.ParsingException; import org.schabi.newpipe.extractor.ParsingException;
import org.schabi.newpipe.extractor.ServiceList;
import org.schabi.newpipe.extractor.StreamExtractor;
import org.schabi.newpipe.extractor.VideoStream;
import org.schabi.newpipe.extractor.services.youtube.YoutubeStreamExtractor; import org.schabi.newpipe.extractor.services.youtube.YoutubeStreamExtractor;
import org.schabi.newpipe.extractor.StreamInfo; import org.schabi.newpipe.extractor.StreamInfo;
@ -31,15 +34,15 @@ import java.io.IOException;
*/ */
public class YoutubeStreamExtractorDefaultTest extends AndroidTestCase { public class YoutubeStreamExtractorDefaultTest extends AndroidTestCase {
private YoutubeStreamExtractor extractor; private StreamExtractor extractor;
public void setUp() throws IOException, ExtractionException { public void setUp() throws IOException, ExtractionException {
/* some anonymus video test /* some anonymus video test
extractor = new YoutubeStreamExtractor("https://www.youtube.com/watch?v=FmG385_uUys", extractor = new YoutubeStreamExtractor("https://www.youtube.com/watch?v=FmG385_uUys",
new Downloader()); */ new Downloader()); */
/* some vevo video (suggested to test against) */ /* some vevo video (suggested to test against) */
extractor = new YoutubeStreamExtractor("https://www.youtube.com/watch?v=YQHsXMglC9A", extractor = ServiceList.getService("Youtube")
new Downloader()); .getExtractorInstance("https://www.youtube.com/watch?v=YQHsXMglC9A", new Downloader());
} }
public void testGetInvalidTimeStamp() throws ParsingException { public void testGetInvalidTimeStamp() throws ParsingException {
@ -48,8 +51,9 @@ public class YoutubeStreamExtractorDefaultTest extends AndroidTestCase {
} }
public void testGetValidTimeStamp() throws ExtractionException, IOException { public void testGetValidTimeStamp() throws ExtractionException, IOException {
YoutubeStreamExtractor extractor = StreamExtractor extractor =
new YoutubeStreamExtractor("https://youtu.be/FmG385_uUys?t=174", new Downloader()); ServiceList.getService("Youtube")
.getExtractorInstance("https://youtu.be/FmG385_uUys?t=174", new Downloader());
assertTrue(Integer.toString(extractor.getTimeStamp()), assertTrue(Integer.toString(extractor.getTimeStamp()),
extractor.getTimeStamp() == 174); extractor.getTimeStamp() == 174);
} }
@ -94,7 +98,7 @@ public class YoutubeStreamExtractorDefaultTest extends AndroidTestCase {
} }
public void testGetVideoStreams() throws ParsingException { public void testGetVideoStreams() throws ParsingException {
for(StreamInfo.VideoStream s : extractor.getVideoStreams()) { for(VideoStream s : extractor.getVideoStreams()) {
assertTrue(s.url, assertTrue(s.url,
s.url.contains("https://")); s.url.contains("https://"));
assertTrue(s.resolution.length() > 0); assertTrue(s.resolution.length() > 0);

View File

@ -4,6 +4,7 @@ import android.test.AndroidTestCase;
import org.schabi.newpipe.Downloader; import org.schabi.newpipe.Downloader;
import org.schabi.newpipe.extractor.ExtractionException; import org.schabi.newpipe.extractor.ExtractionException;
import org.schabi.newpipe.extractor.ServiceList;
import org.schabi.newpipe.extractor.services.youtube.YoutubeStreamExtractor; import org.schabi.newpipe.extractor.services.youtube.YoutubeStreamExtractor;
import java.io.IOException; import java.io.IOException;
@ -38,9 +39,9 @@ public class YoutubeStreamExtractorGemaTest extends AndroidTestCase {
public void testGemaError() throws IOException, ExtractionException { public void testGemaError() throws IOException, ExtractionException {
if(testActive) { if(testActive) {
try { try {
new YoutubeStreamExtractor("https://www.youtube.com/watch?v=3O1_3zBUKM8", ServiceList.getService("Youtube")
.getExtractorInstance("https://www.youtube.com/watch?v=3O1_3zBUKM8",
new Downloader()); new Downloader());
assertTrue("Gema exception not thrown", false);
} catch(YoutubeStreamExtractor.GemaException ge) { } catch(YoutubeStreamExtractor.GemaException ge) {
assertTrue(true); assertTrue(true);
} }

View File

@ -5,17 +5,21 @@ import android.test.AndroidTestCase;
import org.schabi.newpipe.Downloader; import org.schabi.newpipe.Downloader;
import org.schabi.newpipe.extractor.ExtractionException; import org.schabi.newpipe.extractor.ExtractionException;
import org.schabi.newpipe.extractor.ParsingException; import org.schabi.newpipe.extractor.ParsingException;
import org.schabi.newpipe.extractor.ServiceList;
import org.schabi.newpipe.extractor.StreamExtractor;
import org.schabi.newpipe.extractor.StreamInfo; import org.schabi.newpipe.extractor.StreamInfo;
import org.schabi.newpipe.extractor.VideoStream;
import org.schabi.newpipe.extractor.services.youtube.YoutubeStreamExtractor; import org.schabi.newpipe.extractor.services.youtube.YoutubeStreamExtractor;
import java.io.IOException; import java.io.IOException;
public class YoutubeStreamExtractorRestrictedTest extends AndroidTestCase { public class YoutubeStreamExtractorRestrictedTest extends AndroidTestCase {
private YoutubeStreamExtractor extractor; private StreamExtractor extractor;
public void setUp() throws IOException, ExtractionException { public void setUp() throws IOException, ExtractionException {
extractor = new YoutubeStreamExtractor("https://www.youtube.com/watch?v=i6JTvzrpBy0", extractor = ServiceList.getService("Youtube")
new Downloader()); .getExtractorInstance("https://www.youtube.com/watch?v=i6JTvzrpBy0",
new Downloader());
} }
public void testGetInvalidTimeStamp() throws ParsingException { public void testGetInvalidTimeStamp() throws ParsingException {
@ -24,8 +28,9 @@ public class YoutubeStreamExtractorRestrictedTest extends AndroidTestCase {
} }
public void testGetValidTimeStamp() throws ExtractionException, IOException { public void testGetValidTimeStamp() throws ExtractionException, IOException {
YoutubeStreamExtractor extractor = StreamExtractor extractor=ServiceList.getService("Youtube")
new YoutubeStreamExtractor("https://youtu.be/FmG385_uUys?t=174", new Downloader()); .getExtractorInstance("https://youtu.be/FmG385_uUys?t=174",
new Downloader());
assertTrue(Integer.toString(extractor.getTimeStamp()), assertTrue(Integer.toString(extractor.getTimeStamp()),
extractor.getTimeStamp() == 174); extractor.getTimeStamp() == 174);
} }
@ -73,7 +78,7 @@ public class YoutubeStreamExtractorRestrictedTest extends AndroidTestCase {
} }
public void testGetVideoStreams() throws ParsingException { public void testGetVideoStreams() throws ParsingException {
for(StreamInfo.VideoStream s : extractor.getVideoStreams()) { for(VideoStream s : extractor.getVideoStreams()) {
assertTrue(s.url, assertTrue(s.url,
s.url.contains("https://")); s.url.contains("https://"));
assertTrue(s.resolution.length() > 0); assertTrue(s.resolution.length() > 0);

View File

@ -13,6 +13,7 @@ import android.widget.ArrayAdapter;
import org.schabi.newpipe.extractor.MediaFormat; import org.schabi.newpipe.extractor.MediaFormat;
import org.schabi.newpipe.extractor.StreamInfo; import org.schabi.newpipe.extractor.StreamInfo;
import org.schabi.newpipe.extractor.VideoStream;
import java.util.List; import java.util.List;
@ -75,7 +76,7 @@ class ActionBarHandler {
} }
} }
public void setupStreamList(final List<StreamInfo.VideoStream> videoStreams) { public void setupStreamList(final List<VideoStream> videoStreams) {
if (activity != null) { if (activity != null) {
selectedVideoStream = 0; selectedVideoStream = 0;
@ -83,7 +84,7 @@ class ActionBarHandler {
// this array will be shown in the dropdown menu for selecting the stream/resolution. // this array will be shown in the dropdown menu for selecting the stream/resolution.
String[] itemArray = new String[videoStreams.size()]; String[] itemArray = new String[videoStreams.size()];
for (int i = 0; i < videoStreams.size(); i++) { for (int i = 0; i < videoStreams.size(); i++) {
StreamInfo.VideoStream item = videoStreams.get(i); VideoStream item = videoStreams.get(i);
itemArray[i] = MediaFormat.getNameById(item.format) + " " + item.resolution; itemArray[i] = MediaFormat.getNameById(item.format) + " " + item.resolution;
} }
int defaultResolution = getDefaultResolution(videoStreams); int defaultResolution = getDefaultResolution(videoStreams);
@ -108,13 +109,13 @@ class ActionBarHandler {
} }
private int getDefaultResolution(final List<StreamInfo.VideoStream> videoStreams) { private int getDefaultResolution(final List<VideoStream> videoStreams) {
String defaultResolution = defaultPreferences String defaultResolution = defaultPreferences
.getString(activity.getString(R.string.default_resolution_key), .getString(activity.getString(R.string.default_resolution_key),
activity.getString(R.string.default_resolution_value)); activity.getString(R.string.default_resolution_value));
for (int i = 0; i < videoStreams.size(); i++) { for (int i = 0; i < videoStreams.size(); i++) {
StreamInfo.VideoStream item = videoStreams.get(i); VideoStream item = videoStreams.get(i);
if (defaultResolution.equals(item.resolution)) { if (defaultResolution.equals(item.resolution)) {
return i; return i;
} }

View File

@ -73,7 +73,7 @@ public class VideoItemDetailActivity extends AppCompatActivity {
StreamingService[] serviceList = ServiceList.getServices(); StreamingService[] serviceList = ServiceList.getServices();
//StreamExtractor videoExtractor = null; //StreamExtractor videoExtractor = null;
for (int i = 0; i < serviceList.length; i++) { for (int i = 0; i < serviceList.length; i++) {
if (serviceList[i].getUrlIdHandler().acceptUrl(videoUrl)) { if (serviceList[i].getUrlIdHandlerInstance().acceptUrl(videoUrl)) {
arguments.putInt(VideoItemDetailFragment.STREAMING_SERVICE, i); arguments.putInt(VideoItemDetailFragment.STREAMING_SERVICE, i);
currentStreamingService = i; currentStreamingService = i;
//videoExtractor = ServiceList.getService(i).getExtractorInstance(); //videoExtractor = ServiceList.getService(i).getExtractorInstance();

View File

@ -46,6 +46,7 @@ import com.nostra13.universalimageloader.core.listener.ImageLoadingListener;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Vector; import java.util.Vector;
import org.schabi.newpipe.extractor.AudioStream;
import org.schabi.newpipe.extractor.MediaFormat; import org.schabi.newpipe.extractor.MediaFormat;
import org.schabi.newpipe.extractor.ParsingException; import org.schabi.newpipe.extractor.ParsingException;
import org.schabi.newpipe.extractor.ServiceList; import org.schabi.newpipe.extractor.ServiceList;
@ -53,6 +54,7 @@ import org.schabi.newpipe.extractor.StreamExtractor;
import org.schabi.newpipe.extractor.StreamInfo; import org.schabi.newpipe.extractor.StreamInfo;
import org.schabi.newpipe.extractor.StreamPreviewInfo; import org.schabi.newpipe.extractor.StreamPreviewInfo;
import org.schabi.newpipe.extractor.StreamingService; import org.schabi.newpipe.extractor.StreamingService;
import org.schabi.newpipe.extractor.VideoStream;
import org.schabi.newpipe.extractor.services.youtube.YoutubeStreamExtractor; import org.schabi.newpipe.extractor.services.youtube.YoutubeStreamExtractor;
@ -388,8 +390,8 @@ public class VideoItemDetailFragment extends Fragment {
descriptionView.setMovementMethod(LinkMovementMethod.getInstance()); descriptionView.setMovementMethod(LinkMovementMethod.getInstance());
// parse streams // parse streams
Vector<StreamInfo.VideoStream> streamsToUse = new Vector<>(); Vector<VideoStream> streamsToUse = new Vector<>();
for (StreamInfo.VideoStream i : info.video_streams) { for (VideoStream i : info.video_streams) {
if (useStream(i, streamsToUse)) { if (useStream(i, streamsToUse)) {
streamsToUse.add(i); streamsToUse.add(i);
} }
@ -555,7 +557,7 @@ public class VideoItemDetailFragment extends Fragment {
// website which was crawled. Then the ui has to understand this and act right. // website which was crawled. Then the ui has to understand this and act right.
if (info.audio_streams != null) { if (info.audio_streams != null) {
StreamInfo.AudioStream audioStream = AudioStream audioStream =
info.audio_streams.get(getPreferredAudioStreamId(info)); info.audio_streams.get(getPreferredAudioStreamId(info));
String audioSuffix = "." + MediaFormat.getSuffixById(audioStream.format); String audioSuffix = "." + MediaFormat.getSuffixById(audioStream.format);
@ -564,7 +566,7 @@ public class VideoItemDetailFragment extends Fragment {
} }
if (info.video_streams != null) { if (info.video_streams != null) {
StreamInfo.VideoStream selectedStreamItem = info.video_streams.get(selectedStreamId); VideoStream selectedStreamItem = info.video_streams.get(selectedStreamId);
String videoSuffix = "." + MediaFormat.getSuffixById(selectedStreamItem.format); String videoSuffix = "." + MediaFormat.getSuffixById(selectedStreamItem.format);
args.putString(DownloadDialog.FILE_SUFFIX_VIDEO, videoSuffix); args.putString(DownloadDialog.FILE_SUFFIX_VIDEO, videoSuffix);
args.putString(DownloadDialog.VIDEO_URL, selectedStreamItem.url); args.putString(DownloadDialog.VIDEO_URL, selectedStreamItem.url);
@ -591,7 +593,7 @@ public class VideoItemDetailFragment extends Fragment {
boolean useExternalAudioPlayer = PreferenceManager.getDefaultSharedPreferences(activity) boolean useExternalAudioPlayer = PreferenceManager.getDefaultSharedPreferences(activity)
.getBoolean(activity.getString(R.string.use_external_audio_player_key), false); .getBoolean(activity.getString(R.string.use_external_audio_player_key), false);
Intent intent; Intent intent;
StreamInfo.AudioStream audioStream = AudioStream audioStream =
info.audio_streams.get(getPreferredAudioStreamId(info)); info.audio_streams.get(getPreferredAudioStreamId(info));
if (!useExternalAudioPlayer && android.os.Build.VERSION.SDK_INT >= 18) { if (!useExternalAudioPlayer && android.os.Build.VERSION.SDK_INT >= 18) {
//internal music player: explicit intent //internal music player: explicit intent
@ -754,8 +756,8 @@ public class VideoItemDetailFragment extends Fragment {
.show(); .show();
} }
private boolean useStream(StreamInfo.VideoStream stream, Vector<StreamInfo.VideoStream> streams) { private boolean useStream(VideoStream stream, Vector<VideoStream> streams) {
for(StreamInfo.VideoStream i : streams) { for(VideoStream i : streams) {
if(i.resolution.equals(stream.resolution)) { if(i.resolution.equals(stream.resolution)) {
return false; return false;
} }
@ -847,7 +849,7 @@ public class VideoItemDetailFragment extends Fragment {
public void playVideo(final StreamInfo info) { public void playVideo(final StreamInfo info) {
// ----------- THE MAGIC MOMENT --------------- // ----------- THE MAGIC MOMENT ---------------
StreamInfo.VideoStream selectedVideoStream = VideoStream selectedVideoStream =
info.video_streams.get(actionBarHandler.getSelectedVideoStream()); info.video_streams.get(actionBarHandler.getSelectedVideoStream());
if (PreferenceManager.getDefaultSharedPreferences(activity) if (PreferenceManager.getDefaultSharedPreferences(activity)

View File

@ -357,7 +357,8 @@ public class VideoItemListActivity extends AppCompatActivity
} }
private void searchSuggestions(String query) { private void searchSuggestions(String query) {
suggestionSearchRunnable = new SuggestionSearchRunnable(streamingService.getSearchEngineInstance(), suggestionSearchRunnable =
new SuggestionSearchRunnable(streamingService.getSearchEngineInstance(new Downloader()),
query); query);
searchThread = new Thread(suggestionSearchRunnable); searchThread = new Thread(suggestionSearchRunnable);
searchThread.start(); searchThread.start();

View File

@ -185,7 +185,7 @@ public class VideoItemListFragment extends ListFragment {
private void startSearch(String query, int page) { private void startSearch(String query, int page) {
currentRequestId++; currentRequestId++;
terminateThreads(); terminateThreads();
searchRunnable = new SearchRunnable(streamingService.getSearchEngineInstance(), searchRunnable = new SearchRunnable(streamingService.getSearchEngineInstance(new Downloader()),
query, page, currentRequestId); query, page, currentRequestId);
searchThread = new Thread(searchRunnable); searchThread = new Thread(searchRunnable);
searchThread.start(); searchThread.start();

View File

@ -22,6 +22,7 @@ import android.graphics.Bitmap;
/**Common properties between StreamInfo and StreamPreviewInfo.*/ /**Common properties between StreamInfo and StreamPreviewInfo.*/
public abstract class AbstractVideoInfo { public abstract class AbstractVideoInfo {
public int service_id = -1;
public String id = ""; public String id = "";
public String title = ""; public String title = "";
public String uploader = ""; public String uploader = "";

View File

@ -0,0 +1,46 @@
package org.schabi.newpipe.extractor;
/**
* Created by Christian Schabesberger on 04.03.16.
*
* Copyright (C) Christian Schabesberger 2016 <chris.schabesberger@mailbox.org>
* AudioStream.java is part of NewPipe.
*
* NewPipe is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* NewPipe is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
*/
public class AudioStream {
public String url = "";
public int format = -1;
public int bandwidth = -1;
public int sampling_rate = -1;
public AudioStream(String url, int format, int bandwidth, int samplingRate) {
this.url = url; this.format = format;
this.bandwidth = bandwidth; this.sampling_rate = samplingRate;
}
// reveals wether two streams are the same, but have diferent urls
public boolean equalStats(AudioStream cmp) {
return format == cmp.format
&& bandwidth == cmp.bandwidth
&& sampling_rate == cmp.sampling_rate;
}
// revelas wether two streams are equal
public boolean equals(AudioStream cmp) {
return equalStats(cmp)
&& url == cmp.url;
}
}

View File

@ -37,7 +37,7 @@ public class DashMpdParser {
} }
} }
public static List<StreamInfo.AudioStream> getAudioStreams(String dashManifestUrl, public static List<AudioStream> getAudioStreams(String dashManifestUrl,
Downloader downloader) Downloader downloader)
throws DashMpdParsingException { throws DashMpdParsingException {
String dashDoc; String dashDoc;
@ -46,7 +46,7 @@ public class DashMpdParser {
} catch(IOException ioe) { } catch(IOException ioe) {
throw new DashMpdParsingException("Could not get dash mpd: " + dashManifestUrl, ioe); throw new DashMpdParsingException("Could not get dash mpd: " + dashManifestUrl, ioe);
} }
Vector<StreamInfo.AudioStream> audioStreams = new Vector<>(); Vector<AudioStream> audioStreams = new Vector<>();
try { try {
XmlPullParser parser = Xml.newPullParser(); XmlPullParser parser = Xml.newPullParser();
parser.setInput(new StringReader(dashDoc)); parser.setInput(new StringReader(dashDoc));
@ -83,7 +83,7 @@ public class DashMpdParser {
} else if(currentMimeType.equals(MediaFormat.M4A.mimeType)) { } else if(currentMimeType.equals(MediaFormat.M4A.mimeType)) {
format = MediaFormat.M4A.id; format = MediaFormat.M4A.id;
} }
audioStreams.add(new StreamInfo.AudioStream(parser.getText(), audioStreams.add(new AudioStream(parser.getText(),
format, currentBandwidth, currentSamplingRate)); format, currentBandwidth, currentSamplingRate));
} }
break; break;

View File

@ -26,17 +26,29 @@ import java.util.Vector;
*/ */
@SuppressWarnings("ALL") @SuppressWarnings("ALL")
public interface SearchEngine { public abstract class SearchEngine {
public class NothingFoundException extends ExtractionException { public static class NothingFoundException extends ExtractionException {
public NothingFoundException(String message) { public NothingFoundException(String message) {
super(message); super(message);
} }
} }
ArrayList<String> suggestionList(String query,String contentCountry, Downloader dl) private StreamPreviewInfoCollector collector;
public SearchEngine(StreamUrlIdHandler urlIdHandler, int serviceId) {
collector = new StreamPreviewInfoCollector(urlIdHandler, serviceId);
}
public StreamPreviewInfoCollector getStreamPreviewInfoCollector() {
return collector;
}
public abstract ArrayList<String> suggestionList(
String query,String contentCountry, Downloader dl)
throws ExtractionException, IOException; throws ExtractionException, IOException;
//Result search(String query, int page); //Result search(String query, int page);
StreamPreviewInfoCollector search(String query, int page, String contentCountry, Downloader dl) public abstract StreamPreviewInfoCollector search(
String query, int page, String contentCountry, Downloader dl)
throws ExtractionException, IOException; throws ExtractionException, IOException;
} }

View File

@ -31,7 +31,7 @@ import org.schabi.newpipe.extractor.services.youtube.YoutubeService;
public class ServiceList { public class ServiceList {
private static final String TAG = ServiceList.class.toString(); private static final String TAG = ServiceList.class.toString();
private static final StreamingService[] services = { private static final StreamingService[] services = {
new YoutubeService() new YoutubeService(0)
}; };
public static StreamingService[] getServices() { public static StreamingService[] getServices() {
return services; return services;

View File

@ -26,7 +26,9 @@ import java.util.List;
@SuppressWarnings("ALL") @SuppressWarnings("ALL")
public interface StreamExtractor { public abstract class StreamExtractor {
private int serviceId;
public class ExctractorInitException extends ExtractionException { public class ExctractorInitException extends ExtractionException {
public ExctractorInitException(String message) { public ExctractorInitException(String message) {
@ -49,6 +51,10 @@ public interface StreamExtractor {
} }
} }
public StreamExtractor(String url, Downloader dl, int serviceId) {
this.serviceId = serviceId;
}
public abstract int getTimeStamp() throws ParsingException; public abstract int getTimeStamp() throws ParsingException;
public abstract String getTitle() throws ParsingException; public abstract String getTitle() throws ParsingException;
public abstract String getDescription() throws ParsingException; public abstract String getDescription() throws ParsingException;
@ -58,9 +64,9 @@ public interface StreamExtractor {
public abstract String getUploadDate() throws ParsingException; public abstract String getUploadDate() throws ParsingException;
public abstract String getThumbnailUrl() throws ParsingException; public abstract String getThumbnailUrl() throws ParsingException;
public abstract String getUploaderThumbnailUrl() throws ParsingException; public abstract String getUploaderThumbnailUrl() throws ParsingException;
public abstract List<StreamInfo.AudioStream> getAudioStreams() throws ParsingException; public abstract List<AudioStream> getAudioStreams() throws ParsingException;
public abstract List<StreamInfo.VideoStream> getVideoStreams() throws ParsingException; public abstract List<VideoStream> getVideoStreams() throws ParsingException;
public abstract List<StreamInfo.VideoStream> getVideoOnlyStreams() throws ParsingException; public abstract List<VideoStream> getVideoOnlyStreams() throws ParsingException;
public abstract String getDashMpdUrl() throws ParsingException; public abstract String getDashMpdUrl() throws ParsingException;
public abstract int getAgeLimit() throws ParsingException; public abstract int getAgeLimit() throws ParsingException;
public abstract String getAverageRating() throws ParsingException; public abstract String getAverageRating() throws ParsingException;
@ -70,4 +76,7 @@ public interface StreamExtractor {
public abstract List<StreamPreviewInfo> getRelatedVideos() throws ParsingException; public abstract List<StreamPreviewInfo> getRelatedVideos() throws ParsingException;
public abstract StreamUrlIdHandler getUrlIdConverter(); public abstract StreamUrlIdHandler getUrlIdConverter();
public abstract String getPageUrl(); public abstract String getPageUrl();
public int getServiceId() {
return serviceId;
}
} }

View File

@ -55,6 +55,7 @@ public class StreamInfo extends AbstractVideoInfo {
StreamUrlIdHandler uiconv = extractor.getUrlIdConverter(); StreamUrlIdHandler uiconv = extractor.getUrlIdConverter();
streamInfo.service_id = extractor.getServiceId();
streamInfo.webpage_url = extractor.getPageUrl(); streamInfo.webpage_url = extractor.getPageUrl();
streamInfo.id = uiconv.getVideoId(extractor.getPageUrl()); streamInfo.id = uiconv.getVideoId(extractor.getPageUrl());
streamInfo.title = extractor.getTitle(); streamInfo.title = extractor.getTitle();
@ -231,12 +232,15 @@ public class StreamInfo extends AbstractVideoInfo {
public List<StreamPreviewInfo> related_videos = null; public List<StreamPreviewInfo> related_videos = null;
//in seconds. some metadata is not passed using a StreamInfo object! //in seconds. some metadata is not passed using a StreamInfo object!
public int start_position = 0; public int start_position = 0;
//todo: public int service_id = -1;
public List<Exception> errors = new Vector<>(); public List<Exception> errors = new Vector<>();
public StreamInfo() {} public StreamInfo() {}
public void addException(Exception e) {
errors.add(e);
}
/**Creates a new StreamInfo object from an existing AbstractVideoInfo. /**Creates a new StreamInfo object from an existing AbstractVideoInfo.
* All the shared properties are copied to the new StreamInfo.*/ * All the shared properties are copied to the new StreamInfo.*/
@SuppressWarnings("WeakerAccess") @SuppressWarnings("WeakerAccess")
@ -262,57 +266,4 @@ public class StreamInfo extends AbstractVideoInfo {
this.duration = ((StreamPreviewInfo)avi).duration; this.duration = ((StreamPreviewInfo)avi).duration;
} }
} }
public static class VideoStream {
//url of the stream
public String url = "";
public int format = -1;
public String resolution = "";
public VideoStream(String url, int format, String res) {
this.url = url; this.format = format; resolution = res;
}
// reveals wether two streams are the same, but have diferent urls
public boolean equalStats(VideoStream cmp) {
return format == cmp.format
&& resolution == cmp.resolution;
}
// revelas wether two streams are equal
public boolean equals(VideoStream cmp) {
return equalStats(cmp)
&& url == cmp.url;
}
}
@SuppressWarnings("unused")
public static class AudioStream {
public String url = "";
public int format = -1;
public int bandwidth = -1;
public int sampling_rate = -1;
public AudioStream(String url, int format, int bandwidth, int samplingRate) {
this.url = url; this.format = format;
this.bandwidth = bandwidth; this.sampling_rate = samplingRate;
}
// reveals wether two streams are the same, but have diferent urls
public boolean equalStats(AudioStream cmp) {
return format == cmp.format
&& bandwidth == cmp.bandwidth
&& sampling_rate == cmp.sampling_rate;
}
// revelas wether two streams are equal
public boolean equals(AudioStream cmp) {
return equalStats(cmp)
&& url == cmp.url;
}
}
public void addException(Exception e) {
errors.add(e);
}
} }

View File

@ -23,11 +23,13 @@ import org.schabi.newpipe.extractor.services.youtube.YoutubeStreamUrlIdHandler;
*/ */
public class StreamPreviewInfoCollector { public class StreamPreviewInfoCollector {
SearchResult result = new SearchResult(); private SearchResult result = new SearchResult();
StreamUrlIdHandler urlIdHandler = null; private StreamUrlIdHandler urlIdHandler = null;
private int serviceId = -1;
public StreamPreviewInfoCollector(StreamUrlIdHandler handler) { public StreamPreviewInfoCollector(StreamUrlIdHandler handler, int serviceId) {
urlIdHandler = handler; urlIdHandler = handler;
this.serviceId = serviceId;
} }
public void setSuggestion(String suggestion) { public void setSuggestion(String suggestion) {
@ -46,6 +48,7 @@ public class StreamPreviewInfoCollector {
try { try {
StreamPreviewInfo resultItem = new StreamPreviewInfo(); StreamPreviewInfo resultItem = new StreamPreviewInfo();
// importand information // importand information
resultItem.service_id = serviceId;
resultItem.webpage_url = extractor.getWebPageUrl(); resultItem.webpage_url = extractor.getWebPageUrl();
if (urlIdHandler == null) { if (urlIdHandler == null) {
throw new ParsingException("Error: UrlIdHandler not set"); throw new ParsingException("Error: UrlIdHandler not set");
@ -81,7 +84,6 @@ public class StreamPreviewInfoCollector {
addError(e); addError(e);
} }
result.resultList.add(resultItem); result.resultList.add(resultItem);
} catch (Exception e) { } catch (Exception e) {
addError(e); addError(e);

View File

@ -22,16 +22,25 @@ import java.io.IOException;
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>. * along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
*/ */
public interface StreamingService { public abstract class StreamingService {
class ServiceInfo { public class ServiceInfo {
public String name = ""; public String name = "";
} }
ServiceInfo getServiceInfo();
StreamExtractor getExtractorInstance(String url, Downloader downloader) private int serviceId;
public StreamingService(int id) {
serviceId = id;
}
public abstract ServiceInfo getServiceInfo();
public abstract StreamExtractor getExtractorInstance(String url, Downloader downloader)
throws IOException, ExtractionException; throws IOException, ExtractionException;
SearchEngine getSearchEngineInstance(); public abstract SearchEngine getSearchEngineInstance(Downloader downloader);
public abstract StreamUrlIdHandler getUrlIdHandlerInstance();
StreamUrlIdHandler getUrlIdHandler();
public final int getServiceId() {
return serviceId;
}
} }

View File

@ -0,0 +1,44 @@
package org.schabi.newpipe.extractor;
/**
* Created by Christian Schabesberger on 04.03.16.
*
* Copyright (C) Christian Schabesberger 2016 <chris.schabesberger@mailbox.org>
* VideoStream.java is part of NewPipe.
*
* NewPipe is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* NewPipe is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
*/
public class VideoStream {
//url of the stream
public String url = "";
public int format = -1;
public String resolution = "";
public VideoStream(String url, int format, String res) {
this.url = url; this.format = format; resolution = res;
}
// reveals wether two streams are the same, but have diferent urls
public boolean equalStats(VideoStream cmp) {
return format == cmp.format
&& resolution == cmp.resolution;
}
// revelas wether two streams are equal
public boolean equals(VideoStream cmp) {
return equalStats(cmp)
&& url == cmp.url;
}
}

View File

@ -29,7 +29,7 @@ public class YoutubeParsingHelper {
String days = "0"; String days = "0";
String hours = "0"; String hours = "0";
String minutes = "0"; String minutes = "0";
String seconds = "0"; String seconds;
switch(splitInput.length) { switch(splitInput.length) {
case 4: case 4:

View File

@ -14,6 +14,7 @@ import org.schabi.newpipe.extractor.SearchEngine;
import org.schabi.newpipe.extractor.StreamExtractor; import org.schabi.newpipe.extractor.StreamExtractor;
import org.schabi.newpipe.extractor.StreamPreviewInfoCollector; import org.schabi.newpipe.extractor.StreamPreviewInfoCollector;
import org.schabi.newpipe.extractor.StreamPreviewInfoExtractor; import org.schabi.newpipe.extractor.StreamPreviewInfoExtractor;
import org.schabi.newpipe.extractor.StreamUrlIdHandler;
import org.w3c.dom.Node; import org.w3c.dom.Node;
import org.w3c.dom.NodeList; import org.w3c.dom.NodeList;
import org.xml.sax.InputSource; import org.xml.sax.InputSource;
@ -47,15 +48,18 @@ import javax.xml.parsers.ParserConfigurationException;
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>. * along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
*/ */
public class YoutubeSearchEngine implements SearchEngine { public class YoutubeSearchEngine extends SearchEngine {
private static final String TAG = YoutubeSearchEngine.class.toString(); private static final String TAG = YoutubeSearchEngine.class.toString();
public YoutubeSearchEngine(StreamUrlIdHandler urlIdHandler, int serviceId) {
super(urlIdHandler, serviceId);
}
@Override @Override
public StreamPreviewInfoCollector search(String query, int page, String languageCode, Downloader downloader) public StreamPreviewInfoCollector search(String query, int page, String languageCode, Downloader downloader)
throws IOException, ExtractionException { throws IOException, ExtractionException {
StreamPreviewInfoCollector collector = new StreamPreviewInfoCollector( StreamPreviewInfoCollector collector = getStreamPreviewInfoCollector();
new YoutubeStreamUrlIdHandler());
Uri.Builder builder = new Uri.Builder(); Uri.Builder builder = new Uri.Builder();
builder.scheme("https") builder.scheme("https")
.authority("www.youtube.com") .authority("www.youtube.com")

View File

@ -30,7 +30,12 @@ import java.io.IOException;
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>. * along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
*/ */
public class YoutubeService implements StreamingService { public class YoutubeService extends StreamingService {
public YoutubeService(int id) {
super(id);
}
@Override @Override
public ServiceInfo getServiceInfo() { public ServiceInfo getServiceInfo() {
ServiceInfo serviceInfo = new ServiceInfo(); ServiceInfo serviceInfo = new ServiceInfo();
@ -42,19 +47,19 @@ public class YoutubeService implements StreamingService {
throws ExtractionException, IOException { throws ExtractionException, IOException {
StreamUrlIdHandler urlIdHandler = new YoutubeStreamUrlIdHandler(); StreamUrlIdHandler urlIdHandler = new YoutubeStreamUrlIdHandler();
if(urlIdHandler.acceptUrl(url)) { if(urlIdHandler.acceptUrl(url)) {
return new YoutubeStreamExtractor(url, downloader) ; return new YoutubeStreamExtractor(url, downloader, getServiceId());
} }
else { else {
throw new IllegalArgumentException("supplied String is not a valid Youtube URL"); throw new IllegalArgumentException("supplied String is not a valid Youtube URL");
} }
} }
@Override @Override
public SearchEngine getSearchEngineInstance() { public SearchEngine getSearchEngineInstance(Downloader downloader) {
return new YoutubeSearchEngine(); return new YoutubeSearchEngine(getUrlIdHandlerInstance(), getServiceId());
} }
@Override @Override
public StreamUrlIdHandler getUrlIdHandler() { public StreamUrlIdHandler getUrlIdHandlerInstance() {
return new YoutubeStreamUrlIdHandler(); return new YoutubeStreamUrlIdHandler();
} }
} }

View File

@ -10,6 +10,7 @@ import org.jsoup.nodes.Element;
import org.mozilla.javascript.Context; import org.mozilla.javascript.Context;
import org.mozilla.javascript.Function; import org.mozilla.javascript.Function;
import org.mozilla.javascript.ScriptableObject; import org.mozilla.javascript.ScriptableObject;
import org.schabi.newpipe.extractor.AudioStream;
import org.schabi.newpipe.extractor.ExtractionException; import org.schabi.newpipe.extractor.ExtractionException;
import org.schabi.newpipe.extractor.Downloader; import org.schabi.newpipe.extractor.Downloader;
import org.schabi.newpipe.extractor.Parser; import org.schabi.newpipe.extractor.Parser;
@ -19,6 +20,7 @@ import org.schabi.newpipe.extractor.StreamPreviewInfo;
import org.schabi.newpipe.extractor.StreamUrlIdHandler; import org.schabi.newpipe.extractor.StreamUrlIdHandler;
import org.schabi.newpipe.extractor.StreamExtractor; import org.schabi.newpipe.extractor.StreamExtractor;
import org.schabi.newpipe.extractor.MediaFormat; import org.schabi.newpipe.extractor.MediaFormat;
import org.schabi.newpipe.extractor.VideoStream;
import java.io.IOException; import java.io.IOException;
import java.util.List; import java.util.List;
@ -47,7 +49,7 @@ import java.util.regex.Pattern;
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>. * along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
*/ */
public class YoutubeStreamExtractor implements StreamExtractor { public class YoutubeStreamExtractor extends StreamExtractor {
// exceptions // exceptions
@ -181,7 +183,9 @@ public class YoutubeStreamExtractor implements StreamExtractor {
private Downloader downloader; private Downloader downloader;
public YoutubeStreamExtractor(String pageUrl, Downloader dl) throws ExtractionException, IOException { public YoutubeStreamExtractor(String pageUrl, Downloader dl, int serviceId)
throws ExtractionException, IOException {
super(pageUrl, dl, serviceId);
//most common videoInfo fields are now set in our superclass, for all services //most common videoInfo fields are now set in our superclass, for all services
downloader = dl; downloader = dl;
this.pageUrl = pageUrl; this.pageUrl = pageUrl;
@ -430,8 +434,8 @@ public class YoutubeStreamExtractor implements StreamExtractor {
@Override @Override
public List<StreamInfo.AudioStream> getAudioStreams() throws ParsingException { public List<AudioStream> getAudioStreams() throws ParsingException {
Vector<StreamInfo.AudioStream> audioStreams = new Vector<>(); Vector<AudioStream> audioStreams = new Vector<>();
try{ try{
String encoded_url_map; String encoded_url_map;
// playerArgs could be null if the video is age restricted // playerArgs could be null if the video is age restricted
@ -458,7 +462,7 @@ public class YoutubeStreamExtractor implements StreamExtractor {
+ decryptSignature(tags.get("s"), decryptionCode); + decryptSignature(tags.get("s"), decryptionCode);
} }
audioStreams.add(new StreamInfo.AudioStream(streamUrl, audioStreams.add(new AudioStream(streamUrl,
itagItem.mediaFormatId, itagItem.mediaFormatId,
itagItem.bandWidth, itagItem.bandWidth,
itagItem.samplingRate)); itagItem.samplingRate));
@ -472,8 +476,8 @@ public class YoutubeStreamExtractor implements StreamExtractor {
} }
@Override @Override
public List<StreamInfo.VideoStream> getVideoStreams() throws ParsingException { public List<VideoStream> getVideoStreams() throws ParsingException {
Vector<StreamInfo.VideoStream> videoStreams = new Vector<>(); Vector<VideoStream> videoStreams = new Vector<>();
try{ try{
String encoded_url_map; String encoded_url_map;
@ -501,7 +505,7 @@ public class YoutubeStreamExtractor implements StreamExtractor {
streamUrl = streamUrl + "&signature=" streamUrl = streamUrl + "&signature="
+ decryptSignature(tags.get("s"), decryptionCode); + decryptSignature(tags.get("s"), decryptionCode);
} }
videoStreams.add(new StreamInfo.VideoStream( videoStreams.add(new VideoStream(
streamUrl, streamUrl,
itagItem.mediaFormatId, itagItem.mediaFormatId,
itagItem.resolutionString)); itagItem.resolutionString));
@ -524,7 +528,7 @@ public class YoutubeStreamExtractor implements StreamExtractor {
} }
@Override @Override
public List<StreamInfo.VideoStream> getVideoOnlyStreams() throws ParsingException { public List<VideoStream> getVideoOnlyStreams() throws ParsingException {
return null; return null;
} }