From a5c0bd67a82761d5fc8c075f792c1b82693c5dd0 Mon Sep 17 00:00:00 2001 From: lunaticbum Date: Sun, 29 Mar 2026 08:40:59 +0900 Subject: [PATCH 1/2] .. --- .../kotlin/bums/lunatic/launcher/workers/TorrentManager.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/kotlin/bums/lunatic/launcher/workers/TorrentManager.kt b/app/src/main/kotlin/bums/lunatic/launcher/workers/TorrentManager.kt index f8c01d24..7e53edd3 100644 --- a/app/src/main/kotlin/bums/lunatic/launcher/workers/TorrentManager.kt +++ b/app/src/main/kotlin/bums/lunatic/launcher/workers/TorrentManager.kt @@ -157,6 +157,7 @@ class TorrentService : Service() { } catch (e: Exception) { e.printStackTrace() } + _torrentTasks.value = mutableListOf() stopForeground(true) // 💡 상단바 알림 즉시 제거 stopSelf() // 💡 서비스 스스로 종료 (메모리 해제) @@ -240,7 +241,7 @@ class TorrentService : Service() { if (tasks.isNotEmpty()) { updateNotification(tasks) } - delay(15000) + delay(1500) } } } From e056e688081b7eeaa7aa83f710324bef08792f1e Mon Sep 17 00:00:00 2001 From: lunaticbum Date: Sun, 29 Mar 2026 09:18:56 +0900 Subject: [PATCH 2/2] ... --- app/src/main/cpp/MediaAsset.cpp | 4 +- app/src/main/cpp/Renderer.cpp | 2 +- app/src/main/cpp/native_renderer.cpp | 2 +- .../launcher/wall/MyWallpaperService.kt | 87 +++++++++++++++++-- 4 files changed, 83 insertions(+), 12 deletions(-) diff --git a/app/src/main/cpp/MediaAsset.cpp b/app/src/main/cpp/MediaAsset.cpp index 0c744989..38d5584c 100644 --- a/app/src/main/cpp/MediaAsset.cpp +++ b/app/src/main/cpp/MediaAsset.cpp @@ -227,7 +227,7 @@ bool MediaAsset::loadVideoWithFFmpeg(int fd) { } 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_) { LOGE("Could not create SwsContext"); release(); return false; @@ -265,7 +265,7 @@ bool MediaAsset::loadVideoWithFFmpeg(const std::string& path) { frame_ = av_frame_alloc(); packet_ = av_packet_alloc(); if (!frame_ || !packet_) { release(); return false; } 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; } rgbBuffer_.resize(width_ * height_ * 4); LOGI("Successfully loaded video from path: %s", path.c_str()); diff --git a/app/src/main/cpp/Renderer.cpp b/app/src/main/cpp/Renderer.cpp index 9552cff8..2aefd6ae 100644 --- a/app/src/main/cpp/Renderer.cpp +++ b/app/src/main/cpp/Renderer.cpp @@ -252,7 +252,7 @@ void Renderer::renderFrame(ANativeWindow* window) { currentFrameDelay_ = std::chrono::milliseconds(static_cast(1000.0 / currentMedia_.getFps())); LOGI("Media type: Video. Frame delay set to %lldms for %.2f FPS", currentFrameDelay_.count(), currentMedia_.getFps()); } else { - currentFrameDelay_ = std::chrono::milliseconds(33); // 이미지일 경우 30fps + currentFrameDelay_ = std::chrono::milliseconds(70); // 이미지일 경우 30fps LOGI("Media type: Image. Frame delay set to 33ms (~30 FPS)"); } currentState_ = RenderState::ANIMATING; diff --git a/app/src/main/cpp/native_renderer.cpp b/app/src/main/cpp/native_renderer.cpp index 7bec1697..ed9e0e40 100644 --- a/app/src/main/cpp/native_renderer.cpp +++ b/app/src/main/cpp/native_renderer.cpp @@ -93,7 +93,7 @@ Java_bums_lunatic_launcher_wall_NativeRenderer_nativeStartRenderLoop(JNIEnv* env LOGE("Could not get ANativeWindow from Surface."); return; } - ANativeWindow_setBuffersGeometry(window, 0, 0, WINDOW_FORMAT_RGBA_8888); + ANativeWindow_setBuffersGeometry(window, 0, 0, WINDOW_FORMAT_RGBX_8888); renderer->startRenderLoop(window); ANativeWindow_release(window); } diff --git a/app/src/main/kotlin/bums/lunatic/launcher/wall/MyWallpaperService.kt b/app/src/main/kotlin/bums/lunatic/launcher/wall/MyWallpaperService.kt index 88f7c655..3f7edf43 100644 --- a/app/src/main/kotlin/bums/lunatic/launcher/wall/MyWallpaperService.kt +++ b/app/src/main/kotlin/bums/lunatic/launcher/wall/MyWallpaperService.kt @@ -1,6 +1,8 @@ package bums.lunatic.launcher.wall +import android.app.WallpaperManager import android.content.ContentUris +import android.graphics.BitmapFactory import android.os.Environment import android.os.Handler import android.os.HandlerThread @@ -9,6 +11,8 @@ import android.provider.MediaStore import android.service.wallpaper.WallpaperService import android.util.Log import android.view.SurfaceHolder +import androidx.work.ListenableWorker +import bums.lunatic.launcher.utils.Blog import java.io.File class MyWallpaperService : WallpaperService() { @@ -26,7 +30,7 @@ class MyWallpaperService : WallpaperService() { private lateinit var holder: SurfaceHolder private var wasInPreview = false private var nativeRenderer: NativeRenderer? = null - private var mediaFiles: List = emptyList() + private var mediaFiles: MutableList = mutableListOf() private var isVisible = false private var isSurfaceValid = false @@ -187,7 +191,7 @@ class MyWallpaperService : WallpaperService() { nativeRenderer?.setTurnPageDuration(8000) nativeRenderer?.setAnimationMode(NativeRenderer.ANIMATION_MODE_PAN) nativeRenderer?.setTransitionMode(NativeRenderer.TRANSITION_MODE_FADE) - nativeRenderer?.setAnimationSpeed(2.0f) + nativeRenderer?.setAnimationSpeed(1.0f) NativeRenderer.nativeSetNextMediaCallback(nextMediaCallback) @@ -198,12 +202,45 @@ class MyWallpaperService : WallpaperService() { // ... loadMediaFiles, nextMediaCallback, getFdFromPath는 이전과 동일 ... private fun loadMediaFiles() { if (!mediaDir.exists()) mediaDir.mkdirs() - mediaFiles = mediaDir.listFiles() - ?.filter { supportedExtensions.contains(it.extension.lowercase()) } - ?.toList() ?: emptyList() +// mediaFiles = mediaDir.listFiles() +// ?.filter { supportedExtensions.contains(it.extension.lowercase()) } +// ?.toList() ?: emptyList() 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() + 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()) { val initialFile = mediaFiles.random() 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() - mediaFiles = mediaDir.listFiles() - ?.filter { supportedExtensions.contains(it.extension.lowercase()) } - ?.toList() ?: emptyList() +// mediaFiles = mediaDir.listFiles() +// ?.filter { supportedExtensions.contains(it.extension.lowercase()) } +// ?.toList() ?: emptyList() + + val allFiles = mediaDir.listFiles() + val trashFolder = File(mediaDir, "low_res_backup") + if (!trashFolder.exists()) trashFolder.mkdirs() +// val validImages = mutableListOf() + val invalidImages = mutableListOf() + 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() Log.d(TAG, "Callback: Preloading next random media: ${nextFile.absolutePath}")