Skip to content
Snippets Groups Projects
Commit 0eabab95 authored by Nicolas Pomepuy's avatar Nicolas Pomepuy Committed by Geoffrey Métais
Browse files

End of TV migration to kotlin

parent 65d29011
No related branches found
No related tags found
1 merge request!76Kt migration
Showing
with 698 additions and 619 deletions
/*****************************************************************************
* CardPresenter.java
*****************************************************************************
* Copyright © 2014-2015 VLC authors, VideoLAN and VideoLabs
* Author: Geoffrey Métais
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
package org.videolan.vlc.gui.tv;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Build;
import android.text.TextUtils;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import org.videolan.medialibrary.Tools;
import org.videolan.medialibrary.media.MediaLibraryItem;
import org.videolan.medialibrary.media.MediaWrapper;
import org.videolan.vlc.R;
import org.videolan.vlc.VLCApplication;
import org.videolan.vlc.gui.helpers.AudioUtil;
import org.videolan.vlc.gui.helpers.ImageLoaderKt;
import org.videolan.vlc.util.Constants;
import org.videolan.vlc.util.Settings;
import java.util.List;
import androidx.core.content.ContextCompat;
import androidx.leanback.widget.ImageCardView;
import androidx.leanback.widget.Presenter;
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
public class CardPresenter extends Presenter {
private static final String TAG = "CardPresenter";
private Activity mContext;
private Resources mRes;
private static final int CARD_WIDTH = VLCApplication.getAppResources().getDimensionPixelSize(R.dimen.tv_grid_card_thumb_width);
private static final int CARD_HEIGHT = VLCApplication.getAppResources().getDimensionPixelSize(R.dimen.tv_grid_card_thumb_height);
private static Drawable sDefaultCardImage;
private boolean mIsSeenMediaMarkerVisible = true;
public CardPresenter(Activity context){
mContext = context;
mRes = mContext.getResources();
sDefaultCardImage = ContextCompat.getDrawable(mContext, R.drawable.ic_default_cone);
mIsSeenMediaMarkerVisible = Settings.INSTANCE.getInstance(context).getBoolean("media_seen", true);
}
class ViewHolder extends Presenter.ViewHolder {
private ImageCardView mCardView;
public ViewHolder(View view) {
super(view);
mCardView = (ImageCardView) view;
mCardView.getMainImageView().setScaleType(ImageView.ScaleType.FIT_CENTER);
}
void updateCardViewImage(MediaLibraryItem item) {
final boolean noArt = TextUtils.isEmpty(item.getArtworkMrl());
if (item instanceof MediaWrapper) {
final MediaWrapper media = (MediaWrapper) item;
final boolean group = media.getType() == MediaWrapper.TYPE_GROUP;
final boolean folder = media.getType() == MediaWrapper.TYPE_DIR;
final boolean video = media.getType() == MediaWrapper.TYPE_VIDEO;
if (!folder && (group || (video && !media.isThumbnailGenerated()))) {
if (noArt) {
mCardView.getMainImageView().setScaleType(ImageView.ScaleType.FIT_CENTER);
mCardView.setMainImage(new BitmapDrawable(mCardView.getResources(), getDefaultImage(item)));
}
ImageLoaderKt.loadImage(mCardView, item);
return;
}
}
if (noArt) {
mCardView.getMainImageView().setScaleType(ImageView.ScaleType.FIT_CENTER);
mCardView.setMainImage(new BitmapDrawable(mCardView.getResources(), getDefaultImage(item)));
} else ImageLoaderKt.loadImage(mCardView, item);
}
private Bitmap getDefaultImage(MediaLibraryItem mediaLibraryItem) {
Bitmap picture;
final Resources res = mCardView.getResources();
if (mediaLibraryItem.getItemType() == MediaLibraryItem.TYPE_MEDIA && ((MediaWrapper) mediaLibraryItem).getType() == MediaWrapper.TYPE_DIR) {
final MediaWrapper mediaWrapper = (MediaWrapper) mediaLibraryItem;
if (TextUtils.equals(mediaWrapper.getUri().getScheme(), "file"))
picture = BitmapFactory.decodeResource(res, R.drawable.ic_menu_folder_big);
else
picture = BitmapFactory.decodeResource(res, R.drawable.ic_menu_network_big);
} else picture = AudioUtil.readCoverBitmap(Uri.decode(mediaLibraryItem.getArtworkMrl()), res.getDimensionPixelSize(R.dimen.tv_grid_card_thumb_width));
if (picture == null) picture = BitmapFactory.decodeResource(res, TvUtil.INSTANCE.getIconRes(mediaLibraryItem));
return picture;
}
void updateCardViewImage(Drawable image) {
mCardView.setMainImage(image);
mCardView.getMainImageView().setScaleType(ImageView.ScaleType.FIT_CENTER);
}
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent) {
ImageCardView cardView = new ImageCardView(mContext);
cardView.setFocusable(true);
cardView.setFocusableInTouchMode(true);
cardView.setBackgroundColor(ContextCompat.getColor(mContext, R.color.lb_details_overview_bg_color));
cardView.setMainImageDimensions(CARD_WIDTH, CARD_HEIGHT);
return new ViewHolder(cardView);
}
@Override
public void onBindViewHolder(Presenter.ViewHolder viewHolder, final Object item) {
final ViewHolder holder = ((ViewHolder) viewHolder);
if (item instanceof MediaWrapper) {
final MediaWrapper mw = (MediaWrapper) item;
holder.mCardView.setTitleText(mw.getTitle());
holder.mCardView.setContentText(mw.getDescription());
holder.updateCardViewImage(mw);
if (mIsSeenMediaMarkerVisible
&& mw.getType() == MediaWrapper.TYPE_VIDEO
&& mw.getSeen() > 0L)
holder.mCardView.setBadgeImage(ContextCompat.getDrawable(mContext, R.drawable.ic_seen_tv_normal));
holder.view.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
TvUtil.INSTANCE.showMediaDetail(v.getContext(), mw);
return true;
}
});
} else if (item instanceof MediaLibraryItem) {
final MediaLibraryItem mediaLibraryItem = (MediaLibraryItem) item;
holder.mCardView.setTitleText(mediaLibraryItem.getTitle());
holder.mCardView.setContentText(mediaLibraryItem.getDescription());
holder.updateCardViewImage(mediaLibraryItem);
} else if (item instanceof String){
holder.mCardView.setTitleText((String) item);
holder.mCardView.setContentText("");
holder.updateCardViewImage(sDefaultCardImage);
}
}
@Override
public void onBindViewHolder(Presenter.ViewHolder viewHolder, Object item, List<Object> payloads) {
if (payloads.isEmpty()) onBindViewHolder(viewHolder, item);
else {
final ViewHolder holder = ((ViewHolder) viewHolder);
final MediaLibraryItem media = (MediaLibraryItem) item;
for (Object data : payloads) {
switch ((int) data) {
case Constants.UPDATE_DESCRIPTION:
holder.mCardView.setContentText(media.getDescription());
break;
case Constants.UPDATE_THUMB:
ImageLoaderKt.loadImage(holder.mCardView, media);
break;
case Constants.UPDATE_TIME:
final MediaWrapper mediaWrapper = (MediaWrapper) item;
Tools.setMediaDescription(mediaWrapper);
holder.mCardView.setContentText(mediaWrapper.getDescription());
if (mediaWrapper.getTime() > 0) break; //update seen check if time is reset to 0
case Constants.UPDATE_SEEN:
final MediaWrapper mw = (MediaWrapper) item;
if (mIsSeenMediaMarkerVisible && mw.getType() == MediaWrapper.TYPE_VIDEO
&& mw.getSeen() > 0L)
holder.mCardView.setBadgeImage(ContextCompat.getDrawable(mContext, R.drawable.ic_seen_tv_normal));
break;
}
}
}
}
@Override
public void onUnbindViewHolder(Presenter.ViewHolder viewHolder) {
}
@Override
public void onViewAttachedToWindow(Presenter.ViewHolder viewHolder) {
// TODO?
}
}
/*****************************************************************************
* CardPresenter.java
*
* Copyright © 2014-2015 VLC authors, VideoLAN and VideoLabs
* Author: Geoffrey Métais
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*/
package org.videolan.vlc.gui.tv
import android.annotation.TargetApi
import android.app.Activity
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.drawable.BitmapDrawable
import android.graphics.drawable.Drawable
import android.net.Uri
import android.os.Build
import android.text.TextUtils
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import androidx.core.content.ContextCompat
import androidx.leanback.widget.ImageCardView
import androidx.leanback.widget.Presenter
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.ObsoleteCoroutinesApi
import org.videolan.medialibrary.Tools
import org.videolan.medialibrary.media.MediaLibraryItem
import org.videolan.medialibrary.media.MediaWrapper
import org.videolan.vlc.R
import org.videolan.vlc.VLCApplication
import org.videolan.vlc.gui.helpers.AudioUtil
import org.videolan.vlc.gui.helpers.loadImage
import org.videolan.vlc.util.*
@ObsoleteCoroutinesApi
@ExperimentalCoroutinesApi
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
class CardPresenter(private val context: Activity) : Presenter() {
private var mIsSeenMediaMarkerVisible = true
private var sDefaultCardImage: Drawable? = ContextCompat.getDrawable(context, R.drawable.ic_default_cone)
init {
mIsSeenMediaMarkerVisible = Settings.getInstance(context).getBoolean("media_seen", true)
}
inner class ViewHolder(view: View) : Presenter.ViewHolder(view) {
val cardView: ImageCardView = view as ImageCardView
init {
cardView.mainImageView.scaleType = ImageView.ScaleType.FIT_CENTER
}
fun updateCardViewImage(item: MediaLibraryItem) {
val noArt = TextUtils.isEmpty(item.artworkMrl)
if (item is MediaWrapper) {
val group = item.type == MediaWrapper.TYPE_GROUP
val folder = item.type == MediaWrapper.TYPE_DIR
val video = item.type == MediaWrapper.TYPE_VIDEO
if (!folder && (group || video && !item.isThumbnailGenerated)) {
if (noArt) {
cardView.mainImageView.scaleType = ImageView.ScaleType.FIT_CENTER
cardView.mainImage = BitmapDrawable(cardView.resources, getDefaultImage(item))
}
loadImage(cardView, item)
return
}
}
if (noArt) {
cardView.mainImageView.scaleType = ImageView.ScaleType.FIT_CENTER
cardView.mainImage = BitmapDrawable(cardView.resources, getDefaultImage(item))
} else
loadImage(cardView, item)
}
private fun getDefaultImage(mediaLibraryItem: MediaLibraryItem): Bitmap? {
var picture: Bitmap?
val res = cardView.resources
picture = if (mediaLibraryItem.itemType == MediaLibraryItem.TYPE_MEDIA && (mediaLibraryItem as MediaWrapper).type == MediaWrapper.TYPE_DIR) {
if (TextUtils.equals(mediaLibraryItem.uri.scheme, "file"))
BitmapFactory.decodeResource(res, R.drawable.ic_menu_folder_big)
else
BitmapFactory.decodeResource(res, R.drawable.ic_menu_network_big)
} else
AudioUtil.readCoverBitmap(Uri.decode(mediaLibraryItem.artworkMrl), res.getDimensionPixelSize(R.dimen.tv_grid_card_thumb_width))
if (picture == null) picture = BitmapFactory.decodeResource(res, TvUtil.getIconRes(mediaLibraryItem))
return picture
}
fun updateCardViewImage(image: Drawable?) {
cardView.mainImage = image
cardView.mainImageView.scaleType = ImageView.ScaleType.FIT_CENTER
}
}
override fun onCreateViewHolder(parent: ViewGroup): ViewHolder {
val cardView = ImageCardView(context)
cardView.isFocusable = true
cardView.isFocusableInTouchMode = true
cardView.setBackgroundColor(ContextCompat.getColor(context, R.color.lb_details_overview_bg_color))
cardView.setMainImageDimensions(CARD_WIDTH, CARD_HEIGHT)
return ViewHolder(cardView)
}
override fun onBindViewHolder(viewHolder: Presenter.ViewHolder, item: Any) {
val holder = viewHolder as ViewHolder
when (item) {
is MediaWrapper -> {
holder.cardView.titleText = item.title
holder.cardView.contentText = item.description
holder.updateCardViewImage(item)
if (mIsSeenMediaMarkerVisible
&& item.type == MediaWrapper.TYPE_VIDEO
&& item.seen > 0L)
holder.cardView.badgeImage = ContextCompat.getDrawable(context, R.drawable.ic_seen_tv_normal)
holder.view.setOnLongClickListener { v ->
TvUtil.showMediaDetail(v.context, item)
true
}
}
is MediaLibraryItem -> {
holder.cardView.titleText = item.title
holder.cardView.contentText = item.description
holder.updateCardViewImage(item)
}
is String -> {
holder.cardView.titleText = item
holder.cardView.contentText = ""
holder.updateCardViewImage(sDefaultCardImage)
}
}
}
override fun onBindViewHolder(viewHolder: Presenter.ViewHolder, item: Any, payloads: List<Any>?) {
if (payloads!!.isEmpty())
onBindViewHolder(viewHolder, item)
else {
val holder = viewHolder as ViewHolder
val media = item as MediaLibraryItem
for (data in payloads) {
when (data as Int) {
UPDATE_DESCRIPTION -> holder.cardView.contentText = media.description
UPDATE_THUMB -> loadImage(holder.cardView, media)
UPDATE_TIME -> {
val mediaWrapper = item as MediaWrapper
Tools.setMediaDescription(mediaWrapper)
holder.cardView.contentText = mediaWrapper.description
if (mediaWrapper.time <= 0) {
if (mIsSeenMediaMarkerVisible && item.type == MediaWrapper.TYPE_VIDEO
&& item.seen > 0L)
holder.cardView.badgeImage = ContextCompat.getDrawable(context, R.drawable.ic_seen_tv_normal)
}
}
UPDATE_SEEN -> {
val mw = item as MediaWrapper
if (mIsSeenMediaMarkerVisible && mw.type == MediaWrapper.TYPE_VIDEO && mw.seen > 0L)
holder.cardView.badgeImage = ContextCompat.getDrawable(context, R.drawable.ic_seen_tv_normal)
}
}
}
}
}
override fun onUnbindViewHolder(viewHolder: Presenter.ViewHolder) {}
override fun onViewAttachedToWindow(viewHolder: Presenter.ViewHolder?) {
// TODO?
}
companion object {
private const val TAG = "CardPresenter"
private val CARD_WIDTH = VLCApplication.getAppResources().getDimensionPixelSize(R.dimen.tv_grid_card_thumb_width)
private val CARD_HEIGHT = VLCApplication.getAppResources().getDimensionPixelSize(R.dimen.tv_grid_card_thumb_height)
}
}
/*****************************************************************************
* DetailsActivity.java
*****************************************************************************
*
* Copyright © 2014-2015 VLC authors, VideoLAN and VideoLabs
* Author: Geoffrey Métais
*
......@@ -17,21 +17,23 @@
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
package org.videolan.vlc.gui.tv;
*/
package org.videolan.vlc.gui.tv
import android.os.Bundle;
import android.os.Bundle
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.ObsoleteCoroutinesApi
import org.videolan.vlc.R;
import org.videolan.vlc.gui.tv.browser.BaseTvActivity;
import org.videolan.vlc.R
import org.videolan.vlc.gui.tv.browser.BaseTvActivity
public class DetailsActivity extends BaseTvActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.tv_details);
@ExperimentalCoroutinesApi
@ObsoleteCoroutinesApi
class DetailsActivity : BaseTvActivity() {
public override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.tv_details)
}
@Override
protected void refresh() {}
override fun refresh() {}
}
/*****************************************************************************
* DetailsDescriptionPresenter.java
*****************************************************************************
*
* Copyright © 2014-2015 VLC authors, VideoLAN and VideoLabs
* Author: Geoffrey Métais
*
......@@ -17,29 +17,32 @@
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
package org.videolan.vlc.gui.tv;
*/
package org.videolan.vlc.gui.tv
import android.net.Uri;
import androidx.leanback.widget.AbstractDetailsDescriptionPresenter;
import android.net.Uri
import androidx.leanback.widget.AbstractDetailsDescriptionPresenter
public class DetailsDescriptionPresenter extends
AbstractDetailsDescriptionPresenter {
public static final String TAG ="DetailsDescriptionPresenter";
class DetailsDescriptionPresenter : AbstractDetailsDescriptionPresenter() {
@Override
protected void onBindDescription(ViewHolder viewHolder, Object itemData) {
MediaItemDetails details = (MediaItemDetails) itemData;
override fun onBindDescription(viewHolder: ViewHolder, itemData: Any) {
val details = itemData as MediaItemDetails
// In a production app, the itemData object contains the information
// needed to display details for the media item:
// viewHolder.getTitle().setText(details.getShortTitle());
// Here we provide static data for testing purposes:
String body = details.getBody() == null ? Uri.decode(details.getLocation()) :
details.getBody()+"\n"+Uri.decode(details.getLocation());
viewHolder.getTitle().setText(details.getTitle());
viewHolder.getSubtitle().setText(details.getSubTitle());
viewHolder.getBody().setText(body);
val body = if (details.body == null)
Uri.decode(details.location)
else
details.body + "\n" + Uri.decode(details.location)
viewHolder.title.text = details.title
viewHolder.subtitle.text = details.subTitle
viewHolder.body.text = body
}
companion object {
const val TAG = "DetailsDescriptionPresenter"
}
......
/*****************************************************************************
* MainTvActivity.java
*****************************************************************************
* Copyright © 2014-2018 VLC authors, VideoLAN and VideoLabs
* Author: Geoffrey Métais
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
package org.videolan.vlc.gui.tv;
import android.annotation.TargetApi;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.KeyEvent;
import android.view.View;
import android.widget.ProgressBar;
import org.videolan.medialibrary.Medialibrary;
import org.videolan.vlc.MediaParsingServiceKt;
import org.videolan.vlc.R;
import org.videolan.vlc.ScanProgress;
import org.videolan.vlc.StartActivity;
import org.videolan.vlc.gui.preferences.PreferencesActivity;
import org.videolan.vlc.gui.tv.browser.BaseTvActivity;
import org.videolan.vlc.util.Permissions;
import org.videolan.vlc.util.Util;
import androidx.fragment.app.FragmentManager;
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
public class MainTvActivity extends BaseTvActivity {
public static final int ACTIVITY_RESULT_PREFERENCES = 1;
public static final String BROWSER_TYPE = "browser_type";
public static final String TAG = "VLC/MainTvActivity";
protected MainTvFragment mBrowseFragment;
private ProgressBar mProgressBar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Util.checkCpuCompatibility(this);
// Delay access permission dialog prompt to avoid background corruption
if (!Permissions.canReadStorage(this))
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
Permissions.checkReadStoragePermission(MainTvActivity.this, false);
}
}, 1000);
setContentView(R.layout.tv_main);
final FragmentManager fragmentManager = getSupportFragmentManager();
mBrowseFragment = (MainTvFragment) fragmentManager.findFragmentById(R.id.browse_fragment);
mProgressBar = findViewById(R.id.tv_main_progress);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == ACTIVITY_RESULT_PREFERENCES) {
switch (resultCode) {
case PreferencesActivity.RESULT_RESCAN:
MediaParsingServiceKt.reloadLibrary(this);
break;
case PreferencesActivity.RESULT_RESTART:
case PreferencesActivity.RESULT_RESTART_APP:
Intent intent = getIntent();
intent.setClass(this, resultCode == PreferencesActivity.RESULT_RESTART_APP ? StartActivity.class : MainTvActivity.class);
finish();
startActivity(intent);
break;
}
}
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if ((keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE || keyCode == KeyEvent.KEYCODE_BUTTON_Y)) {
return mBrowseFragment.showDetails();
}
return super.onKeyDown(keyCode, event);
}
@Override
protected void onParsingServiceStarted() {
mHandler.sendEmptyMessage(SHOW_LOADING);
}
@Override
protected void onParsingServiceProgress(ScanProgress scanProgress) {
if (mProgressBar.getVisibility() == View.GONE && Medialibrary.getInstance().isWorking())
mHandler.sendEmptyMessage(SHOW_LOADING);
}
@Override
protected void onParsingServiceFinished() {
if (!Medialibrary.getInstance().isWorking())
mHandler.sendEmptyMessageDelayed(HIDE_LOADING, 500);
}
public void hideLoading() {
mHandler.sendEmptyMessageDelayed(HIDE_LOADING, 500);
}
private static final int SHOW_LOADING = 0;
private static final int HIDE_LOADING = 1;
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case SHOW_LOADING:
mProgressBar.setVisibility(View.VISIBLE);
break;
case HIDE_LOADING:
removeMessages(SHOW_LOADING);
mProgressBar.setVisibility(View.GONE);
default:
super.handleMessage(msg);
}
}
};
@Override
protected void refresh() {
MediaParsingServiceKt.reloadLibrary(this);
}
}
/*****************************************************************************
* MainTvActivity.java
*
* Copyright © 2014-2018 VLC authors, VideoLAN and VideoLabs
* Author: Geoffrey Métais
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*/
package org.videolan.vlc.gui.tv
import android.annotation.TargetApi
import android.content.Intent
import android.os.Build
import android.os.Bundle
import android.os.Message
import android.view.KeyEvent
import android.view.View
import android.widget.ProgressBar
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.ObsoleteCoroutinesApi
import org.videolan.medialibrary.Medialibrary
import org.videolan.vlc.R
import org.videolan.vlc.ScanProgress
import org.videolan.vlc.StartActivity
import org.videolan.vlc.gui.preferences.PreferencesActivity
import org.videolan.vlc.gui.tv.browser.BaseTvActivity
import org.videolan.vlc.reloadLibrary
import org.videolan.vlc.util.Permissions
import org.videolan.vlc.util.Util
import org.videolan.vlc.util.WeakHandler
@ExperimentalCoroutinesApi
@ObsoleteCoroutinesApi
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
class MainTvActivity : BaseTvActivity() {
private lateinit var browseFragment: MainTvFragment
private lateinit var progressBar: ProgressBar
private val handler = MainTvActivityHandler(this)
class MainTvActivityHandler(owner: MainTvActivity) : WeakHandler<MainTvActivity>(owner) {
override fun handleMessage(msg: Message) {
val activity = owner ?: return
when (msg.what) {
SHOW_LOADING -> activity.progressBar.visibility = View.VISIBLE
HIDE_LOADING -> {
removeMessages(SHOW_LOADING)
activity.progressBar.visibility = View.GONE
super.handleMessage(msg)
}
else -> super.handleMessage(msg)
}
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Util.checkCpuCompatibility(this)
// Delay access permission dialog prompt to avoid background corruption
if (!Permissions.canReadStorage(this))
handler.postDelayed({ Permissions.checkReadStoragePermission(this@MainTvActivity, false) }, 1000)
setContentView(R.layout.tv_main)
val fragmentManager = supportFragmentManager
browseFragment = fragmentManager.findFragmentById(R.id.browse_fragment) as MainTvFragment
progressBar = findViewById(R.id.tv_main_progress)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == ACTIVITY_RESULT_PREFERENCES) {
when (resultCode) {
PreferencesActivity.RESULT_RESCAN -> this.reloadLibrary()
PreferencesActivity.RESULT_RESTART, PreferencesActivity.RESULT_RESTART_APP -> {
val intent = intent
intent.setClass(this, if (resultCode == PreferencesActivity.RESULT_RESTART_APP) StartActivity::class.java else MainTvActivity::class.java)
finish()
startActivity(intent)
}
}
}
}
override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
return if (keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE || keyCode == KeyEvent.KEYCODE_BUTTON_Y) {
browseFragment.showDetails()
} else super.onKeyDown(keyCode, event)
}
override fun onParsingServiceStarted() {
handler.sendEmptyMessage(SHOW_LOADING)
}
override fun onParsingServiceProgress(scanProgress: ScanProgress?) {
if (progressBar.visibility == View.GONE && Medialibrary.getInstance().isWorking)
handler.sendEmptyMessage(SHOW_LOADING)
}
override fun onParsingServiceFinished() {
if (!Medialibrary.getInstance().isWorking)
handler.sendEmptyMessageDelayed(HIDE_LOADING, 500)
}
fun hideLoading() {
handler.sendEmptyMessageDelayed(HIDE_LOADING, 500)
}
override fun refresh() {
this.reloadLibrary()
}
companion object {
const val ACTIVITY_RESULT_PREFERENCES = 1
const val BROWSER_TYPE = "browser_type"
const val TAG = "VLC/MainTvActivity"
private const val SHOW_LOADING = 0
private const val HIDE_LOADING = 1
}
}
/*****************************************************************************
* MediaItemDetails.java
*****************************************************************************
*
* Copyright © 2014-2015 VLC authors, VideoLAN and VideoLabs
* Author: Geoffrey Métais
*
......@@ -17,77 +17,44 @@
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
package org.videolan.vlc.gui.tv;
import android.os.Parcel;
import android.os.Parcelable;
public class MediaItemDetails implements Parcelable {
private String title, subTitle, body, location, artworkUrl;
public MediaItemDetails(String title, String subTitle, String body, String location, String artworkUrl) {
this.title = title;
this.subTitle = subTitle;
this.body = body;
this.location = location;
this.artworkUrl = artworkUrl;
}
public String getTitle() {
return title;
}
public String getSubTitle() {
return subTitle;
}
public String getBody() {
return body;
}
public String getLocation(){
return location;
}
public String getArtworkUrl() {
return artworkUrl;
}
@Override
public int describeContents() {
// TODO Auto-generated method stub
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(title);
dest.writeString(subTitle);
dest.writeString(body);
dest.writeString(location);
dest.writeString(artworkUrl);
}
public static final Parcelable.Creator<MediaItemDetails> CREATOR
= new Parcelable.Creator<MediaItemDetails>() {
@Override
public MediaItemDetails createFromParcel(Parcel in) {
return new MediaItemDetails(in);
*/
package org.videolan.vlc.gui.tv
import android.os.Parcel
import android.os.Parcelable
data class MediaItemDetails(var title: String? = null, var subTitle: String? = null,
var body: String? = null,
var location: String? = null,
var artworkUrl: String? = null) : Parcelable {
constructor(parcel: Parcel) : this(
parcel.readString(),
parcel.readString(),
parcel.readString(),
parcel.readString(),
parcel.readString())
override fun writeToParcel(parcel: Parcel, flags: Int) {
parcel.writeString(title)
parcel.writeString(subTitle)
parcel.writeString(body)
parcel.writeString(location)
parcel.writeString(artworkUrl)
}
override fun describeContents(): Int {
return 0
}
companion object CREATOR : Parcelable.Creator<MediaItemDetails> {
override fun createFromParcel(parcel: Parcel): MediaItemDetails {
return MediaItemDetails(parcel)
}
@Override
public MediaItemDetails[] newArray(int size) {
return new MediaItemDetails[size];
override fun newArray(size: Int): Array<MediaItemDetails?> {
return arrayOfNulls(size)
}
};
private MediaItemDetails(Parcel in) {
title = in.readString();
subTitle = in.readString();
body = in.readString();
location = in.readString();
artworkUrl = in.readString();
}
}
/*****************************************************************************
* MediaItemDetailsFragment.java
*****************************************************************************
* Copyright © 2014-2019 VLC authors, VideoLAN and VideoLabs
* Author: Geoffrey Métais
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
package org.videolan.vlc.gui.tv;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.text.TextUtils;
import android.widget.Toast;
import org.videolan.libvlc.util.AndroidUtil;
import org.videolan.medialibrary.media.MediaWrapper;
import org.videolan.vlc.R;
import org.videolan.vlc.gui.helpers.AudioUtil;
import org.videolan.vlc.gui.helpers.UiTools;
import org.videolan.vlc.gui.video.VideoPlayerActivity;
import org.videolan.vlc.media.MediaUtils;
import org.videolan.vlc.repository.BrowserFavRepository;
import org.videolan.vlc.util.FileUtils;
import org.videolan.vlc.util.WorkersKt;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.FragmentActivity;
import androidx.leanback.app.BackgroundManager;
import androidx.leanback.app.DetailsSupportFragment;
import androidx.leanback.widget.Action;
import androidx.leanback.widget.ArrayObjectAdapter;
import androidx.leanback.widget.ClassPresenterSelector;
import androidx.leanback.widget.DetailsOverviewRow;
import androidx.leanback.widget.FullWidthDetailsOverviewRowPresenter;
import androidx.leanback.widget.ListRow;
import androidx.leanback.widget.ListRowPresenter;
import androidx.leanback.widget.OnActionClickedListener;
import static org.videolan.vlc.util.Constants.ACTION_REMOTE_STOP;
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
public class MediaItemDetailsFragment extends DetailsSupportFragment {
private static final String TAG = "MediaItemDetailsFragment";
private static final int ID_PLAY = 1;
private static final int ID_LISTEN = 2;
private static final int ID_FAVORITE_ADD = 3;
private static final int ID_FAVORITE_DELETE = 4;
private static final int ID_BROWSE = 5;
private static final int ID_DL_SUBS = 6;
private static final int ID_PLAY_FROM_START = 7;
private BackgroundManager mBackgroundManager;
private ArrayObjectAdapter mRowsAdapter;
private MediaItemDetails mMedia;
private MediaWrapper mMediaWrapper;
private BrowserFavRepository mBrowserFavRepository;
private boolean mMediaStarted;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mBackgroundManager = BackgroundManager.getInstance(requireActivity());
mBackgroundManager.setAutoReleaseOnStop(false);
mBrowserFavRepository = BrowserFavRepository.Companion.getInstance(requireContext());
mMediaStarted = false;
buildDetails();
}
@Override
public void onResume() {
super.onResume();
if (!mBackgroundManager.isAttached()) mBackgroundManager.attachToView(getView());
}
@Override
public void onPause() {
mBackgroundManager.release();
super.onPause();
if (mMediaStarted) {
final Context ctx = getContext();
if (ctx != null) {
ctx.sendBroadcast(new Intent(ACTION_REMOTE_STOP));
}
}
}
private void buildDetails() {
final Bundle extras = requireActivity().getIntent().getExtras();
if (extras == null) return;
mMedia = extras.getParcelable("item");
boolean hasMedia = extras.containsKey("media");
final ClassPresenterSelector selector = new ClassPresenterSelector();
final MediaWrapper media = hasMedia ? (MediaWrapper) extras.getParcelable("media") : new MediaWrapper(AndroidUtil.LocationToUri(mMedia.getLocation()));
if (!hasMedia){
media.setDisplayTitle(mMedia.getTitle());
}
mMediaWrapper = media;
setTitle(media.getTitle());
// Attach your media item details presenter to the row presenter:
FullWidthDetailsOverviewRowPresenter rowPresenter = new FullWidthDetailsOverviewRowPresenter(new DetailsDescriptionPresenter());
final FragmentActivity activity = requireActivity();
final DetailsOverviewRow detailsOverview = new DetailsOverviewRow(mMedia);
final Action actionAdd = new Action(ID_FAVORITE_ADD, getString(R.string.favorites_add));
final Action actionDelete = new Action(ID_FAVORITE_DELETE, getString(R.string.favorites_remove));
rowPresenter.setBackgroundColor(ContextCompat.getColor(activity, R.color.orange500));
rowPresenter.setOnActionClickedListener(new OnActionClickedListener() {
@Override
public void onActionClicked(Action action) {
switch ((int)action.getId()){
case ID_LISTEN:
MediaUtils.INSTANCE.openMedia(activity, mMediaWrapper);
mMediaStarted = true;
break;
case ID_PLAY:
mMediaStarted = false;
TvUtil.INSTANCE.playMedia(activity, media);
activity.finish();
break;
case ID_FAVORITE_ADD:
final Uri uri = Uri.parse(mMedia.getLocation());
final boolean local = "file".equals(uri.getScheme());
if (local) mBrowserFavRepository.addLocalFavItem(uri, mMedia.getTitle(), mMedia.getArtworkUrl());
else mBrowserFavRepository.addNetworkFavItem(uri, mMedia.getTitle(), mMedia.getArtworkUrl());
detailsOverview.removeAction(actionAdd);
detailsOverview.addAction(actionDelete);
mRowsAdapter.notifyArrayItemRangeChanged(0, mRowsAdapter.size());
Toast.makeText(activity, R.string.favorite_added, Toast.LENGTH_SHORT).show();
break;
case ID_FAVORITE_DELETE:
WorkersKt.runIO(new Runnable() {
@Override
public void run() {
mBrowserFavRepository.deleteBrowserFav(Uri.parse(mMedia.getLocation()));
}
});
detailsOverview.removeAction(actionDelete);
detailsOverview.addAction(actionAdd);
mRowsAdapter.notifyArrayItemRangeChanged(0, mRowsAdapter.size());
Toast.makeText(activity, R.string.favorite_removed, Toast.LENGTH_SHORT).show();
break;
case ID_BROWSE:
TvUtil.INSTANCE.openMedia(activity, media, null);
break;
case ID_DL_SUBS:
MediaUtils.INSTANCE.getSubs(requireActivity(), media);
break;
case ID_PLAY_FROM_START:
mMediaStarted = false;
VideoPlayerActivity.Companion.start(getActivity(), media.getUri(), true);
activity.finish();
break;
}
}
});
selector.addClassPresenter(DetailsOverviewRow.class, rowPresenter);
selector.addClassPresenter(ListRow.class,
new ListRowPresenter());
mRowsAdapter = new ArrayObjectAdapter(selector);
WorkersKt.runIO(new Runnable() {
@Override
public void run() {
final Bitmap cover = media.getType() == MediaWrapper.TYPE_AUDIO || media.getType() == MediaWrapper.TYPE_VIDEO
? AudioUtil.readCoverBitmap(mMedia.getArtworkUrl(), 512) : null;
final Bitmap blurred = cover != null ? UiTools.blurBitmap(cover) : null;
final boolean browserFavExists = mBrowserFavRepository.browserFavExists((Uri.parse(mMedia.getLocation())));
final boolean isDir = media.getType() == MediaWrapper.TYPE_DIR;
final boolean canSave = isDir && FileUtils.canSave(media);
WorkersKt.runOnMainThread(new Runnable() {
@Override
public void run() {
if (isDetached()) return;
final Activity context = getActivity();
if (context == null || context.isFinishing()) return;
final Resources res = getResources();
if (isDir) {
detailsOverview.setImageDrawable(ContextCompat.getDrawable(context, TextUtils.equals(media.getUri().getScheme(),"file")
? R.drawable.ic_menu_folder_big
: R.drawable.ic_menu_network_big));
detailsOverview.setImageScaleUpAllowed(true);
detailsOverview.addAction(new Action(ID_BROWSE, res.getString(R.string.browse_folder)));
if (canSave) detailsOverview.addAction(browserFavExists ? actionDelete : actionAdd);
} else if (media.getType() == MediaWrapper.TYPE_AUDIO) {
// Add images and action buttons to the details view
if (cover == null)
detailsOverview.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.ic_default_cone));
else
detailsOverview.setImageBitmap(context, cover);
detailsOverview.addAction(new Action(ID_PLAY, res.getString(R.string.play)));
detailsOverview.addAction(new Action(ID_LISTEN, res.getString(R.string.listen)));
} else if (media.getType() == MediaWrapper.TYPE_VIDEO) {
// Add images and action buttons to the details view
if (cover == null)
detailsOverview.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.ic_default_cone));
else
detailsOverview.setImageBitmap(context, cover);
detailsOverview.addAction(new Action(ID_PLAY, res.getString(R.string.play)));
detailsOverview.addAction(new Action(ID_PLAY_FROM_START, res.getString(R.string.play_from_start)));
if (FileUtils.canWrite(media.getUri()))
detailsOverview.addAction(new Action(ID_DL_SUBS, res.getString(R.string.download_subtitles)));
}
mRowsAdapter.add(detailsOverview);
setAdapter(mRowsAdapter);
if (blurred != null) mBackgroundManager.setBitmap(blurred);
}
});
}
});
}
}
/*****************************************************************************
* MediaItemDetailsFragment.java
*
* Copyright © 2014-2019 VLC authors, VideoLAN and VideoLabs
* Author: Geoffrey Métais
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*/
package org.videolan.vlc.gui.tv
import android.annotation.TargetApi
import android.content.Intent
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.Parcelable
import android.text.TextUtils
import android.widget.Toast
import androidx.core.content.ContextCompat
import androidx.leanback.app.BackgroundManager
import androidx.leanback.app.DetailsSupportFragment
import androidx.leanback.widget.*
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.ObsoleteCoroutinesApi
import org.videolan.libvlc.util.AndroidUtil
import org.videolan.medialibrary.media.MediaWrapper
import org.videolan.vlc.R
import org.videolan.vlc.gui.helpers.AudioUtil
import org.videolan.vlc.gui.helpers.UiTools
import org.videolan.vlc.gui.video.VideoPlayerActivity
import org.videolan.vlc.media.MediaUtils
import org.videolan.vlc.repository.BrowserFavRepository
import org.videolan.vlc.util.ACTION_REMOTE_STOP
import org.videolan.vlc.util.FileUtils
import org.videolan.vlc.util.runIO
import org.videolan.vlc.util.runOnMainThread
@ExperimentalCoroutinesApi
@ObsoleteCoroutinesApi
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
class MediaItemDetailsFragment : DetailsSupportFragment() {
private lateinit var backgroundManager: BackgroundManager
private lateinit var rowsAdapter: ArrayObjectAdapter
private lateinit var mediaItemDetails: MediaItemDetails
private lateinit var mediaWrapper: MediaWrapper
private lateinit var browserFavRepository: BrowserFavRepository
private var mediaStarted: Boolean = false
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
backgroundManager = BackgroundManager.getInstance(requireActivity())
backgroundManager.isAutoReleaseOnStop = false
browserFavRepository = BrowserFavRepository.getInstance(requireContext())
mediaStarted = false
buildDetails()
}
override fun onResume() {
super.onResume()
if (!backgroundManager.isAttached) backgroundManager.attachToView(view)
}
override fun onPause() {
backgroundManager.release()
super.onPause()
if (mediaStarted) {
val ctx = context
ctx?.sendBroadcast(Intent(ACTION_REMOTE_STOP))
}
}
private fun buildDetails() {
val extras = requireActivity().intent.extras ?: return
mediaItemDetails = extras.getParcelable("item") as MediaItemDetails
val hasMedia = extras.containsKey("media")
val selector = ClassPresenterSelector()
val media = (if (hasMedia) extras.getParcelable<Parcelable>("media") else MediaWrapper(AndroidUtil.LocationToUri(mediaItemDetails.location))) as MediaWrapper
if (!hasMedia) {
media.setDisplayTitle(mediaItemDetails.title)
}
mediaWrapper = media
title = media.title
// Attach your media item details presenter to the row presenter:
val rowPresenter = FullWidthDetailsOverviewRowPresenter(DetailsDescriptionPresenter())
val activity = requireActivity()
val detailsOverview = DetailsOverviewRow(mediaItemDetails)
val actionAdd = Action(ID_FAVORITE_ADD.toLong(), getString(R.string.favorites_add))
val actionDelete = Action(ID_FAVORITE_DELETE.toLong(), getString(R.string.favorites_remove))
rowPresenter.backgroundColor = ContextCompat.getColor(activity, R.color.orange500)
rowPresenter.onActionClickedListener = OnActionClickedListener { action ->
when (action.id.toInt()) {
ID_LISTEN -> {
MediaUtils.openMedia(activity, mediaWrapper)
mediaStarted = true
}
ID_PLAY -> {
mediaStarted = false
TvUtil.playMedia(activity, media)
activity.finish()
}
ID_FAVORITE_ADD -> {
val uri = Uri.parse(mediaItemDetails.location)
val local = "file" == uri.scheme
if (local)
browserFavRepository.addLocalFavItem(uri, mediaItemDetails.title
?: "", mediaItemDetails.artworkUrl)
else
browserFavRepository.addNetworkFavItem(uri, mediaItemDetails.title
?: "", mediaItemDetails.artworkUrl)
detailsOverview.removeAction(actionAdd)
detailsOverview.addAction(actionDelete)
rowsAdapter.notifyArrayItemRangeChanged(0, rowsAdapter.size())
Toast.makeText(activity, R.string.favorite_added, Toast.LENGTH_SHORT).show()
}
ID_FAVORITE_DELETE -> {
runIO(Runnable { browserFavRepository.deleteBrowserFav(Uri.parse(mediaItemDetails.location)) })
detailsOverview.removeAction(actionDelete)
detailsOverview.addAction(actionAdd)
rowsAdapter.notifyArrayItemRangeChanged(0, rowsAdapter.size())
Toast.makeText(activity, R.string.favorite_removed, Toast.LENGTH_SHORT).show()
}
ID_BROWSE -> TvUtil.openMedia(activity, media, null)
ID_DL_SUBS -> MediaUtils.getSubs(requireActivity(), media)
ID_PLAY_FROM_START -> {
mediaStarted = false
VideoPlayerActivity.start(requireActivity(), media.uri, true)
activity.finish()
}
}
}
selector.addClassPresenter(DetailsOverviewRow::class.java, rowPresenter)
selector.addClassPresenter(ListRow::class.java,
ListRowPresenter())
rowsAdapter = ArrayObjectAdapter(selector)
runIO(Runnable {
val cover = if (media.type == MediaWrapper.TYPE_AUDIO || media.type == MediaWrapper.TYPE_VIDEO)
AudioUtil.readCoverBitmap(mediaItemDetails.artworkUrl, 512)
else
null
val blurred = if (cover != null) UiTools.blurBitmap(cover) else null
val browserFavExists = browserFavRepository.browserFavExists(Uri.parse(mediaItemDetails.location))
val isDir = media.type == MediaWrapper.TYPE_DIR
val canSave = isDir && FileUtils.canSave(media)
runOnMainThread(Runnable {
if (isDetached) return@Runnable
val context = getActivity()
if (context == null || context.isFinishing) return@Runnable
val res = resources
if (isDir) {
detailsOverview.imageDrawable = ContextCompat.getDrawable(context, if (TextUtils.equals(media.uri.scheme, "file"))
R.drawable.ic_menu_folder_big
else
R.drawable.ic_menu_network_big)
detailsOverview.isImageScaleUpAllowed = true
detailsOverview.addAction(Action(ID_BROWSE.toLong(), res.getString(R.string.browse_folder)))
if (canSave) detailsOverview.addAction(if (browserFavExists) actionDelete else actionAdd)
} else if (media.type == MediaWrapper.TYPE_AUDIO) {
// Add images and action buttons to the details view
if (cover == null)
detailsOverview.imageDrawable = ContextCompat.getDrawable(context, R.drawable.ic_default_cone)
else
detailsOverview.setImageBitmap(context, cover)
detailsOverview.addAction(Action(ID_PLAY.toLong(), res.getString(R.string.play)))
detailsOverview.addAction(Action(ID_LISTEN.toLong(), res.getString(R.string.listen)))
} else if (media.type == MediaWrapper.TYPE_VIDEO) {
// Add images and action buttons to the details view
if (cover == null)
detailsOverview.imageDrawable = ContextCompat.getDrawable(context, R.drawable.ic_default_cone)
else
detailsOverview.setImageBitmap(context, cover)
detailsOverview.addAction(Action(ID_PLAY.toLong(), res.getString(R.string.play)))
detailsOverview.addAction(Action(ID_PLAY_FROM_START.toLong(), res.getString(R.string.play_from_start)))
if (FileUtils.canWrite(media.uri))
detailsOverview.addAction(Action(ID_DL_SUBS.toLong(), res.getString(R.string.download_subtitles)))
}
rowsAdapter.add(detailsOverview)
adapter = rowsAdapter
if (blurred != null) backgroundManager.setBitmap(blurred)
})
})
}
companion object {
private const val TAG = "MediaItemDetailsFragment"
private const val ID_PLAY = 1
private const val ID_LISTEN = 2
private const val ID_FAVORITE_ADD = 3
private const val ID_FAVORITE_DELETE = 4
private const val ID_BROWSE = 5
private const val ID_DL_SUBS = 6
private const val ID_PLAY_FROM_START = 7
}
}
/*****************************************************************************
* SearchActivity.java
*****************************************************************************
*
* Copyright © 2014-2015 VLC authors, VideoLAN and VideoLabs
* Author: Geoffrey Métais
*
......@@ -17,42 +17,42 @@
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
package org.videolan.vlc.gui.tv;
import android.annotation.TargetApi;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import org.videolan.vlc.R;
import androidx.fragment.app.FragmentActivity;
*/
package org.videolan.vlc.gui.tv
import android.annotation.TargetApi
import android.os.Build
import android.os.Bundle
import android.view.View
import android.widget.TextView
import androidx.fragment.app.FragmentActivity
import kotlinx.coroutines.ExperimentalCoroutinesApi
import org.videolan.vlc.R
@ExperimentalCoroutinesApi
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
public class SearchActivity extends FragmentActivity {
private static final String TAG = "VLC/SearchActivity";
class SearchActivity : FragmentActivity() {
private lateinit var fragment: SearchFragment
private var emptyView: TextView? = null
private SearchFragment mFragment;
private TextView mEmptyView;
public override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.tv_search)
fragment = supportFragmentManager.findFragmentById(R.id.search_fragment) as SearchFragment
emptyView = findViewById(R.id.empty)
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.tv_search);
mFragment = (SearchFragment) getSupportFragmentManager()
.findFragmentById(R.id.search_fragment);
mEmptyView = findViewById(R.id.empty);
fun updateEmptyView(empty: Boolean) {
emptyView!!.visibility = if (empty) View.VISIBLE else View.GONE
}
public void updateEmptyView(boolean empty) {
mEmptyView.setVisibility(empty ? View.VISIBLE : View.GONE);
override fun onSearchRequested(): Boolean {
fragment.startRecognition()
return true
}
@Override
public boolean onSearchRequested() {
mFragment.startRecognition();
return true;
companion object {
private val TAG = "VLC/SearchActivity"
}
}
......@@ -121,7 +121,8 @@ open class CategoriesFragment<T : BaseModel<out MediaLibraryItem>> : BrowseSuppo
private fun getCategoryRow(key: String): ListRow {
val fromCache = if (this::categoryRows.isInitialized) categoryRows[key] else null
return fromCache ?: ListRow(HeaderItem(0, key), ArrayObjectAdapter(CardPresenter(activity)))
return fromCache
?: ListRow(HeaderItem(0, key), ArrayObjectAdapter(CardPresenter(requireActivity())))
}
private fun getCategoryId() = when(this) {
......
......@@ -39,7 +39,7 @@ open class GridFragment : VerticalGridSupportFragment(), BrowserFragmentInterfac
val gridPresenter = VerticalGridPresenter()
gridPresenter.numberOfColumns = NUM_COLUMNS
setGridPresenter(gridPresenter)
adapter = ArrayObjectAdapter(CardPresenter(context))
adapter = ArrayObjectAdapter(CardPresenter(requireActivity()))
adapter.clear()
adapter = adapter
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment