Merge branch 'main' of https://dev.lunaticbum.kr/lun_admin/android_multiviewwer
# Conflicts: # app/src/main/kotlin/bums/lunatic/launcher/workers/TorrentManager.kt
This commit is contained in:
commit
416279a11f
@ -227,7 +227,7 @@ bool MediaAsset::loadVideoWithFFmpeg(int fd) {
|
|||||||
}
|
}
|
||||||
width_ = codecCtx_->width;
|
width_ = codecCtx_->width;
|
||||||
height_ = codecCtx_->height;
|
height_ = codecCtx_->height;
|
||||||
swsCtx_ = sws_getContext(width_, height_, codecCtx_->pix_fmt, width_, height_, AV_PIX_FMT_RGBA, SWS_BILINEAR, nullptr, nullptr, nullptr);
|
swsCtx_ = sws_getContext(width_, height_, codecCtx_->pix_fmt, width_, height_, AV_PIX_FMT_BGRA, SWS_BILINEAR, nullptr, nullptr, nullptr);
|
||||||
if (!swsCtx_) {
|
if (!swsCtx_) {
|
||||||
LOGE("Could not create SwsContext");
|
LOGE("Could not create SwsContext");
|
||||||
release(); return false;
|
release(); return false;
|
||||||
@ -265,7 +265,7 @@ bool MediaAsset::loadVideoWithFFmpeg(const std::string& path) {
|
|||||||
frame_ = av_frame_alloc(); packet_ = av_packet_alloc();
|
frame_ = av_frame_alloc(); packet_ = av_packet_alloc();
|
||||||
if (!frame_ || !packet_) { release(); return false; }
|
if (!frame_ || !packet_) { release(); return false; }
|
||||||
width_ = codecCtx_->width; height_ = codecCtx_->height;
|
width_ = codecCtx_->width; height_ = codecCtx_->height;
|
||||||
swsCtx_ = sws_getContext(width_, height_, codecCtx_->pix_fmt, width_, height_, AV_PIX_FMT_RGBA, SWS_BILINEAR, nullptr, nullptr, nullptr);
|
swsCtx_ = sws_getContext(width_, height_, codecCtx_->pix_fmt, width_, height_, AV_PIX_FMT_BGRA, SWS_BILINEAR, nullptr, nullptr, nullptr);
|
||||||
if (!swsCtx_) { release(); return false; }
|
if (!swsCtx_) { release(); return false; }
|
||||||
rgbBuffer_.resize(width_ * height_ * 4);
|
rgbBuffer_.resize(width_ * height_ * 4);
|
||||||
LOGI("Successfully loaded video from path: %s", path.c_str());
|
LOGI("Successfully loaded video from path: %s", path.c_str());
|
||||||
|
|||||||
@ -252,7 +252,7 @@ void Renderer::renderFrame(ANativeWindow* window) {
|
|||||||
currentFrameDelay_ = std::chrono::milliseconds(static_cast<long long>(1000.0 / currentMedia_.getFps()));
|
currentFrameDelay_ = std::chrono::milliseconds(static_cast<long long>(1000.0 / currentMedia_.getFps()));
|
||||||
LOGI("Media type: Video. Frame delay set to %lldms for %.2f FPS", currentFrameDelay_.count(), currentMedia_.getFps());
|
LOGI("Media type: Video. Frame delay set to %lldms for %.2f FPS", currentFrameDelay_.count(), currentMedia_.getFps());
|
||||||
} else {
|
} else {
|
||||||
currentFrameDelay_ = std::chrono::milliseconds(33); // 이미지일 경우 30fps
|
currentFrameDelay_ = std::chrono::milliseconds(70); // 이미지일 경우 30fps
|
||||||
LOGI("Media type: Image. Frame delay set to 33ms (~30 FPS)");
|
LOGI("Media type: Image. Frame delay set to 33ms (~30 FPS)");
|
||||||
}
|
}
|
||||||
currentState_ = RenderState::ANIMATING;
|
currentState_ = RenderState::ANIMATING;
|
||||||
|
|||||||
@ -93,7 +93,7 @@ Java_bums_lunatic_launcher_wall_NativeRenderer_nativeStartRenderLoop(JNIEnv* env
|
|||||||
LOGE("Could not get ANativeWindow from Surface.");
|
LOGE("Could not get ANativeWindow from Surface.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ANativeWindow_setBuffersGeometry(window, 0, 0, WINDOW_FORMAT_RGBA_8888);
|
ANativeWindow_setBuffersGeometry(window, 0, 0, WINDOW_FORMAT_RGBX_8888);
|
||||||
renderer->startRenderLoop(window);
|
renderer->startRenderLoop(window);
|
||||||
ANativeWindow_release(window);
|
ANativeWindow_release(window);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
package bums.lunatic.launcher.wall
|
package bums.lunatic.launcher.wall
|
||||||
|
|
||||||
|
import android.app.WallpaperManager
|
||||||
import android.content.ContentUris
|
import android.content.ContentUris
|
||||||
|
import android.graphics.BitmapFactory
|
||||||
import android.os.Environment
|
import android.os.Environment
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.os.HandlerThread
|
import android.os.HandlerThread
|
||||||
@ -9,6 +11,8 @@ import android.provider.MediaStore
|
|||||||
import android.service.wallpaper.WallpaperService
|
import android.service.wallpaper.WallpaperService
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.SurfaceHolder
|
import android.view.SurfaceHolder
|
||||||
|
import androidx.work.ListenableWorker
|
||||||
|
import bums.lunatic.launcher.utils.Blog
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
class MyWallpaperService : WallpaperService() {
|
class MyWallpaperService : WallpaperService() {
|
||||||
@ -26,7 +30,7 @@ class MyWallpaperService : WallpaperService() {
|
|||||||
private lateinit var holder: SurfaceHolder
|
private lateinit var holder: SurfaceHolder
|
||||||
private var wasInPreview = false
|
private var wasInPreview = false
|
||||||
private var nativeRenderer: NativeRenderer? = null
|
private var nativeRenderer: NativeRenderer? = null
|
||||||
private var mediaFiles: List<File> = emptyList()
|
private var mediaFiles: MutableList<File> = mutableListOf()
|
||||||
private var isVisible = false
|
private var isVisible = false
|
||||||
private var isSurfaceValid = false
|
private var isSurfaceValid = false
|
||||||
|
|
||||||
@ -187,7 +191,7 @@ class MyWallpaperService : WallpaperService() {
|
|||||||
nativeRenderer?.setTurnPageDuration(8000)
|
nativeRenderer?.setTurnPageDuration(8000)
|
||||||
nativeRenderer?.setAnimationMode(NativeRenderer.ANIMATION_MODE_PAN)
|
nativeRenderer?.setAnimationMode(NativeRenderer.ANIMATION_MODE_PAN)
|
||||||
nativeRenderer?.setTransitionMode(NativeRenderer.TRANSITION_MODE_FADE)
|
nativeRenderer?.setTransitionMode(NativeRenderer.TRANSITION_MODE_FADE)
|
||||||
nativeRenderer?.setAnimationSpeed(2.0f)
|
nativeRenderer?.setAnimationSpeed(1.0f)
|
||||||
NativeRenderer.nativeSetNextMediaCallback(nextMediaCallback)
|
NativeRenderer.nativeSetNextMediaCallback(nextMediaCallback)
|
||||||
|
|
||||||
|
|
||||||
@ -198,12 +202,45 @@ class MyWallpaperService : WallpaperService() {
|
|||||||
// ... loadMediaFiles, nextMediaCallback, getFdFromPath는 이전과 동일 ...
|
// ... loadMediaFiles, nextMediaCallback, getFdFromPath는 이전과 동일 ...
|
||||||
private fun loadMediaFiles() {
|
private fun loadMediaFiles() {
|
||||||
if (!mediaDir.exists()) mediaDir.mkdirs()
|
if (!mediaDir.exists()) mediaDir.mkdirs()
|
||||||
mediaFiles = mediaDir.listFiles()
|
// mediaFiles = mediaDir.listFiles()
|
||||||
?.filter { supportedExtensions.contains(it.extension.lowercase()) }
|
// ?.filter { supportedExtensions.contains(it.extension.lowercase()) }
|
||||||
?.toList() ?: emptyList()
|
// ?.toList() ?: emptyList()
|
||||||
|
|
||||||
Log.d(TAG, "Found ${mediaFiles.size} media files.")
|
Log.d(TAG, "Found ${mediaFiles.size} media files.")
|
||||||
|
|
||||||
|
val allFiles = mediaDir.listFiles()
|
||||||
|
val trashFolder = File(mediaDir, "low_res_backup")
|
||||||
|
if (!trashFolder.exists()) trashFolder.mkdirs()
|
||||||
|
val invalidImages = mutableListOf<File>()
|
||||||
|
val wm = WallpaperManager.getInstance(this@MyWallpaperService)
|
||||||
|
val minWidth = wm.desiredMinimumWidth
|
||||||
|
val minHeight = wm.desiredMinimumHeight
|
||||||
|
val requiredSize = Math.max(minWidth, minHeight).times(0.6)
|
||||||
|
for (file in allFiles) {
|
||||||
|
|
||||||
|
if (file.isFile && (file.extension.equals("jpg", true) ||
|
||||||
|
file.extension.equals("png", true) ||
|
||||||
|
file.extension.equals("jpeg", true) ||
|
||||||
|
file.extension.equals("bmp", true) || // BMP 추가
|
||||||
|
file.extension.equals("webp", true))) {
|
||||||
|
|
||||||
|
val options = BitmapFactory.Options().apply { inJustDecodeBounds = true }
|
||||||
|
BitmapFactory.decodeFile(file.absolutePath, options)
|
||||||
|
Blog.LOGE("requiredSize ${requiredSize} w :${options.outWidth} , h : ${options.outHeight}")
|
||||||
|
if (options.outWidth >= requiredSize && options.outHeight >= requiredSize) {
|
||||||
|
mediaFiles.add(file)
|
||||||
|
} else {
|
||||||
|
invalidImages.add(file) // 조건 미달
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 부적합 이미지 이동 처리 (Job 밖에서 따로 돌려도 무방)
|
||||||
|
invalidImages.forEach { file ->
|
||||||
|
val targetFile = File(trashFolder, file.name)
|
||||||
|
file.renameTo(targetFile) // 파일 이동
|
||||||
|
}
|
||||||
|
|
||||||
if (mediaFiles.isNotEmpty()) {
|
if (mediaFiles.isNotEmpty()) {
|
||||||
val initialFile = mediaFiles.random()
|
val initialFile = mediaFiles.random()
|
||||||
Log.d(TAG, "Attempting to load initial random media via preloader: ${initialFile.absolutePath}")
|
Log.d(TAG, "Attempting to load initial random media via preloader: ${initialFile.absolutePath}")
|
||||||
@ -223,9 +260,43 @@ class MyWallpaperService : WallpaperService() {
|
|||||||
if (!mediaDir.exists()) mediaDir.mkdirs()
|
if (!mediaDir.exists()) mediaDir.mkdirs()
|
||||||
|
|
||||||
|
|
||||||
mediaFiles = mediaDir.listFiles()
|
// mediaFiles = mediaDir.listFiles()
|
||||||
?.filter { supportedExtensions.contains(it.extension.lowercase()) }
|
// ?.filter { supportedExtensions.contains(it.extension.lowercase()) }
|
||||||
?.toList() ?: emptyList()
|
// ?.toList() ?: emptyList()
|
||||||
|
|
||||||
|
val allFiles = mediaDir.listFiles()
|
||||||
|
val trashFolder = File(mediaDir, "low_res_backup")
|
||||||
|
if (!trashFolder.exists()) trashFolder.mkdirs()
|
||||||
|
// val validImages = mutableListOf<File>()
|
||||||
|
val invalidImages = mutableListOf<File>()
|
||||||
|
val wm = WallpaperManager.getInstance(this@MyWallpaperService)
|
||||||
|
val minWidth = wm.desiredMinimumWidth
|
||||||
|
val minHeight = wm.desiredMinimumHeight
|
||||||
|
val requiredSize = Math.max(minWidth, minHeight).times(0.6)
|
||||||
|
for (file in allFiles) {
|
||||||
|
|
||||||
|
if (file.isFile && (file.extension.equals("jpg", true) ||
|
||||||
|
file.extension.equals("png", true) ||
|
||||||
|
file.extension.equals("jpeg", true) ||
|
||||||
|
file.extension.equals("bmp", true) || // BMP 추가
|
||||||
|
file.extension.equals("webp", true))) {
|
||||||
|
|
||||||
|
val options = BitmapFactory.Options().apply { inJustDecodeBounds = true }
|
||||||
|
BitmapFactory.decodeFile(file.absolutePath, options)
|
||||||
|
Blog.LOGE("requiredSize ${requiredSize} w :${options.outWidth} , h : ${options.outHeight}")
|
||||||
|
if (options.outWidth >= requiredSize && options.outHeight >= requiredSize) {
|
||||||
|
mediaFiles.add(file)
|
||||||
|
} else {
|
||||||
|
invalidImages.add(file) // 조건 미달
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 부적합 이미지 이동 처리 (Job 밖에서 따로 돌려도 무방)
|
||||||
|
invalidImages.forEach { file ->
|
||||||
|
val targetFile = File(trashFolder, file.name)
|
||||||
|
file.renameTo(targetFile) // 파일 이동
|
||||||
|
}
|
||||||
|
|
||||||
val nextFile = mediaFiles.random()
|
val nextFile = mediaFiles.random()
|
||||||
Log.d(TAG, "Callback: Preloading next random media: ${nextFile.absolutePath}")
|
Log.d(TAG, "Callback: Preloading next random media: ${nextFile.absolutePath}")
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
package bums.lunatic.launcher.workers
|
package bums.lunatic.launcher.workers
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
import android.app.*
|
import android.app.*
|
||||||
import android.content.*
|
import android.content.*
|
||||||
import android.net.*
|
import android.net.*
|
||||||
@ -50,9 +51,10 @@ class TorrentService : Service() {
|
|||||||
fun getService(): TorrentService = this@TorrentService
|
fun getService(): TorrentService = this@TorrentService
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressLint("ServiceCast")
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
notificationManager = getSystemService(Context.CONNECTIVITY_SERVICE) as NotificationManager
|
notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||||
startForegroundService()
|
startForegroundService()
|
||||||
initLibTorrent()
|
initLibTorrent()
|
||||||
|
|
||||||
@ -219,6 +221,29 @@ class TorrentService : Service() {
|
|||||||
val status = handle.status()
|
val status = handle.status()
|
||||||
val state = status.state()
|
val state = status.state()
|
||||||
|
|
||||||
|
val hashStr = status.infoHash().toString()
|
||||||
|
var rawName = status.name()
|
||||||
|
|
||||||
|
if (status.hasMetadata()) {
|
||||||
|
val torrentInfo = handle.torrentFile()
|
||||||
|
if (torrentInfo != null && torrentInfo.isValid) {
|
||||||
|
val realName = torrentInfo.name()
|
||||||
|
if (!realName.isNullOrEmpty()) {
|
||||||
|
rawName = realName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val displayName = if (rawName.isNullOrEmpty() || rawName == hashStr) {
|
||||||
|
if (status.hasMetadata()) {
|
||||||
|
"파일 정보 분석 중..."
|
||||||
|
} else {
|
||||||
|
"메타데이터 수신 중... (${hashStr.take(6)})"
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rawName
|
||||||
|
}
|
||||||
|
|
||||||
val isPaused = status.flags().and_(libtorrent.getPaused()).nonZero()
|
val isPaused = status.flags().and_(libtorrent.getPaused()).nonZero()
|
||||||
val isFinished = status.isFinished
|
val isFinished = status.isFinished
|
||||||
val isDownloading = (state.swig() == torrent_status.state_t.downloading.swigValue())
|
val isDownloading = (state.swig() == torrent_status.state_t.downloading.swigValue())
|
||||||
@ -233,7 +258,7 @@ class TorrentService : Service() {
|
|||||||
|
|
||||||
tasks.add(TorrentTask(
|
tasks.add(TorrentTask(
|
||||||
infoHash = status.infoHash().toString(),
|
infoHash = status.infoHash().toString(),
|
||||||
name = status.name() ?: "알 수 없음",
|
name = displayName,
|
||||||
progress = status.progress() * 100f,
|
progress = status.progress() * 100f,
|
||||||
isPaused = isPaused,
|
isPaused = isPaused,
|
||||||
isQueued = !isPaused && !isFinished && !isDownloading,
|
isQueued = !isPaused && !isFinished && !isDownloading,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user