Merge branch 'dev' into LongTapInSubs

This commit is contained in:
Somethingweirdhere 2018-08-15 23:33:59 +02:00 committed by GitHub
commit a5e89d1dd1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
96 changed files with 2663 additions and 1406 deletions

View File

@ -1,2 +1,3 @@
- [ ] I carefully read the [contribution guidelines](https://github.com/TeamNewPipe/NewPipe/blob/HEAD/.github/CONTRIBUTING.md) and agree to them.
- [ ] I checked if the issue/feature exists in the latest version.
- [ ] I did use the [incredible bugreport to markdown converter](https://teamnewpipe.github.io/CrashReportToMarkdown/) to paste bug reports.

View File

@ -8,8 +8,8 @@ android {
applicationId "org.schabi.newpipe"
minSdkVersion 15
targetSdkVersion 27
versionCode 64
versionName "0.13.5"
versionCode 66
versionName "0.13.7"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
vectorDrawables.useSupportLibrary = true
@ -42,7 +42,7 @@ android {
ext {
supportLibVersion = '27.1.1'
exoPlayerLibVersion = '2.7.3'
exoPlayerLibVersion = '2.8.2'
roomDbLibVersion = '1.1.1'
leakCanaryLibVersion = '1.5.4'
okHttpLibVersion = '3.10.0'
@ -54,7 +54,7 @@ dependencies {
exclude module: 'support-annotations'
}
implementation 'com.github.TeamNewPipe:NewPipeExtractor:bf1c771'
implementation 'com.github.TeamNewPipe:NewPipeExtractor:1eff8c5708'
testImplementation 'junit:junit:4.12'
testImplementation 'org.mockito:mockito-core:2.8.9'

View File

@ -61,6 +61,8 @@ import org.schabi.newpipe.util.ServiceHelper;
import org.schabi.newpipe.util.StateSaver;
import org.schabi.newpipe.util.ThemeHelper;
import static org.schabi.newpipe.extractor.InfoItem.InfoType.PLAYLIST;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
public static final boolean DEBUG = !BuildConfig.BUILD_TYPE.equals("release");
@ -392,31 +394,45 @@ public class MainActivity extends AppCompatActivity {
}
private void handleIntent(Intent intent) {
if (DEBUG) Log.d(TAG, "handleIntent() called with: intent = [" + intent + "]");
try {
if (DEBUG) Log.d(TAG, "handleIntent() called with: intent = [" + intent + "]");
if (intent.hasExtra(Constants.KEY_LINK_TYPE)) {
String url = intent.getStringExtra(Constants.KEY_URL);
int serviceId = intent.getIntExtra(Constants.KEY_SERVICE_ID, 0);
String title = intent.getStringExtra(Constants.KEY_TITLE);
switch (((StreamingService.LinkType) intent.getSerializableExtra(Constants.KEY_LINK_TYPE))) {
case STREAM:
boolean autoPlay = intent.getBooleanExtra(VideoDetailFragment.AUTO_PLAY, false);
NavigationHelper.openVideoDetailFragment(getSupportFragmentManager(), serviceId, url, title, autoPlay);
break;
case CHANNEL:
NavigationHelper.openChannelFragment(getSupportFragmentManager(), serviceId, url, title);
break;
case PLAYLIST:
NavigationHelper.openPlaylistFragment(getSupportFragmentManager(), serviceId, url, title);
break;
if (intent.hasExtra(Constants.KEY_LINK_TYPE)) {
String url = intent.getStringExtra(Constants.KEY_URL);
int serviceId = intent.getIntExtra(Constants.KEY_SERVICE_ID, 0);
String title = intent.getStringExtra(Constants.KEY_TITLE);
switch (((StreamingService.LinkType) intent.getSerializableExtra(Constants.KEY_LINK_TYPE))) {
case STREAM:
boolean autoPlay = intent.getBooleanExtra(VideoDetailFragment.AUTO_PLAY, false);
NavigationHelper.openVideoDetailFragment(getSupportFragmentManager(), serviceId, url, title, autoPlay);
break;
case CHANNEL:
NavigationHelper.openChannelFragment(getSupportFragmentManager(),
serviceId,
url,
title);
break;
case PLAYLIST:
NavigationHelper.openPlaylistFragment(getSupportFragmentManager(),
serviceId,
url,
title);
break;
}
} else if (intent.hasExtra(Constants.KEY_OPEN_SEARCH)) {
String searchString = intent.getStringExtra(Constants.KEY_SEARCH_STRING);
if (searchString == null) searchString = "";
int serviceId = intent.getIntExtra(Constants.KEY_SERVICE_ID, 0);
NavigationHelper.openSearchFragment(
getSupportFragmentManager(),
serviceId,
searchString);
} else {
NavigationHelper.gotoMainFragment(getSupportFragmentManager());
}
} else if (intent.hasExtra(Constants.KEY_OPEN_SEARCH)) {
String searchQuery = intent.getStringExtra(Constants.KEY_QUERY);
if (searchQuery == null) searchQuery = "";
int serviceId = intent.getIntExtra(Constants.KEY_SERVICE_ID, 0);
NavigationHelper.openSearchFragment(getSupportFragmentManager(), serviceId, searchQuery);
} else {
NavigationHelper.gotoMainFragment(getSupportFragmentManager());
} catch (Exception e) {
ErrorActivity.reportUiError(this, e);
}
}
}

View File

@ -10,6 +10,7 @@ import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.preference.PreferenceManager;
import android.util.Log;
import android.view.LayoutInflater;
@ -127,7 +128,14 @@ public class MainFragment extends BaseFragment implements TabLayout.OnTabSelecte
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_search:
NavigationHelper.openSearchFragment(getFragmentManager(), ServiceHelper.getSelectedServiceId(activity), "");
try {
NavigationHelper.openSearchFragment(
getFragmentManager(),
ServiceHelper.getSelectedServiceId(activity),
"");
} catch (Exception e) {
ErrorActivity.reportUiError((AppCompatActivity) getActivity(), e);
}
return true;
}
return super.onOptionsItemSelected(item);
@ -226,7 +234,9 @@ public class MainFragment extends BaseFragment implements TabLayout.OnTabSelecte
FALLBACK_CHANNEL_URL);
String name = preferences.getString(getString(R.string.main_page_selected_channel_name),
FALLBACK_CHANNEL_NAME);
ChannelFragment fragment = ChannelFragment.getInstance(serviceId, url, name);
ChannelFragment fragment = ChannelFragment.getInstance(serviceId,
url,
name);
fragment.useAsFrontPage(true);
return fragment;
} else {
@ -255,20 +265,13 @@ public class MainFragment extends BaseFragment implements TabLayout.OnTabSelecte
for (final String ks : kl.getAvailableKiosks()) {
menu.add(0, KIOSK_MENU_OFFSET + i, Menu.NONE,
KioskTranslator.getTranslatedKioskName(ks, getContext()))
.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem menuItem) {
.setOnMenuItemClickListener(menuItem -> {
try {
NavigationHelper.openKioskFragment(getFragmentManager(), currentServiceId, ks);
} catch (Exception e) {
ErrorActivity.reportError(activity, e,
activity.getClass(),
null,
ErrorActivity.ErrorInfo.make(UserAction.UI_ERROR,
"none", "", R.string.app_ui_crash));
ErrorActivity.reportUiError((AppCompatActivity) getActivity(), e);
}
return true;
}
});
i++;
}

View File

@ -17,6 +17,7 @@ import android.support.v4.content.ContextCompat;
import android.support.v4.view.animation.FastOutSlowInInterpolator;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.text.Html;
import android.text.Spanned;
import android.text.TextUtils;
@ -54,7 +55,7 @@ import org.schabi.newpipe.extractor.InfoItem;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.exceptions.ContentNotAvailableException;
import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.services.youtube.YoutubeStreamExtractor;
import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeStreamExtractor;
import org.schabi.newpipe.extractor.stream.AudioStream;
import org.schabi.newpipe.extractor.stream.Stream;
import org.schabi.newpipe.extractor.stream.StreamInfo;
@ -64,6 +65,7 @@ import org.schabi.newpipe.extractor.stream.VideoStream;
import org.schabi.newpipe.fragments.BackPressable;
import org.schabi.newpipe.fragments.BaseStateFragment;
import org.schabi.newpipe.local.history.HistoryRecordManager;
import org.schabi.newpipe.report.ErrorActivity;
import org.schabi.newpipe.util.StreamItemAdapter;
import org.schabi.newpipe.util.StreamItemAdapter.StreamSizeWrapper;
import org.schabi.newpipe.local.dialog.PlaylistAppendDialog;
@ -365,11 +367,15 @@ public class VideoDetailFragment
if (TextUtils.isEmpty(currentInfo.getUploaderUrl())) {
Log.w(TAG, "Can't open channel because we got no channel URL");
} else {
NavigationHelper.openChannelFragment(
getFragmentManager(),
currentInfo.getServiceId(),
currentInfo.getUploaderUrl(),
currentInfo.getUploaderName());
try {
NavigationHelper.openChannelFragment(
getFragmentManager(),
currentInfo.getServiceId(),
currentInfo.getUploaderUrl(),
currentInfo.getUploaderName());
} catch (Exception e) {
ErrorActivity.reportUiError((AppCompatActivity) getActivity(), e);
}
}
break;
case R.id.detail_thumbnail_root_layout:

View File

@ -6,6 +6,7 @@ import android.content.DialogInterface;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
@ -24,6 +25,7 @@ import org.schabi.newpipe.local.dialog.PlaylistAppendDialog;
import org.schabi.newpipe.info_list.InfoItemDialog;
import org.schabi.newpipe.info_list.InfoListAdapter;
import org.schabi.newpipe.player.playqueue.SinglePlayQueue;
import org.schabi.newpipe.report.ErrorActivity;
import org.schabi.newpipe.util.NavigationHelper;
import org.schabi.newpipe.util.OnClickGesture;
import org.schabi.newpipe.util.StateSaver;
@ -152,18 +154,35 @@ public abstract class BaseListFragment<I, N> extends BaseStateFragment<I> implem
infoListAdapter.setOnChannelSelectedListener(new OnClickGesture<ChannelInfoItem>() {
@Override
public void selected(ChannelInfoItem selectedItem) {
onItemSelected(selectedItem);
NavigationHelper.openChannelFragment(useAsFrontPage ? getParentFragment().getFragmentManager() : getFragmentManager(),
selectedItem.getServiceId(), selectedItem.getUrl(), selectedItem.getName());
try {
onItemSelected(selectedItem);
NavigationHelper.openChannelFragment(useAsFrontPage ?
getParentFragment().getFragmentManager()
: getFragmentManager(),
selectedItem.getServiceId(),
selectedItem.getUrl(),
selectedItem.getName());
} catch (Exception e) {
ErrorActivity.reportUiError((AppCompatActivity) getActivity(), e);
}
}
});
infoListAdapter.setOnPlaylistSelectedListener(new OnClickGesture<PlaylistInfoItem>() {
@Override
public void selected(PlaylistInfoItem selectedItem) {
onItemSelected(selectedItem);
NavigationHelper.openPlaylistFragment(useAsFrontPage ? getParentFragment().getFragmentManager() : getFragmentManager(),
selectedItem.getServiceId(), selectedItem.getUrl(), selectedItem.getName());
try {
onItemSelected(selectedItem);
NavigationHelper.openPlaylistFragment(
useAsFrontPage
? getParentFragment().getFragmentManager()
: getFragmentManager(),
selectedItem.getServiceId(),
selectedItem.getUrl(),
selectedItem.getName());
} catch (Exception e) {
ErrorActivity.reportUiError((AppCompatActivity) getActivity(), e);
}
}
});
@ -178,7 +197,9 @@ public abstract class BaseListFragment<I, N> extends BaseStateFragment<I> implem
private void onStreamSelected(StreamInfoItem selectedItem) {
onItemSelected(selectedItem);
NavigationHelper.openVideoDetailFragment(useAsFrontPage ? getParentFragment().getFragmentManager() : getFragmentManager(),
NavigationHelper.openVideoDetailFragment(useAsFrontPage
? getParentFragment().getFragmentManager()
: getFragmentManager(),
selectedItem.getServiceId(), selectedItem.getUrl(), selectedItem.getName());
}

View File

@ -8,6 +8,9 @@ import android.view.View;
import org.schabi.newpipe.extractor.ListExtractor;
import org.schabi.newpipe.extractor.ListInfo;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler;
import org.schabi.newpipe.extractor.linkhandler.LinkHandler;
import org.schabi.newpipe.util.Constants;
import java.util.Queue;
@ -166,7 +169,6 @@ public abstract class BaseListInfoFragment<I extends ListInfo>
public void handleResult(@NonNull I result) {
super.handleResult(result);
url = result.getUrl();
name = result.getName();
setTitle(name);

View File

@ -33,6 +33,7 @@ import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.channel.ChannelInfo;
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler;
import org.schabi.newpipe.fragments.list.BaseListInfoFragment;
import org.schabi.newpipe.info_list.InfoItemDialog;
import org.schabi.newpipe.local.dialog.PlaylistAppendDialog;
@ -501,7 +502,11 @@ public class ChannelFragment extends BaseListInfoFragment<ChannelInfo> {
if (super.onError(exception)) return true;
int errorId = exception instanceof ExtractionException ? R.string.parsing_error : R.string.general_error;
onUnrecoverableError(exception, UserAction.REQUESTED_CHANNEL, NewPipe.getNameOfService(serviceId), url, errorId);
onUnrecoverableError(exception,
UserAction.REQUESTED_CHANNEL,
NewPipe.getNameOfService(serviceId),
url,
errorId);
return true;
}

View File

@ -11,22 +11,20 @@ import android.view.Menu;
import android.view.MenuInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import org.schabi.newpipe.R;
import org.schabi.newpipe.extractor.ListExtractor;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.StreamingService;
import org.schabi.newpipe.extractor.UrlIdHandler;
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.kiosk.KioskInfo;
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
import org.schabi.newpipe.extractor.linkhandler.ListLinkHandlerFactory;
import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler;
import org.schabi.newpipe.extractor.linkhandler.LinkHandlerFactory;
import org.schabi.newpipe.fragments.list.BaseListInfoFragment;
import org.schabi.newpipe.info_list.InfoItemBuilder;
import org.schabi.newpipe.report.UserAction;
import org.schabi.newpipe.util.ExtractorHelper;
import org.schabi.newpipe.util.KioskTranslator;
import org.schabi.newpipe.util.NavigationHelper;
import icepick.State;
import io.reactivex.Single;
@ -74,10 +72,10 @@ public class KioskFragment extends BaseListInfoFragment<KioskInfo> {
throws ExtractionException {
KioskFragment instance = new KioskFragment();
StreamingService service = NewPipe.getService(serviceId);
UrlIdHandler kioskTypeUrlIdHandler = service.getKioskList()
.getUrlIdHandlerByType(kioskId);
ListLinkHandlerFactory kioskLinkHandlerFactory = service.getKioskList()
.getListLinkHandlerFactoryByType(kioskId);
instance.setInitialData(serviceId,
kioskTypeUrlIdHandler.getUrl(kioskId), kioskId);
kioskLinkHandlerFactory.fromId(kioskId).getUrl(), kioskId);
instance.kioskId = kioskId;
return instance;
}
@ -136,7 +134,10 @@ public class KioskFragment extends BaseListInfoFragment<KioskInfo> {
.getDefaultSharedPreferences(activity)
.getString(getString(R.string.content_country_key),
getString(R.string.default_country_value));
return ExtractorHelper.getKioskInfo(serviceId, url, contentCountry, forceReload);
return ExtractorHelper.getKioskInfo(serviceId,
url,
contentCountry,
forceReload);
}
@Override
@ -145,7 +146,10 @@ public class KioskFragment extends BaseListInfoFragment<KioskInfo> {
.getDefaultSharedPreferences(activity)
.getString(getString(R.string.content_country_key),
getString(R.string.default_country_value));
return ExtractorHelper.getMoreKioskItems(serviceId, url, currentNextPageUrl, contentCountry);
return ExtractorHelper.getMoreKioskItems(serviceId,
url,
currentNextPageUrl,
contentCountry);
}
/*//////////////////////////////////////////////////////////////////////////

View File

@ -6,6 +6,7 @@ import android.content.DialogInterface;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
@ -19,6 +20,7 @@ import android.widget.TextView;
import org.reactivestreams.Subscriber;
import org.reactivestreams.Subscription;
import org.schabi.newpipe.App;
import org.schabi.newpipe.NewPipeDatabase;
import org.schabi.newpipe.R;
import org.schabi.newpipe.database.playlist.model.PlaylistRemoteEntity;
@ -28,12 +30,14 @@ import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.playlist.PlaylistInfo;
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler;
import org.schabi.newpipe.fragments.list.BaseListInfoFragment;
import org.schabi.newpipe.info_list.InfoItemDialog;
import org.schabi.newpipe.local.playlist.RemotePlaylistManager;
import org.schabi.newpipe.player.playqueue.PlayQueue;
import org.schabi.newpipe.player.playqueue.PlaylistPlayQueue;
import org.schabi.newpipe.player.playqueue.SinglePlayQueue;
import org.schabi.newpipe.report.ErrorActivity;
import org.schabi.newpipe.report.UserAction;
import org.schabi.newpipe.util.ExtractorHelper;
import org.schabi.newpipe.util.ImageDisplayConstants;
@ -267,11 +271,16 @@ public class PlaylistFragment extends BaseListInfoFragment<PlaylistInfo> {
if (!TextUtils.isEmpty(result.getUploaderName())) {
headerUploaderName.setText(result.getUploaderName());
if (!TextUtils.isEmpty(result.getUploaderUrl())) {
headerUploaderLayout.setOnClickListener(v ->
headerUploaderLayout.setOnClickListener(v -> {
try {
NavigationHelper.openChannelFragment(getFragmentManager(),
result.getServiceId(), result.getUploaderUrl(),
result.getUploaderName())
);
result.getServiceId(),
result.getUploaderUrl(),
result.getUploaderName());
} catch (Exception e) {
ErrorActivity.reportUiError((AppCompatActivity) getActivity(), e);
}
});
}
}
@ -339,7 +348,11 @@ public class PlaylistFragment extends BaseListInfoFragment<PlaylistInfo> {
if (super.onError(exception)) return true;
int errorId = exception instanceof ExtractionException ? R.string.parsing_error : R.string.general_error;
onUnrecoverableError(exception, UserAction.REQUESTED_PLAYLIST, NewPipe.getNameOfService(serviceId), url, errorId);
onUnrecoverableError(exception,
UserAction.REQUESTED_PLAYLIST,
NewPipe.getNameOfService(serviceId),
url,
errorId);
return true;
}

View File

@ -37,26 +37,30 @@ import org.schabi.newpipe.extractor.ListExtractor;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.StreamingService;
import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.search.SearchEngine;
import org.schabi.newpipe.extractor.search.SearchResult;
import org.schabi.newpipe.extractor.search.SearchExtractor;
import org.schabi.newpipe.extractor.search.SearchInfo;
import org.schabi.newpipe.fragments.BackPressable;
import org.schabi.newpipe.fragments.list.BaseListFragment;
import org.schabi.newpipe.local.history.HistoryRecordManager;
import org.schabi.newpipe.report.ErrorActivity;
import org.schabi.newpipe.report.UserAction;
import org.schabi.newpipe.util.Constants;
import org.schabi.newpipe.util.AnimationUtils;
import org.schabi.newpipe.util.ExtractorHelper;
import org.schabi.newpipe.util.LayoutManagerSmoothScroller;
import org.schabi.newpipe.util.NavigationHelper;
import org.schabi.newpipe.util.ServiceHelper;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
import icepick.State;
@ -65,14 +69,15 @@ import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;
import io.reactivex.schedulers.Schedulers;
import io.reactivex.subjects.PublishSubject;
import static java.util.Arrays.asList;
import static org.schabi.newpipe.util.AnimationUtils.animateView;
public class SearchFragment
extends BaseListFragment<SearchResult, ListExtractor.InfoItemsPage>
extends BaseListFragment<SearchInfo, ListExtractor.InfoItemsPage>
implements BackPressable {
/*//////////////////////////////////////////////////////////////////////////
@ -92,19 +97,29 @@ public class SearchFragment
@State
protected int filterItemCheckedId = -1;
private SearchEngine.Filter filter = SearchEngine.Filter.ANY;
@State
protected int serviceId = Constants.NO_SERVICE_ID;
// this three represet the current search query
@State
protected String searchQuery;
protected String searchString;
@State
protected String lastSearchedQuery;
protected String[] contentFilter;
@State
protected String sortFilter;
// these represtent the last search
@State
protected String lastSearchedString;
@State
protected boolean wasSearchFocused = false;
private int currentPage = 0;
private int currentNextPage = 0;
private Map<Integer, String> menuItemToFilterName;
private StreamingService service;
private String currentPageUrl;
private String nextPageUrl;
private String contentCountry;
private boolean isSuggestionsEnabled = true;
private boolean isSearchHistoryEnabled = true;
@ -130,11 +145,11 @@ public class SearchFragment
/*////////////////////////////////////////////////////////////////////////*/
public static SearchFragment getInstance(int serviceId, String query) {
public static SearchFragment getInstance(int serviceId, String searchString) {
SearchFragment searchFragment = new SearchFragment();
searchFragment.setQuery(serviceId, query);
searchFragment.setQuery(serviceId, searchString, new String[0], "");
if (!TextUtils.isEmpty(query)) {
if (!TextUtils.isEmpty(searchString)) {
searchFragment.setSearchOnResume();
}
@ -202,13 +217,22 @@ public class SearchFragment
if (DEBUG) Log.d(TAG, "onResume() called");
super.onResume();
if (!TextUtils.isEmpty(searchQuery)) {
try {
service = NewPipe.getService(serviceId);
} catch (Exception e) {
ErrorActivity.reportError(getActivity(), e, getActivity().getClass(),
getActivity().findViewById(android.R.id.content),
ErrorActivity.ErrorInfo.make(UserAction.UI_ERROR,
"",
"", R.string.general_error));
}
if (!TextUtils.isEmpty(searchString)) {
if (wasLoading.getAndSet(false)) {
if (currentNextPage > currentPage) loadMoreItems();
else search(searchQuery);
search(searchString, contentFilter, sortFilter);
} else if (infoListAdapter.getItemsList().size() == 0) {
if (savedState == null) {
search(searchQuery);
search(searchString, contentFilter, sortFilter);
} else if (!isLoading.get() && !wasSearchFocused) {
infoListAdapter.clearStreamItemList();
showEmptyState();
@ -218,7 +242,7 @@ public class SearchFragment
if (suggestionDisposable == null || suggestionDisposable.isDisposed()) initSuggestionObserver();
if (TextUtils.isEmpty(searchQuery) || wasSearchFocused) {
if (TextUtils.isEmpty(searchString) || wasSearchFocused) {
showKeyboardSearch();
showSuggestionsPanel();
} else {
@ -247,8 +271,9 @@ public class SearchFragment
public void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case ReCaptchaActivity.RECAPTCHA_REQUEST:
if (resultCode == Activity.RESULT_OK && !TextUtils.isEmpty(searchQuery)) {
search(searchQuery);
if (resultCode == Activity.RESULT_OK
&& !TextUtils.isEmpty(searchString)) {
search(searchString, contentFilter, sortFilter);
} else Log.e(TAG, "ReCaptcha failed");
break;
@ -282,20 +307,22 @@ public class SearchFragment
@Override
public void writeTo(Queue<Object> objectsToSave) {
super.writeTo(objectsToSave);
objectsToSave.add(currentPage);
objectsToSave.add(currentNextPage);
objectsToSave.add(currentPageUrl);
objectsToSave.add(nextPageUrl);
}
@Override
public void readFrom(@NonNull Queue<Object> savedObjects) throws Exception {
super.readFrom(savedObjects);
currentPage = (int) savedObjects.poll();
currentNextPage = (int) savedObjects.poll();
currentPageUrl = (String) savedObjects.poll();
nextPageUrl = (String) savedObjects.poll();
}
@Override
public void onSaveInstanceState(Bundle bundle) {
searchQuery = searchEditText != null ? searchEditText.getText().toString() : searchQuery;
searchString = searchEditText != null
? searchEditText.getText().toString()
: searchString;
super.onSaveInstanceState(bundle);
}
@ -305,8 +332,11 @@ public class SearchFragment
@Override
public void reloadContent() {
if (!TextUtils.isEmpty(searchQuery) || (searchEditText != null && !TextUtils.isEmpty(searchEditText.getText()))) {
search(!TextUtils.isEmpty(searchQuery) ? searchQuery : searchEditText.getText().toString());
if (!TextUtils.isEmpty(searchString)
|| (searchEditText != null && !TextUtils.isEmpty(searchEditText.getText()))) {
search(!TextUtils.isEmpty(searchString)
? searchString
: searchEditText.getText().toString(), new String[0], "");
} else {
if (searchEditText != null) {
searchEditText.setText("");
@ -330,22 +360,35 @@ public class SearchFragment
supportActionBar.setDisplayHomeAsUpEnabled(true);
}
inflater.inflate(R.menu.menu_search, menu);
menuItemToFilterName = new HashMap<>();
int itemId = 0;
boolean isFirstItem = true;
final Context c = getContext();
for(String filter : service.getSearchQIHFactory().getAvailableContentFilter()) {
menuItemToFilterName.put(itemId, filter);
MenuItem item = menu.add(1,
itemId++,
0,
ServiceHelper.getTranslatedFilterString(filter, c));
if(isFirstItem) {
item.setChecked(true);
isFirstItem = false;
}
}
menu.setGroupCheckable(1, true, true);
restoreFilterChecked(menu, filterItemCheckedId);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_filter_all:
case R.id.menu_filter_video:
case R.id.menu_filter_channel:
case R.id.menu_filter_playlist:
changeFilter(item, getFilterFromMenuId(item.getItemId()));
return true;
default:
return super.onOptionsItemSelected(item);
}
List<String> contentFilter = new ArrayList<>(1);
contentFilter.add(menuItemToFilterName.get(item.getItemId()));
changeContentFilter(item, contentFilter);
return true;
}
private void restoreFilterChecked(Menu menu, int itemId) {
@ -354,21 +397,6 @@ public class SearchFragment
if (item == null) return;
item.setChecked(true);
filter = getFilterFromMenuId(itemId);
}
}
private SearchEngine.Filter getFilterFromMenuId(int itemId) {
switch (itemId) {
case R.id.menu_filter_video:
return SearchEngine.Filter.STREAM;
case R.id.menu_filter_channel:
return SearchEngine.Filter.CHANNEL;
case R.id.menu_filter_playlist:
return SearchEngine.Filter.PLAYLIST;
case R.id.menu_filter_all:
default:
return SearchEngine.Filter.ANY;
}
}
@ -379,14 +407,21 @@ public class SearchFragment
private TextWatcher textWatcher;
private void showSearchOnStart() {
if (DEBUG) Log.d(TAG, "showSearchOnStart() called, searchQuery → " + searchQuery+", lastSearchedQuery → " + lastSearchedQuery);
searchEditText.setText(searchQuery);
if (DEBUG) Log.d(TAG, "showSearchOnStart() called, searchQuery → "
+ searchString
+ ", lastSearchedQuery → "
+ lastSearchedString);
searchEditText.setText(searchString);
if (TextUtils.isEmpty(searchQuery) || TextUtils.isEmpty(searchEditText.getText())) {
if (TextUtils.isEmpty(searchString) || TextUtils.isEmpty(searchEditText.getText())) {
searchToolbarContainer.setTranslationX(100);
searchToolbarContainer.setAlpha(0f);
searchToolbarContainer.setVisibility(View.VISIBLE);
searchToolbarContainer.animate().translationX(0).alpha(1f).setDuration(200).setInterpolator(new DecelerateInterpolator()).start();
searchToolbarContainer.animate()
.translationX(0)
.alpha(1f)
.setDuration(200)
.setInterpolator(new DecelerateInterpolator()).start();
} else {
searchToolbarContainer.setTranslationX(0);
searchToolbarContainer.setAlpha(1f);
@ -396,47 +431,38 @@ public class SearchFragment
private void initSearchListeners() {
if (DEBUG) Log.d(TAG, "initSearchListeners() called");
searchClear.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (DEBUG) Log.d(TAG, "onClick() called with: v = [" + v + "]");
if (TextUtils.isEmpty(searchEditText.getText())) {
NavigationHelper.gotoMainFragment(getFragmentManager());
return;
}
searchEditText.setText("");
suggestionListAdapter.setItems(new ArrayList<SuggestionItem>());
showKeyboardSearch();
searchClear.setOnClickListener(v -> {
if (DEBUG) Log.d(TAG, "onClick() called with: v = [" + v + "]");
if (TextUtils.isEmpty(searchEditText.getText())) {
NavigationHelper.gotoMainFragment(getFragmentManager());
return;
}
searchEditText.setText("");
suggestionListAdapter.setItems(new ArrayList<>());
showKeyboardSearch();
});
TooltipCompat.setTooltipText(searchClear, getString(R.string.clear));
searchEditText.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (DEBUG) Log.d(TAG, "onClick() called with: v = [" + v + "]");
if (isSuggestionsEnabled && errorPanelRoot.getVisibility() != View.VISIBLE) {
showSuggestionsPanel();
}
searchEditText.setOnClickListener(v -> {
if (DEBUG) Log.d(TAG, "onClick() called with: v = [" + v + "]");
if (isSuggestionsEnabled && errorPanelRoot.getVisibility() != View.VISIBLE) {
showSuggestionsPanel();
}
});
searchEditText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (DEBUG) Log.d(TAG, "onFocusChange() called with: v = [" + v + "], hasFocus = [" + hasFocus + "]");
if (isSuggestionsEnabled && hasFocus && errorPanelRoot.getVisibility() != View.VISIBLE) {
showSuggestionsPanel();
}
searchEditText.setOnFocusChangeListener((View v, boolean hasFocus) -> {
if (DEBUG) Log.d(TAG, "onFocusChange() called with: v = [" + v + "], hasFocus = [" + hasFocus + "]");
if (isSuggestionsEnabled && hasFocus && errorPanelRoot.getVisibility() != View.VISIBLE) {
showSuggestionsPanel();
}
});
suggestionListAdapter.setListener(new SuggestionListAdapter.OnSuggestionItemSelected() {
@Override
public void onSuggestionItemSelected(SuggestionItem item) {
search(item.query);
search(item.query, new String[0], "");
searchEditText.setText(item.query);
}
@ -469,21 +495,22 @@ public class SearchFragment
}
};
searchEditText.addTextChangedListener(textWatcher);
searchEditText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (DEBUG) {
Log.d(TAG, "onEditorAction() called with: v = [" + v + "], actionId = [" + actionId + "], event = [" + event + "]");
}
if (event != null && (event.getKeyCode() == KeyEvent.KEYCODE_ENTER || event.getAction() == EditorInfo.IME_ACTION_SEARCH)) {
search(searchEditText.getText().toString());
return true;
}
return false;
}
});
searchEditText.setOnEditorActionListener(
(TextView v, int actionId, KeyEvent event) -> {
if (DEBUG) {
Log.d(TAG, "onEditorAction() called with: v = [" + v + "], actionId = [" + actionId + "], event = [" + event + "]");
}
if (event != null
&& (event.getKeyCode() == KeyEvent.KEYCODE_ENTER
|| event.getAction() == EditorInfo.IME_ACTION_SEARCH)) {
search(searchEditText.getText().toString(), new String[0], "");
return true;
}
return false;
});
if (suggestionDisposable == null || suggestionDisposable.isDisposed()) initSuggestionObserver();
if (suggestionDisposable == null || suggestionDisposable.isDisposed())
initSuggestionObserver();
}
private void unsetSearchListeners() {
@ -513,7 +540,8 @@ public class SearchFragment
if (searchEditText == null) return;
if (searchEditText.requestFocus()) {
InputMethodManager imm = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE);
InputMethodManager imm = (InputMethodManager) activity.getSystemService(
Context.INPUT_METHOD_SERVICE);
imm.showSoftInput(searchEditText, InputMethodManager.SHOW_IMPLICIT);
}
}
@ -522,8 +550,10 @@ public class SearchFragment
if (DEBUG) Log.d(TAG, "hideKeyboardSearch() called");
if (searchEditText == null) return;
InputMethodManager imm = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(searchEditText.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
InputMethodManager imm = (InputMethodManager) activity.getSystemService(
Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(searchEditText.getWindowToken(),
InputMethodManager.HIDE_NOT_ALWAYS);
searchEditText.clearFocus();
}
@ -554,10 +584,12 @@ public class SearchFragment
@Override
public boolean onBackPressed() {
if (suggestionsPanel.getVisibility() == View.VISIBLE && infoListAdapter.getItemsList().size() > 0 && !isLoading.get()) {
if (suggestionsPanel.getVisibility() == View.VISIBLE
&& infoListAdapter.getItemsList().size() > 0
&& !isLoading.get()) {
hideSuggestionsPanel();
hideKeyboardSearch();
searchEditText.setText(lastSearchedQuery);
searchEditText.setText(lastSearchedString);
return true;
}
return false;
@ -573,8 +605,10 @@ public class SearchFragment
final Observable<String> observable = suggestionPublisher
.debounce(SUGGESTIONS_DEBOUNCE, TimeUnit.MILLISECONDS)
.startWith(searchQuery != null ? searchQuery : "")
.filter(query -> isSuggestionsEnabled);
.startWith(searchString != null
? searchString
: "")
.filter(searchString -> isSuggestionsEnabled);
suggestionDisposable = observable
.switchMap(query -> {
@ -645,56 +679,44 @@ public class SearchFragment
// no-op
}
private void search(final String query) {
if (DEBUG) Log.d(TAG, "search() called with: query = [" + query + "]");
if (query.isEmpty()) return;
private void search(final String searchString, String[] contentFilter, String sortFilter) {
if (DEBUG) Log.d(TAG, "search() called with: query = [" + searchString + "]");
if (searchString.isEmpty()) return;
try {
final StreamingService service = NewPipe.getServiceByUrl(query);
final StreamingService service = NewPipe.getServiceByUrl(searchString);
if (service != null) {
showLoading();
disposables.add(Observable
.fromCallable(new Callable<Intent>() {
@Override
public Intent call() throws Exception {
return NavigationHelper.getIntentByLink(activity, service, query);
}
})
.fromCallable(() ->
NavigationHelper.getIntentByLink(activity, service, searchString))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<Intent>() {
@Override
public void accept(Intent intent) throws Exception {
getFragmentManager().popBackStackImmediate();
activity.startActivity(intent);
}
}, new Consumer<Throwable>() {
@Override
public void accept(Throwable throwable) throws Exception {
showError(getString(R.string.url_not_supported_toast), false);
}
}));
.subscribe(intent -> {
getFragmentManager().popBackStackImmediate();
activity.startActivity(intent);
}, throwable ->
showError(getString(R.string.url_not_supported_toast), false)));
return;
}
} catch (Exception e) {
// Exception occurred, it's not a url
}
lastSearchedQuery = query;
searchQuery = query;
currentPage = 0;
lastSearchedString = this.searchString;
this.searchString = searchString;
infoListAdapter.clearStreamItemList();
hideSuggestionsPanel();
hideKeyboardSearch();
historyRecordManager.onSearched(serviceId, query)
historyRecordManager.onSearched(serviceId, searchString)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
ignored -> {},
error -> showSnackBarError(error, UserAction.SEARCHED,
NewPipe.getNameOfService(serviceId), query, 0)
NewPipe.getNameOfService(serviceId), searchString, 0)
);
suggestionPublisher.onNext(query);
suggestionPublisher.onNext(searchString);
startLoading(false);
}
@ -703,11 +725,16 @@ public class SearchFragment
super.startLoading(forceLoad);
if (disposables != null) disposables.clear();
if (searchDisposable != null) searchDisposable.dispose();
searchDisposable = ExtractorHelper.searchFor(serviceId, searchQuery, currentPage, contentCountry, filter)
searchDisposable = ExtractorHelper.searchFor(serviceId,
searchString,
Arrays.asList(contentFilter),
sortFilter,
contentCountry)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnEvent((searchResult, throwable) -> isLoading.set(false))
.subscribe(this::handleResult, this::onError);
}
@Override
@ -715,8 +742,13 @@ public class SearchFragment
isLoading.set(true);
showListFooter(true);
if (searchDisposable != null) searchDisposable.dispose();
currentNextPage = currentPage + 1;
searchDisposable = ExtractorHelper.getMoreSearchItems(serviceId, searchQuery, currentNextPage, contentCountry, filter)
searchDisposable = ExtractorHelper.getMoreSearchItems(
serviceId,
searchString,
asList(contentFilter),
sortFilter,
nextPageUrl,
contentCountry)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnEvent((nextItemsResult, throwable) -> isLoading.set(false))
@ -739,19 +771,22 @@ public class SearchFragment
// Utils
//////////////////////////////////////////////////////////////////////////*/
private void changeFilter(MenuItem item, SearchEngine.Filter filter) {
this.filter = filter;
private void changeContentFilter(MenuItem item, List<String> contentFilter) {
this.filterItemCheckedId = item.getItemId();
item.setChecked(true);
if (!TextUtils.isEmpty(searchQuery)) {
search(searchQuery);
this.contentFilter = new String[] {contentFilter.get(0)};
if (!TextUtils.isEmpty(searchString)) {
search(searchString, this.contentFilter, sortFilter);
}
}
private void setQuery(int serviceId, String searchQuery) {
private void setQuery(int serviceId, String searchString, String[] contentfilter, String sortFilter) {
this.serviceId = serviceId;
this.searchQuery = searchQuery;
this.searchString = searchString;
this.contentFilter = contentfilter;
this.sortFilter = sortFilter;
}
/*//////////////////////////////////////////////////////////////////////////
@ -772,8 +807,11 @@ public class SearchFragment
if (DEBUG) Log.d(TAG, "onSuggestionError() called with: exception = [" + exception + "]");
if (super.onError(exception)) return;
int errorId = exception instanceof ParsingException ? R.string.parsing_error : R.string.general_error;
onUnrecoverableError(exception, UserAction.GET_SUGGESTIONS, NewPipe.getNameOfService(serviceId), searchQuery, errorId);
int errorId = exception instanceof ParsingException
? R.string.parsing_error
: R.string.general_error;
onUnrecoverableError(exception, UserAction.GET_SUGGESTIONS,
NewPipe.getNameOfService(serviceId), searchString, errorId);
}
/*//////////////////////////////////////////////////////////////////////////
@ -798,16 +836,19 @@ public class SearchFragment
//////////////////////////////////////////////////////////////////////////*/
@Override
public void handleResult(@NonNull SearchResult result) {
if (!result.errors.isEmpty()) {
showSnackBarError(result.errors, UserAction.SEARCHED, NewPipe.getNameOfService(serviceId), searchQuery, 0);
public void handleResult(@NonNull SearchInfo result) {
if (!result.getErrors().isEmpty()) {
showSnackBarError(result.getErrors(), UserAction.SEARCHED,
NewPipe.getNameOfService(serviceId), searchString, 0);
}
lastSearchedQuery = searchQuery;
lastSearchedString = searchString;
nextPageUrl = result.getNextPageUrl();
currentPageUrl = result.getUrl();
if (infoListAdapter.getItemsList().size() == 0) {
if (!result.getResults().isEmpty()) {
infoListAdapter.addInfoItemList(result.getResults());
if (!result.getRelatedItems().isEmpty()) {
infoListAdapter.addInfoItemList(result.getRelatedItems());
} else {
infoListAdapter.clearStreamItemList();
showEmptyState();
@ -821,12 +862,13 @@ public class SearchFragment
@Override
public void handleNextItems(ListExtractor.InfoItemsPage result) {
showListFooter(false);
currentPage = Integer.parseInt(result.getNextPageUrl());
currentPageUrl = result.getNextPageUrl();
infoListAdapter.addInfoItemList(result.getItems());
if (!result.getErrors().isEmpty()) {
showSnackBarError(result.getErrors(), UserAction.SEARCHED, NewPipe.getNameOfService(serviceId)
, "\"" + searchQuery + "\" → page " + currentPage, 0);
showSnackBarError(result.getErrors(), UserAction.SEARCHED,
NewPipe.getNameOfService(serviceId)
, "\"" + searchString + "\" → page: " + nextPageUrl, 0);
}
super.handleNextItems(result);
}
@ -835,12 +877,15 @@ public class SearchFragment
protected boolean onError(Throwable exception) {
if (super.onError(exception)) return true;
if (exception instanceof SearchEngine.NothingFoundException) {
if (exception instanceof SearchExtractor.NothingFoundException) {
infoListAdapter.clearStreamItemList();
showEmptyState();
} else {
int errorId = exception instanceof ParsingException ? R.string.parsing_error : R.string.general_error;
onUnrecoverableError(exception, UserAction.SEARCHED, NewPipe.getNameOfService(serviceId), searchQuery, errorId);
int errorId = exception instanceof ParsingException
? R.string.parsing_error
: R.string.general_error;
onUnrecoverableError(exception, UserAction.SEARCHED,
NewPipe.getNameOfService(serviceId), searchString, errorId);
}
return true;

View File

@ -6,6 +6,7 @@ import android.os.Parcelable;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.FragmentManager;
import android.support.v7.app.AppCompatActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@ -19,9 +20,11 @@ import org.schabi.newpipe.database.LocalItem;
import org.schabi.newpipe.database.playlist.PlaylistLocalItem;
import org.schabi.newpipe.database.playlist.PlaylistMetadataEntry;
import org.schabi.newpipe.database.playlist.model.PlaylistRemoteEntity;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.local.BaseLocalListFragment;
import org.schabi.newpipe.local.playlist.LocalPlaylistManager;
import org.schabi.newpipe.local.playlist.RemotePlaylistManager;
import org.schabi.newpipe.report.ErrorActivity;
import org.schabi.newpipe.report.UserAction;
import org.schabi.newpipe.util.NavigationHelper;
import org.schabi.newpipe.util.OnClickGesture;
@ -99,19 +102,26 @@ public final class BookmarkFragment
itemListAdapter.setSelectedListener(new OnClickGesture<LocalItem>() {
@Override
public void selected(LocalItem selectedItem) {
// Requires the parent fragment to find holder for fragment replacement
if (getParentFragment() == null) return;
final FragmentManager fragmentManager = getParentFragment().getFragmentManager();
try {
// Requires the parent fragment to find holder for fragment replacement
if (getParentFragment() == null) return;
final FragmentManager fragmentManager = getParentFragment().getFragmentManager();
if (selectedItem instanceof PlaylistMetadataEntry) {
final PlaylistMetadataEntry entry = ((PlaylistMetadataEntry) selectedItem);
NavigationHelper.openLocalPlaylistFragment(fragmentManager, entry.uid,
entry.name);
if (selectedItem instanceof PlaylistMetadataEntry) {
final PlaylistMetadataEntry entry = ((PlaylistMetadataEntry) selectedItem);
NavigationHelper.openLocalPlaylistFragment(fragmentManager, entry.uid,
entry.name);
} else if (selectedItem instanceof PlaylistRemoteEntity) {
final PlaylistRemoteEntity entry = ((PlaylistRemoteEntity) selectedItem);
NavigationHelper.openPlaylistFragment(fragmentManager, entry.getServiceId(),
entry.getUrl(), entry.getName());
} else if (selectedItem instanceof PlaylistRemoteEntity) {
final PlaylistRemoteEntity entry = ((PlaylistRemoteEntity) selectedItem);
NavigationHelper.openPlaylistFragment(
fragmentManager,
entry.getServiceId(),
entry.getUrl(),
entry.getName());
}
} catch (Exception e) {
ErrorActivity.reportUiError((AppCompatActivity) getActivity(), e);
}
}

View File

@ -18,6 +18,7 @@ import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
@ -43,6 +44,7 @@ import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.subscription.SubscriptionExtractor;
import org.schabi.newpipe.fragments.BaseStateFragment;
import org.schabi.newpipe.info_list.InfoListAdapter;
import org.schabi.newpipe.report.UserAction;
import org.schabi.newpipe.local.subscription.services.SubscriptionsExportService;
import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService;
import org.schabi.newpipe.report.UserAction;
@ -325,9 +327,15 @@ public class SubscriptionFragment extends BaseStateFragment<List<SubscriptionEnt
infoListAdapter.setOnChannelSelectedListener(new OnClickGesture<ChannelInfoItem>() {
public void selected(ChannelInfoItem selectedItem) {
// Requires the parent fragment to find holder for fragment replacement
NavigationHelper.openChannelFragment(getParentFragment().getFragmentManager(),
selectedItem.getServiceId(), selectedItem.getUrl(), selectedItem.getName());
try {
// Requires the parent fragment to find holder for fragment replacement
NavigationHelper.openChannelFragment(getParentFragment().getFragmentManager(),
selectedItem.getServiceId(),
selectedItem.getUrl(),
selectedItem.getName());
} catch (Exception e) {
ErrorActivity.reportUiError((AppCompatActivity) getActivity(), e);
}
}
public void held(ChannelInfoItem selectedItem) {

View File

@ -26,9 +26,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Bitmap;
import android.os.Build;
import android.os.IBinder;
import android.support.annotation.IntRange;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.NotificationCompat;
@ -39,17 +37,16 @@ import android.widget.RemoteViews;
import com.google.android.exoplayer2.PlaybackParameters;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.source.MediaSource;
import com.nostra13.universalimageloader.core.assist.FailReason;
import org.schabi.newpipe.BuildConfig;
import org.schabi.newpipe.R;
import org.schabi.newpipe.extractor.MediaFormat;
import org.schabi.newpipe.extractor.stream.AudioStream;
import org.schabi.newpipe.extractor.stream.StreamInfo;
import org.schabi.newpipe.player.event.PlayerEventListener;
import org.schabi.newpipe.player.helper.LockManager;
import org.schabi.newpipe.player.helper.PlayerHelper;
import org.schabi.newpipe.player.playqueue.PlayQueueItem;
import org.schabi.newpipe.util.ListHelper;
import org.schabi.newpipe.player.resolver.AudioPlaybackResolver;
import org.schabi.newpipe.player.resolver.MediaSourceTag;
import org.schabi.newpipe.util.NavigationHelper;
import org.schabi.newpipe.util.ThemeHelper;
@ -94,7 +91,6 @@ public final class BackgroundPlayer extends Service {
private NotificationCompat.Builder notBuilder;
private RemoteViews notRemoteView;
private RemoteViews bigNotRemoteView;
private final String setAlphaMethodName = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) ? "setImageAlpha" : "setAlpha";
private boolean shouldUpdateOnProgress;
@ -192,7 +188,9 @@ public final class BackgroundPlayer extends Service {
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setCustomContentView(notRemoteView)
.setCustomBigContentView(bigNotRemoteView);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) builder.setPriority(NotificationCompat.PRIORITY_MAX);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) {
builder.setPriority(NotificationCompat.PRIORITY_MAX);
}
return builder;
}
@ -249,15 +247,6 @@ public final class BackgroundPlayer extends Service {
notificationManager.notify(NOTIFICATION_ID, notBuilder.build());
}
private void setControlsOpacity(@IntRange(from = 0, to = 255) int opacity) {
if (notRemoteView != null) notRemoteView.setInt(R.id.notificationPlayPause, setAlphaMethodName, opacity);
if (bigNotRemoteView != null) bigNotRemoteView.setInt(R.id.notificationPlayPause, setAlphaMethodName, opacity);
if (notRemoteView != null) notRemoteView.setInt(R.id.notificationFForward, setAlphaMethodName, opacity);
if (bigNotRemoteView != null) bigNotRemoteView.setInt(R.id.notificationFForward, setAlphaMethodName, opacity);
if (notRemoteView != null) notRemoteView.setInt(R.id.notificationFRewind, setAlphaMethodName, opacity);
if (bigNotRemoteView != null) bigNotRemoteView.setInt(R.id.notificationFRewind, setAlphaMethodName, opacity);
}
/*//////////////////////////////////////////////////////////////////////////
// Utils
//////////////////////////////////////////////////////////////////////////*/
@ -279,8 +268,16 @@ public final class BackgroundPlayer extends Service {
protected class BasePlayerImpl extends BasePlayer {
@NonNull final private AudioPlaybackResolver resolver;
BasePlayerImpl(Context context) {
super(context);
this.resolver = new AudioPlaybackResolver(context, dataSource);
}
@Override
public void initPlayer(boolean playOnReady) {
super.initPlayer(playOnReady);
}
@Override
@ -293,30 +290,41 @@ public final class BackgroundPlayer extends Service {
startForeground(NOTIFICATION_ID, notBuilder.build());
}
@Override
public void initThumbnail(final String url) {
resetNotification();
if (notRemoteView != null) notRemoteView.setImageViewResource(R.id.notificationCover, R.drawable.dummy_thumbnail);
if (bigNotRemoteView != null) bigNotRemoteView.setImageViewResource(R.id.notificationCover, R.drawable.dummy_thumbnail);
updateNotification(-1);
super.initThumbnail(url);
/*//////////////////////////////////////////////////////////////////////////
// Thumbnail Loading
//////////////////////////////////////////////////////////////////////////*/
private void updateNotificationThumbnail() {
if (basePlayerImpl == null) return;
if (notRemoteView != null) {
notRemoteView.setImageViewBitmap(R.id.notificationCover,
basePlayerImpl.getThumbnail());
}
if (bigNotRemoteView != null) {
bigNotRemoteView.setImageViewBitmap(R.id.notificationCover,
basePlayerImpl.getThumbnail());
}
}
@Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
super.onLoadingComplete(imageUri, view, loadedImage);
if (loadedImage != null) {
// rebuild notification here since remote view does not release bitmaps, causing memory leaks
resetNotification();
if (notRemoteView != null) notRemoteView.setImageViewBitmap(R.id.notificationCover, loadedImage);
if (bigNotRemoteView != null) bigNotRemoteView.setImageViewBitmap(R.id.notificationCover, loadedImage);
updateNotification(-1);
}
resetNotification();
updateNotificationThumbnail();
updateNotification(-1);
}
@Override
public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
super.onLoadingFailed(imageUri, view, failReason);
resetNotification();
updateNotificationThumbnail();
updateNotification(-1);
}
/*//////////////////////////////////////////////////////////////////////////
// States Implementation
//////////////////////////////////////////////////////////////////////////*/
@Override
public void onPrepared(boolean playWhenReady) {
super.onPrepared(playWhenReady);
@ -390,29 +398,18 @@ public final class BackgroundPlayer extends Service {
// Playback Listener
//////////////////////////////////////////////////////////////////////////*/
protected void onMetadataChanged(@NonNull final PlayQueueItem item,
@Nullable final StreamInfo info,
final int newPlayQueueIndex,
final boolean hasPlayQueueItemChanged) {
if (shouldUpdateOnProgress || hasPlayQueueItemChanged) {
resetNotification();
updateNotification(-1);
updateMetadata();
}
protected void onMetadataChanged(@NonNull final MediaSourceTag tag) {
super.onMetadataChanged(tag);
resetNotification();
updateNotificationThumbnail();
updateNotification(-1);
updateMetadata();
}
@Override
@Nullable
public MediaSource sourceOf(final PlayQueueItem item, final StreamInfo info) {
final MediaSource liveSource = super.sourceOf(item, info);
if (liveSource != null) return liveSource;
final int index = ListHelper.getDefaultAudioFormat(context, info.getAudioStreams());
if (index < 0 || index >= info.getAudioStreams().size()) return null;
final AudioStream audio = info.getAudioStreams().get(index);
return buildMediaSource(audio.getUrl(), PlayerHelper.cacheKeyOf(info, audio),
MediaFormat.getSuffixById(audio.getFormatId()));
return resolver.resolve(info);
}
@Override
@ -439,8 +436,8 @@ public final class BackgroundPlayer extends Service {
}
private void updateMetadata() {
if (activityListener != null && currentInfo != null) {
activityListener.onMetadataUpdate(currentInfo);
if (activityListener != null && getCurrentMetadata() != null) {
activityListener.onMetadataUpdate(getCurrentMetadata().getMetadata());
}
}
@ -531,44 +528,36 @@ public final class BackgroundPlayer extends Service {
updatePlayback();
}
@Override
public void onBlocked() {
super.onBlocked();
setControlsOpacity(77);
updateNotification(-1);
}
@Override
public void onPlaying() {
super.onPlaying();
setControlsOpacity(255);
resetNotification();
updateNotificationThumbnail();
updateNotification(R.drawable.ic_pause_white);
lockManager.acquireWifiAndCpu();
}
@Override
public void onPaused() {
super.onPaused();
resetNotification();
updateNotificationThumbnail();
updateNotification(R.drawable.ic_play_arrow_white);
lockManager.releaseWifiAndCpu();
}
@Override
public void onCompleted() {
super.onCompleted();
setControlsOpacity(255);
resetNotification();
if (bigNotRemoteView != null) bigNotRemoteView.setProgressBar(R.id.notificationProgressBar, 100, 100, false);
if (notRemoteView != null) notRemoteView.setProgressBar(R.id.notificationProgressBar, 100, 100, false);
if (bigNotRemoteView != null) {
bigNotRemoteView.setProgressBar(R.id.notificationProgressBar, 100, 100, false);
}
if (notRemoteView != null) {
notRemoteView.setProgressBar(R.id.notificationProgressBar, 100, 100, false);
}
updateNotificationThumbnail();
updateNotification(R.drawable.ic_replay_white);
lockManager.releaseWifiAndCpu();
}
}

View File

@ -24,16 +24,14 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.media.AudioManager;
import android.net.Uri;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Toast;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.DefaultRenderersFactory;
import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.ExoPlayerFactory;
@ -49,7 +47,6 @@ import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter;
import com.google.android.exoplayer2.util.Util;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.assist.FailReason;
import com.nostra13.universalimageloader.core.listener.ImageLoadingListener;
@ -57,7 +54,6 @@ import com.nostra13.universalimageloader.core.listener.ImageLoadingListener;
import org.schabi.newpipe.Downloader;
import org.schabi.newpipe.R;
import org.schabi.newpipe.extractor.stream.StreamInfo;
import org.schabi.newpipe.extractor.stream.StreamType;
import org.schabi.newpipe.local.history.HistoryRecordManager;
import org.schabi.newpipe.player.helper.AudioReactor;
import org.schabi.newpipe.player.helper.LoadController;
@ -72,6 +68,8 @@ import org.schabi.newpipe.player.playback.PlaybackListener;
import org.schabi.newpipe.player.playqueue.PlayQueue;
import org.schabi.newpipe.player.playqueue.PlayQueueAdapter;
import org.schabi.newpipe.player.playqueue.PlayQueueItem;
import org.schabi.newpipe.player.resolver.MediaSourceTag;
import org.schabi.newpipe.util.ImageDisplayConstants;
import org.schabi.newpipe.util.SerializedCache;
import java.io.IOException;
@ -82,12 +80,12 @@ import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.disposables.Disposable;
import io.reactivex.disposables.SerialDisposable;
import static com.google.android.exoplayer2.Player.DISCONTINUITY_REASON_INTERNAL;
import static com.google.android.exoplayer2.Player.DISCONTINUITY_REASON_PERIOD_TRANSITION;
import static com.google.android.exoplayer2.Player.DISCONTINUITY_REASON_SEEK;
import static com.google.android.exoplayer2.Player.DISCONTINUITY_REASON_SEEK_ADJUSTMENT;
import static org.schabi.newpipe.player.helper.PlayerHelper.getTimeString;
/**
* Base for the players, joining the common properties
@ -108,17 +106,26 @@ public abstract class BasePlayer implements
@NonNull final protected HistoryRecordManager recordManager;
@NonNull final protected CustomTrackSelector trackSelector;
@NonNull final protected PlayerDataSource dataSource;
@NonNull final private LoadControl loadControl;
@NonNull final private RenderersFactory renderFactory;
@NonNull final private SerialDisposable progressUpdateReactor;
@NonNull final private CompositeDisposable databaseUpdateReactor;
/*//////////////////////////////////////////////////////////////////////////
// Intent
//////////////////////////////////////////////////////////////////////////*/
public static final String REPEAT_MODE = "repeat_mode";
public static final String PLAYBACK_PITCH = "playback_pitch";
public static final String PLAYBACK_SPEED = "playback_speed";
public static final String PLAYBACK_QUALITY = "playback_quality";
public static final String PLAY_QUEUE_KEY = "play_queue_key";
public static final String APPEND_ONLY = "append_only";
public static final String SELECT_ON_APPEND = "select_on_append";
@NonNull public static final String REPEAT_MODE = "repeat_mode";
@NonNull public static final String PLAYBACK_PITCH = "playback_pitch";
@NonNull public static final String PLAYBACK_SPEED = "playback_speed";
@NonNull public static final String PLAYBACK_SKIP_SILENCE = "playback_skip_silence";
@NonNull public static final String PLAYBACK_QUALITY = "playback_quality";
@NonNull public static final String PLAY_QUEUE_KEY = "play_queue_key";
@NonNull public static final String APPEND_ONLY = "append_only";
@NonNull public static final String SELECT_ON_APPEND = "select_on_append";
/*//////////////////////////////////////////////////////////////////////////
// Playback
@ -129,12 +136,13 @@ public abstract class BasePlayer implements
protected PlayQueue playQueue;
protected PlayQueueAdapter playQueueAdapter;
protected MediaSourceManager playbackManager;
@Nullable protected MediaSourceManager playbackManager;
protected StreamInfo currentInfo;
protected PlayQueueItem currentItem;
@Nullable private PlayQueueItem currentItem;
@Nullable private MediaSourceTag currentMetadata;
@Nullable private Bitmap currentThumbnail;
protected Toast errorToast;
@Nullable protected Toast errorToast;
/*//////////////////////////////////////////////////////////////////////////
// Player
@ -145,18 +153,11 @@ public abstract class BasePlayer implements
protected final static int PROGRESS_LOOP_INTERVAL_MILLIS = 500;
protected final static int RECOVERY_SKIP_THRESHOLD_MILLIS = 3000; // 3 seconds
protected CustomTrackSelector trackSelector;
protected PlayerDataSource dataSource;
protected SimpleExoPlayer simpleExoPlayer;
protected AudioReactor audioReactor;
protected MediaSessionManager mediaSessionManager;
private boolean isPrepared = false;
private boolean isSynchronizing = false;
protected Disposable progressUpdateReactor;
protected CompositeDisposable databaseUpdateReactor;
//////////////////////////////////////////////////////////////////////////*/
@ -174,29 +175,32 @@ public abstract class BasePlayer implements
context.registerReceiver(broadcastReceiver, intentFilter);
this.recordManager = new HistoryRecordManager(context);
this.progressUpdateReactor = new SerialDisposable();
this.databaseUpdateReactor = new CompositeDisposable();
final String userAgent = Downloader.USER_AGENT;
final DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
this.dataSource = new PlayerDataSource(context, userAgent, bandwidthMeter);
final TrackSelection.Factory trackSelectionFactory =
PlayerHelper.getQualitySelector(context, bandwidthMeter);
this.trackSelector = new CustomTrackSelector(trackSelectionFactory);
this.loadControl = new LoadController(context);
this.renderFactory = new DefaultRenderersFactory(context);
}
public void setup() {
if (simpleExoPlayer == null) initPlayer(/*playOnInit=*/true);
if (simpleExoPlayer == null) {
initPlayer(/*playOnInit=*/true);
}
initListeners();
}
public void initPlayer(final boolean playOnReady) {
if (DEBUG) Log.d(TAG, "initPlayer() called with: context = [" + context + "]");
if (databaseUpdateReactor != null) databaseUpdateReactor.dispose();
databaseUpdateReactor = new CompositeDisposable();
final String userAgent = Downloader.USER_AGENT;
final DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
dataSource = new PlayerDataSource(context, userAgent, bandwidthMeter);
final TrackSelection.Factory trackSelectionFactory =
PlayerHelper.getQualitySelector(context, bandwidthMeter);
trackSelector = new CustomTrackSelector(trackSelectionFactory);
final LoadControl loadControl = new LoadController(context);
final RenderersFactory renderFactory = new DefaultRenderersFactory(context);
simpleExoPlayer = ExoPlayerFactory.newSimpleInstance(renderFactory, trackSelector, loadControl);
simpleExoPlayer.addListener(this);
simpleExoPlayer.setPlayWhenReady(playOnReady);
@ -235,20 +239,24 @@ public abstract class BasePlayer implements
final int repeatMode = intent.getIntExtra(REPEAT_MODE, getRepeatMode());
final float playbackSpeed = intent.getFloatExtra(PLAYBACK_SPEED, getPlaybackSpeed());
final float playbackPitch = intent.getFloatExtra(PLAYBACK_PITCH, getPlaybackPitch());
final boolean playbackSkipSilence = intent.getBooleanExtra(PLAYBACK_SKIP_SILENCE,
getPlaybackSkipSilence());
// Good to go...
initPlayback(queue, repeatMode, playbackSpeed, playbackPitch, /*playOnInit=*/true);
initPlayback(queue, repeatMode, playbackSpeed, playbackPitch, playbackSkipSilence,
/*playOnInit=*/true);
}
protected void initPlayback(@NonNull final PlayQueue queue,
@Player.RepeatMode final int repeatMode,
final float playbackSpeed,
final float playbackPitch,
final boolean playbackSkipSilence,
final boolean playOnReady) {
destroyPlayer();
initPlayer(playOnReady);
setRepeatMode(repeatMode);
setPlaybackParameters(playbackSpeed, playbackPitch);
setPlaybackParameters(playbackSpeed, playbackPitch, playbackSkipSilence);
playQueue = queue;
playQueue.init();
@ -270,7 +278,6 @@ public abstract class BasePlayer implements
if (playQueue != null) playQueue.dispose();
if (audioReactor != null) audioReactor.dispose();
if (playbackManager != null) playbackManager.dispose();
if (databaseUpdateReactor != null) databaseUpdateReactor.dispose();
if (mediaSessionManager != null) mediaSessionManager.dispose();
if (playQueueAdapter != null) {
@ -284,20 +291,22 @@ public abstract class BasePlayer implements
destroyPlayer();
unregisterBroadcastReceiver();
trackSelector = null;
databaseUpdateReactor.clear();
progressUpdateReactor.set(null);
simpleExoPlayer = null;
mediaSessionManager = null;
}
/*//////////////////////////////////////////////////////////////////////////
// Thumbnail Loading
//////////////////////////////////////////////////////////////////////////*/
public void initThumbnail(final String url) {
private void initThumbnail(final String url) {
if (DEBUG) Log.d(TAG, "Thumbnail - initThumbnail() called");
if (url == null || url.isEmpty()) return;
ImageLoader.getInstance().resume();
ImageLoader.getInstance().loadImage(url, this);
ImageLoader.getInstance().loadImage(url, ImageDisplayConstants.DISPLAY_THUMBNAIL_OPTIONS,
this);
}
@Override
@ -310,6 +319,7 @@ public abstract class BasePlayer implements
public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
Log.e(TAG, "Thumbnail - onLoadingFailed() called on imageUri = [" + imageUri + "]",
failReason.getCause());
currentThumbnail = null;
}
@Override
@ -317,64 +327,14 @@ public abstract class BasePlayer implements
if (DEBUG) Log.d(TAG, "Thumbnail - onLoadingComplete() called with: " +
"imageUri = [" + imageUri + "], view = [" + view + "], " +
"loadedImage = [" + loadedImage + "]");
currentThumbnail = loadedImage;
}
@Override
public void onLoadingCancelled(String imageUri, View view) {
if (DEBUG) Log.d(TAG, "Thumbnail - onLoadingCancelled() called with: " +
"imageUri = [" + imageUri + "], view = [" + view + "]");
}
/*//////////////////////////////////////////////////////////////////////////
// MediaSource Building
//////////////////////////////////////////////////////////////////////////*/
public MediaSource buildLiveMediaSource(@NonNull final String sourceUrl,
@C.ContentType final int type) {
if (DEBUG) {
Log.d(TAG, "buildLiveMediaSource() called with: url = [" + sourceUrl +
"], content type = [" + type + "]");
}
if (dataSource == null) return null;
final Uri uri = Uri.parse(sourceUrl);
switch (type) {
case C.TYPE_SS:
return dataSource.getLiveSsMediaSourceFactory().createMediaSource(uri);
case C.TYPE_DASH:
return dataSource.getLiveDashMediaSourceFactory().createMediaSource(uri);
case C.TYPE_HLS:
return dataSource.getLiveHlsMediaSourceFactory().createMediaSource(uri);
default:
throw new IllegalStateException("Unsupported type: " + type);
}
}
public MediaSource buildMediaSource(@NonNull final String sourceUrl,
@NonNull final String cacheKey,
@NonNull final String overrideExtension) {
if (DEBUG) {
Log.d(TAG, "buildMediaSource() called with: url = [" + sourceUrl +
"], cacheKey = [" + cacheKey + "]" +
"], overrideExtension = [" + overrideExtension + "]");
}
if (dataSource == null) return null;
final Uri uri = Uri.parse(sourceUrl);
@C.ContentType final int type = TextUtils.isEmpty(overrideExtension) ?
Util.inferContentType(uri) : Util.inferContentType("." + overrideExtension);
switch (type) {
case C.TYPE_SS:
return dataSource.getLiveSsMediaSourceFactory().createMediaSource(uri);
case C.TYPE_DASH:
return dataSource.getDashMediaSourceFactory().createMediaSource(uri);
case C.TYPE_HLS:
return dataSource.getHlsMediaSourceFactory().createMediaSource(uri);
case C.TYPE_OTHER:
return dataSource.getExtractorMediaSourceFactory(cacheKey).createMediaSource(uri);
default:
throw new IllegalStateException("Unsupported type: " + type);
}
currentThumbnail = null;
}
/*//////////////////////////////////////////////////////////////////////////
@ -510,13 +470,11 @@ public abstract class BasePlayer implements
public abstract void onUpdateProgress(int currentProgress, int duration, int bufferPercent);
protected void startProgressLoop() {
if (progressUpdateReactor != null) progressUpdateReactor.dispose();
progressUpdateReactor = getProgressReactor();
progressUpdateReactor.set(getProgressReactor());
}
protected void stopProgressLoop() {
if (progressUpdateReactor != null) progressUpdateReactor.dispose();
progressUpdateReactor = null;
progressUpdateReactor.set(null);
}
public void triggerProgressUpdate() {
@ -531,7 +489,8 @@ public abstract class BasePlayer implements
private Disposable getProgressReactor() {
return Observable.interval(PROGRESS_LOOP_INTERVAL_MILLIS, TimeUnit.MILLISECONDS)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(ignored -> triggerProgressUpdate());
.subscribe(ignored -> triggerProgressUpdate(),
error -> Log.e(TAG, "Progress update failure: ", error));
}
/*//////////////////////////////////////////////////////////////////////////
@ -545,28 +504,16 @@ public abstract class BasePlayer implements
(manifest == null ? "no manifest" : "available manifest") + ", " +
"timeline size = [" + timeline.getWindowCount() + "], " +
"reason = [" + reason + "]");
if (playQueue == null) return;
switch (reason) {
case Player.TIMELINE_CHANGE_REASON_RESET: // called after #block
case Player.TIMELINE_CHANGE_REASON_PREPARED: // called after #unblock
case Player.TIMELINE_CHANGE_REASON_DYNAMIC: // called after playlist changes
// Ensures MediaSourceManager#update is complete
final boolean isPlaylistStable = timeline.getWindowCount() == playQueue.size();
// Ensure dynamic/livestream timeline changes does not cause negative position
if (isPlaylistStable && !isCurrentWindowValid() && !isSynchronizing) {
if (DEBUG) Log.d(TAG, "Playback - negative time position reached, " +
"clamping to default position.");
seekToDefault();
}
break;
}
maybeUpdateCurrentMetadata();
}
@Override
public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
if (DEBUG) Log.d(TAG, "ExoPlayer - onTracksChanged(), " +
"track group size = " + trackGroups.length);
maybeUpdateCurrentMetadata();
}
@Override
@ -586,6 +533,8 @@ public abstract class BasePlayer implements
} else if (isLoading && !isProgressLoopRunning()) {
startProgressLoop();
}
maybeUpdateCurrentMetadata();
}
@Override
@ -609,6 +558,7 @@ public abstract class BasePlayer implements
}
break;
case Player.STATE_READY: //3
maybeUpdateCurrentMetadata();
maybeCorrectSeekPosition();
if (!isPrepared) {
isPrepared = true;
@ -625,38 +575,19 @@ public abstract class BasePlayer implements
}
private void maybeCorrectSeekPosition() {
if (playQueue == null || simpleExoPlayer == null || currentInfo == null) return;
if (playQueue == null || simpleExoPlayer == null || currentMetadata == null) return;
final int currentSourceIndex = playQueue.getIndex();
final PlayQueueItem currentSourceItem = playQueue.getItem();
if (currentSourceItem == null) return;
final long recoveryPositionMillis = currentSourceItem.getRecoveryPosition();
final boolean isCurrentWindowCorrect =
simpleExoPlayer.getCurrentPeriodIndex() == currentSourceIndex;
final StreamInfo currentInfo = currentMetadata.getMetadata();
final long presetStartPositionMillis = currentInfo.getStartPosition() * 1000;
if (recoveryPositionMillis != PlayQueueItem.RECOVERY_UNSET && isCurrentWindowCorrect) {
// Is recovering previous playback?
if (DEBUG) Log.d(TAG, "Playback - Rewinding to recovery time=" +
"[" + getTimeString((int)recoveryPositionMillis) + "]");
seekTo(recoveryPositionMillis);
playQueue.unsetRecovery(currentSourceIndex);
} else if (isSynchronizing && isLive()) {
if (DEBUG) Log.d(TAG, "Playback - Synchronizing livestream to default time");
// Is still synchronizing?
seekToDefault();
} else if (isSynchronizing && presetStartPositionMillis > 0L) {
if (presetStartPositionMillis > 0L) {
// Has another start position?
if (DEBUG) Log.d(TAG, "Playback - Seeking to preset start " +
"position=[" + presetStartPositionMillis + "]");
// Has another start position?
seekTo(presetStartPositionMillis);
currentInfo.setStartPosition(0);
}
isSynchronizing = false;
}
/**
@ -708,7 +639,7 @@ public abstract class BasePlayer implements
setRecovery();
final Throwable cause = error.getCause();
if (cause instanceof BehindLiveWindowException) {
if (error instanceof BehindLiveWindowException) {
reload();
} else if (cause instanceof UnknownHostException) {
playQueue.error(/*isNetworkProblem=*/true);
@ -727,22 +658,29 @@ public abstract class BasePlayer implements
public void onPositionDiscontinuity(@Player.DiscontinuityReason final int reason) {
if (DEBUG) Log.d(TAG, "ExoPlayer - onPositionDiscontinuity() called with " +
"reason = [" + reason + "]");
// Refresh the playback if there is a transition to the next video
final int newPeriodIndex = simpleExoPlayer.getCurrentPeriodIndex();
if (playQueue == null) return;
/* Discontinuity reasons!! Thank you ExoPlayer lords */
// Refresh the playback if there is a transition to the next video
final int newWindowIndex = simpleExoPlayer.getCurrentWindowIndex();
switch (reason) {
case DISCONTINUITY_REASON_PERIOD_TRANSITION:
if (newPeriodIndex == playQueue.getIndex()) {
// When player is in single repeat mode and a period transition occurs,
// we need to register a view count here since no metadata has changed
if (getRepeatMode() == Player.REPEAT_MODE_ONE &&
newWindowIndex == playQueue.getIndex()) {
registerView();
} else {
playQueue.offsetIndex(+1);
break;
}
case DISCONTINUITY_REASON_SEEK:
case DISCONTINUITY_REASON_SEEK_ADJUSTMENT:
case DISCONTINUITY_REASON_INTERNAL:
if (playQueue.getIndex() != newWindowIndex) {
playQueue.setIndex(newWindowIndex);
}
break;
}
maybeUpdateCurrentMetadata();
}
@Override
@ -788,7 +726,7 @@ public abstract class BasePlayer implements
if (DEBUG) Log.d(TAG, "Playback - onPlaybackBlock() called");
currentItem = null;
currentInfo = null;
currentMetadata = null;
simpleExoPlayer.stop();
isPrepared = false;
@ -805,42 +743,21 @@ public abstract class BasePlayer implements
simpleExoPlayer.prepare(mediaSource);
}
@Override
public void onPlaybackSynchronize(@NonNull final PlayQueueItem item,
@Nullable final StreamInfo info) {
public void onPlaybackSynchronize(@NonNull final PlayQueueItem item) {
if (DEBUG) Log.d(TAG, "Playback - onPlaybackSynchronize() called with " +
(info != null ? "available" : "null") + " info, " +
"item=[" + item.getTitle() + "], url=[" + item.getUrl() + "]");
if (simpleExoPlayer == null || playQueue == null) return;
final boolean onPlaybackInitial = currentItem == null;
final boolean hasPlayQueueItemChanged = currentItem != item;
final boolean hasStreamInfoChanged = currentInfo != info;
final int currentPlayQueueIndex = playQueue.indexOf(item);
final int currentPlaylistIndex = simpleExoPlayer.getCurrentWindowIndex();
final int currentPlaylistSize = simpleExoPlayer.getCurrentTimeline().getWindowCount();
// when starting playback on the last item when not repeating, maybe auto queue
if (info != null && currentPlayQueueIndex == playQueue.size() - 1 &&
getRepeatMode() == Player.REPEAT_MODE_OFF &&
PlayerHelper.isAutoQueueEnabled(context)) {
final PlayQueue autoQueue = PlayerHelper.autoQueueOf(info, playQueue.getStreams());
if (autoQueue != null) playQueue.append(autoQueue.getStreams());
}
// If nothing to synchronize
if (!hasPlayQueueItemChanged && !hasStreamInfoChanged) {
return;
}
if (!hasPlayQueueItemChanged) return;
currentItem = item;
currentInfo = info;
if (hasPlayQueueItemChanged) {
// updates only to the stream info should not trigger another view count
registerView();
initThumbnail(info == null ? item.getThumbnailUrl() : info.getThumbnailUrl());
}
onMetadataChanged(item, info, currentPlayQueueIndex, hasPlayQueueItemChanged);
// Check if on wrong window
if (currentPlayQueueIndex != playQueue.getIndex()) {
@ -855,39 +772,29 @@ public abstract class BasePlayer implements
"index=[" + currentPlayQueueIndex + "] with " +
"playlist length=[" + currentPlaylistSize + "]");
// If not playing correct stream, change window position and sets flag
// for synchronizing once window position is corrected
// @see maybeCorrectSeekPosition()
} else if (currentPlaylistIndex != currentPlayQueueIndex || onPlaybackInitial ||
!isPlaying()) {
if (DEBUG) Log.d(TAG, "Playback - Rewinding to correct" +
" index=[" + currentPlayQueueIndex + "]," +
" from=[" + currentPlaylistIndex + "], size=[" + currentPlaylistSize + "].");
isSynchronizing = true;
simpleExoPlayer.seekToDefaultPosition(currentPlayQueueIndex);
if (item.getRecoveryPosition() != PlayQueueItem.RECOVERY_UNSET) {
simpleExoPlayer.seekTo(currentPlayQueueIndex, item.getRecoveryPosition());
playQueue.unsetRecovery(currentPlayQueueIndex);
} else {
simpleExoPlayer.seekToDefaultPosition(currentPlayQueueIndex);
}
}
}
abstract protected void onMetadataChanged(@NonNull final PlayQueueItem item,
@Nullable final StreamInfo info,
final int newPlayQueueIndex,
final boolean hasPlayQueueItemChanged);
@Nullable
@Override
public MediaSource sourceOf(PlayQueueItem item, StreamInfo info) {
final StreamType streamType = info.getStreamType();
if (!(streamType == StreamType.AUDIO_LIVE_STREAM || streamType == StreamType.LIVE_STREAM)) {
return null;
protected void onMetadataChanged(@NonNull final MediaSourceTag tag) {
final StreamInfo info = tag.getMetadata();
if (DEBUG) {
Log.d(TAG, "Playback - onMetadataChanged() called, playing: " + info.getName());
}
if (!info.getHlsUrl().isEmpty()) {
return buildLiveMediaSource(info.getHlsUrl(), C.TYPE_HLS);
} else if (!info.getDashMpdUrl().isEmpty()) {
return buildLiveMediaSource(info.getDashMpdUrl(), C.TYPE_DASH);
}
return null;
initThumbnail(info.getThumbnailUrl());
registerView();
}
@Override
@ -1020,9 +927,7 @@ public abstract class BasePlayer implements
public void seekTo(long positionMillis) {
if (DEBUG) Log.d(TAG, "seekBy() called with: position = [" + positionMillis + "]");
if (simpleExoPlayer == null || positionMillis < 0 ||
positionMillis > simpleExoPlayer.getDuration()) return;
simpleExoPlayer.seekTo(positionMillis);
if (simpleExoPlayer != null) simpleExoPlayer.seekTo(positionMillis);
}
public void seekBy(long offsetMillis) {
@ -1046,12 +951,14 @@ public abstract class BasePlayer implements
//////////////////////////////////////////////////////////////////////////*/
private void registerView() {
if (databaseUpdateReactor == null || currentInfo == null) return;
databaseUpdateReactor.add(recordManager.onViewed(currentInfo).onErrorComplete()
if (currentMetadata == null) return;
final StreamInfo currentInfo = currentMetadata.getMetadata();
final Disposable viewRegister = recordManager.onViewed(currentInfo).onErrorComplete()
.subscribe(
ignored -> {/* successful */},
error -> Log.e(TAG, "Player onViewed() failure: ", error)
));
);
databaseUpdateReactor.add(viewRegister);
}
protected void reload() {
@ -1065,7 +972,7 @@ public abstract class BasePlayer implements
}
protected void savePlaybackState(final StreamInfo info, final long progress) {
if (info == null || databaseUpdateReactor == null) return;
if (info == null) return;
final Disposable stateSaver = recordManager.saveStreamState(info, progress)
.observeOn(AndroidSchedulers.mainThread())
.onErrorComplete()
@ -1077,7 +984,8 @@ public abstract class BasePlayer implements
}
private void savePlaybackState() {
if (simpleExoPlayer == null || currentInfo == null) return;
if (simpleExoPlayer == null || currentMetadata == null) return;
final StreamInfo currentInfo = currentMetadata.getMetadata();
if (simpleExoPlayer.getCurrentPosition() > RECOVERY_SKIP_THRESHOLD_MILLIS &&
simpleExoPlayer.getCurrentPosition() <
@ -1085,6 +993,34 @@ public abstract class BasePlayer implements
savePlaybackState(currentInfo, simpleExoPlayer.getCurrentPosition());
}
}
private void maybeUpdateCurrentMetadata() {
if (simpleExoPlayer == null) return;
final MediaSourceTag metadata;
try {
metadata = (MediaSourceTag) simpleExoPlayer.getCurrentTag();
} catch (IndexOutOfBoundsException | ClassCastException error) {
return;
}
if (metadata == null) return;
maybeAutoQueueNextStream(metadata);
if (currentMetadata == metadata) return;
currentMetadata = metadata;
onMetadataChanged(metadata);
}
private void maybeAutoQueueNextStream(@NonNull final MediaSourceTag currentMetadata) {
if (playQueue == null || playQueue.getIndex() != playQueue.size() - 1 ||
getRepeatMode() != Player.REPEAT_MODE_OFF ||
!PlayerHelper.isAutoQueueEnabled(context)) return;
// auto queue when starting playback on the last item when not repeating
final PlayQueue autoQueue = PlayerHelper.autoQueueOf(currentMetadata.getMetadata(),
playQueue.getStreams());
if (autoQueue != null) playQueue.append(autoQueue.getStreams());
}
/*//////////////////////////////////////////////////////////////////////////
// Getters and Setters
//////////////////////////////////////////////////////////////////////////*/
@ -1101,19 +1037,35 @@ public abstract class BasePlayer implements
return currentState;
}
@Nullable
public MediaSourceTag getCurrentMetadata() {
return currentMetadata;
}
@NonNull
public String getVideoUrl() {
return currentItem == null ? context.getString(R.string.unknown_content) : currentItem.getUrl();
return currentMetadata == null ? context.getString(R.string.unknown_content) : currentMetadata.getMetadata().getUrl();
}
@NonNull
public String getVideoTitle() {
return currentItem == null ? context.getString(R.string.unknown_content) : currentItem.getTitle();
return currentMetadata == null ? context.getString(R.string.unknown_content) : currentMetadata.getMetadata().getName();
}
@NonNull
public String getUploaderName() {
return currentItem == null ? context.getString(R.string.unknown_content) : currentItem.getUploader();
return currentMetadata == null ? context.getString(R.string.unknown_content) : currentMetadata.getMetadata().getUploaderName();
}
@Nullable
public Bitmap getThumbnail() {
return currentThumbnail == null ?
BitmapFactory.decodeResource(context.getResources(), R.drawable.dummy_thumbnail) :
currentThumbnail;
}
/** Checks if the current playback is a livestream AND is playing at or beyond the live edge */
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
public boolean isLiveEdge() {
if (simpleExoPlayer == null || !isLive()) return false;
@ -1162,19 +1114,22 @@ public abstract class BasePlayer implements
return getPlaybackParameters().pitch;
}
public boolean getPlaybackSkipSilence() {
return getPlaybackParameters().skipSilence;
}
public void setPlaybackSpeed(float speed) {
setPlaybackParameters(speed, getPlaybackPitch());
setPlaybackParameters(speed, getPlaybackPitch(), getPlaybackSkipSilence());
}
public PlaybackParameters getPlaybackParameters() {
final PlaybackParameters defaultParameters = new PlaybackParameters(1f, 1f);
if (simpleExoPlayer == null) return defaultParameters;
if (simpleExoPlayer == null) return PlaybackParameters.DEFAULT;
final PlaybackParameters parameters = simpleExoPlayer.getPlaybackParameters();
return parameters == null ? defaultParameters : parameters;
return parameters == null ? PlaybackParameters.DEFAULT : parameters;
}
public void setPlaybackParameters(float speed, float pitch) {
simpleExoPlayer.setPlaybackParameters(new PlaybackParameters(speed, pitch));
public void setPlaybackParameters(float speed, float pitch, boolean skipSilence) {
simpleExoPlayer.setPlaybackParameters(new PlaybackParameters(speed, pitch, skipSilence));
}
public PlayQueue getPlayQueue() {
@ -1190,7 +1145,7 @@ public abstract class BasePlayer implements
}
public boolean isProgressLoopRunning() {
return progressUpdateReactor != null && !progressUpdateReactor.isDisposed();
return progressUpdateReactor.get() != null;
}
public void setRecovery() {

View File

@ -58,7 +58,6 @@ import com.google.android.exoplayer2.ui.AspectRatioFrameLayout;
import com.google.android.exoplayer2.ui.SubtitleView;
import org.schabi.newpipe.R;
import org.schabi.newpipe.extractor.stream.StreamInfo;
import org.schabi.newpipe.extractor.stream.VideoStream;
import org.schabi.newpipe.fragments.OnScrollBelowItemsListener;
import org.schabi.newpipe.player.helper.PlaybackParameterDialog;
@ -67,6 +66,8 @@ import org.schabi.newpipe.player.playqueue.PlayQueueItem;
import org.schabi.newpipe.player.playqueue.PlayQueueItemBuilder;
import org.schabi.newpipe.player.playqueue.PlayQueueItemHolder;
import org.schabi.newpipe.player.playqueue.PlayQueueItemTouchCallback;
import org.schabi.newpipe.player.resolver.MediaSourceTag;
import org.schabi.newpipe.player.resolver.VideoPlaybackResolver;
import org.schabi.newpipe.util.AnimationUtils;
import org.schabi.newpipe.util.ListHelper;
import org.schabi.newpipe.util.NavigationHelper;
@ -126,7 +127,7 @@ public final class MainVideoPlayer extends AppCompatActivity
hideSystemUi();
setContentView(R.layout.activity_main_player);
playerImpl = new VideoPlayerImpl(this);
playerImpl = new VideoPlayerImpl(this);
playerImpl.setup(findViewById(android.R.id.content));
if (savedInstanceState != null && savedInstanceState.get(KEY_SAVED_STATE) != null) {
@ -181,7 +182,7 @@ public final class MainVideoPlayer extends AppCompatActivity
playerImpl.setPlaybackQuality(playerState.getPlaybackQuality());
playerImpl.initPlayback(playerState.getPlayQueue(), playerState.getRepeatMode(),
playerState.getPlaybackSpeed(), playerState.getPlaybackPitch(),
playerState.wasPlaying());
playerState.isPlaybackSkipSilence(), playerState.wasPlaying());
}
}
@ -210,7 +211,8 @@ public final class MainVideoPlayer extends AppCompatActivity
playerImpl.setRecovery();
playerState = new PlayerState(playerImpl.getPlayQueue(), playerImpl.getRepeatMode(),
playerImpl.getPlaybackSpeed(), playerImpl.getPlaybackPitch(),
playerImpl.getPlaybackQuality(), playerImpl.isPlaying());
playerImpl.getPlaybackQuality(), playerImpl.getPlaybackSkipSilence(),
playerImpl.isPlaying());
StateSaver.tryToSave(isChangingConfigurations(), null, outState, this);
}
@ -352,8 +354,11 @@ public final class MainVideoPlayer extends AppCompatActivity
////////////////////////////////////////////////////////////////////////////
@Override
public void onPlaybackParameterChanged(float playbackTempo, float playbackPitch) {
if (playerImpl != null) playerImpl.setPlaybackParameters(playbackTempo, playbackPitch);
public void onPlaybackParameterChanged(float playbackTempo, float playbackPitch,
boolean playbackSkipSilence) {
if (playerImpl != null) {
playerImpl.setPlaybackParameters(playbackTempo, playbackPitch, playbackSkipSilence);
}
}
///////////////////////////////////////////////////////////////////////////
@ -493,14 +498,11 @@ public final class MainVideoPlayer extends AppCompatActivity
// Playback Listener
//////////////////////////////////////////////////////////////////////////*/
protected void onMetadataChanged(@NonNull final PlayQueueItem item,
@Nullable final StreamInfo info,
final int newPlayQueueIndex,
final boolean hasPlayQueueItemChanged) {
super.onMetadataChanged(item, info, newPlayQueueIndex, false);
protected void onMetadataChanged(@NonNull final MediaSourceTag tag) {
super.onMetadataChanged(tag);
titleTextView.setText(getVideoTitle());
channelTextView.setText(getUploaderName());
titleTextView.setText(tag.getMetadata().getName());
channelTextView.setText(tag.getMetadata().getUploaderName());
}
@Override
@ -533,6 +535,7 @@ public final class MainVideoPlayer extends AppCompatActivity
this.getRepeatMode(),
this.getPlaybackSpeed(),
this.getPlaybackPitch(),
this.getPlaybackSkipSilence(),
this.getPlaybackQuality()
);
context.startService(intent);
@ -554,6 +557,7 @@ public final class MainVideoPlayer extends AppCompatActivity
this.getRepeatMode(),
this.getPlaybackSpeed(),
this.getPlaybackPitch(),
this.getPlaybackSkipSilence(),
this.getPlaybackQuality()
);
context.startService(intent);
@ -649,7 +653,8 @@ public final class MainVideoPlayer extends AppCompatActivity
@Override
public void onPlaybackSpeedClicked() {
PlaybackParameterDialog.newInstance(getPlaybackSpeed(), getPlaybackPitch())
PlaybackParameterDialog
.newInstance(getPlaybackSpeed(), getPlaybackPitch(), getPlaybackSkipSilence())
.show(getSupportFragmentManager(), TAG);
}
@ -679,14 +684,19 @@ public final class MainVideoPlayer extends AppCompatActivity
}
@Override
protected int getDefaultResolutionIndex(final List<VideoStream> sortedVideos) {
return ListHelper.getDefaultResolutionIndex(context, sortedVideos);
}
protected VideoPlaybackResolver.QualityResolver getQualityResolver() {
return new VideoPlaybackResolver.QualityResolver() {
@Override
public int getDefaultResolutionIndex(List<VideoStream> sortedVideos) {
return ListHelper.getDefaultResolutionIndex(context, sortedVideos);
}
@Override
protected int getOverrideResolutionIndex(final List<VideoStream> sortedVideos,
final String playbackQuality) {
return ListHelper.getResolutionIndex(context, sortedVideos, playbackQuality);
@Override
public int getOverrideResolutionIndex(List<VideoStream> sortedVideos,
String playbackQuality) {
return ListHelper.getResolutionIndex(context, sortedVideos, playbackQuality);
}
};
}
/*//////////////////////////////////////////////////////////////////////////
@ -710,7 +720,6 @@ public final class MainVideoPlayer extends AppCompatActivity
@Override
public void onBuffering() {
super.onBuffering();
animatePlayButtons(false, 100);
getRootView().setKeepScreenOn(true);
}
@ -886,7 +895,6 @@ public final class MainVideoPlayer extends AppCompatActivity
@Override
public boolean onDoubleTap(MotionEvent e) {
if (DEBUG) Log.d(TAG, "onDoubleTap() called with: e = [" + e + "]" + "rawXy = " + e.getRawX() + ", " + e.getRawY() + ", xy = " + e.getX() + ", " + e.getY());
if (!playerImpl.isPlaying()) return false;
if (e.getX() > playerImpl.getRootView().getWidth() * 2 / 3) {
playerImpl.onFastForward();

View File

@ -14,21 +14,26 @@ public class PlayerState implements Serializable {
private final float playbackSpeed;
private final float playbackPitch;
@Nullable private final String playbackQuality;
private final boolean playbackSkipSilence;
private final boolean wasPlaying;
PlayerState(@NonNull final PlayQueue playQueue, final int repeatMode,
final float playbackSpeed, final float playbackPitch, final boolean wasPlaying) {
this(playQueue, repeatMode, playbackSpeed, playbackPitch, null, wasPlaying);
final float playbackSpeed, final float playbackPitch,
final boolean playbackSkipSilence, final boolean wasPlaying) {
this(playQueue, repeatMode, playbackSpeed, playbackPitch, null,
playbackSkipSilence, wasPlaying);
}
PlayerState(@NonNull final PlayQueue playQueue, final int repeatMode,
final float playbackSpeed, final float playbackPitch,
@Nullable final String playbackQuality, final boolean wasPlaying) {
@Nullable final String playbackQuality, final boolean playbackSkipSilence,
final boolean wasPlaying) {
this.playQueue = playQueue;
this.repeatMode = repeatMode;
this.playbackSpeed = playbackSpeed;
this.playbackPitch = playbackPitch;
this.playbackQuality = playbackQuality;
this.playbackSkipSilence = playbackSkipSilence;
this.wasPlaying = wasPlaying;
}
@ -62,6 +67,10 @@ public class PlayerState implements Serializable {
return playbackQuality;
}
public boolean isPlaybackSkipSilence() {
return playbackSkipSilence;
}
public boolean wasPlaying() {
return wasPlaying;
}

View File

@ -34,7 +34,6 @@ import android.os.Build;
import android.os.IBinder;
import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.NotificationCompat;
import android.util.DisplayMetrics;
import android.util.Log;
@ -56,16 +55,17 @@ import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.text.CaptionStyleCompat;
import com.google.android.exoplayer2.ui.AspectRatioFrameLayout;
import com.google.android.exoplayer2.ui.SubtitleView;
import com.nostra13.universalimageloader.core.assist.FailReason;
import org.schabi.newpipe.BuildConfig;
import org.schabi.newpipe.R;
import org.schabi.newpipe.extractor.stream.StreamInfo;
import org.schabi.newpipe.extractor.stream.VideoStream;
import org.schabi.newpipe.player.event.PlayerEventListener;
import org.schabi.newpipe.player.helper.LockManager;
import org.schabi.newpipe.player.helper.PlayerHelper;
import org.schabi.newpipe.player.old.PlayVideoActivity;
import org.schabi.newpipe.player.playqueue.PlayQueueItem;
import org.schabi.newpipe.player.resolver.MediaSourceTag;
import org.schabi.newpipe.player.resolver.VideoPlaybackResolver;
import org.schabi.newpipe.util.ListHelper;
import org.schabi.newpipe.util.NavigationHelper;
import org.schabi.newpipe.util.ThemeHelper;
@ -98,6 +98,11 @@ public final class PopupVideoPlayer extends Service {
private static final int MINIMUM_SHOW_EXTRA_WIDTH_DP = 300;
private static final int IDLE_WINDOW_FLAGS = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
private static final int ONGOING_PLAYBACK_WINDOW_FLAGS = IDLE_WINDOW_FLAGS |
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
private WindowManager windowManager;
private WindowManager.LayoutParams windowLayoutParams;
private GestureDetector gestureDetector;
@ -191,14 +196,17 @@ public final class PopupVideoPlayer extends Service {
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
popupWidth = popupRememberSizeAndPos ? sharedPreferences.getFloat(POPUP_SAVED_WIDTH, defaultSize) : defaultSize;
final int layoutParamType = Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.O ? WindowManager.LayoutParams.TYPE_PHONE : WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
final int layoutParamType = Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.O ?
WindowManager.LayoutParams.TYPE_PHONE :
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
windowLayoutParams = new WindowManager.LayoutParams(
(int) popupWidth, (int) getMinimumVideoHeight(popupWidth),
layoutParamType,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
IDLE_WINDOW_FLAGS,
PixelFormat.TRANSLUCENT);
windowLayoutParams.gravity = Gravity.LEFT | Gravity.TOP;
windowLayoutParams.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
int centerX = (int) (screenWidth / 2f - popupWidth / 2f);
int centerY = (int) (screenHeight / 2f - popupHeight / 2f);
@ -228,6 +236,7 @@ public final class PopupVideoPlayer extends Service {
notRemoteView.setTextViewText(R.id.notificationSongName, playerImpl.getVideoTitle());
notRemoteView.setTextViewText(R.id.notificationArtist, playerImpl.getUploaderName());
notRemoteView.setImageViewBitmap(R.id.notificationCover, playerImpl.getThumbnail());
notRemoteView.setOnClickPendingIntent(R.id.notificationPlayPause,
PendingIntent.getBroadcast(this, NOTIFICATION_ID, new Intent(ACTION_PLAY_PAUSE), PendingIntent.FLAG_UPDATE_CURRENT));
@ -243,11 +252,15 @@ public final class PopupVideoPlayer extends Service {
setRepeatModeRemote(notRemoteView, playerImpl.getRepeatMode());
return new NotificationCompat.Builder(this, getString(R.string.notification_channel_id))
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, getString(R.string.notification_channel_id))
.setOngoing(true)
.setSmallIcon(R.drawable.ic_newpipe_triangle_white)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setContent(notRemoteView);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) {
builder.setPriority(NotificationCompat.PRIORITY_MAX);
}
return builder;
}
/**
@ -366,6 +379,12 @@ public final class PopupVideoPlayer extends Service {
}
}
private void updateWindowFlags(final int flags) {
if (windowLayoutParams == null || windowManager == null || playerImpl == null) return;
windowLayoutParams.flags = flags;
windowManager.updateViewLayout(playerImpl.getRootView(), windowLayoutParams);
}
///////////////////////////////////////////////////////////////////////////
protected class VideoPlayerImpl extends VideoPlayer implements View.OnLayoutChangeListener {
@ -428,21 +447,6 @@ public final class PopupVideoPlayer extends Service {
super.destroy();
}
@Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
super.onLoadingComplete(imageUri, view, loadedImage);
if (loadedImage != null) {
// rebuild notification here since remote view does not release bitmaps, causing memory leaks
notBuilder = createNotification();
if (notRemoteView != null) {
notRemoteView.setImageViewBitmap(R.id.notificationCover, loadedImage);
}
updateNotification(-1);
}
}
@Override
public void onFullScreenButtonClicked() {
super.onFullScreenButtonClicked();
@ -459,6 +463,7 @@ public final class PopupVideoPlayer extends Service {
this.getRepeatMode(),
this.getPlaybackSpeed(),
this.getPlaybackPitch(),
this.getPlaybackSkipSilence(),
this.getPlaybackQuality()
);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
@ -510,14 +515,47 @@ public final class PopupVideoPlayer extends Service {
}
@Override
protected int getDefaultResolutionIndex(final List<VideoStream> sortedVideos) {
return ListHelper.getPopupDefaultResolutionIndex(context, sortedVideos);
protected VideoPlaybackResolver.QualityResolver getQualityResolver() {
return new VideoPlaybackResolver.QualityResolver() {
@Override
public int getDefaultResolutionIndex(List<VideoStream> sortedVideos) {
return ListHelper.getPopupDefaultResolutionIndex(context, sortedVideos);
}
@Override
public int getOverrideResolutionIndex(List<VideoStream> sortedVideos,
String playbackQuality) {
return ListHelper.getPopupResolutionIndex(context, sortedVideos,
playbackQuality);
}
};
}
/*//////////////////////////////////////////////////////////////////////////
// Thumbnail Loading
//////////////////////////////////////////////////////////////////////////*/
@Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
super.onLoadingComplete(imageUri, view, loadedImage);
// rebuild notification here since remote view does not release bitmaps,
// causing memory leaks
resetNotification();
updateNotification(-1);
}
@Override
protected int getOverrideResolutionIndex(final List<VideoStream> sortedVideos,
final String playbackQuality) {
return ListHelper.getPopupResolutionIndex(context, sortedVideos, playbackQuality);
public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
super.onLoadingFailed(imageUri, view, failReason);
resetNotification();
updateNotification(-1);
}
@Override
public void onLoadingCancelled(String imageUri, View view) {
super.onLoadingCancelled(imageUri, view);
resetNotification();
updateNotification(-1);
}
/*//////////////////////////////////////////////////////////////////////////
@ -538,8 +576,8 @@ public final class PopupVideoPlayer extends Service {
}
private void updateMetadata() {
if (activityListener != null && currentInfo != null) {
activityListener.onMetadataUpdate(currentInfo);
if (activityListener != null && getCurrentMetadata() != null) {
activityListener.onMetadataUpdate(getCurrentMetadata().getMetadata());
}
}
@ -571,8 +609,9 @@ public final class PopupVideoPlayer extends Service {
public void onRepeatModeChanged(int i) {
super.onRepeatModeChanged(i);
setRepeatModeRemote(notRemoteView, i);
updateNotification(-1);
updatePlayback();
resetNotification();
updateNotification(-1);
}
@Override
@ -585,11 +624,10 @@ public final class PopupVideoPlayer extends Service {
// Playback Listener
//////////////////////////////////////////////////////////////////////////*/
protected void onMetadataChanged(@NonNull final PlayQueueItem item,
@Nullable final StreamInfo info,
final int newPlayQueueIndex,
final boolean hasPlayQueueItemChanged) {
super.onMetadataChanged(item, info, newPlayQueueIndex, false);
protected void onMetadataChanged(@NonNull final MediaSourceTag tag) {
super.onMetadataChanged(tag);
resetNotification();
updateNotification(-1);
updateMetadata();
}
@ -652,56 +690,70 @@ public final class PopupVideoPlayer extends Service {
@Override
public void onBlocked() {
super.onBlocked();
resetNotification();
updateNotification(R.drawable.ic_play_arrow_white);
}
@Override
public void onPlaying() {
super.onPlaying();
updateNotification(R.drawable.ic_pause_white);
videoPlayPause.setBackgroundResource(R.drawable.ic_pause_white);
lockManager.acquireWifiAndCpu();
updateWindowFlags(ONGOING_PLAYBACK_WINDOW_FLAGS);
resetNotification();
updateNotification(R.drawable.ic_pause_white);
videoPlayPause.setBackgroundResource(R.drawable.ic_pause_white);
hideControls(DEFAULT_CONTROLS_DURATION, DEFAULT_CONTROLS_HIDE_TIME);
windowLayoutParams.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
windowManager.updateViewLayout(playerImpl.getRootView(), windowLayoutParams);
startForeground(NOTIFICATION_ID, notBuilder.build());
lockManager.acquireWifiAndCpu();
}
@Override
public void onBuffering() {
super.onBuffering();
resetNotification();
updateNotification(R.drawable.ic_play_arrow_white);
}
@Override
public void onPaused() {
super.onPaused();
updateWindowFlags(IDLE_WINDOW_FLAGS);
resetNotification();
updateNotification(R.drawable.ic_play_arrow_white);
videoPlayPause.setBackgroundResource(R.drawable.ic_play_arrow_white);
lockManager.releaseWifiAndCpu();
windowLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
windowManager.updateViewLayout(playerImpl.getRootView(), windowLayoutParams);
stopForeground(false);
}
@Override
public void onPausedSeek() {
super.onPausedSeek();
videoPlayPause.setBackgroundResource(R.drawable.ic_pause_white);
resetNotification();
updateNotification(R.drawable.ic_play_arrow_white);
videoPlayPause.setBackgroundResource(R.drawable.ic_pause_white);
}
@Override
public void onCompleted() {
super.onCompleted();
updateWindowFlags(IDLE_WINDOW_FLAGS);
resetNotification();
updateNotification(R.drawable.ic_replay_white);
videoPlayPause.setBackgroundResource(R.drawable.ic_replay_white);
lockManager.releaseWifiAndCpu();
windowLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
windowManager.updateViewLayout(playerImpl.getRootView(), windowLayoutParams);
stopForeground(false);
}
@Override
@ -719,16 +771,15 @@ public final class PopupVideoPlayer extends Service {
super.hideControlsAndButton(duration, delay, videoPlayPause);
}
/*//////////////////////////////////////////////////////////////////////////
// Utils
//////////////////////////////////////////////////////////////////////////*/
/*package-private*/ void enableVideoRenderer(final boolean enable) {
final int videoRendererIndex = getRendererIndex(C.TRACK_TYPE_VIDEO);
if (trackSelector != null && videoRendererIndex != RENDERER_UNAVAILABLE) {
trackSelector.setRendererDisabled(videoRendererIndex, !enable);
if (videoRendererIndex != RENDERER_UNAVAILABLE) {
trackSelector.setParameters(trackSelector.buildUponParameters()
.setRendererDisabled(videoRendererIndex, !enable));
}
}

View File

@ -187,6 +187,7 @@ public abstract class ServicePlayerActivity extends AppCompatActivity
this.player.getRepeatMode(),
this.player.getPlaybackSpeed(),
this.player.getPlaybackPitch(),
this.player.getPlaybackSkipSilence(),
null
).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
@ -466,13 +467,16 @@ public abstract class ServicePlayerActivity extends AppCompatActivity
private void openPlaybackParameterDialog() {
if (player == null) return;
PlaybackParameterDialog.newInstance(player.getPlaybackSpeed(),
player.getPlaybackPitch()).show(getSupportFragmentManager(), getTag());
PlaybackParameterDialog.newInstance(player.getPlaybackSpeed(), player.getPlaybackPitch(),
player.getPlaybackSkipSilence()).show(getSupportFragmentManager(), getTag());
}
@Override
public void onPlaybackParameterChanged(float playbackTempo, float playbackPitch) {
if (player != null) player.setPlaybackParameters(playbackTempo, playbackPitch);
public void onPlaybackParameterChanged(float playbackTempo, float playbackPitch,
boolean playbackSkipSilence) {
if (player != null) {
player.setPlaybackParameters(playbackTempo, playbackPitch, playbackSkipSilence);
}
}
////////////////////////////////////////////////////////////////////////////

View File

@ -29,7 +29,6 @@ import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.net.Uri;
import android.os.Build;
import android.os.Handler;
import android.support.annotation.NonNull;
@ -47,11 +46,9 @@ import android.widget.SeekBar;
import android.widget.TextView;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.PlaybackParameters;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.source.MergingMediaSource;
import com.google.android.exoplayer2.source.TrackGroup;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.text.CaptionStyleCompat;
@ -62,21 +59,17 @@ import com.google.android.exoplayer2.video.VideoListener;
import org.schabi.newpipe.R;
import org.schabi.newpipe.extractor.MediaFormat;
import org.schabi.newpipe.extractor.Subtitles;
import org.schabi.newpipe.extractor.stream.AudioStream;
import org.schabi.newpipe.extractor.stream.StreamInfo;
import org.schabi.newpipe.extractor.stream.StreamType;
import org.schabi.newpipe.extractor.stream.VideoStream;
import org.schabi.newpipe.player.helper.PlayerHelper;
import org.schabi.newpipe.player.playqueue.PlayQueueItem;
import org.schabi.newpipe.player.resolver.MediaSourceTag;
import org.schabi.newpipe.player.resolver.VideoPlaybackResolver;
import org.schabi.newpipe.util.AnimationUtils;
import org.schabi.newpipe.util.ListHelper;
import java.util.ArrayList;
import java.util.List;
import static com.google.android.exoplayer2.C.SELECTION_FLAG_AUTOSELECT;
import static com.google.android.exoplayer2.C.TIME_UNSET;
import static org.schabi.newpipe.player.helper.PlayerHelper.formatSpeed;
import static org.schabi.newpipe.player.helper.PlayerHelper.getTimeString;
import static org.schabi.newpipe.util.AnimationUtils.animateView;
@ -105,13 +98,12 @@ public abstract class VideoPlayer extends BasePlayer
public static final int DEFAULT_CONTROLS_DURATION = 300; // 300 millis
public static final int DEFAULT_CONTROLS_HIDE_TIME = 2000; // 2 Seconds
private ArrayList<VideoStream> availableStreams;
private List<VideoStream> availableStreams;
private int selectedStreamIndex;
protected String playbackQuality;
protected boolean wasPlaying = false;
@NonNull final private VideoPlaybackResolver resolver;
/*//////////////////////////////////////////////////////////////////////////
// Views
//////////////////////////////////////////////////////////////////////////*/
@ -162,6 +154,7 @@ public abstract class VideoPlayer extends BasePlayer
public VideoPlayer(String debugTag, Context context) {
super(context);
this.TAG = debugTag;
this.resolver = new VideoPlaybackResolver(context, dataSource, getQualityResolver());
}
public void setup(View rootView) {
@ -241,7 +234,8 @@ public abstract class VideoPlayer extends BasePlayer
// Setup audio session with onboard equalizer
if (Build.VERSION.SDK_INT >= 21) {
trackSelector.setTunnelingAudioSessionId(C.generateAudioSessionIdV21(context));
trackSelector.setParameters(trackSelector.buildUponParameters()
.setTunnelingAudioSessionId(C.generateAudioSessionIdV21(context)));
}
}
@ -297,8 +291,9 @@ public abstract class VideoPlayer extends BasePlayer
0, Menu.NONE, R.string.caption_none);
captionOffItem.setOnMenuItemClickListener(menuItem -> {
final int textRendererIndex = getRendererIndex(C.TRACK_TYPE_TEXT);
if (trackSelector != null && textRendererIndex != RENDERER_UNAVAILABLE) {
trackSelector.setRendererDisabled(textRendererIndex, true);
if (textRendererIndex != RENDERER_UNAVAILABLE) {
trackSelector.setParameters(trackSelector.buildUponParameters()
.setRendererDisabled(textRendererIndex, true));
}
return true;
});
@ -310,68 +305,61 @@ public abstract class VideoPlayer extends BasePlayer
i + 1, Menu.NONE, captionLanguage);
captionItem.setOnMenuItemClickListener(menuItem -> {
final int textRendererIndex = getRendererIndex(C.TRACK_TYPE_TEXT);
if (trackSelector != null && textRendererIndex != RENDERER_UNAVAILABLE) {
if (textRendererIndex != RENDERER_UNAVAILABLE) {
trackSelector.setPreferredTextLanguage(captionLanguage);
trackSelector.setRendererDisabled(textRendererIndex, false);
trackSelector.setParameters(trackSelector.buildUponParameters()
.setRendererDisabled(textRendererIndex, false));
}
return true;
});
}
captionPopupMenu.setOnDismissListener(this);
}
/*//////////////////////////////////////////////////////////////////////////
// Playback Listener
//////////////////////////////////////////////////////////////////////////*/
protected abstract int getDefaultResolutionIndex(final List<VideoStream> sortedVideos);
protected abstract int getOverrideResolutionIndex(final List<VideoStream> sortedVideos, final String playbackQuality);
private void updateStreamRelatedViews() {
if (getCurrentMetadata() == null) return;
final MediaSourceTag tag = getCurrentMetadata();
final StreamInfo metadata = tag.getMetadata();
protected void onMetadataChanged(@NonNull final PlayQueueItem item,
@Nullable final StreamInfo info,
final int newPlayQueueIndex,
final boolean hasPlayQueueItemChanged) {
qualityTextView.setVisibility(View.GONE);
playbackSpeedTextView.setVisibility(View.GONE);
playbackEndTime.setVisibility(View.GONE);
playbackLiveSync.setVisibility(View.GONE);
final StreamType streamType = info == null ? StreamType.NONE : info.getStreamType();
switch (streamType) {
switch (metadata.getStreamType()) {
case AUDIO_STREAM:
surfaceView.setVisibility(View.GONE);
endScreen.setVisibility(View.VISIBLE);
playbackEndTime.setVisibility(View.VISIBLE);
break;
case AUDIO_LIVE_STREAM:
surfaceView.setVisibility(View.GONE);
endScreen.setVisibility(View.VISIBLE);
playbackLiveSync.setVisibility(View.VISIBLE);
break;
case LIVE_STREAM:
surfaceView.setVisibility(View.VISIBLE);
endScreen.setVisibility(View.GONE);
playbackLiveSync.setVisibility(View.VISIBLE);
break;
case VIDEO_STREAM:
if (info.getVideoStreams().size() + info.getVideoOnlyStreams().size() == 0) break;
final List<VideoStream> videos = ListHelper.getSortedStreamVideosList(context,
info.getVideoStreams(), info.getVideoOnlyStreams(), false);
availableStreams = new ArrayList<>(videos);
if (playbackQuality == null) {
selectedStreamIndex = getDefaultResolutionIndex(videos);
} else {
selectedStreamIndex = getOverrideResolutionIndex(videos, getPlaybackQuality());
}
if (metadata.getVideoStreams().size() + metadata.getVideoOnlyStreams().size() == 0)
break;
availableStreams = tag.getSortedAvailableVideoStreams();
selectedStreamIndex = tag.getSelectedVideoStreamIndex();
buildQualityMenu();
qualityTextView.setVisibility(View.VISIBLE);
qualityTextView.setVisibility(View.VISIBLE);
surfaceView.setVisibility(View.VISIBLE);
default:
endScreen.setVisibility(View.GONE);
playbackEndTime.setVisibility(View.VISIBLE);
break;
}
@ -379,69 +367,21 @@ public abstract class VideoPlayer extends BasePlayer
buildPlaybackSpeedMenu();
playbackSpeedTextView.setVisibility(View.VISIBLE);
}
/*//////////////////////////////////////////////////////////////////////////
// Playback Listener
//////////////////////////////////////////////////////////////////////////*/
protected abstract VideoPlaybackResolver.QualityResolver getQualityResolver();
protected void onMetadataChanged(@NonNull final MediaSourceTag tag) {
super.onMetadataChanged(tag);
updateStreamRelatedViews();
}
@Override
@Nullable
public MediaSource sourceOf(final PlayQueueItem item, final StreamInfo info) {
final MediaSource liveSource = super.sourceOf(item, info);
if (liveSource != null) return liveSource;
List<MediaSource> mediaSources = new ArrayList<>();
// Create video stream source
final List<VideoStream> videos = ListHelper.getSortedStreamVideosList(context,
info.getVideoStreams(), info.getVideoOnlyStreams(), false);
final int index;
if (videos.isEmpty()) {
index = -1;
} else if (playbackQuality == null) {
index = getDefaultResolutionIndex(videos);
} else {
index = getOverrideResolutionIndex(videos, getPlaybackQuality());
}
final VideoStream video = index >= 0 && index < videos.size() ? videos.get(index) : null;
if (video != null) {
final MediaSource streamSource = buildMediaSource(video.getUrl(),
PlayerHelper.cacheKeyOf(info, video),
MediaFormat.getSuffixById(video.getFormatId()));
mediaSources.add(streamSource);
}
// Create optional audio stream source
final List<AudioStream> audioStreams = info.getAudioStreams();
final AudioStream audio = audioStreams.isEmpty() ? null : audioStreams.get(
ListHelper.getDefaultAudioFormat(context, audioStreams));
// Use the audio stream if there is no video stream, or
// Merge with audio stream in case if video does not contain audio
if (audio != null && ((video != null && video.isVideoOnly) || video == null)) {
final MediaSource audioSource = buildMediaSource(audio.getUrl(),
PlayerHelper.cacheKeyOf(info, audio),
MediaFormat.getSuffixById(audio.getFormatId()));
mediaSources.add(audioSource);
}
// If there is no audio or video sources, then this media source cannot be played back
if (mediaSources.isEmpty()) return null;
// Below are auxiliary media sources
// Create subtitle sources
for (final Subtitles subtitle : info.getSubtitles()) {
final String mimeType = PlayerHelper.mimeTypesOf(subtitle.getFileType());
if (mimeType == null) continue;
final Format textFormat = Format.createTextSampleFormat(null, mimeType,
SELECTION_FLAG_AUTOSELECT, PlayerHelper.captionLanguageOf(context, subtitle));
final MediaSource textSource = dataSource.getSampleMediaSourceFactory()
.createMediaSource(Uri.parse(subtitle.getURL()), textFormat, TIME_UNSET);
mediaSources.add(textSource);
}
if (mediaSources.size() == 1) {
return mediaSources.get(0);
} else {
return new MergingMediaSource(mediaSources.toArray(
new MediaSource[mediaSources.size()]));
}
return resolver.resolve(info);
}
/*//////////////////////////////////////////////////////////////////////////
@ -460,7 +400,6 @@ public abstract class VideoPlayer extends BasePlayer
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
playbackSeekBar.getThumb().setColorFilter(Color.RED, PorterDuff.Mode.SRC_IN);
animateView(endScreen, false, 0);
loadingPanel.setBackgroundColor(Color.BLACK);
animateView(loadingPanel, true, 0);
animateView(surfaceForeground, true, 100);
@ -470,6 +409,8 @@ public abstract class VideoPlayer extends BasePlayer
public void onPlaying() {
super.onPlaying();
updateStreamRelatedViews();
showAndAnimateControl(-1, true);
playbackSeekBar.setEnabled(true);
@ -480,14 +421,12 @@ public abstract class VideoPlayer extends BasePlayer
loadingPanel.setVisibility(View.GONE);
animateView(currentDisplaySeek, AnimationUtils.Type.SCALE_AND_ALPHA, false, 200);
animateView(endScreen, false, 0);
}
@Override
public void onBuffering() {
if (DEBUG) Log.d(TAG, "onBuffering() called");
loadingPanel.setBackgroundColor(Color.TRANSPARENT);
animateView(loadingPanel, true, 500);
}
@Override
@ -552,8 +491,7 @@ public abstract class VideoPlayer extends BasePlayer
final int textRenderer = getRendererIndex(C.TRACK_TYPE_TEXT);
if (captionTextView == null) return;
if (trackSelector == null || trackSelector.getCurrentMappedTrackInfo() == null ||
textRenderer == RENDERER_UNAVAILABLE) {
if (trackSelector.getCurrentMappedTrackInfo() == null || textRenderer == RENDERER_UNAVAILABLE) {
captionTextView.setVisibility(View.GONE);
return;
}
@ -575,8 +513,8 @@ public abstract class VideoPlayer extends BasePlayer
// Build UI
buildCaptionMenu(availableLanguages);
if (trackSelector.getRendererDisabled(textRenderer) || preferredLanguage == null ||
!availableLanguages.contains(preferredLanguage)) {
if (trackSelector.getParameters().getRendererDisabled(textRenderer) ||
preferredLanguage == null || !availableLanguages.contains(preferredLanguage)) {
captionTextView.setText(R.string.caption_none);
} else {
captionTextView.setText(preferredLanguage);
@ -905,11 +843,12 @@ public abstract class VideoPlayer extends BasePlayer
//////////////////////////////////////////////////////////////////////////*/
public void setPlaybackQuality(final String quality) {
this.playbackQuality = quality;
this.resolver.setPlaybackQuality(quality);
}
@Nullable
public String getPlaybackQuality() {
return playbackQuality;
return resolver.getPlaybackQuality();
}
public AspectRatioFrameLayout getAspectRatioFrameLayout() {

View File

@ -39,10 +39,13 @@ public class MediaSessionManager {
return MediaButtonReceiver.handleIntent(mediaSession, intent);
}
/**
* Should be called on player destruction to prevent leakage.
* */
public void dispose() {
this.sessionConnector.setPlayer(null, null);
this.sessionConnector.setQueueNavigator(null);
this.mediaSession.setActive(false);
this.mediaSession.release();
}
}
}

View File

@ -21,25 +21,34 @@ import static org.schabi.newpipe.player.BasePlayer.DEBUG;
public class PlaybackParameterDialog extends DialogFragment {
@NonNull private static final String TAG = "PlaybackParameterDialog";
public static final double MINIMUM_PLAYBACK_VALUE = 0.25f;
// Minimum allowable range in ExoPlayer
public static final double MINIMUM_PLAYBACK_VALUE = 0.10f;
public static final double MAXIMUM_PLAYBACK_VALUE = 3.00f;
public static final char STEP_UP_SIGN = '+';
public static final char STEP_DOWN_SIGN = '-';
public static final double PLAYBACK_STEP_VALUE = 0.05f;
public static final double NIGHTCORE_TEMPO = 1.20f;
public static final double NIGHTCORE_PITCH_LOWER = 1.15f;
public static final double NIGHTCORE_PITCH_UPPER = 1.25f;
public static final double STEP_ONE_PERCENT_VALUE = 0.01f;
public static final double STEP_FIVE_PERCENT_VALUE = 0.05f;
public static final double STEP_TEN_PERCENT_VALUE = 0.10f;
public static final double STEP_TWENTY_FIVE_PERCENT_VALUE = 0.25f;
public static final double STEP_ONE_HUNDRED_PERCENT_VALUE = 1.00f;
public static final double DEFAULT_TEMPO = 1.00f;
public static final double DEFAULT_PITCH = 1.00f;
public static final double DEFAULT_STEP = STEP_TWENTY_FIVE_PERCENT_VALUE;
public static final boolean DEFAULT_SKIP_SILENCE = false;
@NonNull private static final String INITIAL_TEMPO_KEY = "initial_tempo_key";
@NonNull private static final String INITIAL_PITCH_KEY = "initial_pitch_key";
@NonNull private static final String TEMPO_KEY = "tempo_key";
@NonNull private static final String PITCH_KEY = "pitch_key";
@NonNull private static final String STEP_SIZE_KEY = "step_size_key";
public interface Callback {
void onPlaybackParameterChanged(final float playbackTempo, final float playbackPitch);
void onPlaybackParameterChanged(final float playbackTempo, final float playbackPitch,
final boolean playbackSkipSilence);
}
@Nullable private Callback callback;
@ -50,6 +59,11 @@ public class PlaybackParameterDialog extends DialogFragment {
private double initialTempo = DEFAULT_TEMPO;
private double initialPitch = DEFAULT_PITCH;
private boolean initialSkipSilence = DEFAULT_SKIP_SILENCE;
private double tempo = DEFAULT_TEMPO;
private double pitch = DEFAULT_PITCH;
private double stepSize = DEFAULT_STEP;
@Nullable private SeekBar tempoSlider;
@Nullable private TextView tempoMinimumText;
@ -65,16 +79,26 @@ public class PlaybackParameterDialog extends DialogFragment {
@Nullable private TextView pitchStepDownText;
@Nullable private TextView pitchStepUpText;
@Nullable private CheckBox unhookingCheckbox;
@Nullable private TextView stepSizeOnePercentText;
@Nullable private TextView stepSizeFivePercentText;
@Nullable private TextView stepSizeTenPercentText;
@Nullable private TextView stepSizeTwentyFivePercentText;
@Nullable private TextView stepSizeOneHundredPercentText;
@Nullable private TextView nightCorePresetText;
@Nullable private TextView resetPresetText;
@Nullable private CheckBox unhookingCheckbox;
@Nullable private CheckBox skipSilenceCheckbox;
public static PlaybackParameterDialog newInstance(final double playbackTempo,
final double playbackPitch) {
final double playbackPitch,
final boolean playbackSkipSilence) {
PlaybackParameterDialog dialog = new PlaybackParameterDialog();
dialog.initialTempo = playbackTempo;
dialog.initialPitch = playbackPitch;
dialog.tempo = playbackTempo;
dialog.pitch = playbackPitch;
dialog.initialSkipSilence = playbackSkipSilence;
return dialog;
}
@ -98,6 +122,10 @@ public class PlaybackParameterDialog extends DialogFragment {
if (savedInstanceState != null) {
initialTempo = savedInstanceState.getDouble(INITIAL_TEMPO_KEY, DEFAULT_TEMPO);
initialPitch = savedInstanceState.getDouble(INITIAL_PITCH_KEY, DEFAULT_PITCH);
tempo = savedInstanceState.getDouble(TEMPO_KEY, DEFAULT_TEMPO);
pitch = savedInstanceState.getDouble(PITCH_KEY, DEFAULT_PITCH);
stepSize = savedInstanceState.getDouble(STEP_SIZE_KEY, DEFAULT_STEP);
}
}
@ -106,6 +134,10 @@ public class PlaybackParameterDialog extends DialogFragment {
super.onSaveInstanceState(outState);
outState.putDouble(INITIAL_TEMPO_KEY, initialTempo);
outState.putDouble(INITIAL_PITCH_KEY, initialPitch);
outState.putDouble(TEMPO_KEY, getCurrentTempo());
outState.putDouble(PITCH_KEY, getCurrentPitch());
outState.putDouble(STEP_SIZE_KEY, getCurrentStepSize());
}
/*//////////////////////////////////////////////////////////////////////////
@ -123,7 +155,9 @@ public class PlaybackParameterDialog extends DialogFragment {
.setView(view)
.setCancelable(true)
.setNegativeButton(R.string.cancel, (dialogInterface, i) ->
setPlaybackParameters(initialTempo, initialPitch))
setPlaybackParameters(initialTempo, initialPitch, initialSkipSilence))
.setNeutralButton(R.string.playback_reset, (dialogInterface, i) ->
setPlaybackParameters(DEFAULT_TEMPO, DEFAULT_PITCH, DEFAULT_SKIP_SILENCE))
.setPositiveButton(R.string.finish, (dialogInterface, i) ->
setCurrentPlaybackParameters());
@ -136,9 +170,13 @@ public class PlaybackParameterDialog extends DialogFragment {
private void setupControlViews(@NonNull View rootView) {
setupHookingControl(rootView);
setupSkipSilenceControl(rootView);
setupTempoControl(rootView);
setupPitchControl(rootView);
setupPresetControl(rootView);
changeStepSize(stepSize);
setupStepSizeSelector(rootView);
}
private void setupTempoControl(@NonNull View rootView) {
@ -150,31 +188,15 @@ public class PlaybackParameterDialog extends DialogFragment {
tempoStepDownText = rootView.findViewById(R.id.tempoStepDown);
if (tempoCurrentText != null)
tempoCurrentText.setText(PlayerHelper.formatSpeed(initialTempo));
tempoCurrentText.setText(PlayerHelper.formatSpeed(tempo));
if (tempoMaximumText != null)
tempoMaximumText.setText(PlayerHelper.formatSpeed(MAXIMUM_PLAYBACK_VALUE));
if (tempoMinimumText != null)
tempoMinimumText.setText(PlayerHelper.formatSpeed(MINIMUM_PLAYBACK_VALUE));
if (tempoStepUpText != null) {
tempoStepUpText.setText(getStepUpPercentString(PLAYBACK_STEP_VALUE));
tempoStepUpText.setOnClickListener(view -> {
onTempoSliderUpdated(getCurrentTempo() + PLAYBACK_STEP_VALUE);
setCurrentPlaybackParameters();
});
}
if (tempoStepDownText != null) {
tempoStepDownText.setText(getStepDownPercentString(PLAYBACK_STEP_VALUE));
tempoStepDownText.setOnClickListener(view -> {
onTempoSliderUpdated(getCurrentTempo() - PLAYBACK_STEP_VALUE);
setCurrentPlaybackParameters();
});
}
if (tempoSlider != null) {
tempoSlider.setMax(strategy.progressOf(MAXIMUM_PLAYBACK_VALUE));
tempoSlider.setProgress(strategy.progressOf(initialTempo));
tempoSlider.setProgress(strategy.progressOf(tempo));
tempoSlider.setOnSeekBarChangeListener(getOnTempoChangedListener());
}
}
@ -188,31 +210,15 @@ public class PlaybackParameterDialog extends DialogFragment {
pitchStepUpText = rootView.findViewById(R.id.pitchStepUp);
if (pitchCurrentText != null)
pitchCurrentText.setText(PlayerHelper.formatPitch(initialPitch));
pitchCurrentText.setText(PlayerHelper.formatPitch(pitch));
if (pitchMaximumText != null)
pitchMaximumText.setText(PlayerHelper.formatPitch(MAXIMUM_PLAYBACK_VALUE));
if (pitchMinimumText != null)
pitchMinimumText.setText(PlayerHelper.formatPitch(MINIMUM_PLAYBACK_VALUE));
if (pitchStepUpText != null) {
pitchStepUpText.setText(getStepUpPercentString(PLAYBACK_STEP_VALUE));
pitchStepUpText.setOnClickListener(view -> {
onPitchSliderUpdated(getCurrentPitch() + PLAYBACK_STEP_VALUE);
setCurrentPlaybackParameters();
});
}
if (pitchStepDownText != null) {
pitchStepDownText.setText(getStepDownPercentString(PLAYBACK_STEP_VALUE));
pitchStepDownText.setOnClickListener(view -> {
onPitchSliderUpdated(getCurrentPitch() - PLAYBACK_STEP_VALUE);
setCurrentPlaybackParameters();
});
}
if (pitchSlider != null) {
pitchSlider.setMax(strategy.progressOf(MAXIMUM_PLAYBACK_VALUE));
pitchSlider.setProgress(strategy.progressOf(initialPitch));
pitchSlider.setProgress(strategy.progressOf(pitch));
pitchSlider.setOnSeekBarChangeListener(getOnPitchChangedListener());
}
}
@ -220,7 +226,7 @@ public class PlaybackParameterDialog extends DialogFragment {
private void setupHookingControl(@NonNull View rootView) {
unhookingCheckbox = rootView.findViewById(R.id.unhookCheckbox);
if (unhookingCheckbox != null) {
unhookingCheckbox.setChecked(initialPitch != initialTempo);
unhookingCheckbox.setChecked(pitch != tempo);
unhookingCheckbox.setOnCheckedChangeListener((compoundButton, isChecked) -> {
if (isChecked) return;
// When unchecked, slide back to the minimum of current tempo or pitch
@ -231,24 +237,84 @@ public class PlaybackParameterDialog extends DialogFragment {
}
}
private void setupPresetControl(@NonNull View rootView) {
nightCorePresetText = rootView.findViewById(R.id.presetNightcore);
if (nightCorePresetText != null) {
nightCorePresetText.setOnClickListener(view -> {
final double randomPitch = NIGHTCORE_PITCH_LOWER +
Math.random() * (NIGHTCORE_PITCH_UPPER - NIGHTCORE_PITCH_LOWER);
private void setupSkipSilenceControl(@NonNull View rootView) {
skipSilenceCheckbox = rootView.findViewById(R.id.skipSilenceCheckbox);
if (skipSilenceCheckbox != null) {
skipSilenceCheckbox.setChecked(initialSkipSilence);
skipSilenceCheckbox.setOnCheckedChangeListener((compoundButton, isChecked) ->
setCurrentPlaybackParameters());
}
}
setTempoSlider(NIGHTCORE_TEMPO);
setPitchSlider(randomPitch);
private void setupStepSizeSelector(@NonNull final View rootView) {
stepSizeOnePercentText = rootView.findViewById(R.id.stepSizeOnePercent);
stepSizeFivePercentText = rootView.findViewById(R.id.stepSizeFivePercent);
stepSizeTenPercentText = rootView.findViewById(R.id.stepSizeTenPercent);
stepSizeTwentyFivePercentText = rootView.findViewById(R.id.stepSizeTwentyFivePercent);
stepSizeOneHundredPercentText = rootView.findViewById(R.id.stepSizeOneHundredPercent);
if (stepSizeOnePercentText != null) {
stepSizeOnePercentText.setText(getPercentString(STEP_ONE_PERCENT_VALUE));
stepSizeOnePercentText.setOnClickListener(view ->
changeStepSize(STEP_ONE_PERCENT_VALUE));
}
if (stepSizeFivePercentText != null) {
stepSizeFivePercentText.setText(getPercentString(STEP_FIVE_PERCENT_VALUE));
stepSizeFivePercentText.setOnClickListener(view ->
changeStepSize(STEP_FIVE_PERCENT_VALUE));
}
if (stepSizeTenPercentText != null) {
stepSizeTenPercentText.setText(getPercentString(STEP_TEN_PERCENT_VALUE));
stepSizeTenPercentText.setOnClickListener(view ->
changeStepSize(STEP_TEN_PERCENT_VALUE));
}
if (stepSizeTwentyFivePercentText != null) {
stepSizeTwentyFivePercentText.setText(getPercentString(STEP_TWENTY_FIVE_PERCENT_VALUE));
stepSizeTwentyFivePercentText.setOnClickListener(view ->
changeStepSize(STEP_TWENTY_FIVE_PERCENT_VALUE));
}
if (stepSizeOneHundredPercentText != null) {
stepSizeOneHundredPercentText.setText(getPercentString(STEP_ONE_HUNDRED_PERCENT_VALUE));
stepSizeOneHundredPercentText.setOnClickListener(view ->
changeStepSize(STEP_ONE_HUNDRED_PERCENT_VALUE));
}
}
private void changeStepSize(final double stepSize) {
this.stepSize = stepSize;
if (tempoStepUpText != null) {
tempoStepUpText.setText(getStepUpPercentString(stepSize));
tempoStepUpText.setOnClickListener(view -> {
onTempoSliderUpdated(getCurrentTempo() + stepSize);
setCurrentPlaybackParameters();
});
}
resetPresetText = rootView.findViewById(R.id.presetReset);
if (resetPresetText != null) {
resetPresetText.setOnClickListener(view -> {
setTempoSlider(DEFAULT_TEMPO);
setPitchSlider(DEFAULT_PITCH);
if (tempoStepDownText != null) {
tempoStepDownText.setText(getStepDownPercentString(stepSize));
tempoStepDownText.setOnClickListener(view -> {
onTempoSliderUpdated(getCurrentTempo() - stepSize);
setCurrentPlaybackParameters();
});
}
if (pitchStepUpText != null) {
pitchStepUpText.setText(getStepUpPercentString(stepSize));
pitchStepUpText.setOnClickListener(view -> {
onPitchSliderUpdated(getCurrentPitch() + stepSize);
setCurrentPlaybackParameters();
});
}
if (pitchStepDownText != null) {
pitchStepDownText.setText(getStepDownPercentString(stepSize));
pitchStepDownText.setOnClickListener(view -> {
onPitchSliderUpdated(getCurrentPitch() - stepSize);
setCurrentPlaybackParameters();
});
}
@ -342,10 +408,11 @@ public class PlaybackParameterDialog extends DialogFragment {
//////////////////////////////////////////////////////////////////////////*/
private void setCurrentPlaybackParameters() {
setPlaybackParameters(getCurrentTempo(), getCurrentPitch());
setPlaybackParameters(getCurrentTempo(), getCurrentPitch(), getCurrentSkipSilence());
}
private void setPlaybackParameters(final double tempo, final double pitch) {
private void setPlaybackParameters(final double tempo, final double pitch,
final boolean skipSilence) {
if (callback != null && tempoCurrentText != null && pitchCurrentText != null) {
if (DEBUG) Log.d(TAG, "Setting playback parameters to " +
"tempo=[" + tempo + "], " +
@ -353,27 +420,40 @@ public class PlaybackParameterDialog extends DialogFragment {
tempoCurrentText.setText(PlayerHelper.formatSpeed(tempo));
pitchCurrentText.setText(PlayerHelper.formatPitch(pitch));
callback.onPlaybackParameterChanged((float) tempo, (float) pitch);
callback.onPlaybackParameterChanged((float) tempo, (float) pitch, skipSilence);
}
}
private double getCurrentTempo() {
return tempoSlider == null ? initialTempo : strategy.valueOf(
return tempoSlider == null ? tempo : strategy.valueOf(
tempoSlider.getProgress());
}
private double getCurrentPitch() {
return pitchSlider == null ? initialPitch : strategy.valueOf(
return pitchSlider == null ? pitch : strategy.valueOf(
pitchSlider.getProgress());
}
private double getCurrentStepSize() {
return stepSize;
}
private boolean getCurrentSkipSilence() {
return skipSilenceCheckbox != null && skipSilenceCheckbox.isChecked();
}
@NonNull
private static String getStepUpPercentString(final double percent) {
return STEP_UP_SIGN + PlayerHelper.formatPitch(percent);
return STEP_UP_SIGN + getPercentString(percent);
}
@NonNull
private static String getStepDownPercentString(final double percent) {
return STEP_DOWN_SIGN + PlayerHelper.formatPitch(percent);
return STEP_DOWN_SIGN + getPercentString(percent);
}
@NonNull
private static String getPercentString(final double percent) {
return PlayerHelper.formatPitch(percent);
}
}

View File

@ -241,7 +241,6 @@ public class PlayerHelper {
public static TrackSelection.Factory getQualitySelector(@NonNull final Context context,
@NonNull final BandwidthMeter meter) {
return new AdaptiveTrackSelection.Factory(meter,
AdaptiveTrackSelection.DEFAULT_MAX_INITIAL_BITRATE,
/*bufferDurationRequiredForQualityIncrease=*/1000,
AdaptiveTrackSelection.DEFAULT_MAX_DURATION_FOR_QUALITY_DECREASE_MS,
AdaptiveTrackSelection.DEFAULT_MIN_DURATION_TO_RETAIN_AFTER_DISCARD_MS,
@ -253,7 +252,7 @@ public class PlayerHelper {
}
public static int getShutdownFlingVelocity(@NonNull final Context context) {
return 10000;
return 6000;
}
public static int getTossFlingVelocity(@NonNull final Context context) {

View File

@ -4,6 +4,7 @@ import android.support.annotation.NonNull;
import android.util.Log;
import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.source.BaseMediaSource;
import com.google.android.exoplayer2.source.MediaPeriod;
import com.google.android.exoplayer2.upstream.Allocator;
@ -11,7 +12,7 @@ import org.schabi.newpipe.player.playqueue.PlayQueueItem;
import java.io.IOException;
public class FailedMediaSource implements ManagedMediaSource {
public class FailedMediaSource extends BaseMediaSource implements ManagedMediaSource {
private final String TAG = "FailedMediaSource@" + Integer.toHexString(hashCode());
public static class FailedMediaSourceException extends Exception {
@ -72,11 +73,6 @@ public class FailedMediaSource implements ManagedMediaSource {
return System.currentTimeMillis() >= retryTimestamp;
}
@Override
public void prepareSource(ExoPlayer player, boolean isTopLevelSource, Listener listener) {
Log.e(TAG, "Loading failed source: ", error);
}
@Override
public void maybeThrowSourceInfoRefreshError() throws IOException {
throw new IOException(error);
@ -90,8 +86,14 @@ public class FailedMediaSource implements ManagedMediaSource {
@Override
public void releasePeriod(MediaPeriod mediaPeriod) {}
@Override
public void releaseSource() {}
protected void prepareSourceInternal(ExoPlayer player, boolean isTopLevelSource) {
Log.e(TAG, "Loading failed source: ", error);
}
@Override
protected void releaseSourceInternal() {}
@Override
public boolean shouldBeReplacedWith(@NonNull final PlayQueueItem newIdentity,

View File

@ -1,10 +1,12 @@
package org.schabi.newpipe.player.mediasource;
import android.os.Handler;
import android.support.annotation.NonNull;
import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.source.MediaPeriod;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.source.MediaSourceEventListener;
import com.google.android.exoplayer2.upstream.Allocator;
import org.schabi.newpipe.player.playqueue.PlayQueueItem;
@ -34,7 +36,8 @@ public class LoadedMediaSource implements ManagedMediaSource {
}
@Override
public void prepareSource(ExoPlayer player, boolean isTopLevelSource, Listener listener) {
public void prepareSource(ExoPlayer player, boolean isTopLevelSource,
SourceInfoRefreshListener listener) {
source.prepareSource(player, isTopLevelSource, listener);
}
@ -54,8 +57,18 @@ public class LoadedMediaSource implements ManagedMediaSource {
}
@Override
public void releaseSource() {
source.releaseSource();
public void releaseSource(SourceInfoRefreshListener listener) {
source.releaseSource(listener);
}
@Override
public void addEventListener(Handler handler, MediaSourceEventListener eventListener) {
source.addEventListener(handler, eventListener);
}
@Override
public void removeEventListener(MediaSourceEventListener eventListener) {
source.removeEventListener(eventListener);
}
@Override

View File

@ -3,14 +3,14 @@ package org.schabi.newpipe.player.mediasource;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import com.google.android.exoplayer2.source.DynamicConcatenatingMediaSource;
import com.google.android.exoplayer2.source.ConcatenatingMediaSource;
import com.google.android.exoplayer2.source.ShuffleOrder;
public class ManagedMediaSourcePlaylist {
@NonNull private final DynamicConcatenatingMediaSource internalSource;
@NonNull private final ConcatenatingMediaSource internalSource;
public ManagedMediaSourcePlaylist() {
internalSource = new DynamicConcatenatingMediaSource(/*isPlaylistAtomic=*/false,
internalSource = new ConcatenatingMediaSource(/*isPlaylistAtomic=*/false,
new ShuffleOrder.UnshuffledShuffleOrder(0));
}
@ -32,12 +32,8 @@ public class ManagedMediaSourcePlaylist {
null : (ManagedMediaSource) internalSource.getMediaSource(index);
}
public void dispose() {
internalSource.releaseSource();
}
@NonNull
public DynamicConcatenatingMediaSource getParentMediaSource() {
public ConcatenatingMediaSource getParentMediaSource() {
return internalSource;
}
@ -46,7 +42,7 @@ public class ManagedMediaSourcePlaylist {
//////////////////////////////////////////////////////////////////////////*/
/**
* Expands the {@link DynamicConcatenatingMediaSource} by appending it with a
* Expands the {@link ConcatenatingMediaSource} by appending it with a
* {@link PlaceholderMediaSource}.
*
* @see #append(ManagedMediaSource)
@ -56,17 +52,17 @@ public class ManagedMediaSourcePlaylist {
}
/**
* Appends a {@link ManagedMediaSource} to the end of {@link DynamicConcatenatingMediaSource}.
* @see DynamicConcatenatingMediaSource#addMediaSource
* Appends a {@link ManagedMediaSource} to the end of {@link ConcatenatingMediaSource}.
* @see ConcatenatingMediaSource#addMediaSource
* */
public synchronized void append(@NonNull final ManagedMediaSource source) {
internalSource.addMediaSource(source);
}
/**
* Removes a {@link ManagedMediaSource} from {@link DynamicConcatenatingMediaSource}
* Removes a {@link ManagedMediaSource} from {@link ConcatenatingMediaSource}
* at the given index. If this index is out of bound, then the removal is ignored.
* @see DynamicConcatenatingMediaSource#removeMediaSource(int)
* @see ConcatenatingMediaSource#removeMediaSource(int)
* */
public synchronized void remove(final int index) {
if (index < 0 || index > internalSource.getSize()) return;
@ -75,10 +71,10 @@ public class ManagedMediaSourcePlaylist {
}
/**
* Moves a {@link ManagedMediaSource} in {@link DynamicConcatenatingMediaSource}
* Moves a {@link ManagedMediaSource} in {@link ConcatenatingMediaSource}
* from the given source index to the target index. If either index is out of bound,
* then the call is ignored.
* @see DynamicConcatenatingMediaSource#moveMediaSource(int, int)
* @see ConcatenatingMediaSource#moveMediaSource(int, int)
* */
public synchronized void move(final int source, final int target) {
if (source < 0 || target < 0) return;
@ -99,7 +95,7 @@ public class ManagedMediaSourcePlaylist {
}
/**
* Updates the {@link ManagedMediaSource} in {@link DynamicConcatenatingMediaSource}
* Updates the {@link ManagedMediaSource} in {@link ConcatenatingMediaSource}
* at the given index with a given {@link ManagedMediaSource}.
* @see #update(int, ManagedMediaSource, Runnable)
* */
@ -108,11 +104,11 @@ public class ManagedMediaSourcePlaylist {
}
/**
* Updates the {@link ManagedMediaSource} in {@link DynamicConcatenatingMediaSource}
* Updates the {@link ManagedMediaSource} in {@link ConcatenatingMediaSource}
* at the given index with a given {@link ManagedMediaSource}. If the index is out of bound,
* then the replacement is ignored.
* @see DynamicConcatenatingMediaSource#addMediaSource
* @see DynamicConcatenatingMediaSource#removeMediaSource(int, Runnable)
* @see ConcatenatingMediaSource#addMediaSource
* @see ConcatenatingMediaSource#removeMediaSource(int, Runnable)
* */
public synchronized void update(final int index, @NonNull final ManagedMediaSource source,
@Nullable final Runnable finalizingAction) {

View File

@ -3,20 +3,19 @@ package org.schabi.newpipe.player.mediasource;
import android.support.annotation.NonNull;
import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.source.BaseMediaSource;
import com.google.android.exoplayer2.source.MediaPeriod;
import com.google.android.exoplayer2.upstream.Allocator;
import org.schabi.newpipe.player.playqueue.PlayQueueItem;
import java.io.IOException;
public class PlaceholderMediaSource implements ManagedMediaSource {
public class PlaceholderMediaSource extends BaseMediaSource implements ManagedMediaSource {
// Do nothing, so this will stall the playback
@Override public void prepareSource(ExoPlayer player, boolean isTopLevelSource, Listener listener) {}
@Override public void maybeThrowSourceInfoRefreshError() throws IOException {}
@Override public void maybeThrowSourceInfoRefreshError() {}
@Override public MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator) { return null; }
@Override public void releasePeriod(MediaPeriod mediaPeriod) {}
@Override public void releaseSource() {}
@Override protected void prepareSourceInternal(ExoPlayer player, boolean isTopLevelSource) {}
@Override protected void releaseSourceInternal() {}
@Override
public boolean shouldBeReplacedWith(@NonNull PlayQueueItem newIdentity,

View File

@ -5,12 +5,10 @@ import android.support.annotation.Nullable;
import android.support.v4.util.ArraySet;
import android.util.Log;
import com.google.android.exoplayer2.source.DynamicConcatenatingMediaSource;
import com.google.android.exoplayer2.source.MediaSource;
import org.reactivestreams.Subscriber;
import org.reactivestreams.Subscription;
import org.schabi.newpipe.extractor.stream.StreamInfo;
import org.schabi.newpipe.player.mediasource.FailedMediaSource;
import org.schabi.newpipe.player.mediasource.LoadedMediaSource;
import org.schabi.newpipe.player.mediasource.ManagedMediaSource;
@ -24,10 +22,8 @@ import org.schabi.newpipe.player.playqueue.events.RemoveEvent;
import org.schabi.newpipe.player.playqueue.events.ReorderEvent;
import org.schabi.newpipe.util.ServiceHelper;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
@ -37,8 +33,6 @@ import io.reactivex.Single;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.disposables.Disposable;
import io.reactivex.disposables.SerialDisposable;
import io.reactivex.functions.Consumer;
import io.reactivex.internal.subscriptions.EmptySubscription;
import io.reactivex.schedulers.Schedulers;
import io.reactivex.subjects.PublishSubject;
@ -104,7 +98,6 @@ public class MediaSourceManager {
private final static int MAXIMUM_LOADER_SIZE = WINDOW_SIZE * 2 + 1;
@NonNull private final CompositeDisposable loaderReactor;
@NonNull private final Set<PlayQueueItem> loadingItems;
@NonNull private final SerialDisposable syncReactor;
@NonNull private final AtomicBoolean isBlocked;
@ -144,7 +137,6 @@ public class MediaSourceManager {
this.playQueueReactor = EmptySubscription.INSTANCE;
this.loaderReactor = new CompositeDisposable();
this.syncReactor = new SerialDisposable();
this.isBlocked = new AtomicBoolean(false);
@ -171,8 +163,6 @@ public class MediaSourceManager {
playQueueReactor.cancel();
loaderReactor.dispose();
syncReactor.dispose();
playlist.dispose();
}
/*//////////////////////////////////////////////////////////////////////////
@ -311,21 +301,7 @@ public class MediaSourceManager {
final PlayQueueItem currentItem = playQueue.getItem();
if (isBlocked.get() || currentItem == null) return;
final Consumer<StreamInfo> onSuccess = info -> syncInternal(currentItem, info);
final Consumer<Throwable> onError = throwable -> syncInternal(currentItem, null);
final Disposable sync = currentItem.getStream()
.observeOn(AndroidSchedulers.mainThread())
.subscribe(onSuccess, onError);
syncReactor.set(sync);
}
private void syncInternal(@NonNull final PlayQueueItem item,
@Nullable final StreamInfo info) {
// Ensure the current item is up to date with the play queue
if (playQueue.getItem() == item) {
playbackListener.onPlaybackSynchronize(item, info);
}
playbackListener.onPlaybackSynchronize(currentItem);
}
private synchronized void maybeSynchronizePlayer() {
@ -424,7 +400,8 @@ public class MediaSourceManager {
}
/**
* Checks if the corresponding MediaSource in {@link DynamicConcatenatingMediaSource}
* Checks if the corresponding MediaSource in
* {@link com.google.android.exoplayer2.source.ConcatenatingMediaSource}
* for a given {@link PlayQueueItem} needs replacement, either due to gapless playback
* readiness or playlist desynchronization.
* <br><br>
@ -481,8 +458,6 @@ public class MediaSourceManager {
private void resetSources() {
if (DEBUG) Log.d(TAG, "resetSources() called.");
playlist.dispose();
playlist = new ManagedMediaSourcePlaylist();
}

View File

@ -45,7 +45,7 @@ public interface PlaybackListener {
*
* May be called anytime at any amount once unblock is called.
* */
void onPlaybackSynchronize(@NonNull final PlayQueueItem item, @Nullable final StreamInfo info);
void onPlaybackSynchronize(@NonNull final PlayQueueItem item);
/**
* Requests the listener to resolve a stream info into a media source

View File

@ -0,0 +1,41 @@
package org.schabi.newpipe.player.resolver;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import com.google.android.exoplayer2.source.MediaSource;
import org.schabi.newpipe.extractor.MediaFormat;
import org.schabi.newpipe.extractor.stream.AudioStream;
import org.schabi.newpipe.extractor.stream.StreamInfo;
import org.schabi.newpipe.player.helper.PlayerDataSource;
import org.schabi.newpipe.player.helper.PlayerHelper;
import org.schabi.newpipe.util.ListHelper;
public class AudioPlaybackResolver implements PlaybackResolver {
@NonNull private final Context context;
@NonNull private final PlayerDataSource dataSource;
public AudioPlaybackResolver(@NonNull final Context context,
@NonNull final PlayerDataSource dataSource) {
this.context = context;
this.dataSource = dataSource;
}
@Override
@Nullable
public MediaSource resolve(@NonNull StreamInfo info) {
final MediaSource liveSource = maybeBuildLiveMediaSource(dataSource, info);
if (liveSource != null) return liveSource;
final int index = ListHelper.getDefaultAudioFormat(context, info.getAudioStreams());
if (index < 0 || index >= info.getAudioStreams().size()) return null;
final AudioStream audio = info.getAudioStreams().get(index);
final MediaSourceTag tag = new MediaSourceTag(info);
return buildMediaSource(dataSource, audio.getUrl(), PlayerHelper.cacheKeyOf(info, audio),
MediaFormat.getSuffixById(audio.getFormatId()), tag);
}
}

View File

@ -0,0 +1,51 @@
package org.schabi.newpipe.player.resolver;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import org.schabi.newpipe.extractor.stream.StreamInfo;
import org.schabi.newpipe.extractor.stream.VideoStream;
import java.io.Serializable;
import java.util.Collections;
import java.util.List;
public class MediaSourceTag implements Serializable {
@NonNull private final StreamInfo metadata;
@NonNull private final List<VideoStream> sortedAvailableVideoStreams;
private final int selectedVideoStreamIndex;
public MediaSourceTag(@NonNull final StreamInfo metadata,
@NonNull final List<VideoStream> sortedAvailableVideoStreams,
final int selectedVideoStreamIndex) {
this.metadata = metadata;
this.sortedAvailableVideoStreams = sortedAvailableVideoStreams;
this.selectedVideoStreamIndex = selectedVideoStreamIndex;
}
public MediaSourceTag(@NonNull final StreamInfo metadata) {
this(metadata, Collections.emptyList(), /*indexNotAvailable=*/-1);
}
@NonNull
public StreamInfo getMetadata() {
return metadata;
}
@NonNull
public List<VideoStream> getSortedAvailableVideoStreams() {
return sortedAvailableVideoStreams;
}
public int getSelectedVideoStreamIndex() {
return selectedVideoStreamIndex;
}
@Nullable
public VideoStream getSelectedVideoStream() {
return selectedVideoStreamIndex < 0 ||
selectedVideoStreamIndex >= sortedAvailableVideoStreams.size() ? null :
sortedAvailableVideoStreams.get(selectedVideoStreamIndex);
}
}

View File

@ -0,0 +1,84 @@
package org.schabi.newpipe.player.resolver;
import android.net.Uri;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.util.Util;
import org.schabi.newpipe.extractor.stream.StreamInfo;
import org.schabi.newpipe.extractor.stream.StreamType;
import org.schabi.newpipe.player.helper.PlayerDataSource;
public interface PlaybackResolver extends Resolver<StreamInfo, MediaSource> {
@Nullable
default MediaSource maybeBuildLiveMediaSource(@NonNull final PlayerDataSource dataSource,
@NonNull final StreamInfo info) {
final StreamType streamType = info.getStreamType();
if (!(streamType == StreamType.AUDIO_LIVE_STREAM || streamType == StreamType.LIVE_STREAM)) {
return null;
}
final MediaSourceTag tag = new MediaSourceTag(info);
if (!info.getHlsUrl().isEmpty()) {
return buildLiveMediaSource(dataSource, info.getHlsUrl(), C.TYPE_HLS, tag);
} else if (!info.getDashMpdUrl().isEmpty()) {
return buildLiveMediaSource(dataSource, info.getDashMpdUrl(), C.TYPE_DASH, tag);
}
return null;
}
@NonNull
default MediaSource buildLiveMediaSource(@NonNull final PlayerDataSource dataSource,
@NonNull final String sourceUrl,
@C.ContentType final int type,
@NonNull final MediaSourceTag metadata) {
final Uri uri = Uri.parse(sourceUrl);
switch (type) {
case C.TYPE_SS:
return dataSource.getLiveSsMediaSourceFactory().setTag(metadata)
.createMediaSource(uri);
case C.TYPE_DASH:
return dataSource.getLiveDashMediaSourceFactory().setTag(metadata)
.createMediaSource(uri);
case C.TYPE_HLS:
return dataSource.getLiveHlsMediaSourceFactory().setTag(metadata)
.createMediaSource(uri);
default:
throw new IllegalStateException("Unsupported type: " + type);
}
}
@NonNull
default MediaSource buildMediaSource(@NonNull final PlayerDataSource dataSource,
@NonNull final String sourceUrl,
@NonNull final String cacheKey,
@NonNull final String overrideExtension,
@NonNull final MediaSourceTag metadata) {
final Uri uri = Uri.parse(sourceUrl);
@C.ContentType final int type = TextUtils.isEmpty(overrideExtension) ?
Util.inferContentType(uri) : Util.inferContentType("." + overrideExtension);
switch (type) {
case C.TYPE_SS:
return dataSource.getLiveSsMediaSourceFactory().setTag(metadata)
.createMediaSource(uri);
case C.TYPE_DASH:
return dataSource.getDashMediaSourceFactory().setTag(metadata)
.createMediaSource(uri);
case C.TYPE_HLS:
return dataSource.getHlsMediaSourceFactory().setTag(metadata)
.createMediaSource(uri);
case C.TYPE_OTHER:
return dataSource.getExtractorMediaSourceFactory(cacheKey).setTag(metadata)
.createMediaSource(uri);
default:
throw new IllegalStateException("Unsupported type: " + type);
}
}
}

View File

@ -0,0 +1,8 @@
package org.schabi.newpipe.player.resolver;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
public interface Resolver<Source, Product> {
@Nullable Product resolve(@NonNull Source source);
}

View File

@ -0,0 +1,123 @@
package org.schabi.newpipe.player.resolver;
import android.content.Context;
import android.net.Uri;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.source.MergingMediaSource;
import org.schabi.newpipe.extractor.MediaFormat;
import org.schabi.newpipe.extractor.Subtitles;
import org.schabi.newpipe.extractor.stream.AudioStream;
import org.schabi.newpipe.extractor.stream.StreamInfo;
import org.schabi.newpipe.extractor.stream.VideoStream;
import org.schabi.newpipe.player.helper.PlayerDataSource;
import org.schabi.newpipe.player.helper.PlayerHelper;
import org.schabi.newpipe.util.ListHelper;
import java.util.ArrayList;
import java.util.List;
import static com.google.android.exoplayer2.C.SELECTION_FLAG_AUTOSELECT;
import static com.google.android.exoplayer2.C.TIME_UNSET;
public class VideoPlaybackResolver implements PlaybackResolver {
public interface QualityResolver {
int getDefaultResolutionIndex(final List<VideoStream> sortedVideos);
int getOverrideResolutionIndex(final List<VideoStream> sortedVideos,
final String playbackQuality);
}
@NonNull private final Context context;
@NonNull private final PlayerDataSource dataSource;
@NonNull private final QualityResolver qualityResolver;
@Nullable private String playbackQuality;
public VideoPlaybackResolver(@NonNull final Context context,
@NonNull final PlayerDataSource dataSource,
@NonNull final QualityResolver qualityResolver) {
this.context = context;
this.dataSource = dataSource;
this.qualityResolver = qualityResolver;
}
@Override
@Nullable
public MediaSource resolve(@NonNull StreamInfo info) {
final MediaSource liveSource = maybeBuildLiveMediaSource(dataSource, info);
if (liveSource != null) return liveSource;
List<MediaSource> mediaSources = new ArrayList<>();
// Create video stream source
final List<VideoStream> videos = ListHelper.getSortedStreamVideosList(context,
info.getVideoStreams(), info.getVideoOnlyStreams(), false);
final int index;
if (videos.isEmpty()) {
index = -1;
} else if (playbackQuality == null) {
index = qualityResolver.getDefaultResolutionIndex(videos);
} else {
index = qualityResolver.getOverrideResolutionIndex(videos, getPlaybackQuality());
}
final MediaSourceTag tag = new MediaSourceTag(info, videos, index);
@Nullable final VideoStream video = tag.getSelectedVideoStream();
if (video != null) {
final MediaSource streamSource = buildMediaSource(dataSource, video.getUrl(),
PlayerHelper.cacheKeyOf(info, video),
MediaFormat.getSuffixById(video.getFormatId()), tag);
mediaSources.add(streamSource);
}
// Create optional audio stream source
final List<AudioStream> audioStreams = info.getAudioStreams();
final AudioStream audio = audioStreams.isEmpty() ? null : audioStreams.get(
ListHelper.getDefaultAudioFormat(context, audioStreams));
// Use the audio stream if there is no video stream, or
// Merge with audio stream in case if video does not contain audio
if (audio != null && ((video != null && video.isVideoOnly) || video == null)) {
final MediaSource audioSource = buildMediaSource(dataSource, audio.getUrl(),
PlayerHelper.cacheKeyOf(info, audio),
MediaFormat.getSuffixById(audio.getFormatId()), tag);
mediaSources.add(audioSource);
}
// If there is no audio or video sources, then this media source cannot be played back
if (mediaSources.isEmpty()) return null;
// Below are auxiliary media sources
// Create subtitle sources
for (final Subtitles subtitle : info.getSubtitles()) {
final String mimeType = PlayerHelper.mimeTypesOf(subtitle.getFileType());
if (mimeType == null) continue;
final Format textFormat = Format.createTextSampleFormat(null, mimeType,
SELECTION_FLAG_AUTOSELECT, PlayerHelper.captionLanguageOf(context, subtitle));
final MediaSource textSource = dataSource.getSampleMediaSourceFactory()
.createMediaSource(Uri.parse(subtitle.getURL()), textFormat, TIME_UNSET);
mediaSources.add(textSource);
}
if (mediaSources.size() == 1) {
return mediaSources.get(0);
} else {
return new MergingMediaSource(mediaSources.toArray(
new MediaSource[mediaSources.size()]));
}
}
@Nullable
public String getPlaybackQuality() {
return playbackQuality;
}
public void setPlaybackQuality(@Nullable String playbackQuality) {
this.playbackQuality = playbackQuality;
}
}

View File

@ -277,6 +277,7 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
newpipe_db_shm.delete();
} else {
Toast.makeText(getContext(), R.string.could_not_import_all_files, Toast.LENGTH_LONG)
.show();
}

View File

@ -6,7 +6,7 @@ public class Constants {
public static final String KEY_TITLE = "key_title";
public static final String KEY_LINK_TYPE = "key_link_type";
public static final String KEY_OPEN_SEARCH = "key_open_search";
public static final String KEY_QUERY = "key_query";
public static final String KEY_SEARCH_STRING = "key_search_string";
public static final String KEY_THEME_CHANGE = "key_theme_change";
public static final String KEY_MAIN_PAGE_CHANGE = "key_main_page_change";

View File

@ -38,9 +38,8 @@ import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.exceptions.ReCaptchaException;
import org.schabi.newpipe.extractor.kiosk.KioskInfo;
import org.schabi.newpipe.extractor.playlist.PlaylistInfo;
import org.schabi.newpipe.extractor.search.SearchEngine;
import org.schabi.newpipe.extractor.search.SearchResult;
import org.schabi.newpipe.extractor.services.youtube.YoutubeStreamExtractor;
import org.schabi.newpipe.extractor.search.SearchInfo;
import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeStreamExtractor;
import org.schabi.newpipe.extractor.stream.StreamInfo;
import org.schabi.newpipe.report.ErrorActivity;
import org.schabi.newpipe.report.UserAction;
@ -51,7 +50,6 @@ import java.util.List;
import io.reactivex.Maybe;
import io.reactivex.Single;
import io.reactivex.annotations.NonNull;
public final class ExtractorHelper {
private static final String TAG = ExtractorHelper.class.getSimpleName();
@ -67,29 +65,35 @@ public final class ExtractorHelper {
}
}
public static Single<SearchResult> searchFor(final int serviceId,
final String query,
final int pageNumber,
final String contentCountry,
final SearchEngine.Filter filter) {
public static Single<SearchInfo> searchFor(final int serviceId,
final String searchString,
final List<String> contentFilter,
final String sortFilter,
final String contentCountry) {
checkServiceId(serviceId);
return Single.fromCallable(() ->
SearchResult.getSearchResult(NewPipe.getService(serviceId).getSearchEngine(),
query, pageNumber, contentCountry, filter)
);
SearchInfo.getInfo(NewPipe.getService(serviceId),
NewPipe.getService(serviceId)
.getSearchQIHFactory()
.fromQuery(searchString, contentFilter, sortFilter),
contentCountry));
}
public static Single<InfoItemsPage> getMoreSearchItems(final int serviceId,
final String query,
final int nextPageNumber,
final String searchLanguage,
final SearchEngine.Filter filter) {
final String searchString,
final List<String> contentFilter,
final String sortFilter,
final String pageUrl,
final String contentCountry) {
checkServiceId(serviceId);
return searchFor(serviceId, query, nextPageNumber, searchLanguage, filter)
.map((@NonNull SearchResult searchResult) ->
new InfoItemsPage(searchResult.resultList,
nextPageNumber + "",
searchResult.errors));
return Single.fromCallable(() ->
SearchInfo.getMoreItems(NewPipe.getService(serviceId),
NewPipe.getService(serviceId)
.getSearchQIHFactory()
.fromQuery(searchString, contentFilter, sortFilter),
contentCountry,
pageUrl));
}
public static Single<List<String>> suggestionsFor(final int serviceId,
@ -234,7 +238,6 @@ public final class ExtractorHelper {
serviceId == -1 ? "none" : NewPipe.getNameOfService(serviceId), url + (optionalErrorMessage == null ? "" : optionalErrorMessage), errorId));
}
});
}
/**

View File

@ -443,11 +443,11 @@ public final class ListHelper {
/**
* Are we connected to wifi?
* @param context App context
* @return True if connected to wifi
* @return {@code true} if connected to wifi
*/
private static boolean isWifiActive(Context context)
{
ConnectivityManager manager = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
return manager.getActiveNetworkInfo().getType() == ConnectivityManager.TYPE_WIFI;
return manager != null && manager.getActiveNetworkInfo() != null && manager.getActiveNetworkInfo().getType() == ConnectivityManager.TYPE_WIFI;
}
}

View File

@ -26,10 +26,13 @@ import org.schabi.newpipe.download.DownloadActivity;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.StreamingService;
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.search.SearchExtractor;
import org.schabi.newpipe.extractor.stream.AudioStream;
import org.schabi.newpipe.extractor.stream.Stream;
import org.schabi.newpipe.extractor.stream.StreamInfo;
import org.schabi.newpipe.extractor.stream.VideoStream;
import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler;
import org.schabi.newpipe.extractor.linkhandler.SearchQueryHandler;
import org.schabi.newpipe.fragments.MainFragment;
import org.schabi.newpipe.fragments.detail.VideoDetailFragment;
import org.schabi.newpipe.fragments.list.channel.ChannelFragment;
@ -100,11 +103,13 @@ public class NavigationHelper {
final int repeatMode,
final float playbackSpeed,
final float playbackPitch,
final boolean playbackSkipSilence,
@Nullable final String playbackQuality) {
return getPlayerIntent(context, targetClazz, playQueue, playbackQuality)
.putExtra(BasePlayer.REPEAT_MODE, repeatMode)
.putExtra(BasePlayer.PLAYBACK_SPEED, playbackSpeed)
.putExtra(BasePlayer.PLAYBACK_PITCH, playbackPitch);
.putExtra(BasePlayer.PLAYBACK_PITCH, playbackPitch)
.putExtra(BasePlayer.PLAYBACK_SKIP_SILENCE, playbackSkipSilence);
}
public static void playOnMainPlayer(final Context context, final PlayQueue queue) {
@ -281,9 +286,11 @@ public class NavigationHelper {
return fragmentManager.popBackStackImmediate(SEARCH_FRAGMENT_TAG, 0);
}
public static void openSearchFragment(FragmentManager fragmentManager, int serviceId, String query) {
public static void openSearchFragment(FragmentManager fragmentManager,
int serviceId,
String searchString) {
defaultTransaction(fragmentManager)
.replace(R.id.fragment_holder, SearchFragment.getInstance(serviceId, query))
.replace(R.id.fragment_holder, SearchFragment.getInstance(serviceId, searchString))
.addToBackStack(SEARCH_FRAGMENT_TAG)
.commit();
}
@ -312,7 +319,11 @@ public class NavigationHelper {
.commit();
}
public static void openChannelFragment(FragmentManager fragmentManager, int serviceId, String url, String name) {
public static void openChannelFragment(
FragmentManager fragmentManager,
int serviceId,
String url,
String name) {
if (name == null) name = "";
defaultTransaction(fragmentManager)
.replace(R.id.fragment_holder, ChannelFragment.getInstance(serviceId, url, name))
@ -320,7 +331,10 @@ public class NavigationHelper {
.commit();
}
public static void openPlaylistFragment(FragmentManager fragmentManager, int serviceId, String url, String name) {
public static void openPlaylistFragment(FragmentManager fragmentManager,
int serviceId,
String url,
String name) {
if (name == null) name = "";
defaultTransaction(fragmentManager)
.replace(R.id.fragment_holder, PlaylistFragment.getInstance(serviceId, url, name))
@ -368,10 +382,10 @@ public class NavigationHelper {
// Through Intents
//////////////////////////////////////////////////////////////////////////*/
public static void openSearch(Context context, int serviceId, String query) {
public static void openSearch(Context context, int serviceId, String searchString) {
Intent mIntent = new Intent(context, MainActivity.class);
mIntent.putExtra(Constants.KEY_SERVICE_ID, serviceId);
mIntent.putExtra(Constants.KEY_QUERY, query);
mIntent.putExtra(Constants.KEY_SEARCH_STRING, searchString);
mIntent.putExtra(Constants.KEY_OPEN_SEARCH, true);
context.startActivity(mIntent);
}
@ -465,7 +479,8 @@ public class NavigationHelper {
switch (linkType) {
case STREAM:
rIntent.putExtra(VideoDetailFragment.AUTO_PLAY, PreferenceManager.getDefaultSharedPreferences(context)
rIntent.putExtra(VideoDetailFragment.AUTO_PLAY,
PreferenceManager.getDefaultSharedPreferences(context)
.getBoolean(context.getString(R.string.autoplay_through_intent_key), false));
break;
}

View File

@ -5,7 +5,6 @@ import android.preference.PreferenceManager;
import android.support.annotation.DrawableRes;
import android.support.annotation.StringRes;
import org.schabi.newpipe.BuildConfig;
import org.schabi.newpipe.R;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.ServiceList;
@ -31,6 +30,18 @@ public class ServiceHelper {
}
}
public static String getTranslatedFilterString(String filter, Context c) {
switch(filter) {
case "all": return c.getString(R.string.all);
case "videos": return c.getString(R.string.videos);
case "channels": return c.getString(R.string.channels);
case "playlists": return c.getString(R.string.playlists);
case "tracks": return c.getString(R.string.tracks);
case "users": return c.getString(R.string.users);
default: return filter;
}
}
/**
* Get a resource string with instructions for importing subscriptions for each service.
*

View File

@ -41,7 +41,6 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:scaleType="centerInside"
android:visibility="gone"
tools:background="@android:color/white"
tools:ignore="ContentDescription"

View File

@ -260,13 +260,95 @@
</RelativeLayout>
<View
android:id="@+id/separatorCheckbox"
android:id="@+id/separatorStepSizeSelector"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_below="@+id/pitchControl"
android:layout_margin="@dimen/video_item_search_padding"
android:background="?attr/separator_color"/>
<LinearLayout
android:id="@+id/stepSizeSelector"
android:layout_width="match_parent"
android:layout_height="40dp"
android:orientation="horizontal"
android:layout_below="@id/separatorStepSizeSelector">
<TextView
android:id="@+id/stepSizeText"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:text="@string/playback_step"
android:textStyle="bold"
android:clickable="false"
android:textColor="?attr/colorAccent"/>
<TextView
android:id="@+id/stepSizeOnePercent"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:clickable="true"
android:focusable="true"
android:background="?attr/selectableItemBackground"
android:textColor="?attr/colorAccent"/>
<TextView
android:id="@+id/stepSizeFivePercent"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:clickable="true"
android:focusable="true"
android:background="?attr/selectableItemBackground"
android:textColor="?attr/colorAccent"/>
<TextView
android:id="@+id/stepSizeTenPercent"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:clickable="true"
android:focusable="true"
android:background="?attr/selectableItemBackground"
android:textColor="?attr/colorAccent"/>
<TextView
android:id="@+id/stepSizeTwentyFivePercent"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:clickable="true"
android:focusable="true"
android:background="?attr/selectableItemBackground"
android:textColor="?attr/colorAccent"/>
<TextView
android:id="@+id/stepSizeOneHundredPercent"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:clickable="true"
android:focusable="true"
android:background="?attr/selectableItemBackground"
android:textColor="?attr/colorAccent"/>
</LinearLayout>
<View
android:id="@+id/separatorCheckbox"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_below="@+id/stepSizeSelector"
android:layout_margin="@dimen/video_item_search_padding"
android:background="?attr/separator_color"/>
<CheckBox
android:id="@+id/unhookCheckbox"
android:layout_width="match_parent"
@ -279,33 +361,17 @@
android:layout_centerHorizontal="true"
android:layout_below="@id/separatorCheckbox"/>
<LinearLayout
android:id="@+id/presetSelector"
<CheckBox
android:id="@+id/skipSilenceCheckbox"
android:layout_width="match_parent"
android:layout_height="40dp"
android:orientation="horizontal"
android:layout_below="@id/unhookCheckbox">
<TextView
android:id="@+id/presetNightcore"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:text="@string/playback_nightcore"
android:background="?attr/selectableItemBackground"
android:textColor="?attr/colorAccent"/>
<TextView
android:id="@+id/presetReset"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:text="@string/playback_default"
android:background="?attr/selectableItemBackground"
android:textColor="?attr/colorAccent"/>
</LinearLayout>
android:layout_height="wrap_content"
android:checked="false"
android:clickable="true"
android:focusable="true"
android:text="@string/skip_silence_checkbox"
android:maxLines="1"
android:layout_centerHorizontal="true"
android:layout_below="@id/unhookCheckbox"/>
<!-- END HERE -->

View File

@ -111,7 +111,7 @@
<TextView
android:id="@+id/resizeTextView"
android:layout_width="match_parent"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
android:background="?attr/selectableItemBackground"

View File

@ -4,7 +4,6 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
android:orientation="vertical">
<RelativeLayout
@ -12,7 +11,9 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true"
android:focusable="true">
android:focusable="true"
android:background="?attr/selectableItemBackground">
<ImageView
android:id="@+id/sortButtonIcon"
android:layout_width="48dp"

View File

@ -1,8 +1,8 @@
<?xml version='1.0' encoding='UTF-8'?>
<resources>
<string name="background_player_playing_toast">جاري التشغيل في الخلفية</string>
<string name="background_player_playing_toast">يتم التشغيل في الخلفية</string>
<string name="cancel">إلغاء</string>
<string name="choose_browser">إختر متصفح</string>
<string name="choose_browser">اختر المتصفح</string>
<string name="dark_theme_title">مظلم</string>
<string name="default_audio_format_title">صيغة الصوت الإفتراضية</string>
<string name="default_resolution_title">الدقة الإفتراضية</string>
@ -25,7 +25,6 @@
<string name="kore_not_found">تطبيق Kore غير موجود. هل تريد تثبيته ؟</string>
<string name="light_theme_title">مضيء</string>
<string name="list_thumbnail_view_description">صور معاينة الفيديو</string>
<string name="m4a_description">M4A — جودة أفضل</string>
<string name="network_error">خطأ في الشبكة</string>
<string name="next_video_title">الفيديو التالي</string>
<string name="no_player_found">لا يوجد مشغل فيديو. هل تريد تثبيت VLC ؟</string>
@ -42,7 +41,7 @@
<string name="settings_category_video_audio_title">الفيديو والصوتيات</string>
<string name="share">مشاركة</string>
<string name="share_dialog_title">مشاركة بواسطة</string>
<string name="show_next_and_similar_title">عرض\'مقاطع\'الفيديو\'التالية\'و\'المشابهة\'</string>
<string name="show_next_and_similar_title">عرض الفديوهات \'التالية\'و\'المماثلة\'</string>
<string name="show_play_with_kodi_summary">عرض خيار لتشغيل الفيديو بواسطة Kodi Media Center</string>
<string name="show_play_with_kodi_title">عرض خيار التشغيل بواسطة Kodi</string>
<string name="theme_title">السمة</string>
@ -53,7 +52,6 @@
<string name="use_tor_summary">(إختبارية) إجراء التنزيلات من خلال استخدام بروكسي Tor لزيادة الخصوصية ( تشغيل الفيديو المباشر غير مدعوم حتى الأن ).</string>
<string name="use_tor_title">استخدام Tor</string>
<string name="view_count_text">مشاهدات %1$s</string>
<string name="webm_description">تنسيق حر — WebM</string>
<string name="blocked_by_gema">تم حجبه بواسطة GEMA</string>
<string name="content_not_available">المحتوى غير متاح</string>
<string name="could_not_load_thumbnails">لم يتمكن من تحميل كل صور المعاينة</string>
@ -61,10 +59,10 @@
<string name="parsing_error">تعذرت عملية تحليل الموقع</string>
<string name="youtube_signature_decryption_error">تعذر فك تشفير توقيع رابط الفيديو</string>
<string name="main_bg_subtitle">اضغط بحث للبدء</string>
<string name="subscribe_button_title">إشتراك</string>
<string name="subscribe_button_title">اشتراك</string>
<string name="subscribed_button_title">مشترك</string>
<string name="tab_main">الرئيسية</string>
<string name="tab_subscriptions">الإشتراكات</string>
<string name="tab_subscriptions">الاشتراكات</string>
<string name="fragment_whats_new">ما الجديد</string>
@ -72,7 +70,7 @@
<string name="autoplay_by_calling_app_title">تشغيل تلقائي</string>
<string name="black_theme_title">اسود</string>
<string name="enable_watch_history_title">التاريخ وذاكرة التخزين المؤقت</string>
<string name="settings_category_history_title">التأريخ و ذاكرة التخزين المؤقتة</string>
<string name="settings_category_history_title">التاريخ و ذاكرة التخزين المؤقتة</string>
<string name="content">المحتوى</string>
<string name="downloads">التنزيلات</string>
<string name="downloads_title">التنزيلات</string>
@ -84,24 +82,24 @@
<string name="tab_about">عن التطبيق</string>
<string name="title_activity_history">التاريخ</string>
<string name="action_history">التاريخ</string>
<string name="open_in_popup_mode">فتح في وضع النوافذ المنبثقة</string>
<string name="use_external_video_player_summary">"بعض القرارات لن يكون الصوت عند تمكين هذا الخيار "</string>
<string name="open_in_popup_mode">فتح في وضع النافذة المنبثقة</string>
<string name="use_external_video_player_summary">"بعض الخيارات الدقة لن تحتوي على صوت عند تمكين هذا الخيار "</string>
<string name="popup_mode_share_menu_title">وضع النوافذ المنبثقة NewPipe</string>
<string name="channel_unsubscribed">تم إلغاء اشتراك القناة</string>
<string name="subscription_change_failed">تعذر تغيير في الاشتراك</string>
<string name="channel_unsubscribed">تم إلغاء الاشتراك في القناة</string>
<string name="subscription_change_failed">تعذر تغيير حالة الاشتراك</string>
<string name="subscription_update_failed">تعذر تحديث الاشتراك</string>
<string name="controls_popup_title">نافذة</string>
<string name="autoplay_by_calling_app_summary">تشغيل مقطع الفيديو عند إستدعاء NewPipe من تطبيق آخر</string>
<string name="default_popup_resolution_title">"دقة النوافذ المنبثقة الافتراضية "</string>
<string name="default_popup_resolution_title">الدقة الافتراضية لنوافذ المنبثقة</string>
<string name="show_higher_resolutions_title">"عرض أعلى جودة "</string>
<string name="show_higher_resolutions_summary">بعض الأجهزة فقط تدعم تشغيل مقاطع الفيديو 2K / 4K</string>
<string name="default_video_format_title">تنسيق الفيديو الافتراضي</string>
<string name="popup_remember_size_pos_title">تذكر حجم النافذة و وضعها</string>
<string name="popup_remember_size_pos_summary">تذكر آخر حجم ومكان للنافذة</string>
<string name="popup_remember_size_pos_summary">تذكر آخر مكان و حجم للنافذة المنبثقة</string>
<string name="player_gesture_controls_title">اعدادات إيماءة المشغل</string>
<string name="player_gesture_controls_summary">استخدم إيماءات للتحكم في سطوع وحجم المشغل</string>
<string name="player_gesture_controls_summary">استخدم إيماءات التحكم في سطوع وصوت المشغل</string>
<string name="show_search_suggestions_title">اقتراحات البحث</string>
<string name="show_search_suggestions_summary">عرض الاقتراحات عند البحث</string>
<string name="enable_search_history_title">سجل البحث</string>
@ -114,7 +112,7 @@
<string name="settings_category_player_title">المشغل</string>
<string name="settings_category_player_behavior_title">السلوك</string>
<string name="settings_category_popup_title">المنبثق</string>
<string name="popup_playing_toast">التشغيل في الوضع المنبثق</string>
<string name="popup_playing_toast">يتم التشغيل في الوضع المنبثق</string>
<string name="background_player_append">تم وضعه على قائمة الانتظار في مشغل الخلفية</string>
<string name="popup_playing_append">تم وضعه على قائمة الانتظار في مشغل النافذة المنبثقة</string>
<string name="show_age_restricted_content_title">عرض المحتوى المقيّد بحسب العُمر</string>
@ -170,9 +168,9 @@
<string name="use_old_player_title">استخدام المشغل القديم</string>
<string name="use_old_player_summary">المشغل القديم المدمج في إطار Mediaframework</string>
<string name="short_thousand">ك</string>
<string name="short_million">م</string>
<string name="short_billion">ب</string>
<string name="short_thousand">الف</string>
<string name="short_million">مليون</string>
<string name="short_billion">بليون</string>
<string name="no_subscribers">صفر لا تقم با الإختيار (في بعض اللغات) لأنها ليست \"حالة خاصة\" للأندرويد</string>
<plurals name="subscribers">
@ -186,14 +184,14 @@
<string name="no_views">لاتوجد مشاهدات</string>
<string name="no_videos">لاتوجد فديوهات</string>
<string name="start">بداية</string>
<string name="start">تشغيل</string>
<string name="pause">إيقاف</string>
<string name="view">شغل</string>
<string name="delete">حذف</string>
<string name="checksum">التوقيع</string>
<string name="add">مهمة جديدة</string>
<string name="finish">حسنا</string>
<string name="finish">حسناً</string>
<string name="msg_name">اسم الملف</string>
<string name="msg_threads">العمليات</string>
@ -238,7 +236,7 @@
<string name="title_history_search">البحث</string>
<string name="title_history_view">شاهد</string>
<string name="title_history_view">تمت مشاهدته</string>
<string name="history_disabled">تم تعطيل السجل</string>
<string name="history_empty">التاريخ فارغ</string>
<string name="history_cleared">تم مسح التاريخ</string>
@ -251,7 +249,7 @@
<string name="feed_page_summary">صفحة الخلاصة</string>
<string name="channel_page_summary">صفحة القناة</string>
<string name="select_a_channel">حدد قناة</string>
<string name="no_channel_subscribed_yet">لم يتم الاشتراك في القناة بعد</string>
<string name="no_channel_subscribed_yet">لم يتم الاشتراك في اي قناة بعد</string>
<string name="trending">الترند</string>
<string name="top_50">أفضل 50</string>
<string name="new_and_hot">جديد &amp; وساخن</string>
@ -265,9 +263,9 @@
<string name="reCaptcha_title">تحدي ريكابتشا</string>
<string name="hold_to_append">اضغط للإدراج بقائمة الانتظار</string>
<plurals name="views">
<item quantity="zero">لم تتم المشاهدة</item>
<item quantity="zero">لاتوجد مشاهدة</item>
<item quantity="one">%s مشاهدة</item>
<item quantity="two">"اثنان مشاهدات "</item>
<item quantity="two">مشاهدتين</item>
<item quantity="few">%s مشاهدات كثيرة</item>
<item quantity="many">%s عدد المشاهدات</item>
<item quantity="other">%s أقصى مشاهدات</item>
@ -276,10 +274,10 @@
<plurals name="videos">
<item quantity="zero">صفر</item>
<item quantity="one">واحد</item>
<item quantity="two">اثنان</item>
<item quantity="few">قليل</item>
<item quantity="many">عدد كثير</item>
<item quantity="other">"أخرى "</item>
<item quantity="two">%s اثنان</item>
<item quantity="few">%s قليل</item>
<item quantity="many">%s عدد كثير</item>
<item quantity="other">"%s أخرى "</item>
</plurals>
<string name="recaptcha_request_toast">إعادة طلب كلمة التحقق</string>
@ -289,27 +287,27 @@
<string name="select_a_kiosk">حدد كشك</string>
<string name="kiosk">كشك</string>
<string name="enqueue_on_background">إدراج بقائمة الانتظار على خلفية</string>
<string name="enqueue_on_background">إدراج بقائمة الانتظار في مشغل الخلفية</string>
<string name="enqueue_on_popup">إدراج بقائمة الانتظار على المنبثقة</string>
<string name="start_here_on_background">ابدأ هنا على خلفية المصدر</string>
<string name="default_content_country_title">المحتوى الإفتراضي حسب البلد</string>
<string name="toggle_orientation">تغيير الإتجاه</string>
<string name="switch_to_background">الإنتقال إلى الخلفية</string>
<string name="switch_to_popup">الإنتقال إلى نافذة منبثقة</string>
<string name="switch_to_main">التحول إلى الرئيسية</string>
<string name="switch_to_background">الإنتقال إلى التشغيل في الخلفية</string>
<string name="switch_to_popup">الإنتقال إلى التشغيل في النافذة المنبثقة</string>
<string name="switch_to_main">الإنتقال إلى الرئيسية</string>
<string name="service_title">الخدمة</string>
<string name="drawer_open">فتح الدرج</string>
<string name="drawer_close">إغلاق الدرج</string>
<string name="always">دائمًا</string>
<string name="always">دائماً</string>
<string name="just_once">مرة واحدة فقط</string>
<string name="invalid_url_toast">العنوان خاطئ</string>
<string name="no_player_found_toast">لم يتم العثور على مشغل بث (يمكنك تثبيت VLC لتشغيله)</string>
<string name="no_player_found_toast">لم يتم العثور على مشغل الفديو (يمكنك تثبيت VLC لتشغيله)</string>
<string name="import_data_title">استيراد قاعدة البيانات</string>
<string name="export_data_title">تصدير قاعدة البيانات</string>
<string name="import_data_summary">"سيقوم بالكتابة على سجل التاريخ والاشتراكات الحالية "</string>
<string name="export_data_summary">تصدير سجل, الاشتراكات وقوائم التشغيل.</string>
<string name="export_data_summary">تصدير سجل, الاشتراكات وقوائم التشغيل</string>
<string name="show_info">عرض المعلومات</string>
<string name="controls_add_to_playlist_title">إضافة إلى</string>
@ -334,7 +332,7 @@
<string name="video_player">مشغل الفديو</string>
<string name="always_ask_open_action">السؤال دائمًا</string>
<string name="always_ask_open_action">السؤال دائماً</string>
<string name="preferred_player_fetcher_notification_title">الحصول على المعلومات …</string>
<string name="preferred_player_fetcher_notification_message">تحميل المحتوى المطلوب</string>
@ -342,14 +340,14 @@
<string name="create_playlist">إنشاء قائمة تشغيل جديدة</string>
<string name="delete_playlist">حذف قائمة التشغيل</string>
<string name="rename_playlist">"إعادة تسمية قائمة التشغيل "</string>
<string name="playlist_name_input">التسمية</string>
<string name="playlist_name_input">الأسم</string>
<string name="append_playlist">إضافة إلى قائمة تشغيل</string>
<string name="delete_playlist_prompt">هل تريد حذف قائمة التشغيل هذه ؟</string>
<string name="playlist_creation_success">قائمة التشغيل التي تم إنشاؤها</string>
<string name="playlist_add_stream_success">تمت إضافتها إلى قائمة التشغيل</string>
<string name="playlist_delete_failure">لا يمكن حذف قائمة التشغيل</string>
<string name="resize_fill">ملئ</string>
<string name="resize_fill">ملئ الشاشة</string>
<string name="resize_zoom">تكبير</string>
<string name="caption_font_size_settings_title">حجم خط التسمية</string>
@ -359,7 +357,7 @@
<string name="live_sync">مُزامَنة</string>
<string name="controls_download_desc">تنزيل الملف البث.</string>
<string name="controls_download_desc">تنزيل ملف البث.</string>
<string name="tab_bookmarks">الإشارات مرجعية</string>
<string name="use_inexact_seek_title">استعمال التقديم السريع الغير دقيق</string>
@ -389,38 +387,38 @@
<string name="import_soundcloud_instructions_hint">"معرفك , soundcloud.com/ الخاص بك "</string>
<string name="playback_default">إفتراضي</string>
<string name="download_thumbnail_summary">تعطيل إيقاف جميع الصور المصغرة من تحميل البيانات واستخدام الذاكرة وحفظها. سيؤدي التغيير هذا إلى محو-ذاكرة التخزين المؤقت في الذاكرة-وذاكرة على القرص.</string>
<string name="download_thumbnail_summary">تعطيل إيقاف جميع الصور المصغرة من تحميل البيانات واستخدام الذاكرة وحفظها. سيؤدي التغيير هذا إلى محو-ذاكرة التخزين المؤقت في الذاكرة-وذاكرة على القرص</string>
<string name="metadata_cache_wipe_title">امسح البيانات الوصفية المخزنة مؤقتًا</string>
<string name="metadata_cache_wipe_summary">إزالة جميع بيانات صفحات الويب المخزنة مؤقتًا</string>
<string name="metadata_cache_wipe_complete_notice">تم محو ذاكرة التخزين المؤقت للبيانات الوصفية</string>
<string name="auto_queue_title">وضع البث القادم تلقائيا في قائمة الإنتظار</string>
<string name="auto_queue_summary">رفض البث المشابه في حال كون البث السابق يعمل في حالة عدم التكرار.</string>
<string name="set_as_playlist_thumbnail">إضافة إلى قائمة التشغيل كصورة مصغرة</string>
<string name="auto_queue_summary">رفض البث المشابه في حال كون البث السابق يعمل في حالة عدم التكرار</string>
<string name="set_as_playlist_thumbnail">إضافة صورة مصغرة إلى قائمة التشغيل</string>
<string name="bookmark_playlist">قائمة التشغيل المخزنة</string>
<string name="playlist_thumbnail_change_success">تم تغيير الصورة المصغرة لقائمة التشغيل</string>
<string name="caption_none">بدون تسميات توضيحية</string>
<string name="caption_setting_title">تسميات توضيحية</string>
<string name="caption_setting_description">تعديل مشغل نص التسمية التوضيحية وأنماط الخلفية. يتطلب إعادة تشغيل التطبيق ليصبح ساري المفعول.</string>
<string name="caption_setting_description">تعديل مشغل نص التسمية التوضيحية وأنماط الخلفية. يتطلب إعادة تشغيل التطبيق لتصبح التغييرات سارية المفعول</string>
<string name="enable_leak_canary_title">تمكين LeakCanary</string>
<string name="enable_leak_canary_summary">قد يتسبب مراقبة في تسرب الذاكرة في عدم استجابة التطبيق عند تفريغ السجلات</string>
<string name="enable_leak_canary_summary">قد تتسبب مراقبة تسرب الذاكرة في عدم استجابة التطبيق عند تفريغ السجلات</string>
<string name="enable_disposed_exceptions_title">تقرير الأخطاء خارج دورة الحياة</string>
<string name="enable_disposed_exceptions_summary">فرض الإبلاغ عن استثناءات Rx غير القابلة للتسليم خارج دورة حياة الجزء أو النشاط بعد التخلص منها</string>
<string name="clear_views_history_title">محو سجل المشاهدة</string>
<string name="clear_views_history_summary">احذف محفوظات التدفقات التي تم تشغيلها.</string>
<string name="delete_view_history_alert">حذف سجل المشاهدة بالكامل.</string>
<string name="view_history_deleted">سجل المشاهدة المحذوف.</string>
<string name="clear_views_history_summary">احذف محفوظات الفديوهات التي تم تشغيلها</string>
<string name="delete_view_history_alert">حذف سجل المشاهدة بالكامل</string>
<string name="view_history_deleted">سجل المشاهدة محذوف.</string>
<string name="clear_search_history_title">محو سجل البحث</string>
<string name="clear_search_history_summary">يحذف تاريخ البحث عن الكلمات الرئيسية.</string>
<string name="delete_search_history_alert">حذف محفوظات البحث بالكامل.</string>
<string name="clear_search_history_summary">يحذف تاريخ البحث عن الكلمات الرئيسية</string>
<string name="delete_search_history_alert">حذف محفوظات البحث بالكامل</string>
<string name="search_history_deleted">سجل البحث المحذوف.</string>
<string name="external_player_unsupported_link_type">المشغل الخارجي لا يدعم هذه الأنواع من الروابط</string>
<string name="invalid_source">مصدر ملف / مصدر غير صالح</string>
<string name="invalid_file">الملف غير موجود أو ليس لديه الإذن الكافي للقراءة أو الكتابة إليه</string>
<string name="invalid_file">الملف غير موجود أو ليس لديك الإذن الكافي للقراءة أو الكتابة إليه</string>
<string name="no_streams_available_download">لا توجد تدفقات متاحة للتنزيل</string>
<string name="one_item_deleted">تم حذف عنصر واحد.</string>
@ -433,7 +431,7 @@
<string name="title_last_played">آخر ما تم تشغيله</string>
<string name="title_most_played">الأكثر تشغيلا</string>
<string name="override_current_data">هذا سوف يتجاوز الإعداد الحالي الخاص بك.</string>
<string name="override_current_data">هذا سوف يتجاوز الإعدادت الحالية الخاصة بك.</string>
<string name="preferred_open_action_settings_title">طريقة \'التشغيل\' المفضلة</string>
<string name="preferred_open_action_settings_summary">"الإجراء الافتراضي عند فتح المحتوى — %s"</string>
@ -445,25 +443,25 @@
<string name="subscriptions_import_unsuccessful">تعذر استيراد الاشتراكات</string>
<string name="subscriptions_export_unsuccessful">لا يمكن تصدير الاشتراكات</string>
<string name="import_youtube_instructions">استيراد اشتراكات YouTube عن طريق تنزيل ملف التصدير:
\n
\n1. انتقل إلى عنوان URL هذا: %1$s
\n2. تسجيل الدخول عندما يتطلب
\n3. يجب أن يبدأ تنزيل (وهذا ملف التصدير)</string>
<string name="import_soundcloud_instructions">قم باستيراد ملف تعريف SoundCloud عن طريق كتابة عنوان URL أو معرفك:
\n
\n1. تمكين \"وضع سطح المكتب\" في متصفح الويب (الموقع غير متاح للأجهزة المحمولة)
\n2. انتقل إلى عنوان URL هذا: %1$s
\n3. تسجيل الدخول عندما يتطلب
<string name="import_youtube_instructions">استيراد اشتراكات YouTube عن طريق تنزيل ملف التصدير:
\n
\n1. انتقل إلى عنوان URL هذا: %1$s
\n2. تسجيل الدخول عندما يطلب منك
\n3. يجب أن يبدأ التنزيل (وهذا ملف التصدير)</string>
<string name="import_soundcloud_instructions">قم باستيراد ملف تعريف SoundCloud عن طريق كتابة عنوان URL أو معرفك:
\n
\n1. تمكين \"وضع سطح المكتب\" في متصفح الويب (الموقع غير متاح للأجهزة المحمولة)
\n2. انتقل إلى عنوان URL هذا: %1$s
\n3. تسجيل الدخول عندما يطلب منك
\n4. انسخ عنوان URL للملف الشخصي الذي تمت إعادة توجيهك إليه.</string>
<string name="import_network_expensive_warning">ضع في اعتبارك أن هذه العملية يمكن أن تكون باهظة الثمن.
\n
<string name="import_network_expensive_warning">ضع في اعتبارك أن هذه العملية يمكن أن تكون مكلفة اذا كنت تستخدم بيانات اشتراك انترنت.
\n
\nهل تريد الاستمرار؟</string>
<string name="playback_speed_control">ضوابط سرعة التشغيل</string>
<string name="playback_tempo">سرعة الأداء</string>
<string name="playback_pitch">تردد الصوت</string>
<string name="unhook_checkbox">"النزع (قد يسبب تشويه)"</string>
<string name="unhook_checkbox">نزع الإرتباط (قد يسبب تشويه)</string>
<string name="playback_nightcore">تعديل الايقاع Nightcore</string>
<string name="import_settings">هل تريد أيضا استيراد الإعدادات؟</string>
@ -478,4 +476,18 @@
<string name="limit_data_usage_none_description">لا حدود</string>
<string name="limit_mobile_data_usage_title">الحد من جودة الفيديو عند استخدام بيانات الهاتف المحمول</string>
<string name="skip_silence_checkbox">تسريع إلى الأمام أثناء الصمت</string>
<string name="playback_step">خطوة</string>
<string name="playback_reset">إعادة تعيين</string>
<string name="minimize_on_exit_title">تصغير عند تبديل التطبيق</string>
<string name="minimize_on_exit_summary">الإجراء عند التبديل إلى تطبيق آخر من مشغل الفيديو الرئيسي — %s</string>
<string name="minimize_on_exit_none_description">لاشيء</string>
<string name="minimize_on_exit_background_description">تصغير إلى مشغل الخلفية</string>
<string name="minimize_on_exit_popup_description">تصغير إلى مشغل منبثق</string>
<string name="channels">القنوات</string>
<string name="playlists">قوائم التشغيل</string>
<string name="tracks">المسارات</string>
<string name="users">المستخدمين</string>
</resources>

View File

@ -48,7 +48,6 @@
<string name="play_audio">Audio</string>
<string name="default_audio_format_title">Defolt audio formatı</string>
<string name="default_video_format_title">Defolt video formatı</string>
<string name="m4a_description">M4A — daha yaxşı keyfiyyət</string>
<string name="theme_title">Mövzu</string>
<string name="light_theme_title">ıq</string>
<string name="dark_theme_title">Qaranlıq</string>

View File

@ -33,8 +33,6 @@
<string name="show_play_with_kodi_summary">Amuesa una opción pa reproducir un videu per Kodi</string>
<string name="play_audio">Audiu</string>
<string name="default_audio_format_title">Formatu por defeutu d\'audiu</string>
<string name="webm_description">WebM — formatu llibre</string>
<string name="m4a_description">M4A — calidá meyor</string>
<string name="theme_title">Tema</string>
<string name="dark_theme_title">Escuru</string>
<string name="light_theme_title">Claru</string>

View File

@ -1,14 +1,14 @@
<?xml version='1.0' encoding='UTF-8'?>
<resources><string name="main_bg_subtitle">Натисни на търсене за да започнеш</string>
<resources><string name="main_bg_subtitle">Докоснете търсачката, за да започнете</string>
<string name="view_count_text">%1$s гледания</string>
<string name="upload_date_text">Публикувано на %1$s</string>
<string name="no_player_found">Не е намерен стрийм плейър. Желаете ли да инсталирате VLC?</string>
<string name="install">Инсталирай</string>
<string name="cancel">Затвори</string>
<string name="open_in_browser">Отвори в браузъра</string>
<string name="open_in_popup_mode">Отвори в подпрозорец</string>
<string name="cancel">Отмени</string>
<string name="open_in_browser">Отвори в браузър</string>
<string name="open_in_popup_mode">Отвори в прозорец</string>
<string name="share">Сподели</string>
<string name="download">Сваляне</string>
<string name="download">Изтегли</string>
<string name="search">Търси</string>
<string name="settings">Настройки</string>
<string name="did_you_mean">Може би имахте в предвид: %1$s ?</string>
@ -16,81 +16,79 @@
<string name="choose_browser">Избери браузър</string>
<string name="screen_rotation">ориентация</string>
<string name="use_external_video_player_title">Използвай външен видео плейър</string>
<string name="use_external_video_player_summary">Някои резолюции няма да имат вграден аудио поток ако изберете тази опция</string>
<string name="use_external_video_player_summary">Някои резолюции няма да имат вграден аудио поток, ако тази опция е избрана</string>
<string name="use_external_audio_player_title">Използвай външен аудио плейър</string>
<string name="popup_mode_share_menu_title">Режим малък прозорец на NewPipe</string>
<string name="popup_mode_share_menu_title">NewPipe в прозорец</string>
<string name="subscribe_button_title">Абониране</string>
<string name="subscribed_button_title">Абониран</string>
<string name="channel_unsubscribed">Премахнат абонамент за канала</string>
<string name="subscription_change_failed">Не мога да променя абонаментите</string>
<string name="subscription_update_failed">Не мога да обновя абонаментите</string>
<string name="subscription_change_failed">Неуспешна промяна на абонамента</string>
<string name="subscription_update_failed">Неуспешно обновление на абонамента</string>
<string name="tab_subscriptions">Абонаменти</string>
<string name="fragment_whats_new">Новости</string>
<string name="fragment_whats_new">Обновления</string>
<string name="controls_background_title">Фон</string>
<string name="controls_popup_title">Подпрозорец</string>
<string name="controls_background_title">Във фонов режим</string>
<string name="controls_popup_title">В прозорец</string>
<string name="download_path_title">Локация за запис на клиповете</string>
<string name="download_path_summary">Място за съхранение на свалени клипове</string>
<string name="download_path_dialog_title">Въведи път за съхранение на свалени клипове</string>
<string name="download_path_title">Директория за изтегляне на видео</string>
<string name="download_path_summary">Папка за съхранение на изтеглените видеота</string>
<string name="download_path_dialog_title">Въведете път за съхранение на изтеглените видеота</string>
<string name="download_path_audio_title">Локация за запис на аудио</string>
<string name="download_path_audio_summary">Път за съхранение на свалено аудио</string>
<string name="download_path_audio_dialog_title">Въведи път за съхранение на свалено аудио</string>
<string name="download_path_audio_title">Директория за изтегляне на аудио</string>
<string name="download_path_audio_summary">Папка за съхранение на изтеглено аудио</string>
<string name="download_path_audio_dialog_title">Въведете път за съхранение на изтеглено аудио</string>
<string name="autoplay_by_calling_app_title">Автоматично възпроизвеждане</string>
<string name="autoplay_by_calling_app_summary">Автоматично въпроизвеждане на видео, когато NewPipe е повикан от друго приложение</string>
<string name="autoplay_by_calling_app_summary">Въпроизвежда видео, когато NewPipe е повикан от друго приложение</string>
<string name="default_resolution_title">Резолюция по подразбиране</string>
<string name="default_popup_resolution_title">Резолюция по подразбиране на подпрозореца</string>
<string name="default_popup_resolution_title">Резолюция по подразбиране на прозореца</string>
<string name="show_higher_resolutions_title">Покажи по-високи резолюции</string>
<string name="show_higher_resolutions_summary">Само някои устройства поддържат възпроизвеждане на 2K/4K клипове</string>
<string name="play_with_kodi_title">Въпроизвеждане с Kodi</string>
<string name="kore_not_found">Приложението Kore не е намерено. Желаете ли да го инсталирате?</string>
<string name="show_play_with_kodi_title">Покажи опция \"Въпроизвеждане с Kodi\"</string>
<string name="show_play_with_kodi_summary">Показване на опция за въпроизвеждане на видео чрез Kodi media center</string>
<string name="kore_not_found">Приложението Kore не е намерено. Желаете ли да го инсталирате?</string>
<string name="show_play_with_kodi_title">Покажи „Възпроизвеждане с Kodi“</string>
<string name="show_play_with_kodi_summary">Показване на опция за възпроизвеждане на видео чрез Kodi media center</string>
<string name="play_audio">Аудио</string>
<string name="default_audio_format_title">Аудио формат по подразбиране</string>
<string name="default_video_format_title">Видео формат по подразбиране</string>
<string name="webm_description">WebM — свободен формат</string>
<string name="m4a_description">M4A — по-добро качество</string>
<string name="theme_title">Тема</string>
<string name="theme_title">Тема на външния вид</string>
<string name="light_theme_title">Светла</string>
<string name="dark_theme_title">Тъмна</string>
<string name="black_theme_title">Черна</string>
<string name="popup_remember_size_pos_title">Помни размера и позицията на подпрозореца</string>
<string name="popup_remember_size_pos_summary">Запомни последния размер и позиция на подпрозореца</string>
<string name="popup_remember_size_pos_title">Помни размера и позицията на прозореца</string>
<string name="popup_remember_size_pos_summary">Използвай размера и позицията на прозореца от предишния път</string>
<string name="player_gesture_controls_title">Контролиране на плейъра чрез жестове</string>
<string name="player_gesture_controls_summary">Използвай жестове за да контролираш яркостта и силата на звука на плейъра</string>
<string name="player_gesture_controls_summary">Позволи използване на жестове за контрол на яркостта и силата на звука на плейъра</string>
<string name="show_search_suggestions_title">Предложения за търсене</string>
<string name="show_search_suggestions_summary">Показвай предположения по време на търсене</string>
<string name="show_search_suggestions_summary">Показвай предложения за търсене</string>
<string name="enable_search_history_title">История на търсенията</string>
<string name="enable_search_history_summary">Съхранявай заявките за търсене локално</string>
<string name="enable_watch_history_title">История и кеш-памет</string>
<string name="enable_watch_history_summary">Следи изгледаните клипове</string>
<string name="resume_on_audio_focus_gain_title">Поднови клип при възобновяване на фокуса</string>
<string name="resume_on_audio_focus_gain_summary">Продължава въпроизвеждането след прекъсване (например, телефонно обаждане)</string>
<string name="download_dialog_title">Свалени</string>
<string name="enable_watch_history_summary">Запаметявай кои видеота са гледани</string>
<string name="resume_on_audio_focus_gain_title">Възобнови при връщане на фокус</string>
<string name="resume_on_audio_focus_gain_summary">Продължавай възпроизвеждането след прекъсване (например телефонно обаждане)</string>
<string name="download_dialog_title">Изтегли</string>
<string name="next_video_title">Следващ клип</string>
<string name="show_next_and_similar_title">Показвай „следващи“ и „подобни“ клипове</string>
<string name="show_hold_to_append_title">Показвай поле със съвет \"Задръж за добавяне\"</string>
<string name="url_not_supported_toast">Неподдържан URL</string>
<string name="show_next_and_similar_title">Показвай „следващ“ и „подобни“</string>
<string name="show_hold_to_append_title">Показвай съвет „задръж за добавяне“</string>
<string name="url_not_supported_toast">Непознат URL</string>
<string name="search_language_title">Език на съдържанието по подразбиране</string>
<string name="settings_category_player_title">Плейър</string>
<string name="settings_category_player_behavior_title">Поведение</string>
<string name="settings_category_video_audio_title">Видео &amp; Аудио</string>
<string name="settings_category_history_title">История и кеш-памет</string>
<string name="settings_category_popup_title">Подпрозорец</string>
<string name="settings_category_popup_title">Нов прозорец</string>
<string name="settings_category_appearance_title">Външност</string>
<string name="settings_category_other_title">Други</string>
<string name="background_player_playing_toast">Въпроизвеждане във фонов режим</string>
<string name="popup_playing_toast">Въпроизвеждане в подпрозорец</string>
<string name="background_player_playing_toast">Възпроизвеждане във фонов режим</string>
<string name="popup_playing_toast">Възпроизвеждане в подпрозорец</string>
<string name="background_player_append">Включен в опашката на фоновия плейър</string>
<string name="popup_playing_append">Включен в опашката за възпроизвеждане в подпрозорец</string>
<string name="popup_playing_append">Включен в опашката в нов прозорец</string>
<string name="play_btn_text">Възпроизвеждане</string>
<string name="content">Съдържание</string>
<string name="show_age_restricted_content_title">Покажи съдържание с ограничение във възрастта</string>
<string name="show_age_restricted_content_title">Покажи съдържание за възрастни</string>
<string name="video_is_age_restricted">Съдържание за възрастни. Разрешаването на такова съдържание става от Настройки.</string>
<string name="duration_live">на живо</string>
<string name="downloads">Изтегляния</string>
@ -111,17 +109,17 @@
<string name="play_all">Възпроизведи всички</string>
<string name="notification_channel_name">Известия от NewPipe</string>
<string name="notification_channel_description">Известия за фоновия плейър и плейъра на подпрозореца на NewPipe</string>
<string name="notification_channel_description">Известия за фоновия плейър и плейъра в отделен прозорец на NewPipe</string>
<string name="unknown_content">[Неизвестен]</string>
<string name="general_error">Грешка</string>
<string name="network_error">Проблем с мрежата</string>
<string name="could_not_load_thumbnails">Не мога да заредя всички миниатюри</string>
<string name="parsing_error">Не мога да интерпретирам правилно уебсайта</string>
<string name="light_parsing_error">Не мога да интерпретирам изцяло правилно уебсайта</string>
<string name="parsing_error">Неуспешно пресъздаване на уебсайта</string>
<string name="light_parsing_error">Не мога да пресъздам изцяло уебсайта</string>
<string name="content_not_available">Съдържанието не е налично</string>
<string name="blocked_by_gema">Блокирано от GEMA</string>
<string name="blocked_by_gema">Блокирано от GEMA</string>
<string name="could_not_setup_download_menu">Не мога да настроя меню за сваляне</string>
<string name="live_streams_not_supported">Това е предаване на живо, което все още не се поддържа.</string>
<string name="could_not_get_stream">Не мога да достъпя нито един поток</string>
@ -131,7 +129,7 @@
<string name="player_unrecoverable_failure">Критичен проблем с плейъра</string>
<string name="player_recoverable_failure">Опит за възстановяване от възникналия проблем с плейъра</string>
<string name="sorry_string">Съжаляваме, но това не би трябвало да се случва.</string>
<string name="sorry_string">Съжаляваме, това не би трябвало да се случва.</string>
<string name="error_report_button_text">Докладвай за грешката чрез имейл</string>
<string name="error_snackbar_message">Съжаляваме, възникнаха някои грешки.</string>
<string name="error_snackbar_action">ДОКЛАД</string>
@ -141,23 +139,23 @@
<string name="error_details_headline">Подробности:</string>
<string name="detail_thumbnail_view_description">Миниатюра на клипа</string>
<string name="detail_uploader_thumbnail_view_description">Миниатюра на аватаря на качилия клипа</string>
<string name="detail_thumbnail_view_description">Миниатюра на видео</string>
<string name="detail_uploader_thumbnail_view_description">Миниатюра на аватара на качилия видео</string>
<string name="detail_likes_img_view_description">Харесвания</string>
<string name="detail_dislikes_img_view_description">Нехаресвания</string>
<string name="use_tor_title">Използвай Tor</string>
<string name="use_tor_summary">(Експериментално) Пренасочвай трафика при сваляне към мрежата на Tor за по-високо ниво на поверителност (стриймването на клипове все още не се поддържа).</string>
<string name="use_tor_title">Използвай Tor</string>
<string name="use_tor_summary">(Експериментално) Пренасочвай трафика при сваляне към мрежата на Tor за по-високо ниво на поверителност (стриймването на видео все още не се поддържа).</string>
<string name="report_error">Докладвай за грешка</string>
<string name="search_no_results">Няма резултати</string>
<string name="empty_subscription_feed_subtitle">Тук все още няма нищо</string>
<string name="empty_subscription_feed_subtitle">Тук няма нищо</string>
<string name="err_dir_create">Не мога да създам директория за свалянията в \'%1$s\'</string>
<string name="info_dir_created">Създадох директория за свалянията в \'%1$s\'</string>
<string name="err_dir_create">Неуспешно създаване на директория за изтеглени в „%1$s“</string>
<string name="info_dir_created">Бе създадена директория за свалянията в „%1$s“</string>
<string name="video">Видео</string>
<string name="audio">Аудио</string>
<string name="retry">Опитай отново</string>
<string name="storage_permission_denied">Отказан достъп до хранилището (провери правата)</string>
<string name="storage_permission_denied">Достъпа до хранилището е отказан</string>
<string name="use_old_player_title">Използвай стария плейър</string>
<string name="use_old_player_summary">Използваю стария вграден Mediaframewoek плейър</string>
@ -181,54 +179,54 @@
<string name="pause">Пауза</string>
<string name="view">Начало</string>
<string name="delete">Изтрий</string>
<string name="checksum">Чексума</string>
<string name="checksum">Контролна сума</string>
<string name="finish">Готово</string>
<string name="finish">ОК</string>
<string name="msg_name">Име на файла</string>
<string name="msg_threads">Нишки</string>
<string name="msg_error">Грешка</string>
<string name="msg_server_unsupported">Сървърът не се поддържа</string>
<string name="msg_exists">Файлът вече съществува</string>
<string name="msg_url_malform">Неправилен формат на URL-а или няма връзка</string>
<string name="msg_running">NewPipe Сваляне</string>
<string name="msg_running_detail">Натисни за подробности</string>
<string name="msg_url_malform">Неправилен хиперлинк или няма връзка с Интернет</string>
<string name="msg_running">NewPipe Изтегляне</string>
<string name="msg_running_detail">Докосни за подробности</string>
<string name="msg_wait">Моля, изчакайте…</string>
<string name="msg_copied">Копирано в клипборда</string>
<string name="settings_file_charset_title">Позволени символи в името на файловете</string>
<string name="settings_file_replacement_character_summary">Невалидните символи се заменят с тази стойност</string>
<string name="settings_file_replacement_character_title">Стойност за замяна</string>
<string name="settings_file_replacement_character_title">Символ за замяна</string>
<string name="charset_letters_and_digits">Букви и цифри</string>
<string name="title_activity_about">За NewPipe</string>
<string name="action_settings">Настройки</string>
<string name="action_about">Относно приложението</string>
<string name="title_licenses">Лицензи от трети страни</string>
<string name="error_unable_to_load_license">Не мога да заредя лицензите</string>
<string name="error_unable_to_load_license">Неуспешно зареждане на лиценза</string>
<string name="action_open_website">Отвори уебсайта</string>
<string name="tab_about">Относно приложението</string>
<string name="tab_contributors">Допринесли</string>
<string name="tab_licenses">Лицензии</string>
<string name="app_description">Безплатен и лек YouTube фронтенд за Android.</string>
<string name="tab_licenses">Лицензи</string>
<string name="app_description">Безплатно и леко поточно предаване за Android.</string>
<string name="view_on_github">Виж в GitHub</string>
<string name="controls_download_desc">Изтегли стрийм файл.</string>
<string name="show_info">Покажи инфо</string>
<string name="tab_main">NewPipe</string>
<string name="tab_main">Главен</string>
<string name="tab_bookmarks">Отметки</string>
<string name="controls_add_to_playlist_title">Добави към</string>
<string name="use_inexact_seek_title">Използвай бързо, но неточно превъртане</string>
<string name="use_inexact_seek_summary">Неточното превъртане позволява на плейъра да превърта кадри по-бързо с намалена прецизност</string>
<string name="download_thumbnail_title">Зареждай иконки</string>
<string name="use_inexact_seek_summary">Неточното превъртане позволява на плейъра да превърта кадри по-бързо, с намалена прецизност</string>
<string name="download_thumbnail_title">Зареждай миниатюри</string>
<string name="thumbnail_cache_wipe_complete_notice">Кеш-паметта с изображения е изтрита</string>
<string name="metadata_cache_wipe_title">Изчисти кешираните метаданни</string>
<string name="metadata_cache_wipe_summary">Изчисти всички кешираини метаданни за уебстраници</string>
<string name="metadata_cache_wipe_complete_notice">Кеш-паметта с метаданни бе изчистена</string>
<string name="auto_queue_title">Автоматично пускай следващия</string>
<string name="auto_queue_summary">Автоматично прибавяне на сродно съдържание при неповтарящ се преглед .</string>
<string name="default_content_country_title">Държава по подразбиране, за която да бъде показвано подходящо съдържание</string>
<string name="metadata_cache_wipe_title">Изтрий кешираните метаданни</string>
<string name="metadata_cache_wipe_summary">Премахни всички метаданни за уебстраници от кеш-паметта</string>
<string name="metadata_cache_wipe_complete_notice">Кеш-паметта с метаданни бе изтрита</string>
<string name="auto_queue_title">Автоматично нареди на опашка следващия</string>
<string name="auto_queue_summary">"Автоматично прибавяне на сродно съдържание при неповтарящ се преглед . "</string>
<string name="default_content_country_title">Държава, за която да бъде показвано съдържание</string>
<string name="service_title">Услуга</string>
<string name="settings_category_debug_title">Отстраняване на грешки</string>
<string name="always">Винаги</string>
@ -236,22 +234,22 @@
<string name="file">Файл</string>
<string name="toggle_orientation">Смени ориентацията</string>
<string name="switch_to_background">Мини към фонов режим</string>
<string name="switch_to_popup">Мини към изкачащ прозорец</string>
<string name="switch_to_background">Мини във фонов режим</string>
<string name="switch_to_popup">Мини към нов прозорец</string>
<string name="switch_to_main">Мини в основен режим</string>
<string name="import_data_title">Внасяне на база данни</string>
<string name="export_data_title">Изнасяне на база данни</string>
<string name="import_data_title">Импортиране на база данни</string>
<string name="export_data_title">Експортиране на база данни</string>
<string name="import_data_summary">Ще замени текущите история и абонаменти</string>
<string name="export_data_summary">Изнасяне на история, абонаменти и плейлисти</string>
<string name="clear_views_history_title">Изчисти историята с изгледани</string>
<string name="export_data_summary">Експортиране на историята, абонаментите и плейлистите</string>
<string name="clear_views_history_title">Изтрий историята с изгледани</string>
<string name="delete_view_history_alert">Изтрий цялата история с изгледани.</string>
<string name="view_history_deleted">Историята с изгледани е изтрита.</string>
<string name="clear_search_history_title">Изтрий историята на търсенията</string>
<string name="clear_search_history_summary">Изтрива историята с въвежданите за търсене ключови думи.</string>
<string name="delete_search_history_alert">Изтрий цялата история на гледанията.</string>
<string name="delete_search_history_alert">Изтрий цялата история на търсенията.</string>
<string name="search_history_deleted">Историята на търсенията е изтрита.</string>
<string name="youtube_signature_decryption_error">URL подписът на видеото не можа да бъде дешифрован</string>
<string name="youtube_signature_decryption_error">URL подписът на клипа не можа да бъде дешифрован</string>
<string name="external_player_unsupported_link_type">Външните плейъри не поддържат този вид линкове</string>
<string name="invalid_url_toast">Невалиден URL</string>
<string name="invalid_directory">Невалидна директория</string>
@ -272,16 +270,195 @@
<string name="toast_no_player">Няма инсталирано приложение, което да изпълни този файл</string>
<string name="copyright" formatted="true">© %1$s от %2$s под лиценза %3$s</string>
<string name="contribution_title">Направи принос</string>
<string name="contribution_encouragement">За всичко, което се сетите: превод, промени по дизайна, изчистване на кода или много сериозни промени по кода помощта е винаги добре дошла. Колкото повече се прави по това, толкова по-добре се получава.</string>
<string name="donation_title">Направи дарение</string>
<string name="donation_encouragement">NewPipe се разработва от доброволни разработчици, което отделят от своето време, за да ви доставят най-доброто преживяване. Дайте от себе си, за да помогнете на разработчиците да направят NewPipe още по-добро приложение, докато се наслаждават на едно кафе от вас.</string>
<string name="contribution_title">Съдействайте</string>
<string name="contribution_encouragement">За всичко, което се сетите: превод, промени по дизайна, изчистване на кода или много сериозни промени по кода помощта е винаги добре дошла. Колкото повече развитие, толкова по-добре!</string>
<string name="donation_title">Направете дарение</string>
<string name="donation_encouragement">NewPipe се разработва от доброволци, които отделят от своето време, за да ви доставят най-доброто преживяване. Дайте от себе си в замяна, за да помогнете на разработчиците да направят NewPipe още по-добро приложение, докато се наслаждават на едно кафе от вас.</string>
<string name="give_back">Дари</string>
<string name="website_title">Уебсайт</string>
<string name="website_encouragement">Посетете сайта на NewPipe за повече информация и новини.</string>
<string name="privacy_policy_title">Политиката на NewPipe за личните данни</string>
<string name="privacy_policy_encouragement">Проектът NewPipe се отнася много сериозно към вашата поверителност. За това, приложението не събира никакви данни без вашето съгласие.
\nНашата политика за личните данни обяснява подробно какви данни изпращате и къде се съхраняват, когато изпращате съобщения за грешки.</string>
<string name="read_privacy_policy">Прочетет нашата политика за поверителност</string>
<string name="read_privacy_policy">Прочетете нашата политика за поверителност</string>
<string name="app_license_title">Лицензът на NewPipe</string>
<string name="no_player_found_toast">Липсва стрийм плейър (можете да изтеглите VLC, за да пуснете стрийма)</string>
<string name="download_thumbnail_summary">Изключете, за да спрете зареждането на всички миниатюри, спестявайки трафик и памет. При промяна на тази настройка, текущата кеш-памет на изображенията ще бъде изтрита.</string>
<string name="show_hold_to_append_summary">Показвай подсказка, когато е избран фонов режим или режим в прозорец на страницата с детайли на съответния клип</string>
<string name="clear_views_history_summary">Изтрива историята на възпроизвежданите стриймове.</string>
<string name="video_streams_empty">Не са намерени видео стриймове</string>
<string name="audio_streams_empty">Не са намерени аудио стриймове</string>
<string name="info_labels">"Какво:\\nЗаявка:\\nЕзик на съдържанието:\\nУслуга:\\nВреме по GMT:\\nПакет:\\nВерсия:\\nОС версия: "</string>
<string name="list_thumbnail_view_description">Миниатюра на видео</string>
<string name="user_report">Потребителски доклад</string>
<string name="detail_drag_description">Пренареди чрез плъзгане</string>
<string name="start">Начало</string>
<string name="delete_one">Изтрий един</string>
<string name="rename">Преименувай</string>
<string name="add">Нова цел</string>
<string name="no_available_dir">Моля, изберете достъпна папка за изтегляния</string>
<string name="msg_popup_permission">Това разрешение се изисква за
\nвъзпроизвеждане в отделен прозорец</string>
<string name="one_item_deleted">1 елемент е изтрит.</string>
<string name="reCaptchaActivity">reCAPTCHA</string>
<string name="reCaptcha_title">reCAPTCHA заявка</string>
<string name="recaptcha_request_toast">Изисква се въвеждане на reCAPTCHA</string>
<string name="settings_category_downloads_title">Изтегляне</string>
<string name="charset_most_special_characters">Повечето специални символи</string>
<string name="app_license">NewPipe е безплатен „copyleft“ софтуер: Можете да го използвате, изучавате, споделяте и подобрявате по ваше усмотрение. В частност, Вие можете да препубликувате и/или модифицирате приложението според правилата на Главния обществен лиценз на ГНУ, издаден от Фондацията за свободен софтуер версия 3 на лиценза или по-нова.</string>
<string name="read_full_license">Прочетете лиценза</string>
<string name="title_activity_history">История</string>
<string name="title_history_search">Търсения</string>
<string name="title_history_view">Гледани</string>
<string name="history_disabled">Историята е изключена</string>
<string name="action_history">История</string>
<string name="history_empty">Историята е празна</string>
<string name="history_cleared">Историята е изчистена</string>
<string name="item_deleted">Елементът е изтрит</string>
<string name="delete_item_search_history">Искате ли да изтриете този елемент от историята на търсенията?</string>
<string name="delete_stream_history_prompt">Искате ли да изтриете този елемент от историята на гледанията?</string>
<string name="delete_all_history_prompt">Окончателно ли искате да изтриете всички елементи от историята на гледанията?</string>
<string name="title_last_played">Последно възпроизвеждани</string>
<string name="title_most_played">Най-възпроизвеждани</string>
<string name="main_page_content">Съдържание на главната страница</string>
<string name="blank_page_summary">Празна страница</string>
<string name="kiosk_page_summary">Страница-павилион</string>
<string name="subscription_page_summary">Страница с абонаменти</string>
<string name="feed_page_summary">Страница с акценти от вашите абонаменти</string>
<string name="channel_page_summary">Страница на определен канал</string>
<string name="select_a_channel">Изберете канал</string>
<string name="no_channel_subscribed_yet">За момента нямате абонаменти</string>
<string name="select_a_kiosk">Изберете павилион</string>
<string name="export_complete_toast">Експортирането приключи</string>
<string name="import_complete_toast">Импортирането приключи</string>
<string name="no_valid_zip_file">Невалиден ZIP файл</string>
<string name="could_not_import_all_files">Внимание: не всички файлове бяха импортирани успешно.</string>
<string name="override_current_data">Това ще замени текущата Ви инсталация.</string>
<string name="import_settings">Желаете ли също да импортирате настройките?</string>
<string name="kiosk">Павилион</string>
<string name="trending">Набиращи популярност</string>
<string name="top_50">Топ 50</string>
<string name="new_and_hot">Ново и горещо</string>
<string name="title_activity_background_player">Във фонов режим</string>
<string name="title_activity_popup_player">В прозорец</string>
<string name="play_queue_remove">Премахни</string>
<string name="play_queue_stream_detail">Детайли</string>
<string name="play_queue_audio_settings">Аудио настройки</string>
<string name="hold_to_append">Задръжте, за да поставите на опашката</string>
<string name="enqueue_on_background">На опашката във „фонов режим“</string>
<string name="enqueue_on_popup">На опашката в „режим в прозорец“</string>
<string name="start_here_on_main">Възпроизвеждане от тук</string>
<string name="start_here_on_background">Възпроизвеждане от тук във фонов режим</string>
<string name="start_here_on_popup">Възпроизвеждане от тук в прозорец</string>
<string name="drawer_open">Отвори навигационната лента</string>
<string name="drawer_close">Затвори навигационната лента</string>
<string name="drawer_header_action_paceholder_text">Тук нещо ще се появи скоро ;D</string>
<string name="preferred_open_action_settings_title">Действие при повикване от друго приложение</string>
<string name="preferred_open_action_settings_summary">Действие по подразбиране при отваряне на съдържание — %s</string>
<string name="video_player">Видео плейър</string>
<string name="background_player">Във фонов режим</string>
<string name="popup_player">В прозорец</string>
<string name="always_ask_open_action">Винаги питай</string>
<string name="preferred_player_fetcher_notification_title">Получаване на инфо…</string>
<string name="preferred_player_fetcher_notification_message">Зареждане на заявеното съдържание</string>
<string name="create_playlist">Създай Нов Плейлист</string>
<string name="delete_playlist">Изтрий Плейлист</string>
<string name="rename_playlist">Преименувай Прелист</string>
<string name="playlist_name_input">Име</string>
<string name="append_playlist">Добави Към Плейлист</string>
<string name="set_as_playlist_thumbnail">Задай като миниатюра на плейлиста</string>
<string name="bookmark_playlist">Миниатюрата на плейлиста е сменена</string>
<string name="unbookmark_playlist">Премахни отметката</string>
<string name="delete_playlist_prompt">Искате ли да изтриете този плейлист?</string>
<string name="playlist_creation_success">Плейлистът е създаден</string>
<string name="playlist_add_stream_success">Добавено към плейлист</string>
<string name="playlist_thumbnail_change_success">Миниатюрата на плейлиста е сменена</string>
<string name="playlist_delete_failure">Плейлистът не можа да бъде изтрит</string>
<string name="caption_none">Без надписи</string>
<string name="resize_fit">Приспособи</string>
<string name="resize_fill">Запълни</string>
<string name="resize_zoom">Увеличи</string>
<string name="caption_auto_generated">Авто-генерирани</string>
<string name="caption_setting_title">Надписи</string>
<string name="caption_setting_description">Модифицирай мащаба на текста и фона на надписите. Изисква рестарт на приложението, за да се приложат промените.</string>
<string name="enable_leak_canary_title">Включи LeakCanary</string>
<string name="enable_leak_canary_summary">Следенето за пропускане на памет може да направи приложението нестабилно</string>
<string name="enable_disposed_exceptions_title">Докладвай за извънредни грешки</string>
<string name="import_export_title">Импортиране/експортиране</string>
<string name="import_title">Импортирай</string>
<string name="import_from">Импортирай от</string>
<string name="export_to">Експортирай в</string>
<string name="import_ongoing">Импортиране…</string>
<string name="export_ongoing">Експортиране…</string>
<string name="import_file_title">Файл с данни за импортиране</string>
<string name="previous_export">Предишно експортиране</string>
<string name="subscriptions_import_unsuccessful">Неуспешно импортиране на абонатите</string>
<string name="subscriptions_export_unsuccessful">Неуспешно експортиране на абонатите</string>
<string name="import_youtube_instructions">Импортирайте YouTube абонаментите, чрез изтегляне на нужния файл:
\n
\n1. Посетете тази връзка: %1$s
\n2. Влезте в акаунта си, когато това се изиска
\n3. Изтеглянето трябва да започне (това е експортирания файл)</string>
<string name="import_soundcloud_instructions">Импортирайте SoundCloud профил чрез въвеждане на хипервръзката към него или чрез вашия ID:
\n
\n1. Включете „десктоп режим“ в браузър (сайтът е недостъпен за мобилни устройства)
\n2. Посетете връзката: %1$s
\n3. Влезте в профила си, ако се изисква
\n4. Копирайте хипервръзката на профилната страница, към която сте насочени.</string>
<string name="import_soundcloud_instructions_hint">вашиятID, soundcloud.com/вашиятID</string>
<string name="import_network_expensive_warning">Това действие може да изразходва голямо количество данни от вашия трафик.
\n
\nЖелаете ли да продължите?</string>
<string name="playback_speed_control">Управление скоростта на възпроизвеждане</string>
<string name="playback_tempo">Темпо</string>
<string name="playback_pitch">Височина</string>
<string name="skip_silence_checkbox">Бързо превъртане при тишина</string>
<string name="start_accept_privacy_policy">От съображения към Общия европейски регламент относно защитата на данните, Ви привличаме вниманието към политиката за поверителност на NewPipe. Моля, прочетете я внимателно.
\nТрябва да сте съгласни с условията, за да ни изпратите доклада за грешката.</string>
<string name="accept">Приеми</string>
<string name="decline">Откажи</string>
<string name="limit_data_usage_none_description">Без ограничения</string>
<string name="limit_mobile_data_usage_title">Ограничена резолюция при мобилни данни</string>
<string name="minimize_on_exit_title">Минимизирай при преход към друго приложение</string>
<string name="minimize_on_exit_summary">Действие при преминаване към друго приложение от видео плейъра — %s</string>
<string name="minimize_on_exit_none_description">Без минимизиране</string>
<string name="minimize_on_exit_background_description">Минимизирай във фонов режим</string>
<string name="minimize_on_exit_popup_description">Минимизирай в прозорец</string>
<string name="channels">Канали</string>
<string name="playlists">Плейлисти</string>
<string name="tracks">Песни</string>
<string name="users">Потребители</string>
<string name="playback_reset">Възстанови</string>
</resources>

View File

@ -46,8 +46,6 @@
<string name="play_audio">অডিও</string>
<string name="default_audio_format_title">ডিফল্ট অডিও ফরম্যাট</string>
<string name="default_video_format_title">পছন্দসই ভিডিও ফরম্যাট</string>
<string name="webm_description">WebM — বিনামূল্য/স্বাধীন ফরম্যাট</string>
<string name="m4a_description">m4a — ভালো মানের</string>
<string name="theme_title">থিম</string>
<string name="light_theme_title">উজ্জ্বল</string>
<string name="dark_theme_title">অন্ধকার</string>

View File

@ -23,8 +23,6 @@
<string name="play_audio">Àudio</string>
<string name="default_audio_format_title">Format d\'àudio per defecte</string>
<string name="default_video_format_title">Format de vídeo per defecte</string>
<string name="webm_description">WebM — format lliure</string>
<string name="m4a_description">M4A — millor qualitat</string>
<string name="theme_title">Tema</string>
<string name="light_theme_title">Clar</string>
<string name="dark_theme_title">Fosc</string>
@ -61,7 +59,7 @@
<string name="import_data_title">Importa una base de dades</string>
<string name="export_data_title">Exporta una base de dades</string>
<string name="export_data_summary">Exporta l\'historial, les subscripcions i les llistes de reproducció.</string>
<string name="export_data_summary">Exporta l\'historial, les subscripcions i les llistes de reproducció</string>
<string name="general_error">Error</string>
<string name="network_error">Error de xarxa</string>
<string name="video">Vídeo</string>
@ -226,7 +224,7 @@
<string name="detail_likes_img_view_description">M\'agrada</string>
<string name="detail_dislikes_img_view_description">No m\'agrada</string>
<string name="use_tor_title">Fes servir el Tor</string>
<string name="use_tor_summary">(En proves) Força el trànsit de baixada a través del Tot per a més privadesa (no compatible encara amb les emissions de vídeo).</string>
<string name="use_tor_summary">(En proves) Força el trànsit de baixada a través del Tor per a més privadesa (no compatible encara amb les emissions de vídeo).</string>
<string name="report_error">Informa sobre un error</string>
<string name="user_report">Informe de l\'usuari</string>
<string name="search_no_results">Cap resultat</string>
@ -310,7 +308,7 @@
<string name="main_bg_subtitle">Toqueu el botó de cerca per començar</string>
<string name="use_external_video_player_summary">En algunes resolucions NO hi haurà àudio quan aquesta opció estigui activada</string>
<string name="use_external_audio_player_title">Reproductor d\'àudio extern</string>
<string name="download_thumbnail_summary">Desactiveu-ho per evitar que es carreguin les miniatures i estalviar dades i memòria. Si canvieu aquesta opció, s\'esborrarà la memòria cau d\'imatges tant de la memòria com de l\'emmagatzematge.</string>
<string name="download_thumbnail_summary">Desactiveu-ho per evitar que es carreguin les miniatures i estalviar dades i memòria. Si canvieu aquesta opció, s\'esborrarà la memòria cau d\'imatges tant de la memòria com de l\'emmagatzematge</string>
<string name="enable_search_history_summary">Emmagatzema les cerques localment</string>
<string name="enable_watch_history_summary">Registra els vídeos visualitzats</string>
<string name="resume_on_audio_focus_gain_title">Reprèn automàticament</string>
@ -390,7 +388,7 @@
<string name="unhook_checkbox">Desvincula (pot provocar distorsió)</string>
<string name="playback_nightcore">Nightcore</string>
<string name="metadata_cache_wipe_summary">Elimina totes les dades de llocs web de la memòria cau</string>
<string name="auto_queue_summary">Afegeix a la cua un vídeo relacionat quan es reprodueix l\'últim vídeo en una cua sense repetició.</string>
<string name="auto_queue_summary">Afegeix a la cua un vídeo relacionat quan es reprodueix l\'últim vídeo en una cua sense repetició</string>
<string name="show_hold_to_append_title">Mostra els missatges d\'ajuda</string>
<string name="show_hold_to_append_summary">Mostra un missatge d\'ajuda quan el botó de mode en segon pla o emergent estigui premut a la pàgina de detalls d\'un vídeo</string>
<string name="info_labels">Què ha passat:\\nPetició:\\nIdioma del contingut:\\nServei:\\nHora GMT:\\nPaquet:\\nVersió:\\nVersió del SO:</string>
@ -425,17 +423,17 @@
<string name="no_streams_available_download">No hi ha vídeos que es puguin baixar</string>
<string name="caption_setting_title">Subtítols</string>
<string name="caption_setting_description">Modifica la mida del text i el fons dels subtítols. Cal reiniciar l\'aplicació per aplicar els canvis.</string>
<string name="caption_setting_description">Modifica la mida del text i el fons dels subtítols. Cal reiniciar l\'aplicació per aplicar els canvis</string>
<string name="toast_no_player">No s\'ha trobat cap aplicació que pugui reproduir aquest fitxer</string>
<string name="clear_views_history_title">Esborra l\'historial de reproduccions</string>
<string name="clear_views_history_summary">Esborra l\'historial dels vídeos que s\'han reproduït.</string>
<string name="delete_view_history_alert">Esborra tot l\'historial de reproduccions.</string>
<string name="clear_views_history_summary">Esborra l\'historial dels vídeos que s\'han reproduït</string>
<string name="delete_view_history_alert">Esborra tot l\'historial de reproduccions</string>
<string name="view_history_deleted">S\'ha esborrat l\'historial de reproduccions.</string>
<string name="clear_search_history_title">Esborra l\'historial de cerca</string>
<string name="clear_search_history_summary">Esborra l\'historial de paraules cercades.</string>
<string name="delete_search_history_alert">Esborra tot l\'historial de cerca.</string>
<string name="clear_search_history_summary">Esborra l\'historial de paraules cercades</string>
<string name="delete_search_history_alert">Esborra tot l\'historial de cerca</string>
<string name="search_history_deleted">S\'ha esborrat l\'historial de cerca.</string>
<string name="one_item_deleted">S\'ha esborrat 1 element.</string>
@ -452,4 +450,18 @@
<string name="decline">Rebutja</string>
<string name="limit_data_usage_none_description">Sense restriccions</string>
<string name="limit_mobile_data_usage_title">Restringeix la resolució quan es facin servir dades mòbils</string>
<string name="minimize_on_exit_title">Minimitza en canviar d\'aplicació</string>
<string name="minimize_on_exit_summary">Acció en canviar a una altra aplicació des del reproductor de vídeo principal — %s</string>
<string name="minimize_on_exit_none_description">Cap</string>
<string name="minimize_on_exit_background_description">Minimitza al reproductor en segon pla</string>
<string name="minimize_on_exit_popup_description">Minimitza al reproductor emergent</string>
<string name="skip_silence_checkbox">Avança ràpid durant el silenci</string>
<string name="playback_step">Pas</string>
<string name="playback_reset">Reinicialitza</string>
<string name="channels">Canals</string>
<string name="playlists">Llistes de reproducció</string>
<string name="tracks">Pistes</string>
<string name="users">Usuaris</string>
</resources>

View File

@ -23,4 +23,100 @@
<string name="popup_mode_share_menu_title">NewPipe弹出模式</string>
<string name="subscribe_button_title">订阅</string>
<string name="subscribed_button_title">订阅</string>
<string name="channel_unsubscribed">取消订阅成功</string>
<string name="subscription_change_failed">无法更改订阅</string>
<string name="subscription_update_failed">无法更新订阅</string>
<string name="show_info">显示详情</string>
<string name="tab_main">主页</string>
<string name="tab_subscriptions">订阅</string>
<string name="tab_bookmarks">书签</string>
<string name="fragment_whats_new">新功能</string>
<string name="controls_background_title">后台</string>
<string name="controls_popup_title">弹出窗口</string>
<string name="controls_add_to_playlist_title">添加到</string>
<string name="download_path_title">视频下载路径</string>
<string name="download_path_summary">储存视频文件的路径</string>
<string name="download_path_dialog_title">输入视频的下载地址</string>
<string name="download_path_audio_title">音频下载路径</string>
<string name="download_path_audio_summary">储存音频的路径</string>
<string name="download_path_audio_dialog_title">输入音频的下载路径</string>
<string name="autoplay_by_calling_app_title">自动播放</string>
<string name="autoplay_by_calling_app_summary">NewPipes被其它程序调用时播放视频</string>
<string name="default_resolution_title">默认分辨率</string>
<string name="default_popup_resolution_title">默认弹出窗口分辨率</string>
<string name="show_higher_resolutions_title">显示更高的分辨率</string>
<string name="show_higher_resolutions_summary">只有部分设备支持播放 2K/4K 视频</string>
<string name="play_with_kodi_title">用 Kodi 播放</string>
<string name="kore_not_found">没找到 Kore 应用,需要安装它吗?</string>
<string name="show_play_with_kodi_title">显示“用 Kodi 播放”选项</string>
<string name="show_play_with_kodi_summary">显示用 Kodi媒体中心 播放视频的选项</string>
<string name="play_audio">音频</string>
<string name="default_audio_format_title">默认音频格式</string>
<string name="default_video_format_title">默认视频格式</string>
<string name="theme_title">主题</string>
<string name="light_theme_title">亮色</string>
<string name="dark_theme_title">酷黑</string>
<string name="black_theme_title">黑色</string>
<string name="popup_remember_size_pos_title">记住弹出窗口的尺寸与位置</string>
<string name="popup_remember_size_pos_summary">记住上一次弹出窗口的位置以及大小</string>
<string name="thumbnail_cache_wipe_complete_notice">清理照片内存</string>
<string name="minimize_on_exit_popup_description">最小化弹出播放器</string>
<string name="clear_views_history_title">清楚观看历史</string>
<string name="search_history_deleted">已删除搜索历史</string>
<string name="general_error">错误</string>
<string name="network_error">网络错误</string>
<string name="report_error">举报错误</string>
<string name="search_no_results">没有结果</string>
<string name="start">开始</string>
<string name="pause">暂停</string>
<string name="view">播放</string>
<string name="create">创建</string>
<string name="delete">删除</string>
<string name="delete_all">删除所有</string>
<string name="add">新任务</string>
<string name="finish">
\n</string>
<string name="msg_error">错误
\n</string>
<string name="msg_server_unsupported">服务器无法支持</string>
<string name="msg_exists">文件已存在</string>
<string name="msg_running">NewPipe 下载中</string>
<string name="msg_wait">请稍等…</string>
<string name="charset_letters_and_digits">字母与数字</string>
<string name="charset_most_special_characters">最特别的字符</string>
<string name="toast_no_player">这个文件里没有已下载应用程式</string>
<string name="title_activity_about">关于NewPipe</string>
<string name="action_settings">设置</string>
<string name="action_about">关于</string>
<string name="title_licenses">第三方执照</string>
<string name="action_open_website">打开网页</string>
<string name="unbookmark_playlist">删除书签</string>
<string name="delete_playlist_prompt">请问你要删除这个列表吗?</string>
<string name="playlist_creation_success">已创建播放列表</string>
<string name="playlist_add_stream_success">已加入播放列表</string>
<string name="playback_step">步骤</string>
<string name="playback_reset">重置</string>
<string name="start_accept_privacy_policy">为了遵守欧洲通用数据保护法规GDPR,我们请你注意NewPipe的隐私政策.请仔细阅读.
\n你必须接受它才能将错误报告发送给我们.</string>
<string name="accept">接受</string>
<string name="decline">拒绝</string>
<string name="limit_data_usage_none_description">没有限制</string>
<string name="limit_mobile_data_usage_title">使用移动数据时的解析度限制</string>
<string name="minimize_on_exit_title">最小化应用程序切换</string>
<string name="minimize_on_exit_summary">从主视频播放器切换到其他应用程序时的操作 - %s</string>
<string name="minimize_on_exit_none_description">没有</string>
<string name="minimize_on_exit_background_description">最小化背景播放器</string>
</resources>

View File

@ -32,8 +32,6 @@
<string name="show_play_with_kodi_summary">Zobrazit možnost přehrání videa pomocí multimediálního centra Kodi</string>
<string name="play_audio">Zvuk</string>
<string name="default_audio_format_title">Výchozí formát zvuku</string>
<string name="webm_description">WebM — volný formát</string>
<string name="m4a_description">M4A — lepší kvalita</string>
<string name="theme_title">Téma</string>
<string name="dark_theme_title">Tmavé</string>
<string name="light_theme_title">Světlé</string>

View File

@ -24,8 +24,6 @@
<string name="show_play_with_kodi_summary">Zeigt eine Option an, über die man Videos mit Kodi abspielen kann</string>
<string name="play_audio">Audio</string>
<string name="default_audio_format_title">Bevorzugtes Audioformat</string>
<string name="webm_description">WebM — freies Format</string>
<string name="m4a_description">M4A — bessere Qualität</string>
<string name="download_dialog_title">Herunterladen</string>
<string name="next_video_title">Nächstes Video</string>
<string name="show_next_and_similar_title">\'Nächste\' und \'ähnliche\' Videos anzeigen</string>
@ -329,7 +327,7 @@
<string name="import_data_title">Datenbank importieren</string>
<string name="export_data_title">Datenbank exportieren</string>
<string name="import_data_summary">Wird deinen Verlauf und deine Abos überschreiben</string>
<string name="export_data_summary">Verlauf, Abos und Wiedergabelisten exportieren.</string>
<string name="export_data_summary">Verlauf, Abos und Wiedergabelisten exportieren</string>
<string name="no_valid_zip_file">Keine gültige ZIP-Datei</string>
<string name="could_not_import_all_files">Warnung: Nicht alle Dateien konnten importiert werden.</string>
<string name="override_current_data">Dies wird deine aktuellen Einstellungen überschreiben.</string>
@ -418,12 +416,12 @@
<string name="playback_speed_control">Wiedergabegeschwindigkeitsregler</string>
<string name="playback_tempo">Geschwindigkeit</string>
<string name="playback_pitch">Tonhöhe</string>
<string name="unhook_checkbox">Aushaken (kann zu Verzerrungen führen)</string>
<string name="unhook_checkbox">Verknüpfung aufheben (kann zu Verzerrungen führen)</string>
<string name="playback_nightcore">Nightcore</string>
<string name="playback_default">Standard</string>
<string name="download_thumbnail_summary">Deaktiviere diese Option, um das Laden aller Miniaturansichten zu stoppen und Daten und Speicherverbrauch zu sparen. Wenn du dies änderst, wird sowohl der In-Memory- als auch der On-Disk-Image-Cache gelöscht.</string>
<string name="download_thumbnail_summary">Deaktiviere diese Option, um das Laden aller Miniaturansichten zu stoppen und Daten und Speicherverbrauch zu sparen. Wenn du dies änderst, wird sowohl der In-Memory- als auch der On-Disk-Image-Cache gelöscht</string>
<string name="auto_queue_title">Nächsten Stream automatisch einreihen</string>
<string name="auto_queue_summary">Automatisches Anhängen eines verwandten Streams beim Abspielen des letzten Streams in einer nicht wiederholten Warteschlange.</string>
<string name="auto_queue_summary">Automatisches Anhängen eines verwandten Streams beim Abspielen des letzten Streams in einer nicht wiederholten Warteschlange</string>
<string name="drawer_header_action_paceholder_text">Hier wird bald etwas stehen ;D</string>
@ -456,17 +454,17 @@
<string name="preferred_open_action_settings_summary">Standardaktion beim Öffnen von Inhalten - %s</string>
<string name="caption_setting_title">Untertitel</string>
<string name="caption_setting_description">Ändere Textgröße und Hintergrundstil des Untertitels im Player. Wird erst nach Neustart des App wirksam.</string>
<string name="caption_setting_description">Ändere Textgröße und Hintergrundstil des Untertitels im Player. Wird erst nach Neustart des App wirksam</string>
<string name="toast_no_player">Keine App zum Abspielen dieser Datei installiert</string>
<string name="clear_views_history_title">Verlauf leeren</string>
<string name="clear_views_history_summary">Löscht den Verlauf der abgespielten Streams.</string>
<string name="delete_view_history_alert">Löscht den ganzen Verlauf.</string>
<string name="clear_views_history_summary">Löscht den Verlauf der abgespielten Streams</string>
<string name="delete_view_history_alert">Löscht den ganzen Verlauf</string>
<string name="view_history_deleted">Verlauf gelöscht.</string>
<string name="clear_search_history_title">Suchverlauf löschen</string>
<string name="clear_search_history_summary">Lösche Verlauf der Suchschlüsselwörter.</string>
<string name="delete_search_history_alert">Lösche gesamten Suchverlauf.</string>
<string name="clear_search_history_summary">Lösche Verlauf der Suchschlüsselwörter</string>
<string name="delete_search_history_alert">Lösche gesamten Suchverlauf</string>
<string name="search_history_deleted">Suchverlauf gelöscht.</string>
<string name="one_item_deleted">1 Element gelöscht.</string>
@ -483,4 +481,18 @@
\nDu musst den Datenschutzrichtlinien zustimmen, um den Fehlerbericht an uns zu senden.</string>
<string name="limit_data_usage_none_description">Unbegrenzt</string>
<string name="limit_mobile_data_usage_title">Auflösung bei Verwendung mobiler Daten begrenzen</string>
<string name="minimize_on_exit_title">Minimieren beim Anwendungswechsel</string>
<string name="minimize_on_exit_summary">Aktion beim Umschalten auf eine andere Anwendung vom Haupt-Videoplayer - %s</string>
<string name="minimize_on_exit_none_description">Keine</string>
<string name="minimize_on_exit_background_description">Zum Hintergrund-Player minimieren</string>
<string name="minimize_on_exit_popup_description">Zum Popup-Player minimieren</string>
<string name="skip_silence_checkbox">Vorspulen während der Stille</string>
<string name="playback_step">Schritt</string>
<string name="playback_reset">Zurücksetzen</string>
<string name="channels">Kanäle</string>
<string name="playlists">Wiedergabelisten</string>
<string name="tracks">Titel</string>
<string name="users">Nutzer</string>
</resources>

View File

@ -32,8 +32,6 @@
<string name="show_play_with_kodi_summary">Προβολή μιας επιλογής για αναπαραγωγή με το Kodi media center.</string>
<string name="play_audio">Ήχος</string>
<string name="default_audio_format_title">Προεπιλεγμένη μορφή ήχου</string>
<string name="webm_description">WebM — δωρεάν format</string>
<string name="m4a_description">m4a — καλύτερη ποιότητα</string>
<string name="theme_title">Θέμα</string>
<string name="dark_theme_title">Σκοτεινό</string>
<string name="light_theme_title">Φωτεινό</string>
@ -62,4 +60,43 @@
<string name="info_dir_created">Δημιουργήθηκε ο φάκελος \'%1$s\'</string>
<string name="short_billion">Δ</string>
<string name="open_in_popup_mode">Άνοιγμα σε αναδυόμενο παράθυρο</string>
<string name="subscribe_button_title">Εγγραφή</string>
<string name="subscribed_button_title">Εγγεγραμμένος</string>
<string name="show_higher_resolutions_summary">Μόνο μερικές συσκευές υποστηρίζουν την αναπαραγωγή 2K/4K βίντεο</string>
<string name="black_theme_title">Μαύρο</string>
<string name="show_search_suggestions_title">Προτάσεις αναζήτησης</string>
<string name="enable_search_history_title">Ιστορικό αναζήτησης</string>
<string name="downloads">Λήψεις</string>
<string name="downloads_title">Λήψεις</string>
<string name="all">Όλα</string>
<string name="channel">Κανάλι</string>
<string name="yes">Ναι</string>
<string name="later">Αργότερα</string>
<string name="filter">Φίλτρο</string>
<string name="general_error">Σφάλμα</string>
<string name="error_snackbar_action">ΑΝΑΦΟΡΑ</string>
<string name="what_device_headline">Πληροφορίες:</string>
<string name="what_happened_headline">Τι συνέβη:</string>
<string name="your_comment">Το σχόλιό σας (στα Αγγλικά):</string>
<string name="error_details_headline">Λεπτομέρειες:</string>
<string name="report_error">Αναφορά Σφάλματος</string>
<string name="video">Βίντεο</string>
<string name="audio">Ήχος</string>
<string name="pause">Παύση</string>
<string name="delete">Διαγραφή</string>
<string name="msg_error">Σφάλμα</string>
<string name="msg_exists">Το αρχείο υπάρχει ήδη</string>
<string name="msg_running_detail">Πατήστε για λεπτομέρειες</string>
<string name="settings_category_downloads_title">Λήψη</string>
<string name="charset_letters_and_digits">Γράμματα και ψηφία</string>
<string name="action_settings">Ρυθμίσεις</string>
<string name="action_open_website">Άνοιγμα ιστοσελίδας</string>
<string name="tab_licenses">Άδειες</string>
<string name="title_activity_history">Ιστορικό</string>
<string name="action_history">Ιστορικό</string>
<string name="show_info">Εμφάνιση πληροφοριών</string>
</resources>

View File

@ -21,8 +21,6 @@
<string name="show_play_with_kodi_title">Montri \"Ludi per Kodi\"-opcion</string>
<string name="play_audio">Sono</string>
<string name="default_audio_format_title">Defaŭlta sondosierformo</string>
<string name="webm_description">WebM — libera dosierformo</string>
<string name="m4a_description">m4a — pli bona kvalito</string>
<string name="theme_title">Etoso</string>
<string name="dark_theme_title">Malluma</string>
<string name="light_theme_title">Luma</string>

View File

@ -24,8 +24,6 @@
<string name="show_play_with_kodi_summary">Mostrar una opción para reproducir vídeo con Kodi Media Center</string>
<string name="play_audio">Audio</string>
<string name="default_audio_format_title">Formato de audio por defecto</string>
<string name="webm_description">WebM — formato libre</string>
<string name="m4a_description">M4A — mejor calidad</string>
<string name="download_dialog_title">Descargar</string>
<string name="next_video_title">Siguiente vídeo</string>
<string name="url_not_supported_toast">URL no soportada</string>
@ -330,7 +328,7 @@ abrir en modo popup</string>
<string name="import_data_title">Importar base de datos</string>
<string name="export_data_title">Exportar base de datos</string>
<string name="import_data_summary">Reemplazará su historial actual y sus suscripciones</string>
<string name="export_data_summary">Exportar historial, suscripciones y listas de reproducción.</string>
<string name="export_data_summary">Exportar historial, suscripciones y listas de reproducción</string>
<string name="export_complete_toast">Exportación completa</string>
<string name="import_complete_toast">Importación completa</string>
<string name="no_valid_zip_file">Archivo ZIP no válido</string>
@ -403,7 +401,7 @@ abrir en modo popup</string>
<string name="use_inexact_seek_title">Usar búsqueda rápida inexacta</string>
<string name="use_inexact_seek_summary">La búsqueda inexacta permite al reproductor buscar posiciones más rápido con menor precisión</string>
<string name="auto_queue_title">Auto-encolar la siguiente transmisión</string>
<string name="auto_queue_summary">Auto-añadir un vídeo relacionado al reproducir el último vídeo en una cola no repetitiva.</string>
<string name="auto_queue_summary">Auto-añadir un vídeo relacionado al reproducir el último vídeo en una cola no repetitiva</string>
<string name="live">DIRECTO</string>
<string name="live_sync">SINCRONIZAR</string>
<string name="file">Archivo</string>
@ -445,7 +443,7 @@ abrir en modo popup</string>
\n
\n¿Desea continuar?</string>
<string name="download_thumbnail_title">Cargar Miniaturas</string>
<string name="download_thumbnail_summary">Descativar todas las miniaturas para evitar que se carguen, guarden datos y usen memoria. Al cambiar esto se borrarán tanto la caché de imágenes en la memoria como en el disco.</string>
<string name="download_thumbnail_summary">Descativar todas las miniaturas para evitar que se carguen, guarden datos y usen memoria. Al cambiar esto se borrarán tanto la caché de imágenes en la memoria como en el disco</string>
<string name="thumbnail_cache_wipe_complete_notice">Caché de imagen limpiado</string>
<string name="metadata_cache_wipe_title">Metadatos eliminados del caché</string>
<string name="metadata_cache_wipe_summary">Eliminar todos los datos de la página web en caché</string>
@ -453,7 +451,7 @@ abrir en modo popup</string>
<string name="playback_speed_control">Controles de velocidad de reproducción</string>
<string name="playback_tempo">Tiempo</string>
<string name="playback_pitch">Tono</string>
<string name="unhook_checkbox">Desenganchar (puede casusar distorsión)</string>
<string name="unhook_checkbox">Desenganchar (puede causar distorsión)</string>
<string name="playback_nightcore">Nightcore (tipo de música)</string>
<string name="playback_default">Reproducción por defecto</string>
<string name="no_streams_available_download">No hay streams disponibles para descargar</string>
@ -464,15 +462,15 @@ abrir en modo popup</string>
<string name="toast_no_player">No hay ninguna app instalada para reproducir este archivo</string>
<string name="caption_setting_title">Subtítulos</string>
<string name="caption_setting_description">Modificar la escala de texto de los subtítulos y los estilos de fondo del reproductor. Requiere el reinicio de la app para que surta efecto.</string>
<string name="caption_setting_description">Modificar la escala de texto de los subtítulos y los estilos de fondo del reproductor. Requiere el reinicio de la app para que surta efecto</string>
<string name="clear_views_history_title">Borrar historial de reproducciones</string>
<string name="clear_views_history_summary">Elimina el historial de las transmisiones reproducidas.</string>
<string name="delete_view_history_alert">Elimina todo el historial de reproducciones.</string>
<string name="clear_views_history_summary">Elimina el historial de las transmisiones reproducidas</string>
<string name="delete_view_history_alert">Elimina todo el historial de reproducciones</string>
<string name="view_history_deleted">Historial de reproducciones eliminado.</string>
<string name="clear_search_history_title">Borrar historial de búsqueda</string>
<string name="clear_search_history_summary">Elimina el historial de palabras clave de búsqueda.</string>
<string name="delete_search_history_alert">Elimina todo el historial de búsqueda.</string>
<string name="clear_search_history_summary">Elimina el historial de palabras clave de búsqueda</string>
<string name="delete_search_history_alert">Elimina todo el historial de búsqueda</string>
<string name="search_history_deleted">Historial de búsquedas eliminado.</string>
<string name="one_item_deleted">1 elemento eliminado.</string>
@ -488,4 +486,18 @@ abrir en modo popup</string>
<string name="limit_data_usage_none_description">Sin límite</string>
<string name="limit_mobile_data_usage_title">Limitar resolución cuando se use Datos Móviles</string>
<string name="minimize_on_exit_title">Mimimizar al cambiar de aplicación</string>
<string name="minimize_on_exit_summary">Acción de cambiar a otra aplicación desde el reproductor principal</string>
<string name="minimize_on_exit_none_description">Ninguna</string>
<string name="minimize_on_exit_background_description">Minimizar al reproductor de fondo</string>
<string name="minimize_on_exit_popup_description">Minimizar el reproductor emergente</string>
<string name="skip_silence_checkbox">Avance rápido durante el silencio</string>
<string name="playback_step">Paso</string>
<string name="playback_reset">Reiniciar</string>
<string name="channels">Canales</string>
<string name="users">Usuarios</string>
<string name="playlists">Listas de reproducción</string>
<string name="tracks">Pistas</string>
</resources>

View File

@ -58,8 +58,6 @@
<string name="play_audio">Heli</string>
<string name="default_audio_format_title">Heli vaikevorming</string>
<string name="default_video_format_title">Video vaikevorming</string>
<string name="webm_description">WebM — libre vorming</string>
<string name="m4a_description">M4A — parem kvaliteet</string>
<string name="theme_title">Teema</string>
<string name="light_theme_title">Hele</string>
<string name="dark_theme_title">Tume</string>
@ -69,13 +67,13 @@
<string name="use_inexact_seek_title">Kasuta ebatäpset kerimist</string>
<string name="use_inexact_seek_summary">Ebatäpne kerimine lubab pleieril otsida asukohta kiiremini täpsuse arvel</string>
<string name="download_thumbnail_title">Laadi pisipildid</string>
<string name="download_thumbnail_summary">Keela, peatamaks pisipiltide laadimine ja vähenda andme- ja mälukasutust. Selle muutmine puhastab nii sisemälu kui piltide vahemälu andmekandjal.</string>
<string name="download_thumbnail_summary">Keela, peatamaks pisipiltide laadimine ja vähenda andme- ja mälukasutust. Selle muutmine puhastab nii sisemälu kui piltide vahemälu andmekandjal</string>
<string name="thumbnail_cache_wipe_complete_notice">Pildid kustutati vahemälust</string>
<string name="metadata_cache_wipe_title">Kustuta metaandmed vahemälust</string>
<string name="metadata_cache_wipe_summary">Kustuta veebilehtede andmed vahemälust</string>
<string name="metadata_cache_wipe_complete_notice">Metaandmed kustutati vahemälust</string>
<string name="auto_queue_title">Järgmine voog automaatselt järjekorda</string>
<string name="auto_queue_summary">Lisa seotud voog automaatselt, kui esitusel on viimane voog mittekorduvast järjekorrast.</string>
<string name="auto_queue_summary">Lisa seotud voog automaatselt, kui esitusel on viimane voog mittekorduvast järjekorrast</string>
<string name="player_gesture_controls_title">Pleieri juhtimise viiped</string>
<string name="player_gesture_controls_summary">Luba viiped helitugevuse ja ereduse juhtimiseks</string>
<string name="show_search_suggestions_title">Kuva soovitused</string>
@ -143,14 +141,14 @@
<string name="import_data_title">Impordi andmebaas</string>
<string name="export_data_title">Ekspordi andmebaas</string>
<string name="import_data_summary">Alistab praeguse ajaloo ja tellimused</string>
<string name="export_data_summary">Ekspordi ajalugu, tellimused ja pleilistid.</string>
<string name="export_data_summary">Ekspordi ajalugu, tellimused ja pleilistid</string>
<string name="clear_views_history_title">Puhasta vaatamiste ajalugu</string>
<string name="clear_views_history_summary">Kustutab vaadatud voogude ajaloo.</string>
<string name="delete_view_history_alert">Kustuta kogu vaatamiste ajalugu.</string>
<string name="clear_views_history_summary">Kustutab vaadatud voogude ajaloo</string>
<string name="delete_view_history_alert">Kustuta kogu vaatamiste ajalugu</string>
<string name="view_history_deleted">Vaatamiste ajalugu kustutati.</string>
<string name="clear_search_history_title">Kustuta otsinguajalugu</string>
<string name="clear_search_history_summary">Kustutab otsisõnade ajaloo.</string>
<string name="delete_search_history_alert">Kustuta kogu otsinguajalugu.</string>
<string name="clear_search_history_summary">Kustutab otsisõnade ajaloo</string>
<string name="delete_search_history_alert">Kustuta kogu otsinguajalugu</string>
<string name="search_history_deleted">Otsinguajalugu kustutati.</string>
<string name="general_error">Viga</string>
<string name="network_error">Võrgu viga</string>
@ -382,7 +380,7 @@
<string name="caption_auto_generated">Automaatselt loodud</string>
<string name="caption_setting_title">Subtiitrid</string>
<string name="caption_setting_description">Kohanda pleieri subtiitrite teksti suurust ja tausta. Jõustamiseks tuleb rakendus taaskäivitada.</string>
<string name="caption_setting_description">Kohanda pleieri subtiitrite teksti suurust ja tausta. Jõustamiseks tuleb rakendus taaskäivitada</string>
<string name="enable_leak_canary_summary">Mälulekke seire võib põhjustada rakenduse hangumise</string>

View File

@ -22,8 +22,6 @@
<string name="show_play_with_kodi_summary">Erakutsi bideoa Kodi multimedia zentroarekin erreproduzitzeko aukera</string>
<string name="play_audio">Audioa</string>
<string name="default_audio_format_title">Audio formatu lehenetsia</string>
<string name="webm_description">WebM — formatu librea</string>
<string name="m4a_description">M4A — kalitate hobea</string>
<string name="download_dialog_title">Deskargatu</string>
<string name="next_video_title">Hurrengo bideoa</string>
<string name="show_next_and_similar_title">Erakutsi \'hurrengo\' eta \'antzeko\' bideoak</string>
@ -328,21 +326,21 @@
<string name="metadata_cache_wipe_summary">Kendu cache-ko wegbuneen datu guztiak</string>
<string name="metadata_cache_wipe_complete_notice">Metadatuen cache-a ezabatuta</string>
<string name="auto_queue_title">Gehitu ilarara hurrengo jarioa</string>
<string name="auto_queue_summary">Gehitu erlazionatutako jario bat azken jarioa jo bitartean errepikapenik gabeko ilara batean.</string>
<string name="auto_queue_summary">Gehitu erlazionatutako jario bat azken jarioa jo bitartean errepikapenik gabeko ilara batean</string>
<string name="settings_category_debug_title">Arazketa</string>
<string name="file">Fitxategia</string>
<string name="import_data_title">Inportatu datu-basea</string>
<string name="export_data_title">Esportatu datu-basea</string>
<string name="import_data_summary">Zure uneko historiala eta harpidetzak gainidatziko ditu</string>
<string name="export_data_summary">Esportatu historiala, harpidetzak eta erreprodukzio-zerrendak.</string>
<string name="export_data_summary">Esportatu historiala, harpidetzak eta erreprodukzio-zerrendak</string>
<string name="clear_views_history_title">Garbitu ikusitakoaren historiala</string>
<string name="clear_views_history_summary">Jotako jarioen historiala ezabatzen du.</string>
<string name="delete_view_history_alert">Ezabatu ikusitakoaren historial osoa.</string>
<string name="clear_views_history_summary">Jotako jarioen historiala ezabatzen du</string>
<string name="delete_view_history_alert">Ezabatu ikusitakoaren historial osoa</string>
<string name="view_history_deleted">Ikusitakoaren historiala ezabatuta.</string>
<string name="clear_search_history_title">Garbitu bilaketa historiala</string>
<string name="clear_search_history_summary">Ezabatu bilaketa gakoen historiala.</string>
<string name="delete_search_history_alert">Ezabatu bilaketen historial osoa.</string>
<string name="clear_search_history_summary">Ezabatu bilaketa gakoen historiala</string>
<string name="delete_search_history_alert">Ezabatu bilaketen historial osoa</string>
<string name="search_history_deleted">Bilaketen historiala ezabatuta.</string>
<string name="invalid_directory">Direktorio baliogabea</string>
<string name="invalid_source">Fitxategi edo edukiaren iturri baliogabea</string>
@ -407,7 +405,7 @@
<string name="caption_auto_generated">Automatikoki sortuak</string>
<string name="caption_setting_title">Azpitituluak</string>
<string name="caption_setting_description">Aldatu azpitituluen testuaren eskala eta atzealdeko estiloa. Aplikazioa berrabiarazi behar da aldaketak aplikatzeko.</string>
<string name="caption_setting_description">Aldatu azpitituluen testuaren eskala eta atzealdeko estiloa. Aplikazioa berrabiarazi behar da aldaketak aplikatzeko</string>
<string name="enable_leak_canary_title">Gaitu LeakCanary</string>
<string name="enable_leak_canary_summary">Memoria galeren monitorizazioa. Aplikazioak agian ez du erantzungo memoriaren aitortza egin bitartean</string>
@ -453,7 +451,7 @@
<string name="import_settings">Ezarpenak ere inportatu nahi dituzu?</string>
<string name="use_inexact_seek_summary">Bilaketa ez zehatzak posizioak azkarrago baina prezisio gutxiagoz bilatzea ahalbidetzen du</string>
<string name="download_thumbnail_summary">"Desgaitu iruditxoak kargatzea gelditzeko eta datuak eta memoria aurrezteko. Hau aldatzean memoria eta diskoko irudien cache-ak garbituko dira."</string>
<string name="download_thumbnail_summary">"Desgaitu iruditxoak kargatzea gelditzeko eta datuak eta memoria aurrezteko. Hau aldatzean memoria eta diskoko irudien cache-ak garbituko dira"</string>
<string name="app_license">NewPipe Software Librea eta Copyleft da: Nahi eran erabili, ikertu, partekatu eta hobetu dezakezu. Zehazki, elkarbanatzea eta aldatzea Free Software Foundation-ek argitaratutako GNU General Public License-ren 3. bertsioa edo berriagoren baten terminoen arabera egiteko baimena duzu.</string>
<string name="enable_disposed_exceptions_summary">Behartu aktibitatearen bizitza ziklotik kanpo baztertu eta gero entregatu ezin diren Rx salbuespenen inguruko txostena</string>
@ -468,4 +466,18 @@
<string name="limit_data_usage_none_description">Mugagabea</string>
<string name="limit_mobile_data_usage_title">Mugatu bereizmena datu mugikorrak erabiltzean</string>
<string name="skip_silence_checkbox">Aurreratu azkar isilunea dagoenean</string>
<string name="playback_step">Urratsa</string>
<string name="playback_reset">Leheneratu</string>
<string name="minimize_on_exit_title">Minimizatu aplikazioa aldatzean</string>
<string name="minimize_on_exit_summary">Ekintza bideo erreproduzigailu nagusitik beste aplikazio batera aldatzean — %s</string>
<string name="minimize_on_exit_none_description">Bat ere ez</string>
<string name="minimize_on_exit_background_description">Minimizatu bigarren planoko erreproduzigailura</string>
<string name="minimize_on_exit_popup_description">Minimizatu laster-liho erreproduzigailura</string>
<string name="channels">Kanalak</string>
<string name="playlists">Erreprodukzio-zerrendak</string>
<string name="tracks">Pistak</string>
<string name="users">Erabiltzaileak</string>
</resources>

View File

@ -35,8 +35,6 @@
<string name="show_play_with_kodi_summary">نمایش گزینه‌ای برای پخش ویدیو با مرکز رسانهٔ کودی.</string>
<string name="play_audio">صدا</string>
<string name="default_audio_format_title">قالب صدای پیش‌گزیده</string>
<string name="webm_description">قالب آزاد — WebM</string>
<string name="m4a_description">کیفیت بهتر — m4a</string>
<string name="theme_title">زمینه</string>
<string name="dark_theme_title">تیره</string>
<string name="light_theme_title">روشن</string>

View File

@ -54,8 +54,6 @@
<string name="play_audio">Ääni</string>
<string name="default_audio_format_title">Oletusääniformaatti</string>
<string name="default_video_format_title">Oletusvideoformaatti</string>
<string name="webm_description">WebM — vapaa formaatti</string>
<string name="m4a_description">M4A — parempi laatu</string>
<string name="theme_title">Teema</string>
<string name="light_theme_title">Kirkas</string>
<string name="dark_theme_title">Tumma</string>

View File

@ -24,8 +24,6 @@
<string name="view_count_text">%1$s vues</string>
<string name="play_audio">Audio</string>
<string name="default_audio_format_title">Format audio par défaut</string>
<string name="webm_description">WebM  format libre</string>
<string name="m4a_description">M4A  meilleure qualité</string>
<string name="download_dialog_title">Télécharger</string>
<string name="next_video_title">Vidéo suivante</string>
<string name="show_next_and_similar_title">Afficher les vidéos \"suivantes\" et \"similaires\"</string>
@ -384,7 +382,7 @@
<string name="use_inexact_seek_title">Recherche rapide approximative</string>
<string name="use_inexact_seek_summary">Permettre au lecteur d\'accéder plus rapidement à une position au détriment de la précision</string>
<string name="download_thumbnail_title">Charger miniatures</string>
<string name="download_thumbnail_summary">Désactiver pour arrêter le chargement de toutes les miniatures et sauvegarder les données et l\'utilisation de la mémoire. Modifier cela effacera à la fois le cache d\'image en mémoire et sur disque.</string>
<string name="download_thumbnail_summary">Désactiver pour arrêter le chargement de toutes les miniatures et sauvegarder les données et l\'utilisation de la mémoire. Modifier cela effacera à la fois le cache d\'image en mémoire et sur disque</string>
<string name="thumbnail_cache_wipe_complete_notice">Images en cache effacées</string>
<string name="metadata_cache_wipe_title">Effacer les données en cache</string>
<string name="metadata_cache_wipe_summary">Effacer toutes les pages web mises en cache</string>
@ -403,7 +401,7 @@
<string name="controls_download_desc">Télécharger le fichier de flux</string>
<string name="auto_queue_title">Vidéo suivante en file d\'attente</string>
<string name="auto_queue_summary">Ajout automatique d\'un flux connexe lors de la lecture du dernier flux dans une file d\'attente non répétitive.</string>
<string name="auto_queue_summary">Ajout automatique d\'un morceau suggéré lors de la lecture du dernier morceau dans une file d\'attente non bouclée.</string>
<string name="settings_category_debug_title">Débogage</string>
<string name="resize_fill">Remplir</string>
<string name="caption_auto_generated">Générés automatiquement</string>
@ -434,11 +432,11 @@
\n3. Un téléchargement va démarrer (ce sera celui du fichier nécessaire à l\'importation des abonnements)"</string>
<string name="import_soundcloud_instructions">Pour importer vos abonnements SoundCloud, vous devez connaitre l\'URL de votre profil ou votre identifiant (id). Si vous le savez, tapez-le ci-dessous.
\n
\nSi vous ne le connaissez pas, veuillez suivre les étapes suivantes :
\nSi vous ne le connaissez pas, veuillez suivre les étapes suivantes :
\n
\n1. Activer le \"mode bureau\" dans votre navigateur (le site n\'est pas accesible en mode mobile)
\n2. Suivez ce : %1$s
\n3. Connectez-vous à votre compte
\n1. Activer le \"mode bureau\" dans votre navigateur (le site n\'est pas accesible en mode mobile)
\n2. Suivez cette URL : %1$s
\n3. Connectez-vous à votre compte
\n4. Copier l\'URL vers lequel vous venez d\'être redirigé (qui est l\'URL de votre profil)</string>
<string name="import_soundcloud_instructions_hint">votreID, soundcloud.com/votreid</string>
@ -448,7 +446,7 @@
<string name="playback_speed_control">Vitesse de lecture</string>
<string name="playback_tempo">Cadence</string>
<string name="unhook_checkbox">Unhook (déformations possibles)</string>
<string name="unhook_checkbox">Détacher (déformations possibles)</string>
<string name="playback_default">Défaut</string>
<string name="preferred_open_action_settings_title">Ouvrir de préférence avec</string>
<string name="preferred_open_action_settings_summary">Action par défaut lors de l\'ouverture de contenu - %s</string>
@ -485,4 +483,18 @@
\nVous devez l\'accepter pour nous envoyer le rapport de bug.</string>
<string name="limit_data_usage_none_description">Pas de limite</string>
<string name="limit_mobile_data_usage_title">Limiter la résolution en données mobile</string>
</resources>
<string name="channels">Chaînes</string>
<string name="playlists">Listes de lecture</string>
<string name="tracks">Pistes</string>
<string name="users">Utilisateurs</string>
<string name="skip_silence_checkbox">Accélérer pendant les silences</string>
<string name="playback_step">Étape</string>
<string name="playback_reset">Réinitialiser</string>
<string name="minimize_on_exit_title">Minimiser lors du changement d\'application</string>
<string name="minimize_on_exit_summary">Action lors du changement d\'applications depuis le lecteur vidéo —%s</string>
<string name="minimize_on_exit_none_description">Aucune</string>
<string name="minimize_on_exit_background_description">Lecture en arrière plan</string>
<string name="minimize_on_exit_popup_description">Mettre en lecteur popup</string>
</resources>

View File

@ -32,7 +32,7 @@
<string name="download_path_audio_dialog_title">הכנס נתיב לשמירת קבצי שמע</string>
<string name="autoplay_by_calling_app_title">נגן אוטומטית</string>
<string name="autoplay_by_calling_app_summary">הפעל סרטון אוטומטית כאשר NewPipe נפתח דרך אפליקציה אחרת</string>
<string name="autoplay_by_calling_app_summary">מנגן סרטון כאשר NewPipe נפתח דרך אפליקציה אחרת</string>
<string name="default_resolution_title">רזולוציית ברירת המחדל</string>
<string name="default_popup_resolution_title">רזולוציית ברירת המחדל לחלון צץ</string>
<string name="show_higher_resolutions_title">הצג רזולוציות גבוהות יותר</string>
@ -44,8 +44,6 @@
<string name="play_audio">שמע</string>
<string name="default_audio_format_title">תבנית ברירת המחדל לשמע</string>
<string name="default_video_format_title">תבנית סרט ברירת מחדל</string>
<string name="webm_description">WebM — תבנית חופשית</string>
<string name="m4a_description">M4A — איכות גבוהה יותר</string>
<string name="theme_title">ערכת נושא</string>
<string name="light_theme_title">מואר</string>
<string name="dark_theme_title">חשוך</string>
@ -119,7 +117,7 @@
<string name="enable_search_history_title">היסטוריית חיפושים</string>
<string name="enable_search_history_summary">שמור חיפושים מקומית</string>
<string name="enable_watch_history_title">היסטוריה</string>
<string name="enable_watch_history_title">היסטוריה ומטמון</string>
<string name="enable_watch_history_summary">המשך לעקוב אחר סרטונים שנצפו</string>
<string name="resume_on_audio_focus_gain_title">המשך לנגן בעת חזרת המיקוד ליישום</string>
<string name="resume_on_audio_focus_gain_summary">המשך לנגן לאחר הפרעות (לדוגמה: שיחות טלפון)</string>
@ -386,4 +384,16 @@
\n3. ההורדה אמורה להתחיל (זהו קובץ היצוא)</string>
<string name="playback_tempo">קצב</string>
<string name="playback_default">ברירת מחדל</string>
</resources>
<string name="use_inexact_seek_title">השתמש בחיפוש מהיר שאינו מדויק</string>
<string name="use_inexact_seek_summary">חיפוש לא מדויק מאפשר לנגן לחפש נקודת זמן מהר יותר, עם דיוק מופחת</string>
<string name="download_thumbnail_title">טען תמונות ממוזערות</string>
<string name="download_thumbnail_summary">"השבת כדי לעצור את טעינת כל התמונות הממוזערות וחסוך בשימוש בנתונים ובזכרון. השינוי ימחק את המטמון בזכרון ובדיסק. "</string>
<string name="metadata_cache_wipe_summary">הסר את כל נתוני העמודים במטמון</string>
<string name="auto_queue_title">אוטומטית הכנס לתור את ההזרמה הבאה</string>
<string name="auto_queue_summary">"אוטומטית הוסף הזרמה קשורה כאשר ההזרמה האחרונה לא נמצאת במצב הזרמה חוזרת של התור. "</string>
<string name="toggle_orientation">כפתור כיוון</string>
<string name="switch_to_main">החלף לראשי</string>
<string name="import_data_summary">פעולה זו תדרוס את ההיסטוריה ורשימת המנויים הקיימת.</string>
<string name="clear_views_history_summary">"מחק הסטוריה של ניגונים קודמים. "</string>
</resources>

View File

@ -87,8 +87,6 @@
<string name="show_play_with_kodi_summary">उस विकल्प को दिखाए जिसमे Kodi Media Center के जरिये विडियो प्ले किया जाता है</string>
<string name="default_audio_format_title">डिफ़ॉल्ट ऑडियो का फॉर्मेट</string>
<string name="default_video_format_title">डिफ़ॉल्ट विडियो का फॉर्मेट</string>
<string name="webm_description">webm - फ्री फॉर्मेट</string>
<string name="m4a_description">M4A - बेहतर क्वालिटी</string>
<string name="theme_title">एप्प का नया रूप</string>
<string name="dark_theme_title">काला</string>
<string name="popup_remember_size_pos_title">विडियो पॉपअप की आकर और उसकी स्थति को याद रखे</string>

View File

@ -54,8 +54,6 @@
<string name="play_audio">Zvuk</string>
<string name="default_audio_format_title">Zadani format zvuka</string>
<string name="default_video_format_title">Zadani format videozapisa</string>
<string name="webm_description">WebM - slobodni format</string>
<string name="m4a_description">M4A - bolja kvaliteta</string>
<string name="theme_title">Tema</string>
<string name="light_theme_title">Svijetla</string>
<string name="dark_theme_title">Tamna</string>

View File

@ -24,8 +24,6 @@
<string name="show_play_with_kodi_summary">Mutat egy opciót a videók Kodi médiaközponttal való lejátszására.</string>
<string name="play_audio">Hang</string>
<string name="default_audio_format_title">Alapértelmezett hang formátum</string>
<string name="webm_description">WebM — szabad formátum</string>
<string name="m4a_description">m4a — jobb minőség</string>
<string name="download_dialog_title">Letöltés</string>
<string name="next_video_title">Következő videó</string>
<string name="url_not_supported_toast">A webcím nem támogatott</string>

View File

@ -32,8 +32,6 @@
<string name="show_play_with_kodi_summary">Tampilkan opsi untuk memutar video via media center Kodi</string>
<string name="play_audio">Audio</string>
<string name="default_audio_format_title">Format audio baku</string>
<string name="webm_description">WebM — format bebas</string>
<string name="m4a_description">M4A — kualitas lebih baik</string>
<string name="theme_title">Tema</string>
<string name="dark_theme_title">Gelap</string>
<string name="light_theme_title">Terang</string>

View File

@ -24,8 +24,6 @@
<string name="show_play_with_kodi_summary">Mostra l\'opzione per riprodurre i video tramite Kodi</string>
<string name="play_audio">Audio</string>
<string name="default_audio_format_title">Formato audio predefinito</string>
<string name="webm_description">WebM — formato libero</string>
<string name="m4a_description">M4A — miglior qualità</string>
<string name="download_dialog_title">Scarica</string>
<string name="next_video_title">Prossimo video</string>
<string name="show_next_and_similar_title">Mostra \'prossimi\' video e video \'simili\'</string>
@ -454,7 +452,7 @@
<string name="playback_speed_control">Controlli della velocità di riproduzione</string>
<string name="playback_tempo">Tempo</string>
<string name="playback_pitch">Tono</string>
<string name="unhook_checkbox">Slega (può causare distorsione)</string>
<string name="unhook_checkbox">Scollega (può causare distorsione)</string>
<string name="playback_nightcore">Nightcore</string>
<string name="playback_default">Valore predefinito</string>
<string name="no_streams_available_download">Nessun flusso disponibile per il download</string>
@ -491,4 +489,14 @@
<string name="limit_data_usage_none_description">Senza limiti</string>
<string name="limit_mobile_data_usage_title">Limita la risoluzione quando si utilizzano dati mobili</string>
</resources>
<string name="skip_silence_checkbox">Avanzamento veloce durante il silenzio</string>
<string name="playback_step">Step</string>
<string name="playback_reset">Reset</string>
<string name="minimize_on_exit_title">Minimizza al cambio applicazione</string>
<string name="minimize_on_exit_summary">Azione quando si passa ad un\'altra applicazione dal lettore video principale — %s</string>
<string name="minimize_on_exit_none_description">Nessuna</string>
<string name="minimize_on_exit_background_description">Minimizza al lettore in sottofondo</string>
<string name="minimize_on_exit_popup_description">Minimizza al lettore popup</string>
</resources>

View File

@ -23,8 +23,6 @@
<string name="show_play_with_kodi_summary">Kodi メディアセンター経由で動画を再生するための設定を表示します</string>
<string name="play_audio">音楽</string>
<string name="default_audio_format_title">デフォルトの音楽形式</string>
<string name="webm_description">WebM形式</string>
<string name="m4a_description">m4a形式</string>
<string name="download_dialog_title">保存</string>
<string name="next_video_title">次の動画</string>
<string name="show_next_and_similar_title">\"次の動画\"と\"関連動画\"を表示します</string>

View File

@ -24,8 +24,6 @@
<string name="show_play_with_kodi_summary">비디오를 Kodi media center를 사용해 재생하는 옵션을 표시합니다</string>
<string name="play_audio">오디오</string>
<string name="default_audio_format_title">기본 오디오 형식</string>
<string name="webm_description">WebM — 공개형 무료 자유 포맷입니다</string>
<string name="m4a_description">m4a — 보다 나은 품질을 제공합니다</string>
<string name="download_dialog_title">다운로드</string>
<string name="next_video_title">다음 비디오</string>
<string name="show_next_and_similar_title">다음 및 유사한 비디오 표시</string>

View File

@ -58,8 +58,6 @@
<string name="play_audio">ده‌نگ</string>
<string name="default_audio_format_title">جۆری سه‌ره‌كی ده‌نگ</string>
<string name="default_video_format_title">جۆری سه‌ره‌كی ڤیدیۆ</string>
<string name="webm_description">WebM — جۆری ئاسایی</string>
<string name="m4a_description">M4A — كوالێتی به‌رزتر</string>
<string name="theme_title">ڕووكار</string>
<string name="light_theme_title">ڕووناك</string>
<string name="dark_theme_title">تاریك</string>

View File

@ -43,8 +43,6 @@
<string name="play_audio">Garso įrašas</string>
<string name="default_audio_format_title">Numatytasos garso formatas</string>
<string name="default_video_format_title">Numatytasos vaizdo formatas</string>
<string name="webm_description">WebM — laisvas formatas</string>
<string name="m4a_description">M4A - geresnė kokybė</string>
<string name="theme_title">Tema</string>
<string name="light_theme_title">Šviesi</string>
<string name="dark_theme_title">Tamsi</string>

View File

@ -59,8 +59,6 @@
<string name="play_audio">Звук</string>
<string name="default_audio_format_title">Стандарден аудио формат</string>
<string name="default_video_format_title">Стандарден видео формат</string>
<string name="webm_description">WebM — слободен формат</string>
<string name="m4a_description">М4А — подобар квалитет</string>
<string name="theme_title">Тема</string>
<string name="light_theme_title">Светла</string>
<string name="dark_theme_title">Темна</string>

View File

@ -32,8 +32,6 @@
<string name="show_play_with_kodi_summary">Vis valg for avspilling via Kodi mediasenter</string>
<string name="play_audio">Lyd</string>
<string name="default_audio_format_title">Forvalgt lydformat</string>
<string name="webm_description">WebM — fritt format</string>
<string name="m4a_description">M4A — bedre kvalitet</string>
<string name="theme_title">Drakt</string>
<string name="dark_theme_title">Mørk</string>
<string name="light_theme_title">Lys</string>
@ -477,4 +475,18 @@
<string name="decline">Avslå</string>
<string name="limit_data_usage_none_description">Ubegrenset</string>
<string name="limit_mobile_data_usage_title">Begrens oppløsning når mobildata brukes</string>
<string name="minimize_on_exit_title">Minimer ved programbytte</string>
<string name="minimize_on_exit_summary">Handling ved bytting til annet program fra hovedspiller — %s</string>
<string name="minimize_on_exit_none_description">Ingen</string>
<string name="minimize_on_exit_background_description">Minimer til bakgrunnsspiller</string>
<string name="minimize_on_exit_popup_description">Minimer til oppsprettsspiller</string>
<string name="channels">Kanaler</string>
<string name="playlists">Spillelister</string>
<string name="tracks">Spor</string>
<string name="users">Brukere</string>
<string name="skip_silence_checkbox">Hurtig foroverspoling ved stillhet</string>
<string name="playback_step">Steg</string>
<string name="playback_reset">Tilbakestill</string>
</resources>

View File

@ -59,8 +59,6 @@
<string name="play_audio">Audio</string>
<string name="default_audio_format_title">Standaardaudioformaat</string>
<string name="default_video_format_title">Standaardvideoformaat</string>
<string name="webm_description">WebM — vrij formaat</string>
<string name="m4a_description">M4A — betere kwaliteit</string>
<string name="theme_title">Thema</string>
<string name="light_theme_title">Licht</string>
<string name="dark_theme_title">Donker</string>
@ -448,4 +446,14 @@
<string name="decline">Weigeren</string>
<string name="limit_data_usage_none_description">Onbeperkt</string>
<string name="limit_mobile_data_usage_title">Resolutie beperken bij gebruik van mobiele gegevens</string>
<string name="minimize_on_exit_title">Minimaliseren bij overschakelen naar anderen app</string>
<string name="minimize_on_exit_summary">Actie bij overschakelen van videospeler naar anderen app — %s</string>
<string name="minimize_on_exit_none_description">Geen</string>
<string name="minimize_on_exit_background_description">Afspelen in achtergrond</string>
<string name="minimize_on_exit_popup_description">Afspelen in pop-up</string>
<string name="skip_silence_checkbox">Doorspoelen tijdens stilte</string>
<string name="playback_step">Stap</string>
<string name="playback_reset">Standaardwaarden herstellen</string>
</resources>

View File

@ -24,8 +24,6 @@
<string name="show_play_with_kodi_summary">Toont een optie om een video op een Kodi media center af te spelen</string>
<string name="play_audio">Audio</string>
<string name="default_audio_format_title">Standaardaudioformaat</string>
<string name="webm_description">WebM — vrij formaat</string>
<string name="m4a_description">M4A — betere kwaliteit</string>
<string name="download_dialog_title">Downloaden</string>
<string name="next_video_title">Volgende video</string>
<string name="url_not_supported_toast">URL wordt niet ondersteund</string>
@ -331,7 +329,7 @@ te openen in pop-upmodus</string>
<string name="import_data_title">Database importeren</string>
<string name="export_data_title">Database exporteren</string>
<string name="import_data_summary">Dit zal je huidige geschiedenis en abonnementen overschrijven</string>
<string name="export_data_summary">Exporteer geschiedenis, abonnementen en speellijsten.</string>
<string name="export_data_summary">Exporteer geschiedenis, abonnementen en speellijsten</string>
<string name="export_complete_toast">Export voltooid</string>
<string name="import_complete_toast">Import voltooid</string>
<string name="no_valid_zip_file">Geen geldig ZIP-bestand</string>
@ -399,7 +397,7 @@ te openen in pop-upmodus</string>
<string name="use_inexact_seek_title">Snelle, minder exact spoelen gebruiken</string>
<string name="use_inexact_seek_summary">Minder exact spoelen laat de speler sneller posities zoeken met verminderde precisie</string>
<string name="auto_queue_title">Volgende stream automatisch in wachtrij plaatsen</string>
<string name="auto_queue_summary">Automatisch een gerelateerde stream toekennen bij het afspelen van de laatste stream in een niet-herhalende afspeelwachtlijst.</string>
<string name="auto_queue_summary">Automatisch een gerelateerde stream toekennen bij het afspelen van de laatste stream in een niet-herhalende afspeelwachtlijst</string>
<string name="live_sync">SYNCHRONISEREN</string>
<string name="file">Bestand</string>
@ -441,7 +439,7 @@ te openen in pop-upmodus</string>
\n
\nWil je doorgaan?</string>
<string name="download_thumbnail_title">Miniatuurvoorbeelden laden</string>
<string name="download_thumbnail_summary">Schakel dit uit om alle miniatuurvoorbeelden niet meer te laden; dit bespaart gegevens en geheugen. Het wijzigen van deze instelling wist het geheugen en de afbeeldingscache.</string>
<string name="download_thumbnail_summary">Schakel dit uit om alle miniatuurvoorbeelden niet meer te laden; dit bespaart gegevens en geheugen. Het wijzigen van deze instelling wist het geheugen en de afbeeldingscache</string>
<string name="thumbnail_cache_wipe_complete_notice">Afbeeldingscache gewist</string>
<string name="metadata_cache_wipe_title">Gecachete metagegevens wissen</string>
<string name="metadata_cache_wipe_summary">Alle gecachete webpagina-gegevens wissen</string>
@ -449,7 +447,7 @@ te openen in pop-upmodus</string>
<string name="playback_speed_control">Afspeelsnelheidbesturing</string>
<string name="playback_tempo">Tempo</string>
<string name="playback_pitch">Toon</string>
<string name="unhook_checkbox">Ontkoppelen (kan ruis veroorzaken)</string>
<string name="unhook_checkbox">Ontlinken (kan ruis veroorzaken)</string>
<string name="playback_nightcore">Nightcore</string>
<string name="playback_default">Standaard</string>
<string name="preferred_open_action_settings_title">Voorkeursactie voor openen</string>
@ -458,17 +456,17 @@ te openen in pop-upmodus</string>
<string name="no_streams_available_download">Geen streams beschikbaar voor downloaden</string>
<string name="caption_setting_title">Bijschriften</string>
<string name="caption_setting_description">Bijschriftgrootte en achtergrondstijlen wijzigen. Vereist een herstart van de app.</string>
<string name="caption_setting_description">Bijschriftgrootte en achtergrondstijlen wijzigen. Vereist een herstart van de app</string>
<string name="toast_no_player">Er is geen app geïnstalleerd die dit bestand kan afspelen</string>
<string name="clear_views_history_title">Kijkgeschiedenis wissen</string>
<string name="clear_views_history_summary">Verwijdert de geschiedenis van afgespeelde streams.</string>
<string name="delete_view_history_alert">Verwijdert de gehele kijkgeschiedenis.</string>
<string name="clear_views_history_summary">Verwijdert de geschiedenis van afgespeelde streams</string>
<string name="delete_view_history_alert">Verwijdert de gehele kijkgeschiedenis</string>
<string name="view_history_deleted">Kijkgeschiedenis verwijderd.</string>
<string name="clear_search_history_title">Zoekgeschiedenis wissen</string>
<string name="clear_search_history_summary">Verwijdert de gebruikte zoektermen.</string>
<string name="delete_search_history_alert">Verwijdert de gehele geschiedenis.</string>
<string name="clear_search_history_summary">Verwijdert de gebruikte zoektermen</string>
<string name="delete_search_history_alert">Verwijdert de gehele geschiedenis</string>
<string name="search_history_deleted">Zoekgeschiedenis verwijderd.</string>
<string name="one_item_deleted">1 item verwijderd.</string>
@ -485,4 +483,18 @@ te openen in pop-upmodus</string>
<string name="decline">Weigeren</string>
<string name="limit_data_usage_none_description">Ongelimiteerd</string>
<string name="limit_mobile_data_usage_title">Resolutie beperken bij gebruik van mobiele gegevens</string>
<string name="minimize_on_exit_title">Minimaliseren bij overschakelen naar andere app</string>
<string name="minimize_on_exit_summary">Actie bij overschakelen van videospeler naar andere app — %s</string>
<string name="minimize_on_exit_none_description">Geen</string>
<string name="minimize_on_exit_background_description">Afspelen op achtergrond</string>
<string name="minimize_on_exit_popup_description">Afspelen in pop-upvenster</string>
<string name="skip_silence_checkbox">Vooruitspoelen tijdens stilte</string>
<string name="playback_step">Stap</string>
<string name="playback_reset">Standaardwaarden</string>
<string name="channels">Kanalen</string>
<string name="playlists">Afspeellijsten</string>
<string name="tracks">Nummers</string>
<string name="users">Gebruikers</string>
</resources>

View File

@ -35,8 +35,6 @@
<string name="show_play_with_kodi_summary">Wyświetl opcję, aby odtworzyć wideo przez Kodi</string>
<string name="play_audio">Audio</string>
<string name="default_audio_format_title">Domyślny format audio</string>
<string name="webm_description">WebM — otwarty i darmowy format</string>
<string name="m4a_description">M4A — lepsza jakość</string>
<string name="theme_title">Motyw</string>
<string name="dark_theme_title">Ciemny</string>
<string name="light_theme_title">Jasny</string>

View File

@ -5,7 +5,6 @@
<string name="your_comment">Seu comentário (em inglês):</string>
<string name="what_happened_headline">O que aconteceu:</string>
<string name="what_device_headline">Informações:</string>
<string name="webm_description">WebM — formato aberto</string>
<string name="view_count_text">%1$s visualizações</string>
<string name="view">Reproduzir</string>
<string name="video_is_age_restricted">Vídeo com restrição de idade. Permissão para vídeos com essa restrição podem ser feitas no menu configurações.</string>
@ -78,7 +77,6 @@
<string name="downloads">Downloads</string>
<string name="downloads_title">Downloads</string>
<string name="did_you_mean">Você quis dizer: %1$s ?</string>
<string name="m4a_description">M4A — melhor qualidade</string>
<string name="add">Nova missão</string>
<string name="app_ui_crash">App/interface parou</string>
<string name="background_player_playing_toast">Reproduzindo em segundo plano</string>
@ -100,7 +98,7 @@
<string name="msg_threads">Threads</string>
<string name="msg_url_malform">URL inválida ou internet indisponível</string>
<string name="no_available_dir">Selecione uma pasta para download</string>
<string name="no_player_found">Nenhum player de stream encontrado. Deseja Instalar o VLC?</string>
<string name="no_player_found">Nenhum player de stream encontrado. Deseja instalar o VLC?</string>
<string name="parsing_error">Não foi possível interpretar o site</string>
<string name="play_audio">Áudio</string>
<string name="play_btn_text">Reproduzir</string>
@ -310,7 +308,7 @@ abrir em modo popup</string>
<string name="import_data_title">Importar base de dados</string>
<string name="export_data_title">Exportar base de dados</string>
<string name="import_data_summary">Isso irá sobrescrever seu histórico e inscrições</string>
<string name="export_data_summary">Exportar histórico, inscrições e listas de reprodução.</string>
<string name="export_data_summary">Exportar histórico, inscrições e listas de reprodução</string>
<string name="export_complete_toast">Exportação completa</string>
<string name="import_complete_toast">Importação completa</string>
<string name="no_valid_zip_file">Não há nenhum arquivo ZIP válido</string>
@ -379,7 +377,7 @@ abrir em modo popup</string>
<string name="use_inexact_seek_title">Usar índice de indexação rápido porém não preciso</string>
<string name="use_inexact_seek_summary">Usar índice de indexação inexato</string>
<string name="auto_queue_title">Adicionar a próxima stream à fila automaticamente</string>
<string name="auto_queue_summary">Auto anexar uma stream relacionada quando a reprodução iniciar na última stream em uma fila não repetitiva.</string>
<string name="auto_queue_summary">Auto anexar uma stream relacionada quando a reprodução iniciar na última stream em uma fila não repetitiva</string>
<string name="live_sync">Sincronizar</string>
<string name="file">Arquivo</string>
@ -427,9 +425,9 @@ abrir em modo popup</string>
<string name="metadata_cache_wipe_complete_notice">Cache de metadados foi limpo</string>
<string name="playback_speed_control">Controles de Velocidade de Reprodução</string>
<string name="playback_tempo">"Tempo "</string>
<string name="download_thumbnail_summary">Desabilite para para de carregar todas as miniaturas e economizar dados e uso de memória. Alterar esta configuração irá limpar o cache de imagens na memória e em disco.</string>
<string name="download_thumbnail_summary">Desabilite para para de carregar todas as miniaturas e economizar dados e uso de memória. Alterar esta configuração irá limpar o cache de imagens na memória e em disco</string>
<string name="playback_pitch">Passo</string>
<string name="unhook_checkbox">Desenganchar</string>
<string name="unhook_checkbox">Desvincular (pode causar distorção)</string>
<string name="playback_default">Padrão</string>
<string name="preferred_open_action_settings_title">Ação de \'abrir\' preferida</string>
<string name="preferred_open_action_settings_summary">Ação padrão quando abrir conteúdo — %s</string>
@ -439,18 +437,18 @@ abrir em modo popup</string>
<string name="drawer_open">Abrir gaveta</string>
<string name="drawer_close">Fechar gaveta</string>
<string name="caption_setting_title">Legendas</string>
<string name="caption_setting_description">Modifique o tamanho da legenda e o estilo da tela de fundo. Necessário reiniciar o aplicativo para ter efeito.</string>
<string name="caption_setting_description">Modifique o tamanho da legenda e o estilo da tela de fundo. Necessário reiniciar o aplicativo para ter efeito</string>
<string name="playback_nightcore">Night-core</string>
<string name="toast_no_player">Nenhum player instalado para reproduzir este arquivo</string>
<string name="clear_views_history_title">"Limpar histórico de já assistidos "</string>
<string name="clear_views_history_summary">Deleta o histórico de videos já reproduzidos.</string>
<string name="delete_view_history_alert">Deleta todo o histórico de já reproduzidos.</string>
<string name="clear_views_history_summary">Deleta o histórico de videos já reproduzidos</string>
<string name="delete_view_history_alert">Deleta todo o histórico de já reproduzidos</string>
<string name="view_history_deleted">Histórico de já assistidos deletado.</string>
<string name="clear_search_history_title">Limpar histórico de pesquisa</string>
<string name="clear_search_history_summary">Deleta histórico de palavras chave pesquisadas.</string>
<string name="delete_search_history_alert">Deletar todo o histórico de pesquisa.</string>
<string name="clear_search_history_summary">Deleta histórico de palavras chave pesquisadas</string>
<string name="delete_search_history_alert">Deletar todo o histórico de pesquisa</string>
<string name="search_history_deleted">Histórico de pesquisa deletado.</string>
<string name="one_item_deleted">1 item deletado.</string>
@ -467,4 +465,19 @@ abrir em modo popup</string>
<string name="decline">Recusar</string>
<string name="limit_data_usage_none_description">Ilimitado</string>
<string name="limit_mobile_data_usage_title">Limitar resolução quando dados móveis estiverem em uso</string>
<string name="minimize_on_exit_title">Minimizar ao trocar de aplicativo</string>
<string name="minimize_on_exit_summary">Ação ao trocar de aplicativo quando estiver no reprodutor de vídeo principal — %s</string>
<string name="minimize_on_exit_none_description">"Nenhuma "</string>
<string name="minimize_on_exit_background_description">Minimizar para reprodutor em plano de fundo</string>
<string name="minimize_on_exit_popup_description">Minimizar para reprodutor popup</string>
<string name="skip_silence_checkbox">Avançar rapidamente durante silêncio</string>
<string name="playback_step">Parar
\n</string>
<string name="playback_reset">Reiniciar</string>
<string name="channels">Canais</string>
<string name="playlists">Listas de reprodução</string>
<string name="tracks">Faixas</string>
<string name="users">Usuários</string>
</resources>

View File

@ -26,8 +26,6 @@
<string name="show_play_with_kodi_summary">Mostra uma opção para reproduzir o vídeo no Kodi</string>
<string name="play_audio">Áudio</string>
<string name="default_audio_format_title">Formato áudio padrão</string>
<string name="webm_description">WebM — formato livre</string>
<string name="m4a_description">M4A — melhor qualidade</string>
<string name="download_dialog_title">Descarregar</string>
<string name="next_video_title">Vídeo seguinte</string>
<string name="show_next_and_similar_title">Mostrar vídeos \'seguintes\' e \'semelhantes\'</string>

View File

@ -33,8 +33,6 @@
<string name="play_audio">Audio</string>
<string name="default_audio_format_title">Format audio implicit</string>
<string name="info_dir_created">Directorul de descărcare \'%1$s\' a fost creat</string>
<string name="webm_description">WebM — format liber</string>
<string name="m4a_description">M4A — calitate superioară</string>
<string name="theme_title">Temă</string>
<string name="dark_theme_title">Întunecat</string>
<string name="light_theme_title">Luminos</string>

View File

@ -1,7 +1,7 @@
<?xml version='1.0' encoding='UTF-8'?>
<resources>
<string name="view_count_text">%1$s просмотров</string>
<string name="upload_date_text">Опубликован в %1$s</string>
<string name="upload_date_text">Опубликовано %1$s</string>
<string name="no_player_found">Потоковый плеер не найден. Установить VLC?</string>
<string name="install">Установить</string>
<string name="cancel">Отмена</string>
@ -14,24 +14,22 @@
<string name="share_dialog_title">Поделиться с помощью</string>
<string name="choose_browser">Выбрать браузер</string>
<string name="screen_rotation">поворот</string>
<string name="download_path_title">Путь для загрузки видео</string>
<string name="download_path_title">Путь загрузки видео</string>
<string name="download_path_summary">Папка для хранения загруженных видео</string>
<string name="download_path_dialog_title">Введите путь к папке для загрузки видео</string>
<string name="default_resolution_title">Разрешение по умолчанию</string>
<string name="play_with_kodi_title">Воспроизвести с помощью Kodi</string>
<string name="play_with_kodi_title">Воспроизвести в Kodi</string>
<string name="kore_not_found">Приложение Kore не найдено. Установить его?</string>
<string name="show_play_with_kodi_title">Показывать опцию «Воспроизвести с помощью Kodi»</string>
<string name="show_play_with_kodi_summary">Показать опцию воспроизведения видео через Kodi media center</string>
<string name="show_play_with_kodi_title">\"Воспроизвести в Kodi\"</string>
<string name="show_play_with_kodi_summary">Показать опцию воспроизведения видео через медиацентр Kodi</string>
<string name="play_audio">Аудио</string>
<string name="default_audio_format_title">Формат аудио по умолчанию</string>
<string name="webm_description">WebM — свободный формат</string>
<string name="m4a_description">M4A — лучше качество</string>
<string name="download_dialog_title">Скачать</string>
<string name="next_video_title">Следующее видео</string>
<string name="url_not_supported_toast">URL не поддерживается</string>
<string name="show_next_and_similar_title">Показывать \'следующее\' и \'предложенные\' видео</string>
<string name="show_next_and_similar_title">\"Следующее\" и \"Предложенные\"</string>
<string name="search_language_title">Язык контента по умолчанию</string>
<string name="settings_category_video_audio_title">Видео и Аудио</string>
<string name="settings_category_video_audio_title">Видео и аудио</string>
<string name="settings_category_appearance_title">Внешний вид</string>
<string name="settings_category_other_title">Другое</string>
@ -40,8 +38,8 @@
<string name="detail_uploader_thumbnail_view_description">Миниатюра аватара пользователя</string>
<string name="detail_dislikes_img_view_description">Не понравилось</string>
<string name="detail_likes_img_view_description">Понравилось</string>
<string name="use_external_video_player_title">Использовать внешний видеоплеер</string>
<string name="use_external_audio_player_title">Использовать внешний аудиоплеер</string>
<string name="use_external_video_player_title">Внешний видеоплеер</string>
<string name="use_external_audio_player_title">Внешний аудиоплеер</string>
<string name="background_player_playing_toast">Воспроизведение в фоновом режиме</string>
<string name="theme_title">Тема</string>
<string name="dark_theme_title">Тёмная</string>
@ -51,7 +49,7 @@
<string name="network_error">Ошибка сети</string>
<string name="use_tor_title">Использовать Tor</string>
<string name="download_path_audio_title">Папка для загрузки аудио</string>
<string name="download_path_audio_title">Путь загрузки аудио</string>
<string name="download_path_audio_summary">Папка для хранения загруженных аудио</string>
<string name="download_path_audio_dialog_title">Введите путь к папке для загрузки аудио</string>
@ -59,7 +57,7 @@
<string name="msg_wait">Подождите…</string>
<string name="msg_exists">Файл уже существует</string>
<string name="msg_threads">Потоки</string>
<string name="finish">OK</string>
<string name="finish">ОК</string>
<string name="start">Начать</string>
<string name="pause">Пауза</string>
<string name="delete">Удалить</string>
@ -69,17 +67,17 @@
<string name="msg_error">Ошибка</string>
<string name="msg_server_unsupported">Сервер не поддерживается</string>
<string name="msg_running">NewPipe скачивает</string>
<string name="msg_url_malform">Неправильный URL или нет доступа к интернету</string>
<string name="msg_running_detail">Нажмите для деталей</string>
<string name="msg_url_malform">Неверный URL или нет доступа к интернету</string>
<string name="msg_running_detail">Подробности</string>
<string name="msg_copied">Скопировано в буфер обмена</string>
<string name="no_available_dir">Выберите доступную папку для загрузки</string>
<string name="show_age_restricted_content_title">Показывать контент с ограничением по возрасту</string>
<string name="show_age_restricted_content_title">Контент 18+</string>
<string name="general_error">Ошибка</string>
<string name="your_comment">Ваш комментарий (на английском):</string>
<string name="err_dir_create">Невозможно создать папку для загрузки \'%1$s\'</string>
<string name="autoplay_by_calling_app_title">Воспроизводить автоматически</string>
<string name="your_comment">Ваш комментарий (English):</string>
<string name="err_dir_create">Не удалось создать папку для загрузки \"%1$s\"</string>
<string name="autoplay_by_calling_app_title">Автовоспроизведение</string>
<string name="autoplay_by_calling_app_summary">Воспроизводить видео при вызове NewPipe из другого приложения</string>
<string name="content">Контент</string>
<string name="video_is_age_restricted">Видео с возрастными ограничениями. Разрешить подобный контент можно в настройках.</string>
@ -95,29 +93,29 @@
<string name="could_not_setup_download_menu">Не удалось создать меню загрузки</string>
<string name="live_streams_not_supported">Это прямая трансляция, они пока не поддерживаются.</string>
<string name="could_not_load_image">Не удалось загрузить изображение</string>
<string name="app_ui_crash">"Падение приложения/пользовательского интерфейса "</string>
<string name="app_ui_crash">Падение приложения/UI</string>
<string name="sorry_string">Простите, это не должно было произойти.</string>
<string name="error_report_button_text">Отправить отчёт об ошибке по электронной почте</string>
<string name="error_report_button_text">Отправить отчёт по e-mail</string>
<string name="error_snackbar_message">Простите, произошли ошибки.</string>
<string name="error_snackbar_action">ОТЧЁТ</string>
<string name="what_device_headline">Информация:</string>
<string name="what_happened_headline">Что произошло:</string>
<string name="error_details_headline">Детали:</string>
<string name="error_details_headline">Подробности:</string>
<string name="use_tor_summary">(Экспериментально) Загружать через Tor для повышения конфиденциальности (прямые трансляции пока не поддерживаются).</string>
<string name="report_error">Сообщить об ошибке</string>
<string name="user_report">Сообщить о нарушении</string>
<string name="info_dir_created">Создана папка для загрузок \'%1$s\'</string>
<string name="info_dir_created">Создана папка для загрузок \"%1$s\"</string>
<string name="video">Видео</string>
<string name="audio">Аудио</string>
<string name="retry">Повторить попытку</string>
<string name="storage_permission_denied">В доступе к хранилищу было отказано</string>
<string name="storage_permission_denied">Нет доступа к накопителю</string>
<string name="could_not_load_thumbnails">Не удалось загрузить все миниатюры</string>
<string name="youtube_signature_decryption_error">Не удалось расшифровать подпись URL у видео</string>
<string name="could_not_get_stream">Не удалось найти ни один поток</string>
<string name="could_not_get_stream">Не удалось найти ни одного потока</string>
<string name="view">Воспроизвести</string>
@ -125,19 +123,19 @@
<string name="controls_background_title">В фоне</string>
<string name="controls_popup_title">В окне</string>
<string name="show_higher_resolutions_summary">Только некоторые устройства могут воспроизводить 2K/4K видео</string>
<string name="show_higher_resolutions_summary">Только некоторые устройства могут воспроизводить видео в 2K/4K</string>
<string name="default_video_format_title">Формат видео по умолчанию</string>
<string name="black_theme_title">Чёрная</string>
<string name="popup_remember_size_pos_title">Запоминать размер и положение всплывающего окна</string>
<string name="player_gesture_controls_summary">Использовать жесты для изменения яркости и громкости</string>
<string name="popup_remember_size_pos_title">Восстановить окно</string>
<string name="player_gesture_controls_summary">Изменять яркость и громкость жестами</string>
<string name="settings_category_popup_title">Всплывающее окно</string>
<string name="popup_playing_toast">Воспроизведение во всплывающем окне</string>
<string name="channel">Канал</string>
<string name="yes">Да</string>
<string name="refresh">Обновить</string>
<string name="clear">Очистить</string>
<string name="use_old_player_title">Использовать старый плеер</string>
<string name="player_gesture_controls_title">Контроль жестов</string>
<string name="use_old_player_title">Старый плеер</string>
<string name="player_gesture_controls_title">Управление жестами</string>
<string name="all">Всё</string>
<string name="filter">Фильтр</string>
@ -149,7 +147,7 @@
<string name="reCaptchaActivity">reCAPTCHA</string>
<string name="open_in_popup_mode">Открыть в отдельном окне</string>
<string name="show_search_suggestions_summary">Показывать подсказки в поиске</string>
<string name="show_search_suggestions_summary">Отображать подсказки при поиске</string>
<string name="later">Позже</string>
<string name="disabled">Отключено</string>
@ -160,16 +158,16 @@
<string name="short_billion"> млрд.</string>
<string name="short_thousand"> тыс.</string>
<string name="default_popup_resolution_title">Разрешение в режиме всплывающего окна</string>
<string name="popup_remember_size_pos_summary">Запоминать последний размер и положение всплывающего окна</string>
<string name="show_search_suggestions_title">Поисковые подсказки</string>
<string name="default_popup_resolution_title">Разрешение всплывающего окна</string>
<string name="popup_remember_size_pos_summary">Запоминать размер и положение всплывающего окна</string>
<string name="show_search_suggestions_title">Варианты поиска</string>
<string name="best_resolution">Лучшее разрешение</string>
<string name="use_old_player_summary">Старый встроенный плеер на Mediaframework</string>
<string name="reCaptcha_title">Запрос reCAPTCHA</string>
<string name="recaptcha_request_toast">Запрошен ввод reCAPTCHA</string>
<string name="show_higher_resolutions_title">Показывать более высокое разрешение</string>
<string name="show_higher_resolutions_title">Высокие разрешения</string>
<string name="popup_mode_share_menu_title">NewPipe в окне</string>
<string name="title_activity_about">О NewPipe</string>
<string name="action_settings">Настройки</string>
@ -182,7 +180,7 @@
<string name="tab_about">О приложении</string>
<string name="tab_contributors">Участники</string>
<string name="read_full_license">Прочитать лицензию</string>
<string name="app_description">Библиотека лёгкого потокового воспроизведения на Android.</string>
<string name="app_description">Свободное легковесное потоковое воспроизведение на Android.</string>
<string name="view_on_github">Открыть на GitHub</string>
<string name="contribution_encouragement">Приветствуется всё — идеи, перевод, изменения дизайна, чистка кода или огромные изменения в коде. Чем больше сделано, тем лучше!</string>
<string name="copyright" formatted="true">© %1$s %2$s под лицензией %3$s</string>
@ -198,9 +196,9 @@
<string name="enable_search_history_title">История поиска</string>
<string name="enable_search_history_summary">Хранить поисковые запросы локально</string>
<string name="enable_watch_history_title">История и Кэш</string>
<string name="enable_watch_history_title">История и кэш</string>
<string name="enable_watch_history_summary">Запоминать просмотренные видео</string>
<string name="resume_on_audio_focus_gain_title">Возобновлять при возврате фокуса</string>
<string name="resume_on_audio_focus_gain_title">Возобновить при фокусе</string>
<string name="resume_on_audio_focus_gain_summary">Возобновлять воспроизведение после перерывов (например, телефонных звонков)</string>
@ -208,12 +206,12 @@
<string name="notification_channel_description">Уведомления для NewPipe в фоне и во всплывающем окне</string>
<string name="settings_category_downloads_title">Загрузки</string>
<string name="settings_file_charset_title">Допустимые символы в именах файлов</string>
<string name="settings_file_charset_title">Допустимые символы имён файлов</string>
<string name="settings_file_replacement_character_summary">Недопустимые символы заменяются на этот</string>
<string name="settings_file_replacement_character_title">Символ для замены</string>
<string name="charset_letters_and_digits">Буквы и цифры</string>
<string name="charset_most_special_characters">Большинство специальных символов</string>
<string name="charset_most_special_characters">Большинство спецсимволов</string>
<string name="title_activity_history">История</string>
<string name="title_history_search">История поиска</string>
@ -225,12 +223,12 @@
<string name="settings_category_player_title">Плеер</string>
<string name="settings_category_player_behavior_title">Поведение</string>
<string name="settings_category_history_title">История и кеш</string>
<string name="settings_category_history_title">История и кэш</string>
<string name="playlist">Плейлист</string>
<string name="undo">Отменить</string>
<string name="search_no_results">Нет результатов</string>
<string name="empty_subscription_feed_subtitle">Тут ничего нет</string>
<string name="empty_subscription_feed_subtitle">Ничего нет</string>
<string name="no_subscribers">Нет подписчиков</string>
<plurals name="subscribers">
@ -279,72 +277,72 @@
<string name="play_queue_remove">Удалить</string>
<string name="subscribed_button_title">Вы подписаны</string>
<string name="channel_unsubscribed">Подписка отменена</string>
<string name="show_hold_to_append_title">Показать \"держать, чтобы добавить\" подсказку</string>
<string name="show_hold_to_append_summary">Показывать подсказку при нажатии на иконку «В окне» или «В фоне» на странице сведений о видео</string>
<string name="show_hold_to_append_title">\"Зажмите, чтобы добавить\"</string>
<string name="show_hold_to_append_summary">Показать подсказку при нажатии \"В окне\" или \"В фоне\" на странице сведений о видео</string>
<string name="unknown_content">[Неизвестно]</string>
<string name="player_recoverable_failure">Восстановление после ошибки проигрывателя</string>
<string name="player_recoverable_failure">Восстановление после ошибки плеера</string>
<string name="title_activity_background_player">В фоне</string>
<string name="title_activity_popup_player">В окне</string>
<string name="hold_to_append">Зажмите, чтобы добавить в очередь</string>
<string name="enqueue_on_background">Добавить в очередь «В фоне»</string>
<string name="enqueue_on_popup">Добавить в очередь «В окне»</string>
<string name="start_here_on_main">Воспроизвести тут</string>
<string name="start_here_on_background">Воспроизвести в фоне</string>
<string name="start_here_on_popup">Воспроизвести в окне</string>
<string name="enqueue_on_background">В очередь \"В фоне\"</string>
<string name="enqueue_on_popup">В очередь \"В окне\"</string>
<string name="start_here_on_main">Видеоплеер</string>
<string name="start_here_on_background">Фоновый плеер</string>
<string name="start_here_on_popup">Плеер в окне</string>
<string name="no_player_found_toast">Потоковый плеер не найден (вы можете установить VLC)</string>
<string name="default_content_country_title">Страна контента по умолчанию</string>
<string name="service_title">Сервис</string>
<string name="always">Всегда</string>
<string name="just_once">Только один раз</string>
<string name="just_once">Только сейчас</string>
<string name="toggle_orientation">Переключить ориентацию</string>
<string name="switch_to_background">Перейти в фон</string>
<string name="switch_to_popup">Перейти в окно</string>
<string name="switch_to_main">Перейти в главное окно</string>
<string name="player_unrecoverable_failure">Ошибка проигрывателя без возможности восстановления</string>
<string name="external_player_unsupported_link_type">Внешние проигрыватели не поддерживают ссылки этих типов</string>
<string name="player_unrecoverable_failure">Ошибка плеера без возможности восстановления</string>
<string name="external_player_unsupported_link_type">Внешние плееры не поддерживают ссылки этих типов</string>
<string name="invalid_url_toast">Неверная ссылка</string>
<string name="video_streams_empty">Потоки видео не найдены</string>
<string name="audio_streams_empty">Потоки аудио не найдены</string>
<string name="donation_title">Пожертвовать</string>
<string name="donation_encouragement">NewPipe разрабатывается волонтерами, которые проводят время, принося вам лучший опыт. Вернитесь, чтобы помочь разработчикам сделать NewPipe еще лучше, наслаждаясь чашечкой кофе.</string>
<string name="donation_encouragement">Разработчики NewPipe ценой своего свободного времени делают вашу жизнь чуть удобнее. Отплатите им тем же — наслаждаясь чашечкой кофе, они смогут сделать NewPipe ещё лучше.</string>
<string name="give_back">Воздать должное</string>
<string name="website_title">Веб-сайт</string>
<string name="website_encouragement">Посетите сайт NewPipe для большей информации и новостей.</string>
<string name="drawer_open">Открыть лоток</string>
<string name="drawer_close">Закрыть лоток</string>
<string name="website_encouragement">Для получения более подробной информации и последних новостей о NewPipe посетите наш веб-сайт.</string>
<string name="drawer_open">Открыть боковую панель</string>
<string name="drawer_close">Закрыть боковую панель</string>
<string name="video_player">Проигрыватель видео</string>
<string name="background_player">Фоновый проигрыватель</string>
<string name="video_player">Видеоплеер</string>
<string name="background_player">Фоновый плеер</string>
<string name="popup_player">Плеер в окне</string>
<string name="always_ask_player">Всегда спрашивать</string>
<string name="preferred_player_fetcher_notification_title">Получение информации</string>
<string name="preferred_player_fetcher_notification_title">Получение сведений</string>
<string name="preferred_player_fetcher_notification_message">Загрузка запрошенного контента</string>
<string name="controls_download_desc">Загрузка файла прямой трансляции.</string>
<string name="show_info">Показать информацию</string>
<string name="show_info">Показать сведения</string>
<string name="tab_bookmarks">Закладки</string>
<string name="controls_add_to_playlist_title">Добавить к</string>
<string name="use_inexact_seek_title">Использовать быстрый, но неточный поиск</string>
<string name="use_inexact_seek_summary">Неточный поиск позволяет плееру искать позицию быстрее, но с пониженной точностью</string>
<string name="auto_queue_title">Автоматическая очередь следующего стрима</string>
<string name="auto_queue_summary">Автоматически добавлять связанные видео, при воспроизведении с последнего видео в неповторяющейся очереди.</string>
<string name="use_inexact_seek_title">Быстрый поиск позиции</string>
<string name="use_inexact_seek_summary">Неточный поиск позволяет плееру искать позицию быстрее, но менее точно</string>
<string name="auto_queue_title">Автодополнение очереди</string>
<string name="auto_queue_summary">Добавлять похожие потоки в очередь при воспроизведении последнего, если не включён повтор</string>
<string name="settings_category_debug_title">Отладка</string>
<string name="file">Файл</string>
<string name="import_data_title">Импорт данных</string>
<string name="export_data_title">Экспорт данных</string>
<string name="import_data_summary">Ваша текущая история и подписки будут перезаписаны</string>
<string name="export_data_summary">Экспорт истории, подписок и плейлистов.</string>
<string name="invalid_directory">Неправильная директория</string>
<string name="invalid_source">Неправильный файл/контент источника</string>
<string name="export_data_summary">Экспорт истории, подписок и плейлистов</string>
<string name="invalid_directory">Неверная папка</string>
<string name="invalid_source">Неверный файл или источник контента</string>
<string name="invalid_file">Файл не существует или нет разрешения на его чтение или запись</string>
<string name="file_name_empty_error">Имя файла не может быть пустым</string>
<string name="error_occurred_detail">Произошла ошибка: %1$s</string>
@ -357,37 +355,37 @@
<string name="dismiss">Отклонить</string>
<string name="rename">Переименовать</string>
<string name="delete_stream_history_prompt">Вы хотите удалить этот элемент из истории поиска?</string>
<string name="delete_all_history_prompt">Вы уверены, что хотите удалить все элементы из истории?</string>
<string name="title_last_played">Последнее проигрывание</string>
<string name="title_most_played">Наиболее проигрываемые</string>
<string name="delete_stream_history_prompt">Удалить этот элемент из истории поиска?</string>
<string name="delete_all_history_prompt">Удалить все элементы из истории?</string>
<string name="title_last_played">Недавно проигранные</string>
<string name="title_most_played">Часто проигрываемые</string>
<string name="export_complete_toast">Экспорт завершён</string>
<string name="import_complete_toast">Импорт завершён</string>
<string name="no_valid_zip_file">Нет верного Zip файла</string>
<string name="could_not_import_all_files">Предупреждение: нет возможности импорта всех файлов.</string>
<string name="override_current_data">Это перезапишет вашу текущую установку.</string>
<string name="no_valid_zip_file">Нет верного Zip-файла</string>
<string name="could_not_import_all_files">Внимание: не все файлы были импортированы.</string>
<string name="override_current_data">Текущие данные будут заменены.</string>
<string name="drawer_header_action_paceholder_text">Скоро что-то тут появится ;D</string>
<string name="drawer_header_action_paceholder_text">Скоро здесь кое-что появится ;D</string>
<string name="always_ask_open_action">Всегда спрашивать</string>
<string name="create_playlist">Создать новый плейлист</string>
<string name="create_playlist">Создать плейлист</string>
<string name="delete_playlist">Удалить плейлист</string>
<string name="rename_playlist">Переименовать плейлист</string>
<string name="playlist_name_input">Имя</string>
<string name="append_playlist">Добавить в плейлист</string>
<string name="set_as_playlist_thumbnail">Установить как иконку плейлиста</string>
<string name="set_as_playlist_thumbnail">На миниатюру плейлиста</string>
<string name="bookmark_playlist">Добавить плейлист в закладки</string>
<string name="unbookmark_playlist">Удалить закладку</string>
<string name="delete_playlist_prompt">Вы хотите удалить этот плейлист?</string>
<string name="delete_playlist_prompt">Удалить этот плейлист?</string>
<string name="playlist_creation_success">Плейлист создан</string>
<string name="playlist_add_stream_success">Добавлено в плейлист</string>
<string name="playlist_thumbnail_change_success">Иконка плейлиста изменена</string>
<string name="playlist_delete_failure">Нельзя удалить плейлист</string>
<string name="playlist_thumbnail_change_success">Миниатюра плейлиста изменена</string>
<string name="playlist_delete_failure">Не удалось удалить плейлист</string>
<string name="caption_none">Без титров</string>
@ -406,8 +404,8 @@
<string name="enable_leak_canary_title">Включить LeakCanary</string>
<string name="enable_leak_canary_summary">Мониторинг утечки памяти может привести к зависанию приложения</string>
<string name="enable_disposed_exceptions_title">Ошибки отчёта вне очереди</string>
<string name="enable_disposed_exceptions_summary">Принудительная отчетность об исключении исключаемых Rx исключений за пределами фрагмента или жизненного цикла деятельности после удаления</string>
<string name="enable_disposed_exceptions_title">Сообщать об ошибках жизненного цикла</string>
<string name="enable_disposed_exceptions_summary">Принудительно сообщать о недоставляемых Rx-исключениях вне фрагмента или жизненного цикла после удаления</string>
<string name="import_export_title">Импорт/Экспорт</string>
<string name="import_title">Импорт</string>
@ -420,8 +418,8 @@
<string name="import_file_title">Импорт файла</string>
<string name="previous_export">Предыдущий экспорт</string>
<string name="subscriptions_import_unsuccessful">Нельзя импортировать подписки</string>
<string name="subscriptions_export_unsuccessful">Нельзя экспортировать подписки</string>
<string name="subscriptions_import_unsuccessful">Не удалось импортировать подписки</string>
<string name="subscriptions_export_unsuccessful">Не удалось экспортировать подписки</string>
<string name="import_youtube_instructions">Импорт подписок из YouTube загрузкой файла экспорта:
\n
@ -436,53 +434,67 @@
\n4. Скопируйте адрес из адресной строки.</string>
<string name="import_soundcloud_instructions_hint">вашID, soundcloud.com/вашID</string>
<string name="import_network_expensive_warning">Эта операция может использовать большие объемы сетевого трафика.
<string name="import_network_expensive_warning">Это действие может вызвать большой расход трафика.
\n
\nПродолжить?</string>
<string name="download_thumbnail_title">Загружать миниатюры</string>
<string name="download_thumbnail_summary">Отключите, чтобы перестать загружать миниатюры и начать экономить трафик и память. Изменение настройки очистит кеш изображений в памяти и на диске.</string>
<string name="thumbnail_cache_wipe_complete_notice">Кеш изображений очищен</string>
<string name="metadata_cache_wipe_title">Очистить кеш метаданных</string>
<string name="metadata_cache_wipe_complete_notice">Кеш метаданных очищен</string>
<string name="download_thumbnail_summary">Отключите, чтобы не загружать миниатюры и сэкономить трафик и память. Изменение настройки очистит кэш изображений в памяти и накопителе</string>
<string name="thumbnail_cache_wipe_complete_notice">Кэш изображений очищен</string>
<string name="metadata_cache_wipe_title">Очистить кэш метаданных</string>
<string name="metadata_cache_wipe_complete_notice">Кэш метаданных очищен</string>
<string name="playback_speed_control">Управление скоростью воспроизведения</string>
<string name="playback_tempo">Темп</string>
<string name="playback_pitch">Тон</string>
<string name="unhook_checkbox">Независимо (может вызвать искажение)</string>
<string name="unhook_checkbox">Независимо (искажения)</string>
<string name="playback_nightcore">Nightcore</string>
<string name="playback_default">По умолчанию</string>
<string name="metadata_cache_wipe_summary">Удалить все загруженные данные веб-страниц</string>
<string name="preferred_open_action_settings_summary">Действие по умолчанию при открытии контента — %s</string>
<string name="preferred_open_action_settings_summary">При открытии ссылки на контент — %s</string>
<string name="no_streams_available_download">Нет потоков, доступных для загрузки</string>
<string name="caption_setting_title">Титры</string>
<string name="toast_no_player">Нет приложения, установленного для воспроизведения этого файла</string>
<string name="toast_no_player">Приложение для воспроизведения этого файла не установлено</string>
<string name="caption_setting_description">Изменить размер заголовка и фоновые стили. Требуется перезапуск приложения для изменений.</string>
<string name="caption_setting_description">Изменить размер и фон титров. Изменения вступят в силу после перезапуска</string>
<string name="clear_views_history_title">Очистить историю просмотров</string>
<string name="delete_view_history_alert">Удалить всю историю просмотров.</string>
<string name="view_history_deleted">История просмотров была удалена.</string>
<string name="delete_view_history_alert">Вся история просмотров будет удалена</string>
<string name="view_history_deleted">История просмотров удалена.</string>
<string name="clear_search_history_title">Очистить историю поиска</string>
<string name="clear_search_history_summary">Удалить историю поисковых запросов.</string>
<string name="clear_views_history_summary">Удаляет историю воспроизведенных потоков.</string>
<string name="delete_search_history_alert">Удалить всю историю поиска.</string>
<string name="search_history_deleted">Удалить историю поиска.</string>
<string name="clear_search_history_summary">Удалить историю поисковых запросов</string>
<string name="clear_views_history_summary">Удалить историю воспроизведённых потоков</string>
<string name="delete_search_history_alert">Вся история поиска будет удалена</string>
<string name="search_history_deleted">История поиска удалена.</string>
<string name="one_item_deleted">1 элемент удалён.</string>
<string name="app_license">NewPipe - программное обеспечение copyleft libre: вы можете использовать, изучать и улучшать его по своему усмотрению. В частности, вы можете распространять и/или изменять его в соответствии с GNU General Public License, опубликованным Free Software Foundation, либо версией 3 License, либо (по вашему выбору) любой более поздней версии.</string>
<string name="preferred_open_action_settings_title">Предпочтительное действие \'Открыть\'</string>
<string name="import_settings">Желаете ли вы также импортировать настройки?</string>
<string name="app_license">NewPipe — свободное программное обеспечение: вы можете использовать, изучать и улучшать его по своему усмотрению. В частности, вы можете распространять и/или изменять его в соответствии с условиями GNU General Public License, опубликованной Free Software Foundation, либо версии 3, либо (по вашему выбору) любой более поздней версии.</string>
<string name="preferred_open_action_settings_title">При открытии контента</string>
<string name="import_settings">Хотите импортировать настройки?</string>
<string name="privacy_policy_title">Политика конфиденциальности NewPipe</string>
<string name="privacy_policy_encouragement">Проект NewPipe очень серьезно относится к вашей конфиденциальности. Поэтому приложение не собирает никаких данных без вашего согласия.
\nПолитика конфиденциальности NewPipe подробно объясняет, какие данные отправляются и хранятся при отправке отчета о сбоях.</string>
<string name="read_privacy_policy">Прочитать политику конфиденциальности</string>
<string name="start_accept_privacy_policy">Чтобы соответствовать Европейскому стандарту защиты данных (GDPR), мы обращаем ваше внимание на политику конфиденциальности NewPipe. Пожалуйста, внимательно прочитайте его.
\nВы должны принять её, чтобы отправить нам отчет об ошибке.</string>
<string name="privacy_policy_encouragement">Проект NewPipe очень серьёзно относится к вашей конфиденциальности. Поэтому приложение не собирает никаких данных без вашего согласия.
\nПолитика конфиденциальности NewPipe подробно объясняет, какие данные отправляются и хранятся при отправке отчёта о сбоях.</string>
<string name="read_privacy_policy">Прочитать политику</string>
<string name="start_accept_privacy_policy">В соответствии с Общим регламентом по защите данных ЕС (GDPR), обращаем ваше внимание на политику конфиденциальности NewPipe. Пожалуйста, внимательно ознакомьтесь с ней.
\nВам необходимо принять её условия, чтобы отправить нам отчёт об ошибке.</string>
<string name="accept">Принять</string>
<string name="decline">Отклонить</string>
<string name="limit_data_usage_none_description">Безлимитный</string>
<string name="limit_mobile_data_usage_title">Предельное разрешение при использовании мобильных данных</string>
</resources>
<string name="limit_data_usage_none_description">Без ограничений</string>
<string name="limit_mobile_data_usage_title">Предел разрешения в мобильной сети</string>
<string name="channels">Каналы</string>
<string name="playlists">Плейлисты</string>
<string name="tracks">Дорожки</string>
<string name="users">Пользователи</string>
<string name="skip_silence_checkbox">Пропускать тишину</string>
<string name="playback_step">Шаг</string>
<string name="playback_reset">Сброс</string>
<string name="minimize_on_exit_title">При сворачивании плеера</string>
<string name="minimize_on_exit_summary">При переключении со стандартного плеера на другое приложение — %s</string>
<string name="minimize_on_exit_none_description">Ничего не делать</string>
<string name="minimize_on_exit_background_description">Фоновый плеер</string>
<string name="minimize_on_exit_popup_description">Плеер в окне</string>
</resources>

View File

@ -32,8 +32,6 @@
<string name="show_play_with_kodi_summary">Zobrazovať možnosť prehrať video cez mediálne centrum Kodi</string>
<string name="play_audio">Zvuk</string>
<string name="default_audio_format_title">Predvolený zvukový formát</string>
<string name="webm_description">WebM — voľný formát</string>
<string name="m4a_description">M4A — lepšia kvalita</string>
<string name="theme_title">Téma</string>
<string name="dark_theme_title">Tmavá</string>
<string name="light_theme_title">Svetlá</string>
@ -361,7 +359,7 @@
<string name="always_ask_open_action">Vždy sa opýtať</string>
<string name="preferred_player_fetcher_notification_title">Získavajú sa informácie…</string>
<string name="preferred_player_fetcher_notification_message">Požadovaný obsah sa načítava</string>
<string name="preferred_player_fetcher_notification_message">Načítanie požadované obsahu</string>
<string name="create_playlist">Vytvoriť nový zoznam skladieb</string>
<string name="delete_playlist">Vymazať zoznam skladieb</string>
@ -374,7 +372,7 @@
<string name="unbookmark_playlist">Odstrániť Záložku</string>
<string name="delete_playlist_prompt">Chcete odstrániť tento zoznam skladieb?</string>
<string name="playlist_creation_success">Zoznam skladieb bol vytvorený</string>
<string name="playlist_creation_success">Zoznam skladieb vytvorený</string>
<string name="playlist_add_stream_success">Pridané do zoznamu skladieb</string>
<string name="playlist_thumbnail_change_success">Miniatúra zoznamu skladieb bola zmenená</string>
<string name="playlist_delete_failure">Nemožno odstrániť zoznam skladieb</string>
@ -414,18 +412,18 @@
<string name="drawer_header_action_paceholder_text">Čoskoro sa tu niečo objaví ;D</string>
<string name="preferred_open_action_settings_title">Preferovaná akcia pri otvorení</string>
<string name="preferred_open_action_settings_title">Preferovaná akcia \'otvoriť\'</string>
<string name="preferred_open_action_settings_summary">Predvolená akcia pri otváraní obsahu — %s</string>
<string name="caption_auto_generated">Automaticky vygenerované</string>
<string name="caption_setting_title">Nastavenie titulkov</string>
<string name="caption_setting_description">Upravte mierku textu titulkov a štýly pozadia. Vyžaduje reštartovanie prehrávača.</string>
<string name="caption_setting_description">Upravte mierku textu titulkov a štýly pozadia. Vyžaduje reštart prehrávača.</string>
<string name="enable_leak_canary_title">Povoliť službu LeakCanary</string>
<string name="enable_leak_canary_summary">Monitorovanie pretečenia pamäte môže spôsobiť, že aplikácia nebude reagovať</string>
<string name="enable_disposed_exceptions_title">Nahlásiť mimocyklické chyby</string>
<string name="enable_disposed_exceptions_title">Nahlásiť mimo-cyklické chyby</string>
<string name="enable_disposed_exceptions_summary">Vynútenie hlásenia nedodržateľných výnimiek Rx, ktoré sa vyskytnú mimo časového cyklu fragmentu alebo aktivity po zlikvidovaní</string>
<string name="import_export_title">Import/Export
@ -451,14 +449,14 @@
\n2. Po výzve sa prihláste do svojho účtu
\n3. Sťahovanie by malo začať (to je exportovaný zoznam)
\n</string>
<string name="import_soundcloud_instructions">"Pre importovanie vašich SoundCloud dát, musíte poznať adresu URL alebo ID vašeho profilu. Ak poznáte jedno alebo druhé, zadajte ho do nižšie uvedeného vstupu a ste pripravení ísť.
\n
\nAk nepoznáte ani URL ani ID vašeho profilu, môžete postupovať nasledovne:
\n
\n1. V niektorom prehliadači povoľte režim \"desktop\" (web nie je dostupný pre mobilné zariadenia)
\n2. Prejdite na túto adresu URL: %1$s
\n3. Po výzve sa prihláste do svojho účtu
\n4. Skopírujte adresu URL, na ktorú ste boli presmerovaní (to je adresa vášho profilu)
<string name="import_soundcloud_instructions">"Importovať SoundCloud profil zadaním URL adresy alebo vášho ID:
\n
\nAk nepoznáte ani URL ani ID vašeho profilu, môžete postupovať nasledovne:
\n
\n1. V niektorom prehliadači povoľte režim \"desktop\" (web nie je dostupný pre mobilné zariadenia)
\n2. Prejdite na túto adresu URL: %1$s
\n3. Po výzve sa prihláste do svojho účtu
\n4. Skopírujte adresu URL, na ktorú ste boli presmerovaní (to je adresa vášho profilu).
\n"</string>
<string name="import_soundcloud_instructions_hint">ID,soundcloud.com/ID</string>
@ -483,4 +481,16 @@
<string name="one_item_deleted">1 položka bola vymazaná.</string>
<string name="app_license">"NewPipe je slobodný softvér pod licenciou copyleft. Môžete ho používať, študovať a vylepšovať ako len chcete. Konkrétne ho môžete šíriť a/alebo upravovať pod podmienkami Všeobecnej verejnej licencie GNU, ako ju publikuje Free Software Foundation, buď verzia 3 licencie, alebo (podľa vašej voľby) ktorákoľvek neskoršia verzia."</string>
<string name="privacy_policy_title">Ochrana osobných údajov v NewPipe</string>
<string name="privacy_policy_encouragement">NewPipe projekt berie vaše súkromie vážne. Preto aplikácia nezhromažďuje žiadne údaje bez vášho súhlasu.
\nNewPipe v ochrane súkromia podrobne vysvetľuje, aké údaje budú odoslané a uložené pri hlásení o páde.</string>
<string name="read_privacy_policy">Prečítajte si pravidlá ochrany osobných údajov</string>
<string name="import_settings">Chcete zároveň importovať aj nastavenia?</string>
<string name="start_accept_privacy_policy">V súlade s Európskym Všeobecným Nariadením o Ochrane Údajov (GDPR), chceme upriamiť vašu pozornosť na ochranu osobných údajov v NewPipe. Starostlivo si ich prečítajte. Musíte ich prijať pred nahlásením chyby.</string>
<string name="accept">Prijať</string>
<string name="decline">Odmietnuť</string>
<string name="limit_data_usage_none_description">Bez limitu</string>
<string name="limit_mobile_data_usage_title">Limitovať rozlíšenie pri použití mobilných dát</string>
</resources>

View File

@ -25,8 +25,6 @@
<string name="show_play_with_kodi_title">Pokaži možnost \"Predvajaj s Kodi\"</string>
<string name="default_audio_format_title">Privzet zapis zvoka</string>
<string name="play_audio">Zvok</string>
<string name="webm_description">WebM — prost zapis</string>
<string name="m4a_description">M4A — višja kakovost posnetkov</string>
<string name="download_dialog_title">Prejem</string>
<string name="next_video_title">Naslednji video</string>
<string name="show_next_and_similar_title">Pokaži naslednji video in podobne posnetke</string>

View File

@ -24,8 +24,6 @@
<string name="show_play_with_kodi_summary">Приказ опције за пуштање видеа у Коди медија центру</string>
<string name="play_audio">Аудио</string>
<string name="default_audio_format_title">Подразумевани формат звука</string>
<string name="webm_description">WebM — слободни формат</string>
<string name="m4a_description">M4A — бољи квалитет</string>
<string name="download_dialog_title">Преузми</string>
<string name="next_video_title">Следећи видео</string>
<string name="url_not_supported_toast">УРЛ није подржан</string>

View File

@ -4,7 +4,7 @@
<string name="no_player_found">Ingen strömspelare hittades. Vill du installera VLC?</string>
<string name="install">Installera</string>
<string name="cancel">Avbryt</string>
<string name="open_in_browser">Öppna i bläddrare</string>
<string name="open_in_browser">Öppna i webbläsare</string>
<string name="open_in_popup_mode">Öppna i popup-läge</string>
<string name="share">Dela</string>
<string name="download">Ladda ner</string>
@ -12,7 +12,7 @@
<string name="settings">Inställningar</string>
<string name="did_you_mean">Menade du: %1$s ?</string>
<string name="share_dialog_title">Dela med</string>
<string name="choose_browser">Välj bläddrare</string>
<string name="choose_browser">Välj webbläsare</string>
<string name="screen_rotation">rotering</string>
<string name="use_external_video_player_title">Använd extern videospelare</string>
<string name="use_external_video_player_summary">Några upplösningar kommer INTE ha ljud när det här alternativet är aktiverat</string>
@ -25,9 +25,9 @@
<string name="download_path_summary">Genväg för att lagra nerladdade videor i</string>
<string name="download_path_dialog_title">Fyll i genvägen som videor ska laddas ner till</string>
<string name="download_path_audio_title">Plats för att ladda ner ljud till</string>
<string name="download_path_audio_summary">Plats för att lagra nerladdat ljud i</string>
<string name="download_path_audio_dialog_title">Ange nerladdningsplats för ljudfiler</string>
<string name="download_path_audio_title">Genväg för nerladdning av ljud</string>
<string name="download_path_audio_summary">Genväg för att lagra nerladdade ljudfiler i</string>
<string name="download_path_audio_dialog_title">Fyll i genvägen som ljudfiler ska laddas ner till</string>
<string name="autoplay_by_calling_app_summary">Automatiskt spelar en video upp när NewPipe öppnas av en annan app</string>
<string name="default_resolution_title">Standardupplösning</string>
@ -41,8 +41,6 @@
<string name="play_audio">Ljud</string>
<string name="default_audio_format_title">Standardformat för ljud</string>
<string name="default_video_format_title">Videoformat som föredras</string>
<string name="webm_description">WebM — öppet format</string>
<string name="m4a_description">M4A — bättre kvalité</string>
<string name="theme_title">Tema</string>
<string name="light_theme_title">Ljus</string>
<string name="dark_theme_title">Mörk</string>
@ -120,7 +118,7 @@
<string name="fragment_whats_new">Vad är nytt</string>
<string name="autoplay_by_calling_app_title">Autospela</string>
<string name="autoplay_by_calling_app_title">Spela upp automatiskt</string>
<string name="enable_search_history_title">Sök historik</string>
<string name="enable_search_history_summary">Spara sökfrågor lokalt</string>
<string name="enable_watch_history_title">Historik &amp; Cacheminne</string>
@ -189,7 +187,7 @@
<string name="no_videos">Inga videor</string>
<plurals name="videos">
<item quantity="one">%s video</item>
<item quantity="other">%s videon</item>
<item quantity="other">%s videor</item>
</plurals>
<string name="start">Start</string>
@ -292,7 +290,7 @@
<string name="use_inexact_seek_title">Använda snabb inexact sökning</string>
<string name="download_thumbnail_title">Ladda miniatyrer</string>
<string name="download_thumbnail_summary">Inaktivera för att stoppa alla miniatyrer från lastning och spara på nät och minnesanvändning. Ändring av detta kommer att rensa cache-minnet.</string>
<string name="download_thumbnail_summary">Inaktivera för att stoppa alla miniatyrbilder från att ladda och spara på data och minnesanvändning. Ändring av detta kommer att rensa cache-minnet</string>
<string name="thumbnail_cache_wipe_complete_notice">Bild cacheminnet var rensad</string>
<string name="service_title">Tjänst</string>
<string name="settings_category_debug_title">Debug</string>
@ -301,4 +299,172 @@
<string name="file">Fil</string>
<string name="toggle_orientation">Byta orientationen</string>
</resources>
<string name="metadata_cache_wipe_title">Rensa metadatan i cacheminnet</string>
<string name="no_player_found_toast">Ingen strömspelare hittades (du kan installera VLC för att spela upp)</string>
<string name="controls_download_desc">Ladda ned sändning.</string>
<string name="use_inexact_seek_summary">"Ej exakt sökning tillåter spelaren att söka positioner snabbare med minskad precision "</string>
<string name="metadata_cache_wipe_summary">Ta bort alla cachade webbsidor</string>
<string name="metadata_cache_wipe_complete_notice">Metadata cache rensad</string>
<string name="auto_queue_title">"Köa nästa ström automatiskt "</string>
<string name="auto_queue_summary">Lägg automatiskt till en relaterad ström när du spelar den sista strömmen i en ej upprepad kö</string>
<string name="default_content_country_title">Standard innehåll land</string>
<string name="channels">Kanaler</string>
<string name="playlists">Spellistor</string>
<string name="tracks">Spår</string>
<string name="users">Användare</string>
<string name="switch_to_background">Växla till Bakgrunden</string>
<string name="switch_to_popup">Växla till popup</string>
<string name="switch_to_main">Växla till main</string>
<string name="import_data_title">Importera databas</string>
<string name="export_data_title">Exportera databas</string>
<string name="import_data_summary">Kommer att skriva över din nuvarande historik och prenumerationer</string>
<string name="export_data_summary">Exportera historik, prenumerationer och spellistor</string>
<string name="clear_views_history_title">Rensa visningshistorik</string>
<string name="clear_views_history_summary">Tar bort historiken för spelade videoklipp</string>
<string name="delete_view_history_alert">Ta bort hela visningshistoriken</string>
<string name="view_history_deleted">Visningshistorik borttagen.</string>
<string name="clear_search_history_title">Rensa sökhistorik</string>
<string name="clear_search_history_summary">Tar bort historiken för sökta nyckelord</string>
<string name="delete_search_history_alert">Ta bort hela sökhistoriken</string>
<string name="search_history_deleted">Sökhistorik borttagen.</string>
<string name="external_player_unsupported_link_type">Externa spelare stöder inte dessa typer av länkar</string>
<string name="invalid_url_toast">Ogiltig URL</string>
<string name="video_streams_empty">Inga videoströmmar hittades</string>
<string name="audio_streams_empty">Inga ljudspår hittades</string>
<string name="invalid_directory">Ogiltig katalog</string>
<string name="invalid_source">Ogiltig fil/innehålls källa</string>
<string name="invalid_file">Filen finns inte eller otillräcklig behörighet att läsa eller skriva till den</string>
<string name="file_name_empty_error">Filnamnet får inte vara tomt</string>
<string name="error_occurred_detail">Ett fel uppstod: %1$s</string>
<string name="no_streams_available_download">Inga strömmar är tillgängliga för nedladdning</string>
<string name="detail_drag_description">Dra för att ändra ordning</string>
<string name="create">Skapa</string>
<string name="delete_one">Ta bort en</string>
<string name="delete_all">Ta bort alla</string>
<string name="dismiss">Avfärda</string>
<string name="rename">Döp om</string>
<string name="one_item_deleted">1 objekt borttaget.</string>
<string name="toast_no_player">Ingen app installerad för att spela upp filen</string>
<string name="privacy_policy_title">NewPipes Sekretesspolicy</string>
<string name="privacy_policy_encouragement">"NewPipe projektet tar din integritet på största allvar. Appen samlar därför inte in några uppgifter utan ditt medgivande. NewPipes Sekretesspolicy förklarar i detalj vad för data som skickas och lagras när du skickar en kraschrapport."</string>
<string name="read_privacy_policy">Läs sekretesspolicy</string>
<string name="app_license">NewPipe är copyleft fri programvara: Du kan använda, studera, dela och förbättra den som du vill. Specifikt kan du distribuera och/eller modifiera det under villkoren för GNU General Public License som publicerats av Free Software Foundation, antingen version 3 av licensen, eller (om du så önskar) en senare version.</string>
<string name="delete_stream_history_prompt">Vill du ta bort det här föremålet från visningshistoriken?</string>
<string name="delete_all_history_prompt">Är du säker du vill ta bort alla föremål från historiken?</string>
<string name="title_last_played">Senast spelade</string>
<string name="title_most_played">Mest spelade</string>
<string name="export_complete_toast">Exporteringen har slutförts</string>
<string name="import_complete_toast">Importeringen har slutförts</string>
<string name="no_valid_zip_file">Ingen giltig ZIP-fil</string>
<string name="could_not_import_all_files">Varning: det gick inte att importera alla filer.</string>
<string name="override_current_data">Det här kommer skriva över dina nuvarande inställningar.</string>
<string name="import_settings">Vill du också importera inställningar?</string>
<string name="drawer_open">Öppna navigationspanelen</string>
<string name="drawer_close">Stäng navigationspanelen</string>
<string name="drawer_header_action_paceholder_text">Något kommer att visas här snart ;D</string>
<string name="preferred_open_action_settings_title">Föredra \'öppna\' åtgärden</string>
<string name="preferred_open_action_settings_summary">Standardåtgärden när du öppnar innehåll — %s</string>
<string name="video_player">Videospelare</string>
<string name="background_player">Bakgrundsspelare</string>
<string name="popup_player">Popup-spelare</string>
<string name="always_ask_open_action">Fråga alltid</string>
<string name="preferred_player_fetcher_notification_title">Hämtar information…</string>
<string name="preferred_player_fetcher_notification_message">Laddar begärt innehåll</string>
<string name="create_playlist">Skapa ny spellista</string>
<string name="delete_playlist">Radera spellista</string>
<string name="rename_playlist">Byt namn på spellista</string>
<string name="playlist_name_input">Namn</string>
<string name="append_playlist">Lägg till i spellistan</string>
<string name="set_as_playlist_thumbnail">Använd som spellistans miniatyrbild</string>
<string name="bookmark_playlist">Bokmärk spellistan</string>
<string name="unbookmark_playlist">Ta bort bokmärke</string>
<string name="delete_playlist_prompt">Vill du ta bort den här spellistan?</string>
<string name="playlist_creation_success">Spellistan skapades</string>
<string name="playlist_add_stream_success">Tillagad i spellistan</string>
<string name="playlist_thumbnail_change_success">"Spellistans miniatyrbild förändrades "</string>
<string name="playlist_delete_failure">Kunde inte ta bort spellistan</string>
<string name="caption_none">Ingen textning</string>
<string name="resize_fit">Passa</string>
<string name="resize_fill">Fyll</string>
<string name="resize_zoom">Zoom</string>
<string name="caption_auto_generated">Auto-genererade</string>
<string name="caption_setting_title">Textning</string>
<string name="caption_setting_description">Ändra spelaren textskala och bakgrundsstil. Kräver att appen startar om för att träder i kraft</string>
<string name="enable_leak_canary_title">Aktivera LeakCanary</string>
<string name="enable_leak_canary_summary">Minnesläcka övervakning kan orsaka att appen inte svarar under heap dumpning</string>
<string name="enable_disposed_exceptions_title">Rapportera Out-of-lifecycle fel</string>
<string name="enable_disposed_exceptions_summary">Tvinga rapportering av otillåtna Rx-undantag utanför fragment eller aktivitetslivscykel efter uppstädning</string>
<string name="import_export_title">Importera/Exportera</string>
<string name="import_title">Importera</string>
<string name="import_from">Importera från</string>
<string name="export_to">Exportera till</string>
<string name="import_ongoing">Importera…</string>
<string name="export_ongoing">Exporterar…</string>
<string name="import_file_title">Importera fil</string>
<string name="previous_export">Föregående export</string>
<string name="subscriptions_import_unsuccessful">Kunde inte importera prenumerationer</string>
<string name="subscriptions_export_unsuccessful">kunde inte exportera prenumerationer</string>
<string name="import_youtube_instructions">Importera YouTube-prenumerationer genom att hämta export-filen:
\n
\n1. Gå till följande webbadress: %1$s
\n2. Logga in när du blir tillfrågad
\n3. En nedladdning ska starta (det är export-filen)</string>
<string name="import_soundcloud_instructions">Importera en SoundCloud profil genom att skriva in webbadressen eller ditt ID:
\n
\n1. Aktivera \"skrivbordsläge\" i en webbläsare (sidan är inte tillgänglig för mobila enheter)
\n2. Gå till följande webbadress: %1$s
\n3. Logga in när du blir tillfrågad
\n4. Kopiera profilens webbadress som du blev omdirigerad till.</string>
<string name="import_soundcloud_instructions_hint">dittID, soundcloud.com/dittid</string>
<string name="import_network_expensive_warning">Tänk på att operationer kan vara nätverks intensiv.
\n
\nVill du fortsätta?</string>
<string name="playback_speed_control">Uppspelningshastighet Kontroller</string>
<string name="playback_tempo">Tempo</string>
<string name="playback_pitch">Pitch</string>
<string name="unhook_checkbox">Avlänka (kan orsaka förvrängning)</string>
<string name="skip_silence_checkbox">Snabbspola vid frånvaro av ljud</string>
<string name="playback_step">Steg</string>
<string name="playback_reset">Återställ</string>
<string name="start_accept_privacy_policy">För att uppfylla den Europeiska dataskyddsförordningen (GDPR), uppmärksammar vi NewPipes sekretesspolicy. Läs den noggrant. Du måste acceptera det om du vill skicka felrapporten.</string>
<string name="accept">Acceptera</string>
<string name="decline">Avböj</string>
<string name="limit_data_usage_none_description">Ingen gräns</string>
<string name="limit_mobile_data_usage_title">Begränsa upplösningen när du använder mobil data</string>
<string name="minimize_on_exit_title">"Minimera vid växling av applikationen "</string>
<string name="minimize_on_exit_summary">Åtgärd när du växlar till andra applikationer från huvudvideospelare — %s</string>
<string name="minimize_on_exit_none_description">Ingen</string>
<string name="minimize_on_exit_background_description">Minimera till Bakgrunds-spelare</string>
<string name="minimize_on_exit_popup_description">Minimera till popup-spelare</string>
</resources>

View File

@ -34,8 +34,6 @@
<string name="show_play_with_kodi_title">\"Kodi ile oynat\" seçeneğini göster</string>
<string name="show_play_with_kodi_summary">Kodi ortam merkezi aracılığıyla video oynatmak için bir seçenek görüntüler</string>
<string name="default_audio_format_title">Öntanımlı ses biçimi</string>
<string name="webm_description">WebM — özgür biçim</string>
<string name="m4a_description">M4A — daha iyi kalite</string>
<string name="theme_title">Tema</string>
<string name="dark_theme_title">Koyu</string>
<string name="light_theme_title">ık</string>
@ -119,16 +117,16 @@
<string name="could_not_setup_download_menu">İndirme menüsü ayarlanamadı</string>
<string name="open_in_popup_mode">ılır pencere kipinde aç</string>
<string name="popup_mode_share_menu_title">NewPipe açılır pencere kipi</string>
<string name="open_in_popup_mode">ılır oynatıcı kipinde aç</string>
<string name="popup_mode_share_menu_title">NewPipe açılır oynatıcı kipi</string>
<string name="default_popup_resolution_title">Öntanımlıılır pencere çözünürlüğü</string>
<string name="default_popup_resolution_title">Öntanımlıılır oynatıcı çözünürlüğü</string>
<string name="show_higher_resolutions_title">Daha yüksek çözünürlükleri göster</string>
<string name="show_higher_resolutions_summary">Yalnızca bazı aygıtlar 2K/4K video oynatmayı destekler</string>
<string name="default_video_format_title">Öntanımlı video biçimi</string>
<string name="black_theme_title">Siyah</string>
<string name="popup_playing_toast">ılır pencere kipinde oynatılıyor</string>
<string name="popup_playing_toast">ılır oynatıcı kipinde oynatılıyor</string>
<string name="all">Tümü</string>
<string name="channel">Kanal</string>
<string name="yes">Evet</string>
@ -148,7 +146,7 @@
<string name="short_million">M</string>
<string name="short_billion">B</string>
<string name="msg_popup_permission">Bu izin açılır pencere kipinde
<string name="msg_popup_permission">Bu izin açılır oynatıcı kipinde
\naçmak için gerekli</string>
<string name="reCaptchaActivity">reCAPTCHA</string>
@ -156,16 +154,16 @@
<string name="recaptcha_request_toast">reCAPTCHA Formu istendi</string>
<string name="controls_background_title">Arka Plan</string>
<string name="controls_popup_title">ılır Pencere</string>
<string name="controls_popup_title">ılır Oynatıcı</string>
<string name="filter">Süz</string>
<string name="refresh">Yenile</string>
<string name="clear">Temizle</string>
<string name="popup_remember_size_pos_title">ılır pencere boyutunu ve konumunu hatırla</string>
<string name="popup_remember_size_pos_summary">ılır pencerenin ayarlandığı son boyutu ve konumu hatırla</string>
<string name="popup_remember_size_pos_title">ılır oynatıcı boyutunu ve konumunu hatırla</string>
<string name="popup_remember_size_pos_summary">ılır oynatıcının ayarlandığı son boyutu ve konumu hatırla</string>
<string name="settings_category_popup_title">ılır Pencere</string>
<string name="settings_category_popup_title">ılır Oynatıcı</string>
<string name="popup_resizing_indicator_title">Boyutlandırılıyor</string>
<string name="use_external_video_player_summary">Bu seçenek etkinken bazı çözünürlüklerin sesi olmayacaktır</string>
@ -224,7 +222,7 @@
<string name="undo">Geri Al</string>
<string name="notification_channel_name">NewPipe Bildirimi</string>
<string name="notification_channel_description">NewPipe Arka Plan ve Açılır Pencere Oynatıcıları için Bildirimler</string>
<string name="notification_channel_description">NewPipe Arka Plan ve Açılır Oynatıcılar için Bildirimler</string>
<string name="search_no_results">Sonuç yok</string>
<string name="empty_subscription_feed_subtitle">Burada Cırcır Böceklerinden Başka Şey Yok</string>
@ -257,9 +255,9 @@
<string name="item_deleted">Öge silindi</string>
<string name="delete_item_search_history">Bu içeriği arama geçmişinden silmek istiyor musunuz?</string>
<string name="show_hold_to_append_title">\"Kuyruğa almak İçin bas\" ipucunu göster</string>
<string name="show_hold_to_append_summary">Video ayrıntıları sayfasında arka plan veya açılır pencere düğmesine basıldığında ipucu göster</string>
<string name="show_hold_to_append_summary">Video ayrıntıları sayfasında arka plan veya açılır oynatıcı düğmesine basıldığında ipucu göster</string>
<string name="background_player_append">Arka plan oynatıcıda kuyruğa eklendi</string>
<string name="popup_playing_append">ılır pencere oynatıcıda kuyruğa eklendi</string>
<string name="popup_playing_append">ılır oynatıcıda kuyruğa eklendi</string>
<string name="play_all">Tümünü Oynat</string>
<string name="unknown_content">[Bilinmeyen]</string>
@ -283,16 +281,16 @@
<string name="top_50">En İyi 50</string>
<string name="new_and_hot">Yeni ve sıcak</string>
<string name="title_activity_background_player">Arka Plan Oynatıcı</string>
<string name="title_activity_popup_player">ılır Pencere Oynatıcı</string>
<string name="title_activity_popup_player">ılır Oynatıcı</string>
<string name="play_queue_remove">Kaldır</string>
<string name="play_queue_stream_detail">Ayrıntılar</string>
<string name="play_queue_audio_settings">Ses Ayarları</string>
<string name="hold_to_append">Kuyruğa Almak İçin Bas</string>
<string name="enqueue_on_background">Arka Planda Kuyruğa Al</string>
<string name="enqueue_on_popup">ılır Pencerede Kuyruğa Al</string>
<string name="enqueue_on_popup">ılır Oynatıcıda Kuyruğa Al</string>
<string name="start_here_on_main">Burada Oynatmaya Başla</string>
<string name="start_here_on_background">Burada Arka Planda Başlat</string>
<string name="start_here_on_popup">Burada Açılır Pencerede Başlat</string>
<string name="start_here_on_popup">Burada Açılır Oynatıcıda Başlat</string>
<string name="donation_title">Bağış yapın</string>
<string name="donation_encouragement">NewPipe, size en iyi deneyimi sunmak için zamanını harcayan gönüllüler tarafından geliştirilmiştir. Bir fincan kahveyi yudumlarken NewPipe\'ı daha da iyi yapmaları için geliştiricilere yardımcı olun.</string>
<string name="give_back">Geri ver</string>
@ -302,7 +300,7 @@
<string name="service_title">Hizmet</string>
<string name="toggle_orientation">Yönelimi Değiştir</string>
<string name="switch_to_background">Arka Plana Geç</string>
<string name="switch_to_popup">ılır Pencereye Geç</string>
<string name="switch_to_popup">ılır Oynatıcıya Geç</string>
<string name="switch_to_main">Ana Görünüme Geç</string>
<string name="drawer_open">Çekmeceyi Aç</string>
@ -318,7 +316,7 @@
<string name="video_player">Video oynatıcı</string>
<string name="background_player">Arka plan oynatıcı</string>
<string name="popup_player">ılır pencere oynatıcı</string>
<string name="popup_player">ılır oynatıcı</string>
<string name="always_ask_player">Her zaman sor</string>
<string name="preferred_player_fetcher_notification_title">Bilgi alınıyor…</string>
@ -326,7 +324,7 @@
<string name="import_data_title">Veri tabanını içe aktar</string>
<string name="export_data_title">Veri tabanını dışa aktar</string>
<string name="import_data_summary">Şu anki geçmişinizi ve aboneliklerinizi geçersiz kılar</string>
<string name="export_data_summary">Geçmişi, abonelikleri ve oynatma listelerini dışa aktar.</string>
<string name="export_data_summary">Geçmişi, abonelikleri ve oynatma listelerini dışa aktar</string>
<string name="export_complete_toast">Dışa aktarım bitti</string>
<string name="import_complete_toast">İçe aktarım bitti</string>
<string name="no_valid_zip_file">Geçerli ZIP dosyası yok</string>
@ -395,7 +393,7 @@
<string name="use_inexact_seek_title">Hızlı isabetsiz konumlama kullan</string>
<string name="use_inexact_seek_summary">İsabetsiz konumlama, oynatıcının azaltılmış kesinlikle daha hızlı konumlama yapmasını sağlar</string>
<string name="auto_queue_title">Sonraki akışı kendiliğinden kuyruğa ekle</string>
<string name="auto_queue_summary">Yinelemeyen bir kuyruktaki son akış oynatılırken ilgili bir akışı kendiliğinden sonuna ekle.</string>
<string name="auto_queue_summary">Yinelemeyen bir kuyruktaki son akış oynatılırken ilgili bir akışı kendiliğinden sonuna ekle</string>
<string name="live_sync">EŞZAMANLA</string>
<string name="file">Dosya</string>
@ -437,7 +435,7 @@
\n
\nDevam etmek istiyor musunuz?</string>
<string name="download_thumbnail_title">Küçük resimleri yükle</string>
<string name="download_thumbnail_summary">Küçük resimlerin hepsinin yüklenmesini engellemek ve bellek ve veri kullanımını azaltmak için devre dışı bırakın. Bunu değiştirmek, hem bellekteki hem de diskteki resim önbelleğini temizler.</string>
<string name="download_thumbnail_summary">Küçük resimlerin hepsinin yüklenmesini engellemek ve bellek ve veri kullanımını azaltmak için devre dışı bırakın. Bunu değiştirmek, hem bellekteki hem de diskteki resim önbelleğini temizler</string>
<string name="thumbnail_cache_wipe_complete_notice">Resim önbelleği temizlendi</string>
<string name="metadata_cache_wipe_title">Önbelleklenmiş üst veriyi temizle</string>
<string name="metadata_cache_wipe_summary">Önbelleklenmiş tüm web sayfası verisini kaldır</string>
@ -446,7 +444,7 @@
<string name="playback_tempo">Hız</string>
<string name="playback_default">Öntanımlı</string>
<string name="playback_pitch">Ses titreşimi</string>
<string name="unhook_checkbox">Çengeli Çıkar (bozukluğa neden olabilir)</string>
<string name="unhook_checkbox">Bağlantıyı kes (bozulmalara neden olabilir)</string>
<string name="playback_nightcore">Nightcore</string>
<string name="no_streams_available_download">İndirmeye uygun akış yok</string>
@ -454,17 +452,17 @@
<string name="preferred_open_action_settings_summary">İçerik açılırken öntanımlı eylem — %s</string>
<string name="caption_setting_title">Ek Açıklamalar</string>
<string name="caption_setting_description">Oynatıcı ek açıklamalar metin boyutunu ve arka plan biçimlerini düzenle. Etki için uygulamayı yeniden başlatmak gerekir.</string>
<string name="caption_setting_description">Oynatıcı ek açıklamalar metin boyutunu ve arka plan biçimlerini düzenle. Etki için uygulamayı yeniden başlatmak gerekir</string>
<string name="toast_no_player">Bu dosyayı oynatmak için kurulan uygulama yok</string>
<string name="clear_views_history_title">İzleme geçmişini temizle</string>
<string name="clear_views_history_summary">Oynatılan akışların geçmişini siler.</string>
<string name="delete_view_history_alert">Tüm izleme geçmişini sil.</string>
<string name="clear_views_history_summary">Oynatılan akışların geçmişini siler</string>
<string name="delete_view_history_alert">Tüm izleme geçmişini sil</string>
<string name="view_history_deleted">İzleme geçmişi silindi.</string>
<string name="clear_search_history_title">Arama geçmişini temizle</string>
<string name="clear_search_history_summary">Aranan anahtar sözcüklerin geçmişini siler.</string>
<string name="delete_search_history_alert">Tüm arama geçmişini sil.</string>
<string name="clear_search_history_summary">Aranan anahtar sözcüklerin geçmişini siler</string>
<string name="delete_search_history_alert">Tüm arama geçmişini sil</string>
<string name="search_history_deleted">Arama geçmişi silindi.</string>
<string name="one_item_deleted">1 öge silindi.</string>
@ -481,4 +479,18 @@
<string name="decline">Kabul etme</string>
<string name="limit_data_usage_none_description">Sınırsız</string>
<string name="limit_mobile_data_usage_title">Mobil veri kullanırken çözünürlüğü sınırla</string>
<string name="minimize_on_exit_title">Uygulama geçişinde küçült</string>
<string name="minimize_on_exit_summary">Ana video oynatıcıdan başka bir uygulamaya geçişteki eylem — %s</string>
<string name="minimize_on_exit_none_description">Yok</string>
<string name="minimize_on_exit_background_description">Arka plan oynatıcıya küçült</string>
<string name="minimize_on_exit_popup_description">ılır oynatıcıya küçült</string>
<string name="skip_silence_checkbox">Sessizlik sırasında hızlı ileri</string>
<string name="playback_step">Adım</string>
<string name="playback_reset">Sıfırla</string>
<string name="channels">Kanallar</string>
<string name="playlists">Oynatma Listeleri</string>
<string name="tracks">Parçalar</string>
<string name="users">Kullanıcılar</string>
</resources>

View File

@ -34,8 +34,6 @@
<string name="show_play_with_kodi_summary">Показувати опцію відтворення відео за допомогою Kodi media center</string>
<string name="play_audio">Аудіо</string>
<string name="default_audio_format_title">Типовий аудіо формат</string>
<string name="webm_description">WebM — вільний формат</string>
<string name="m4a_description">M4A — ліпша якість</string>
<string name="theme_title">Тема</string>
<string name="dark_theme_title">Темна</string>
<string name="light_theme_title">Світла</string>
@ -192,7 +190,7 @@
<string name="import_data_title">Імпортувати базу</string>
<string name="export_data_title">Експортувати базу</string>
<string name="import_data_summary">Це перепише чинну історію та підписання</string>
<string name="export_data_summary">Експортувати історію, підписання та плейлисти.</string>
<string name="export_data_summary">Експортувати історію, підписання та плейлисти</string>
<string name="player_stream_failure">Неможливо відтворити цей стрим</string>
<string name="player_recoverable_failure">Відновлююсь після помилки програвача</string>
<string name="invalid_url_toast">Помилкова URL</string>
@ -387,7 +385,7 @@
<string name="use_inexact_seek_title">Використовувати неточне шукання</string>
<string name="use_inexact_seek_summary">Неточне шукання дозволяє програвачеві рухатися позиціями швидше, проте з меншою точністю</string>
<string name="auto_queue_title">Автоматично додати до черги наступний стрим</string>
<string name="auto_queue_summary">Автоматично додавати пов\'язаний стрим під час відтворення останнього у неповторювальній черзі.</string>
<string name="auto_queue_summary">Автоматично додавати пов\'язаний стрим під час відтворення останнього у неповторювальній черзі</string>
<string name="live_sync">СИНХРОНІЗАЦІЯ</string>
<string name="file">Теки</string>
@ -429,7 +427,7 @@
\n
\nПродовжуватимете?</string>
<string name="download_thumbnail_title">Завантажити ескізи</string>
<string name="download_thumbnail_summary">Відключити аби зупинити завантаження ескізів та заощадити використання ресурсів та пам\'яті. Увімкнення функції призведе до повного вичищення кешу зображень.</string>
<string name="download_thumbnail_summary">Відключити аби зупинити завантаження ескізів та заощадити використання ресурсів та пам\'яті. Увімкнення функції призведе до повного вичищення кешу зображень</string>
<string name="thumbnail_cache_wipe_complete_notice">Кеш зображень стерто</string>
<string name="metadata_cache_wipe_title">Стерти кеш метаданих</string>
<string name="metadata_cache_wipe_summary">"Усунути всі кешовані дані веб-сторінки "</string>
@ -446,17 +444,17 @@
<string name="preferred_open_action_settings_summary">Типова дія під час відкриття вмісту — %s</string>
<string name="caption_setting_title">Субтитри</string>
<string name="caption_setting_description">Змінення маштабу тексту субтитрів та фонових стилів. Увімкнення функції потребує перезавантаження застосунку.</string>
<string name="caption_setting_description">Змінення маштабу тексту субтитрів та фонових стилів. Увімкнення функції потребує перезавантаження застосунку</string>
<string name="toast_no_player">Не знайдено відповідного застосунку для відтворення цього файла</string>
<string name="clear_views_history_title">Очистити історію переглядів</string>
<string name="clear_views_history_summary">Видаляє історію відтворень.</string>
<string name="delete_view_history_alert">Видалити всю історію переглядів.</string>
<string name="clear_views_history_summary">Видаляє історію відтворень</string>
<string name="delete_view_history_alert">Видалити всю історію переглядів</string>
<string name="view_history_deleted">Історію переглядів було видалено.</string>
<string name="clear_search_history_title">Очистити історію пошуків</string>
<string name="clear_search_history_summary">Видаляє історію шуканих ключових слів.</string>
<string name="delete_search_history_alert">Видалити всю пошукову історію.</string>
<string name="clear_search_history_summary">Видаляє історію шуканих ключових слів</string>
<string name="delete_search_history_alert">Видалити всю пошукову історію</string>
<string name="search_history_deleted">Пошукову історію було видалено.</string>
<string name="one_item_deleted">Видалено один фраґмент.</string>
@ -473,4 +471,18 @@
<string name="decline">Відхилити</string>
<string name="limit_data_usage_none_description">Безмежно</string>
<string name="limit_mobile_data_usage_title">Обмежити роздільну здатність під час користування мобільним інтернетом</string>
<string name="skip_silence_checkbox">Перемотувати підчас тиші</string>
<string name="playback_step">Крок</string>
<string name="playback_reset">Скинути</string>
<string name="minimize_on_exit_title">Зменшити при перемкненні застосунку</string>
<string name="minimize_on_exit_summary">Дія при перемкненні до інших застосунків з головного відео-програвачу — %s</string>
<string name="minimize_on_exit_none_description">Жодних</string>
<string name="minimize_on_exit_background_description">Зменшити до фонового програвачу</string>
<string name="minimize_on_exit_popup_description">Зменшити до віконного програвачу</string>
<string name="channels">Канали</string>
<string name="playlists">Плейлисти</string>
<string name="tracks">Стежки</string>
<string name="users">Користувачі</string>
</resources>

View File

@ -4,10 +4,19 @@
<string name="upload_date_text">کوشائع ہوا</string>
<string name="install">انسٹال</string>
<string name="cancel">منسوخ کریں</string>
<string name="share">اشتراک کریں</string>
<string name="share">بانٹیں</string>
<string name="download">ڈاؤن لوڈکریں</string>
<string name="search">تلاش کریں</string>
<string name="did_you_mean">نتائج دکھارہاہےبرائے</string>
<string name="did_you_mean">کیا آپ کا مطلب تھا</string>
<string name="open_in_browser">انٹرنیٹ میں کھولیں</string>
<string name="settings">ترتیبات</string>
<string name="no_player_found">کوئیstream پلیئر نہیں ملا.کیا آپ VLC انسٹال کرنا چاہتے ہیں؟</string>
<string name="no_player_found_toast">کوئیstream پلیئر نہیں ملا.(آپ VLC انسٹال کر سکتے ہیے)</string>
<string name="open_in_popup_mode">PopUp موڈ میں کھولیں</string>
<string name="controls_download_desc">سٹریم فائل ڈاؤن لوڈ کریں.</string>
<string name="share_dialog_title">کے ساتھ بانٹیں</string>
<string name="choose_browser">Internet Browser منتخب کریں
\n</string>
<string name="screen_rotation">rotation کرو</string>
<string name="use_external_video_player_title">external video player استعمال کریں</string>
</resources>

View File

@ -41,8 +41,6 @@
<string name="play_audio">Âm thanh</string>
<string name="default_audio_format_title">Định dạng âm thanh mặc định</string>
<string name="default_video_format_title">Định dạng video ưa thích</string>
<string name="webm_description">WebM — Định dạng miễn phí</string>
<string name="m4a_description">M4a — chất lượng tốt hơn</string>
<string name="controls_background_title">Nền</string>
<string name="theme_title">Chủ đề</string>
<string name="light_theme_title">Sáng</string>

View File

@ -26,8 +26,6 @@
<string name="show_play_with_kodi_summary">显示 Kodi 媒体中心播放视频的选项</string>
<string name="play_audio">音频</string>
<string name="default_audio_format_title">默认音频格式</string>
<string name="webm_description">WebM — 开放格式</string>
<string name="m4a_description">M4A — 品质更佳</string>
<string name="theme_title">主题</string>
<string name="dark_theme_title">灰暗</string>
<string name="light_theme_title">明亮</string>
@ -461,4 +459,7 @@
<string name="limit_data_usage_none_description">不限制</string>
<string name="limit_mobile_data_usage_title">使用移动数据时限制分辨率</string>
<string name="channels">更多频道</string>
<string name="playlists">更多频道</string>
<string name="users">用户们</string>
</resources>

View File

@ -22,8 +22,6 @@
<string name="show_play_with_kodi_summary">顯示以 Kodi 媒體中心播放影片的選項</string>
<string name="play_audio">聲音</string>
<string name="default_audio_format_title">預設聲音檔案格式</string>
<string name="webm_description">WebM — 開放格式</string>
<string name="m4a_description">M4A — 更佳畫質</string>
<string name="theme_title">主題</string>
<string name="dark_theme_title">黑暗</string>
<string name="light_theme_title">明亮</string>

View File

@ -26,8 +26,6 @@
<string name="kore_not_found">找不到Kore您要安裝Kore嗎</string>
<string name="show_play_with_kodi_title">顯示「用Kodi播放」的選項</string>
<string name="default_audio_format_title">預設音訊格式</string>
<string name="webm_description">WebM — 開放格式</string>
<string name="m4a_description">M4A — 畫質更佳</string>
<string name="theme_title">主題</string>
<string name="dark_theme_title">灰暗</string>
<string name="light_theme_title">明亮</string>
@ -271,7 +269,7 @@
<string name="import_data_title">匯入資料庫</string>
<string name="export_data_title">匯出資料庫</string>
<string name="import_data_summary">將覆蓋您目前的歷史記錄和訂閱</string>
<string name="export_data_summary">匯出歷史記錄、訂閱和播放清單</string>
<string name="export_data_summary">匯出歷史記錄、訂閱和播放清單</string>
<string name="give_back">返回</string>
<string name="website_encouragement">欲了解更多關於 NewPipe 的資訊和新聞,請造訪我們的網站。</string>
<string name="main_page_content">首頁內容</string>
@ -382,7 +380,7 @@
<string name="use_inexact_seek_title">使用粗略但快速的尋找</string>
<string name="use_inexact_seek_summary">粗略尋找讓播放器更快找到影片的進度位置</string>
<string name="auto_queue_title">自動播放隊列中下一部影片</string>
<string name="auto_queue_summary">在非重複播放佇列中的最後一個串流上開始播放時,自動附上相關串流</string>
<string name="auto_queue_summary">在非重複播放佇列中的最後一個串流上開始播放時,自動附上相關串流</string>
<string name="live_sync">同步</string>
<string name="file">檔案</string>
@ -424,7 +422,7 @@
\n3. 詢問時登入到您的帳號
\n4. 複製您被重新導向到的網址。</string>
<string name="download_thumbnail_title">載入縮圖</string>
<string name="download_thumbnail_summary">停用後NewPipe將不再載入縮圖減少數據使用與騰空儲存空間亦會清除記憶體和磁碟上的縮圖快取</string>
<string name="download_thumbnail_summary">停用後NewPipe將不再載入縮圖減少數據使用與騰空儲存空間亦會清除記憶體和磁碟上的縮圖快取</string>
<string name="thumbnail_cache_wipe_complete_notice">已清除圖片快取</string>
<string name="metadata_cache_wipe_title">抹除快取中介資料</string>
<string name="metadata_cache_wipe_summary">移除所有網頁的快取資料</string>
@ -432,7 +430,7 @@
<string name="playback_speed_control">播放速度控制</string>
<string name="playback_tempo">節拍</string>
<string name="playback_pitch">間距</string>
<string name="unhook_checkbox">解除 (可能導致失真)</string>
<string name="unhook_checkbox">解除連結(可能導致失真)</string>
<string name="playback_nightcore">Nightcore</string>
<string name="playback_default">預設</string>
<string name="preferred_open_action_settings_title">偏好的「開啟」動作</string>
@ -441,17 +439,17 @@
<string name="no_streams_available_download">沒有可供下載的串流</string>
<string name="caption_setting_title">字幕</string>
<string name="caption_setting_description">調整播放器字幕大小與背景樣式。必須重新啟動應用程式才會生效</string>
<string name="caption_setting_description">調整播放器字幕大小與背景樣式。必須重新啟動應用程式才會生效</string>
<string name="toast_no_player">未安裝可播放此檔案的應用程式</string>
<string name="clear_views_history_title">清除觀看歷史</string>
<string name="clear_views_history_summary">刪除播放過的串流歷史</string>
<string name="delete_view_history_alert">刪除全部的觀看歷史</string>
<string name="clear_views_history_summary">刪除播放過的串流歷史</string>
<string name="delete_view_history_alert">刪除全部的觀看歷史</string>
<string name="view_history_deleted">觀看歷史已刪除。</string>
<string name="clear_search_history_title">清除觀看歷史</string>
<string name="clear_search_history_summary">刪除搜尋關鍵字的歷史</string>
<string name="delete_search_history_alert">刪除全部的搜尋歷史</string>
<string name="clear_search_history_summary">刪除搜尋關鍵字的歷史</string>
<string name="delete_search_history_alert">刪除全部的搜尋歷史</string>
<string name="search_history_deleted">搜尋歷史已刪除。</string>
<string name="one_item_deleted">已刪除 1 個項目。</string>
@ -468,4 +466,18 @@
<string name="decline">下降</string>
<string name="limit_data_usage_none_description">沒有限制</string>
<string name="limit_mobile_data_usage_title">當您使用行動網路時限制解析度</string>
<string name="minimize_on_exit_title">在應用程式切換時最小化</string>
<string name="minimize_on_exit_summary">當從主影片播放器切換到其他應用程式時要進行的動作 — %s</string>
<string name="minimize_on_exit_none_description"></string>
<string name="minimize_on_exit_background_description">最小化為背景播放器</string>
<string name="minimize_on_exit_popup_description">最小化為彈出式播放器</string>
<string name="skip_silence_checkbox">在靜音時快轉</string>
<string name="playback_step">步進</string>
<string name="playback_reset">重設</string>
<string name="channels">頻道</string>
<string name="playlists">播放清單</string>
<string name="tracks"></string>
<string name="users">使用者</string>
</resources>

View File

@ -93,8 +93,8 @@
<string name="audio_m4a_key" translatable="false">audio_m4a</string>
<string name="audio_webm_key" translatable="false">audio_webm</string>
<string-array name="audio_format_description_list" translatable="false">
<item>@string/m4a_description</item>
<item>@string/webm_description</item>
<item>M4A</item>
<item>WebM</item>
</string-array>
<string-array name="audio_format_values_list" translatable="false">
<item>@string/audio_m4a_key</item>

View File

@ -65,8 +65,6 @@
<string name="play_audio">Audio</string>
<string name="default_audio_format_title">Default audio format</string>
<string name="default_video_format_title">Default video format</string>
<string name="webm_description">WebM — libre format</string>
<string name="m4a_description">M4A — better quality</string>
<string name="theme_title">Theme</string>
<string name="light_theme_title">Light</string>
<string name="dark_theme_title">Dark</string>
@ -126,7 +124,12 @@
<string name="error_report_title">Error report</string>
<string name="all">All</string>
<string name="channel">Channel</string>
<string name="channels">Channels</string>
<string name="playlist">Playlist</string>
<string name="playlists">Playlists</string>
<string name="videos">Videos</string>
<string name="tracks">Tracks</string>
<string name="users">Users</string>
<string name="yes">Yes</string>
<string name="later">Later</string>
<string name="disabled">Disabled</string>
@ -480,9 +483,10 @@
<string name="playback_speed_control">Playback Speed Controls</string>
<string name="playback_tempo">Tempo</string>
<string name="playback_pitch">Pitch</string>
<string name="unhook_checkbox">Unhook (may cause distortion)</string>
<string name="playback_nightcore">Nightcore</string>
<string name="playback_default">Default</string>
<string name="unhook_checkbox">Unlink (may cause distortion)</string>
<string name="skip_silence_checkbox">Fast-forward during silence</string>
<string name="playback_step">Step</string>
<string name="playback_reset">Reset</string>
<!-- GDPR dialog -->
<string name="start_accept_privacy_policy">In order to comply with the European General Data Protection Regulation (GDPR), we herby draw your attention to NewPipe\'s privacy policy. Please read it carefully.\nYou must accept it to send us the bug report.</string>

View File

@ -6,7 +6,7 @@ buildscript {
google()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.1.2'
classpath 'com.android.tools.build:gradle:3.1.3'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files

View File

@ -0,0 +1,28 @@
### Improvements
- Disable burgermenu icon animation #1486
- undo delete of downloads #1472
- Download option in share menu #1498
- Added share option to long tap menu #1454
- Minimize main player on exit #1354
- Library version update and database backup fix #1510
- ExoPlayer 2.8.2 Update #1392
- Reworked the playback speed control dialog to support different step sizes for faster speed change.
- Added a toggle to fast-forward during silences in playback speed control. This should be helpful for audiobooks and certain music genres, and can bring a true seamless experience (and can break a song with lots of silences =\\).
- Refactored media source resolution to allow passing metadata alongside media internally in the player, rather than doing so manually. Now we have a single source of metadata and is directly available when playback starts.
- Fixed remote playlist metadata not updating when new metadata is available when playlist fragment is opened.
- Various UI fixes: #1383, background player notification controls now always white, easier to shutdown popup player through flinging
- Use new extractor with refactored architecture for multiservice
### Fixes
- Fix #1440 Broken Video Info Layout #1491
- View history fix #1497
- #1495, by updating the metadata (thumbnail, title and video count) as soon as the user access the playlist.
- #1475, by registering a view in the database when the user starts a video on external player on detail fragment.
- Fix creen timeout in case of popup mode. #1463 (Fixed #640)
- Main video player fix #1509
- [#1412] Fixed repeat mode causing player NPE when new intent is received while player activity is in background.
- Fixed minimizing player to popup does not destroy player when popup permission is not granted.

View File

@ -0,0 +1,34 @@
# Changelog of v0.13.7
### Fixed
- Fix sort filter issues of v0.13.6
# Changelog of v0.13.6
### Improvements
- Disable burgermenu icon animation #1486
- undo delete of downloads #1472
- Download option in share menu #1498
- Added share option to long tap menu #1454
- Minimize main player on exit #1354
- Library version update and database backup fix #1510
- ExoPlayer 2.8.2 Update #1392
- Reworked the playback speed control dialog to support different step sizes for faster speed change.
- Added a toggle to fast-forward during silences in playback speed control. This should be helpful for audiobooks and certain music genres, and can bring a true seamless experience (and can break a song with lots of silences =\\).
- Refactored media source resolution to allow passing metadata alongside media internally in the player, rather than doing so manually. Now we have a single source of metadata and is directly available when playback starts.
- Fixed remote playlist metadata not updating when new metadata is available when playlist fragment is opened.
- Various UI fixes: #1383, background player notification controls now always white, easier to shutdown popup player through flinging
- Use new extractor with refactored architecture for multiservice
### Fixes
- Fix #1440 Broken Video Info Layout #1491
- View history fix #1497
- #1495, by updating the metadata (thumbnail, title and video count) as soon as the user access the playlist.
- #1475, by registering a view in the database when the user starts a video on external player on detail fragment.
- Fix creen timeout in case of popup mode. #1463 (Fixed #640)
- Main video player fix #1509
- [#1412] Fixed repeat mode causing player NPE when new intent is received while player activity is in background.
- Fixed minimizing player to popup does not destroy player when popup permission is not granted.