Skip to content

Commit

Permalink
( #1 ) PSP Enhancement: Hide clock bar & show title-subtitle separator
Browse files Browse the repository at this point in the history
Background color can now be adjusted (now only for main Vsh View)
  • Loading branch information
EmiyaSyahriel committed Nov 28, 2020
1 parent 170b87f commit 2146e47
Show file tree
Hide file tree
Showing 7 changed files with 198 additions and 60 deletions.
29 changes: 29 additions & 0 deletions app/src/main/java/id/psw/vshlauncher/Patch.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@ package id.psw.vshlauncher
import android.graphics.Bitmap
import android.graphics.Color
import android.graphics.Rect
import android.os.Handler
import android.os.HandlerThread
import android.view.PixelCopy
import android.widget.VideoView
import java.lang.Exception
import java.lang.Integer.parseInt
import kotlin.math.ceil
import kotlin.math.floor
import kotlin.math.roundToInt
Expand Down Expand Up @@ -71,4 +77,27 @@ fun Bitmap.getDominantColorMean(alsoCalculateAlpha:Boolean = false):Int{

val finalAlpha = if(alsoCalculateAlpha) a / validPixels else 255
return Color.argb(finalAlpha,r/validPixels,g/validPixels,b/validPixels)
}

fun VideoView.getFrame(width:Int, height:Int, callback: (Bitmap?) -> Unit){
val bitmap : Bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565)
try{
val ht = HandlerThread("")

}catch(e:Exception){}
}

fun String.hexColorToInt():Int{
if(this.length <= 8) throw IllegalArgumentException("Please use #AARRGGBB hex format, e.g #FF00FF00 for opaque green")
if(this[0] != '#') throw IllegalArgumentException("Use # prefix please")
val bd = StringBuilder(2)
bd.clear().append(this[1]).append(this[2])
val aa = parseInt(bd.toString(), 16)
bd.clear().append(this[3]).append(this[4])
val rr = parseInt(bd.toString(), 16)
bd.clear().append(this[5]).append(this[6])
val gg = parseInt(bd.toString(), 16)
bd.clear().append(this[7]).append(this[8])
val bb = parseInt(bd.toString(), 16)
return Color.argb(aa,rr,gg,bb)
}
45 changes: 40 additions & 5 deletions app/src/main/java/id/psw/vshlauncher/VSH.kt
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ class VSH : AppCompatActivity(), VshDialogView.IDialogBackable {
const val PREF_USE_GAMEBOOT = "xmb_USE_GAMEBOOT"
const val PREF_DYNAMIC_TWINKLE = "xmb_DYNAMIC_P3T"
const val PREF_IS_FIRST_RUN = "xmb_not_new_user"
const val PREF_BACKGROUND_COLOR = "xmb_menu_backgroundColor"
}

private var returnFromGameboot = false
Expand Down Expand Up @@ -195,6 +196,7 @@ class VSH : AppCompatActivity(), VshDialogView.IDialogBackable {
scrOrientation = prefs.getInt(PREF_ORIENTATION_KEY, ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)
useGameBoot = prefs.getBoolean(PREF_USE_GAMEBOOT, true)
dynamicThemeTwinkles = prefs.getBoolean(PREF_DYNAMIC_TWINKLE, true)
VshView.menuBackgroundColor = prefs.getInt(PREF_BACKGROUND_COLOR, Color.argb(0,0,0,0))
}

private fun checkFileReadWritePermission(){
Expand Down Expand Up @@ -309,7 +311,34 @@ class VSH : AppCompatActivity(), VshDialogView.IDialogBackable {

settings.items.add(
VshSettingIcon(
0xd18034, this,
0xd1805, this,
"Set Menu Background Color", VshSettingIcon.ICON_ANDROID,
{ showBackgroundColorDialog() },
{ "Menu background (hidden when menu is hidden)" }
)
)

settings.items.add(
VshSettingIcon(
0xd1806, this,
"Hide Clock Bar", VshSettingIcon.ICON_ANDROID,
{ VshView.hideClock = !VshView.hideClock },
{ VshView.hideClock.toLocalizedString() }
)
)

settings.items.add(
VshSettingIcon(
0xd1807, this,
"Show Description Separator", VshSettingIcon.ICON_ANDROID,
{ VshView.descriptionSeparator = !VshView.descriptionSeparator },
{ VshView.descriptionSeparator.toLocalizedString() }
)
)

settings.items.add(
VshSettingIcon(
0xd1808, this,
getString(R.string.setting_gameboot_custom_guide), VshSettingIcon.ICON_ANDROID,
{ launchURL("https://github.com/EmiyaSyahriel/CrossLauncher#animation-modding" )},
{ getString(R.string.common_click_here) }
Expand Down Expand Up @@ -394,7 +423,6 @@ class VSH : AppCompatActivity(), VshDialogView.IDialogBackable {
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
if(!isOnMenu) return false
var retval = false
val confirmButton = xMarksTheSpot.choose(KeyEvent.KEYCODE_BUTTON_A, KeyEvent.KEYCODE_BUTTON_B)

when(keyCode){
KeyEvent.KEYCODE_DPAD_UP -> {
Expand All @@ -413,14 +441,21 @@ class VSH : AppCompatActivity(), VshDialogView.IDialogBackable {
vsh.setSelection(1,0)
retval = true
}
KeyEvent.KEYCODE_ENTER, KeyEvent.KEYCODE_DPAD_CENTER, confirmButton ->{
KeyEvent.KEYCODE_ENTER, KeyEvent.KEYCODE_DPAD_CENTER, mimickedConfirmButton ->{
if(vsh.isOnOptions){
vsh.executeCurrentOptionItem()
}else{
vsh.executeCurrentItem()
}
retval = true
}
KeyEvent.KEYCODE_DEL, mimickedCancelButton ->{
if(vsh.isOnOptions){
vsh.switchOptionPopupVisibility()
}else{
vsh.hideMenu = !vsh.hideMenu
}
}
KeyEvent.KEYCODE_MENU, KeyEvent.KEYCODE_TAB, KeyEvent.KEYCODE_BUTTON_Y -> {
vsh.isOnOptions = !vsh.isOnOptions
retval = true
Expand All @@ -437,7 +472,7 @@ class VSH : AppCompatActivity(), VshDialogView.IDialogBackable {
if(yIndex < 0) yIndex = vsh.selectedY
vsh.setSelectionAbs(vsh.selectedX, yIndex)
}
}catch (e:java.lang.Exception){}
}catch (e : Exception){}
}
}
return retval || super.onKeyDown(keyCode, event)
Expand Down Expand Up @@ -612,7 +647,7 @@ class VSH : AppCompatActivity(), VshDialogView.IDialogBackable {
try{
startActivity(intent)
overridePendingTransition(R.anim.anim_ps3_zoomfadein, R.anim.anim_ps3_zoomfadeout)
}catch (e:java.lang.Exception){
}catch (e: Exception){
Toast.makeText(this, "This video type is not supported", Toast.LENGTH_SHORT).show()
}
}
Expand Down
34 changes: 34 additions & 0 deletions app/src/main/java/id/psw/vshlauncher/VshActivityExtension.kt
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
package id.psw.vshlauncher

import android.app.AlertDialog
import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
import android.text.Editable
import android.text.InputType
import android.text.method.DigitsKeyListener
import android.widget.EditText
import android.widget.Toast
import id.psw.vshlauncher.customtypes.HexInputFilter
import id.psw.vshlauncher.views.VshView

/**
* A file that contains extensions for the main VSH Activity
Expand Down Expand Up @@ -40,3 +47,30 @@ fun VSH.launchURL(url:String){
Toast.makeText(this, "No default browser found in device.", Toast.LENGTH_SHORT).show()
}
}

/** TODO: Extend to use XMB-like dialog instead */
fun VSH.showBackgroundColorDialog(){
val textView = EditText(this)
val currentColor = VshView.menuBackgroundColor.toString(16)
textView.inputType= InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS
textView.filters = arrayOf(HexInputFilter())
textView.text.clear()
textView.text.append("#$currentColor")
AlertDialog.Builder(this)
.setView(textView)
.setPositiveButton("Set"){ dialog,_ ->
try{
VshView.menuBackgroundColor = textView.text.toString().hexColorToInt()
prefs.edit().putInt(VSH.PREF_BACKGROUND_COLOR, VshView.menuBackgroundColor).apply()
dialog.dismiss()
}catch(e:Exception){
Toast.makeText(this, e.message, Toast.LENGTH_LONG).show()
}
}
.setNegativeButton("Cancel"){ dialog,_ ->
dialog.dismiss()
}
.setTitle("Set Menu Background Color")
.create()
.show()
}
31 changes: 31 additions & 0 deletions app/src/main/java/id/psw/vshlauncher/customtypes/HexInputFilter.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package id.psw.vshlauncher.customtypes

import android.text.InputFilter
import android.text.Spanned
import java.util.*


class HexInputFilter : InputFilter {
companion object{
private val hexItems = "#0123456789ABCDEFabcdef"
}

override fun filter(
source: CharSequence?,
start: Int,
end: Int,
dest: Spanned?,
dstart: Int,
dend: Int
): CharSequence {

val sb = StringBuilder()

for (i in start until end) {
val chr = (source?.get(i) ?: ' ').toUpperCase()
val validHex = hexItems.contains(chr)
if(validHex) sb.append(chr)
}
return sb.toString().toUpperCase(Locale.ROOT)
}
}
98 changes: 47 additions & 51 deletions app/src/main/java/id/psw/vshlauncher/icontypes/VideoIcon.kt
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
package id.psw.vshlauncher.icontypes

import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Point
import android.graphics.SurfaceTexture
import android.media.MediaMetadataRetriever
import android.media.MediaPlayer
import android.media.ThumbnailUtils
import android.net.Uri
import android.provider.MediaStore
import android.view.Surface
import android.view.SurfaceView
import android.view.TextureView
import android.widget.Toast
import android.widget.VideoView
import androidx.core.graphics.scale
import id.psw.vshlauncher.*
import id.psw.vshlauncher.views.VshView
import java.io.File
import java.lang.Exception

// TODO : fix cursor is mostly null when created this icon, causing the icon appear corrupted
class VideoIcon(itemID:Int, private val vsh: VSH, private val path: String) : VshY(itemID) {
class VideoIcon(itemID:Int, private val vsh: VSH, private val path: String) : VshY(itemID), TextureView.SurfaceTextureListener {

companion object{
var doVideoPreview = false
Expand All @@ -34,14 +37,21 @@ class VideoIcon(itemID:Int, private val vsh: VSH, private val path: String) : Vs
private var metadata : VideoMetadata
private var isValid = false

private var thumbnailVp : VideoView? = null
private var videoReady = false
private var lastPreviewPos = 0
private var thumbnailStart = 0
private var thumbnailEnd = 0
private var currentTime = 0f
private var isPaused = false
private var thumbnailStart = 0f
private var thumbnailEnd = 10f
private var fps = 30

private var mp = MediaPlayer()
private var texView = TextureView(vsh)
private var srView = SurfaceView(vsh)
private var surface : Surface? = null

private var scaledSelectedAlbumArt : Bitmap = transparentBitmap
private var scaledUnselectedAlbumArt : Bitmap = transparentBitmap

private var currentVideoBitmap : Bitmap = transparentBitmap

init{
loadCorruptedIcon()
Expand All @@ -51,9 +61,9 @@ class VideoIcon(itemID:Int, private val vsh: VSH, private val path: String) : Vs
val size = file.length().toSize()
val albumArt = ThumbnailUtils.createVideoThumbnail(file.absolutePath, MediaStore.Video.Thumbnails.MINI_KIND) ?: transparentBitmap
bakeAlbumArt(albumArt)
loadVideoPreview()
thumbnailStart = 0
thumbnailEnd = 30000
thumbnailStart = 0f
thumbnailEnd = 10f
startGrabberThread()
isValid=true
VideoMetadata(itemID, file, fileName, size, albumArt)
}catch(e:Exception){
Expand Down Expand Up @@ -85,59 +95,45 @@ class VideoIcon(itemID:Int, private val vsh: VSH, private val path: String) : Vs
* TODO: Can be optimized further by caching the canvas and bitmap to variable
*/
private fun getCurrentVideoBitmap(selected:Boolean = true) : Bitmap{

val width = (if(selected) selectedIconSizeWidth else unselectedIconSize).toInt() * vsh.vsh.density
val height = (if(selected) selectedIconSize else unselectedIconSize).toInt()* vsh.vsh.density
if(doVideoPreview) {
val tvp = thumbnailVp
if(tvp != null){
val retval = Bitmap.createBitmap(width.toInt(), height.toInt(), Bitmap.Config.ARGB_8888)
val retCan = Canvas(retval)
retCan.drawColor(Color.BLACK)
tvp.draw(retCan)
return retval
}
currentTime += VshView.deltaTime
if(currentTime >= thumbnailEnd) currentTime = thumbnailStart
return currentVideoBitmap
}

return if(selected) scaledSelectedAlbumArt else scaledUnselectedAlbumArt
}

/**
* Load video preview of the view in case user do set it to true
*/
private fun loadVideoPreview(){
if(doVideoPreview){
val tvp = VideoView(vsh)
// set it to loop and mute audio since we shouldn't play the audio on preview anyway
tvp.setOnPreparedListener {
with(it) {
isLooping = true
setVolume(0f, 0f)
}
videoReady = true
}
tvp.setVideoPath(path)
thumbnailVp = tvp
}
override fun onSurfaceTextureAvailable(surface: SurfaceTexture?, width: Int, height: Int) {
this.surface = Surface(surface)
}

override fun onSurfaceTextureSizeChanged(surface: SurfaceTexture?, width: Int, height: Int) { }

override fun onSurfaceTextureDestroyed(surface: SurfaceTexture?): Boolean = false

override fun onSurfaceTextureUpdated(surface: SurfaceTexture?) { this.surface = Surface(surface) }

/**
* Pause the video player if
*/
override fun onHidden() {
val tvp = thumbnailVp
if(tvp != null && doVideoPreview){
if(tvp.canPause()){
lastPreviewPos = tvp.currentPosition
tvp.pause()
}
}
isPaused = true
}

override fun onScreen() {
val tvp = thumbnailVp
if(tvp != null && doVideoPreview && videoReady){
tvp.seekTo(lastPreviewPos)
tvp.start()
isPaused = false
}

private fun startGrabberThread(){
if(doVideoPreview){
mp.setDataSource(path)
mp.setSurface(surface)
texView.surfaceTextureListener = this
mp.isLooping = true
mp.setOnPreparedListener { mp.start() }
}
}

Expand All @@ -151,7 +147,7 @@ class VideoIcon(itemID:Int, private val vsh: VSH, private val path: String) : Vs
}
}

// TODO: Create a small video thumbnail and fix squared aspect ratio problem
// TODO: Create a small video thumbnail
override val selectedIcon: Bitmap
get() = getCurrentVideoBitmap(true)

Expand Down
Loading

0 comments on commit 2146e47

Please sign in to comment.