From 5d73cc12327a61aeeae7ac251cf6a31b8a9977d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 21 Oct 2025 13:56:46 +0800 Subject: [PATCH] Media: save media cover to temp file --- src/detection/media/media_apple.m | 25 ++++++++++++----- src/detection/media/media_linux.c | 11 +++----- src/detection/media/media_windows.c | 6 +---- src/detection/media/media_windows.dll.cpp | 33 +++++++++++++---------- src/detection/media/media_windows.dll.h | 5 +--- 5 files changed, 43 insertions(+), 37 deletions(-) diff --git a/src/detection/media/media_apple.m b/src/detection/media/media_apple.m index 19dc9dc52..b3dbc8822 100644 --- a/src/detection/media/media_apple.m +++ b/src/detection/media/media_apple.m @@ -5,6 +5,7 @@ #import #import +#import // https://github.com/andrewwiik/iOS-Blocks/blob/master/Widgets/Music/MediaRemote.h extern void MRMediaRemoteGetNowPlayingInfo(dispatch_queue_t dispatcher, void(^callback)(_Nullable CFDictionaryRef info)) __attribute__((weak_import)); @@ -30,7 +31,21 @@ static const char* getMediaByMediaRemote(FFMediaResult* result) ffCfDictGetString(info, CFSTR("kMRMediaRemoteNowPlayingInfoTitle"), &result->song); ffCfDictGetString(info, CFSTR("kMRMediaRemoteNowPlayingInfoArtist"), &result->artist); ffCfDictGetString(info, CFSTR("kMRMediaRemoteNowPlayingInfoAlbum"), &result->album); - ffCfDictGetDataAsString(info, CFSTR("kMRMediaRemoteNowPlayingInfoArtworkData"), &result->cover); + NSData* artworkData = (__bridge NSData*) CFDictionaryGetValue(info, CFSTR("kMRMediaRemoteNowPlayingInfoArtworkData")); + if (artworkData) + { + CFStringRef mime = (CFStringRef) CFDictionaryGetValue(info, CFSTR("kMRMediaRemoteNowPlayingInfoArtworkMIMEType")); +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + FF_CFTYPE_AUTO_RELEASE CFStringRef uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, mime, NULL); + FF_CFTYPE_AUTO_RELEASE CFStringRef ext = UTTypeCopyPreferredTagWithClass(uti, kUTTagClassFilenameExtension); +#pragma clang diagnostic pop + NSString *tmpDir = NSTemporaryDirectory(); + NSString *uuid = [[NSUUID UUID] UUIDString]; + NSString *path = [tmpDir stringByAppendingPathComponent:[NSString stringWithFormat:@"ff_%@.%@", uuid, ext ? (__bridge NSString *) ext : @"img"]]; + if ([artworkData writeToFile:path atomically:NO]) + ffStrbufSetS(&result->cover, path.UTF8String); + } } else error = "MRMediaRemoteGetNowPlayingInfo() failed"; @@ -91,7 +106,7 @@ int ffPrintMediaByMediaRemote(void) ffStrbufPutTo(&media.album, stdout); ffStrbufPutTo(&media.playerId, stdout); ffStrbufPutTo(&media.player, stdout); - ffStrbufWriteTo(&media.cover, stdout); // Raw data + ffStrbufWriteTo(&media.cover, stdout); ffStrbufDestroy(&media.status); ffStrbufDestroy(&media.song); ffStrbufDestroy(&media.artist); @@ -118,15 +133,11 @@ static const char* getMediaByAuthorizedProcess(FFMediaResult* result) if (buffer.length == 0) return "No media found"; // status\ntitle\nartist\nalbum\nbundleName\nappName - FFstrbuf* const varList[] = { &result->status, &result->song, &result->artist, &result->album, &result->playerId, &result->player }; + FFstrbuf* const varList[] = { &result->status, &result->song, &result->artist, &result->album, &result->playerId, &result->player, &result->cover }; char* line = NULL; size_t len = 0; for (uint32_t i = 0; i < ARRAY_SIZE(varList) && ffStrbufGetline(&line, &len, &buffer); ++i) ffStrbufSetS(varList[i], line); - ffStrbufGetlineRestore(&line, &len, &buffer); - line++; // Skip the newline before the cover data - if (line < buffer.chars + buffer.length) - ffStrbufSetNS(&result->cover, buffer.length - (uint32_t) (line - buffer.chars), line); return NULL; } diff --git a/src/detection/media/media_linux.c b/src/detection/media/media_linux.c index a3562fb27..5daa93605 100644 --- a/src/detection/media/media_linux.c +++ b/src/detection/media/media_linux.c @@ -77,8 +77,8 @@ static bool parseMprisMetadata(FFDBusData* data, DBusMessageIter* rootIterator, ffDBusGetString(data, &dictIterator, &path); if (ffStrbufStartsWithS(&path, "file:///")) { - uint32_t j = 0; - for (uint32_t i = (uint32_t) strlen("file:///") - 1; i < path.length; ++i, ++j) + ffStrbufEnsureFree(&result->cover, path.length - (uint32_t) strlen("file://")); + for (uint32_t i = (uint32_t) strlen("file://"); i < path.length; ++i) { if (path.chars[i] == '%') { @@ -86,17 +86,14 @@ static bool parseMprisMetadata(FFDBusData* data, DBusMessageIter* rootIterator, break; char str[] = { path.chars[i + 1], path.chars[i + 2], 0 }; const char decodedChar = (char) strtoul(str, NULL, 16); - path.chars[j] = decodedChar; i += 2; + ffStrbufAppendC(&result->cover, decodedChar); } else { - path.chars[j] = path.chars[i]; + ffStrbufAppendC(&result->cover, path.chars[i]); } } - path.chars[j] = '\0'; - path.length = j; - ffReadFileBuffer(path.chars, &result->cover); } } } diff --git a/src/detection/media/media_windows.c b/src/detection/media/media_windows.c index cdc01cac0..37c083a42 100644 --- a/src/detection/media/media_windows.c +++ b/src/detection/media/media_windows.c @@ -32,12 +32,8 @@ static const char* getMedia(FFMediaResult* media) ffStrbufSetWS(&media->song, result.song); ffStrbufSetWS(&media->artist, result.artist); ffStrbufSetWS(&media->album, result.album); + ffStrbufSetWS(&media->cover, result.cover); ffStrbufSetStatic(&media->status, result.status); - - ffStrbufDestroy(&media->cover); - media->cover.chars = (char*) result.coverImageData; - media->cover.length = result.coverImageSize; - media->cover.allocated = result.coverImageSize + 1; return NULL; } diff --git a/src/detection/media/media_windows.dll.cpp b/src/detection/media/media_windows.dll.cpp index cf81cf09c..0ea2987dd 100644 --- a/src/detection/media/media_windows.dll.cpp +++ b/src/detection/media/media_windows.dll.cpp @@ -2,9 +2,9 @@ #include #include #include +#include #include -#include - +#include extern "C" { @@ -16,6 +16,7 @@ const char* ffWinrtDetectMedia(FFWinrtMediaResult* result) // Make it a separate dll in order not to break Windows 7 support using namespace winrt::Windows::Media::Control; using namespace winrt::Windows::ApplicationModel; + using namespace winrt::Windows::Storage; using namespace winrt::Windows::Storage::Streams; try @@ -69,20 +70,24 @@ const char* ffWinrtDetectMedia(FFWinrtMediaResult* result) { try { - auto stream = thumbRef.OpenReadAsync().get(); - uint64_t size = stream.Size(); - if (size > 0) + if (auto stream = thumbRef.OpenReadAsync().get()) { - auto contentType = stream.ContentType(); - auto ibuffer = Buffer(static_cast(size)); - auto readBuffer = stream.ReadAsync(ibuffer, static_cast(size), InputStreamOptions::None).get(); - uint32_t length = readBuffer.Length(); - auto reader = DataReader::FromBuffer(readBuffer); + if (stream.Size() > 0) + { + Buffer buffer(static_cast(stream.Size())); + stream.ReadAsync(buffer, buffer.Capacity(), InputStreamOptions::None).get(); - result->coverImageSize = length; - result->coverImageData = (uint8_t*) ::malloc(length + 1); - reader.ReadBytes(winrt::array_view(result->coverImageData, result->coverImageSize)); - result->coverImageData[length] = 0; + wchar_t tempPath[MAX_PATH]; + if (GetTempPathW(MAX_PATH, tempPath) > 0) + { + auto tempFolder = StorageFolder::GetFolderFromPathAsync(tempPath).get(); + auto tempFile = tempFolder.CreateFileAsync(L"ff_thumb.img", CreationCollisionOption::GenerateUniqueName).get(); + FileIO::WriteBufferAsync(tempFile, buffer).get(); + + ::wcsncpy(result->cover, tempFile.Path().data(), FF_MEDIA_WIN_RESULT_BUFLEN); + result->cover[FF_MEDIA_WIN_RESULT_BUFLEN - 1] = L'\0'; + } + } } } catch (...) diff --git a/src/detection/media/media_windows.dll.h b/src/detection/media/media_windows.dll.h index 9118328f8..005d3cf62 100644 --- a/src/detection/media/media_windows.dll.h +++ b/src/detection/media/media_windows.dll.h @@ -9,11 +9,8 @@ typedef struct FFWinrtMediaResult wchar_t song[FF_MEDIA_WIN_RESULT_BUFLEN]; wchar_t artist[FF_MEDIA_WIN_RESULT_BUFLEN]; wchar_t album[FF_MEDIA_WIN_RESULT_BUFLEN]; + wchar_t cover[FF_MEDIA_WIN_RESULT_BUFLEN]; const char* status; - - // Caller is responsible for freeing it using free() - uint8_t* coverImageData; - uint32_t coverImageSize; } FFWinrtMediaResult; __attribute__((__dllexport__))