diff --git a/CMakeLists.txt b/CMakeLists.txt index b1dffb22f..1f4d3b2f8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -160,7 +160,11 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WARNING_FLAGS} -Werror=incompatible-pointe if(WIN32 OR Haiku) enable_language(CXX) - set(CMAKE_CXX_STANDARD 17) + if(WIN32) + set(CMAKE_CXX_STANDARD 20) + else() + set(CMAKE_CXX_STANDARD 17) + endif() set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WARNING_FLAGS}") endif() @@ -1065,7 +1069,7 @@ elseif(WIN32) src/detection/locale/locale_windows.c src/detection/localip/localip_windows.c src/detection/gamepad/gamepad_windows.c - src/detection/media/media_windows.c + src/detection/media/media_windows.cpp src/detection/memory/memory_windows.c src/detection/mouse/mouse_windows.c src/detection/physicalmemory/physicalmemory_linux.c @@ -1332,6 +1336,14 @@ endif() if(WIN32) list(APPEND LIBFASTFETCH_SRC src/detection/gpu/gpu_intel.c) list(APPEND LIBFASTFETCH_SRC src/detection/gpu/gpu_amd.c) + + include(CheckIncludeFileCXX) + CHECK_INCLUDE_FILE_CXX("winrt/Windows.Foundation.h" HAVE_WINRT) + if(HAVE_WINRT) + message(STATUS "WinRT headers are available, media detection will use WinRT APIs") + else() + message(STATUS "WinRT headers are NOT available, media detection will be disabled") + endif() endif() include(CheckFunctionExists) check_function_exists(wcwidth HAVE_WCWIDTH) @@ -1434,7 +1446,7 @@ if(LINUX) elseif(ANDROID) target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE _XOPEN_SOURCE _FILE_OFFSET_BITS=64 "$<$:__BIONIC_FORTIFY>" "$<$:__BIONIC_FORTIFY_RUNTIME_CHECKS_ENABLED>") elseif(WIN32) - target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE WIN32_LEAN_AND_MEAN _WIN32_WINNT=0x0A00 NOMINMAX UNICODE) # "$<$:_FORTIFY_SOURCE=3>" + target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE WIN32_LEAN_AND_MEAN WINRT_LEAN_AND_MEAN _WIN32_WINNT=0x0A00 NOMINMAX UNICODE) # "$<$:_FORTIFY_SOURCE=3>" elseif(APPLE) target_compile_definitions(libfastfetch PUBLIC _GNU_SOURCE _XOPEN_SOURCE __STDC_WANT_LIB_EXT1__ _FILE_OFFSET_BITS=64 _DARWIN_C_SOURCE) elseif(OpenBSD) @@ -1745,6 +1757,12 @@ elseif(WIN32) PRIVATE "mincore" ) endif() + if(HAVE_WINRT) + target_link_libraries(libfastfetch + PRIVATE + "RuntimeObject" + ) + endif() elseif(FreeBSD) target_link_libraries(libfastfetch PRIVATE "m" @@ -1831,20 +1849,6 @@ target_link_libraries(libfastfetch target_compile_options(libfastfetch PRIVATE $<$:-fno-exceptions -fno-rtti>) -if(WIN32) - set(CMAKE_CXX_STANDARD 20) - include(CheckIncludeFileCXX) - CHECK_INCLUDE_FILE_CXX("winrt/Windows.Foundation.h" HAVE_WINRT) - if(HAVE_WINRT) - add_library(ffwinrt MODULE src/detection/media/media_windows.dll.cpp) - target_link_libraries(ffwinrt PRIVATE "RuntimeObject") - target_compile_definitions(ffwinrt PRIVATE WIN32_LEAN_AND_MEAN=1 WINRT_LEAN_AND_MEAN=1) - target_link_options(ffwinrt - PRIVATE "-static" # stdc++, winpthread, gcc_s, etc. - ) - endif() - set(CMAKE_CXX_STANDARD 17) -endif() if(FreeBSD) set(CMAKE_REQUIRED_INCLUDES "/usr/local/include" "/usr/include") endif() @@ -1891,6 +1895,8 @@ if(NOT WIN32) message(WARNING "pthread_timedjoin_np was not found; networking timeout will not work") endif() endif() +elseif(HAVE_WINRT) + target_compile_definitions(libfastfetch PRIVATE FF_HAVE_WINRT=1) endif() set(PACKAGES_DISABLE_LIST "") @@ -2037,13 +2043,6 @@ if (TARGET flashfetch) ) endif() -if (TARGET ffwinrt) - install( - TARGETS ffwinrt - DESTINATION "${CMAKE_INSTALL_BINDIR}" - ) -endif() - install( FILES "${CMAKE_SOURCE_DIR}/completions/${CMAKE_PROJECT_NAME}.bash" DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/bash-completion/completions" diff --git a/src/common/impl/init.c b/src/common/impl/init.c index 91aa015eb..80fb37124 100644 --- a/src/common/impl/init.c +++ b/src/common/impl/init.c @@ -260,6 +260,9 @@ void ffListFeatures(void) { #if FF_HAVE_EMBEDDED_PCIIDS "Embedded pciids\n" #endif +#if FF_HAVE_WINRT + "WinRT headers\n" +#endif #if FF_WIN81_COMPAT "Windows 8.1 Compatibility\n" #endif diff --git a/src/common/windows/com.hpp b/src/common/windows/com.hpp index 16bb1ac71..8a0de559f 100644 --- a/src/common/windows/com.hpp +++ b/src/common/windows/com.hpp @@ -2,6 +2,7 @@ #ifdef __cplusplus + #include "common/attributes.h" #include const char* ffInitCom(void); diff --git a/src/detection/media/media_windows.c b/src/detection/media/media_windows.c deleted file mode 100644 index c9d534a8d..000000000 --- a/src/detection/media/media_windows.c +++ /dev/null @@ -1,42 +0,0 @@ -#include "common/library.h" -#include "common/windows/unicode.h" -#include "media.h" -#include "media_windows.dll.h" - -static const char* getMedia(FFMediaResult* media, bool saveCover) { - FF_LIBRARY_LOAD_MESSAGE(libffwinrt, "libffwinrt" FF_LIBRARY_EXTENSION, 0) - FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libffwinrt, ffWinrtDetectMedia) - libffwinrt = NULL; // Don't close libffwinrt or it may crash - - FFWinrtMediaResult result = {}; - - const char* error = ffffWinrtDetectMedia(&result, saveCover); - if (error) { - ffStrbufSetStatic(&media->error, error); - return NULL; - } - - ffStrbufSetWS(&media->playerId, result.playerId); - if (result.playerName[0]) { - ffStrbufSetWS(&media->player, result.playerName); - } else { - ffStrbufSet(&media->player, &media->playerId); - if (ffStrbufEndsWithIgnCaseS(&media->player, ".exe")) { - ffStrbufSubstrBefore(&media->player, media->player.length - 4); - } - } - 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); - if (media->cover.length > 0) { - media->removeCoverAfterUse = true; - } - return NULL; -} - -void ffDetectMediaImpl(FFMediaResult* media, bool saveCover) { - const char* error = getMedia(media, saveCover); - ffStrbufAppendS(&media->error, error); -} diff --git a/src/detection/media/media_windows.cpp b/src/detection/media/media_windows.cpp new file mode 100644 index 000000000..7cf9eacc4 --- /dev/null +++ b/src/detection/media/media_windows.cpp @@ -0,0 +1,344 @@ +extern "C" { +#include "media.h" +#include "common/time.h" +#include "common/windows/unicode.h" +} + +#if FF_HAVE_WINRT + #include + #include + #include + #include + + #include + #include + #include + #include + + #include "common/windows/com.hpp" + +using winrt::impl::abi_t; +using winrt::Windows::Foundation::IAsyncOperation; +using winrt::Windows::Foundation::IAsyncOperationWithProgress; + +static inline void deleteHstring(HSTRING* pstr) { + if (*pstr) { + WindowsDeleteString(*pstr); + } +} + +static inline void ffStrbufSetHstring(FFstrbuf* destination, HSTRING value) { + uint32_t length = 0; + const wchar_t* raw = WindowsGetStringRawBuffer(value, &length); + ffStrbufSetNWS(destination, length, raw); +} + +template +static inline HRESULT ffGetActivationFactory(const wchar_t* className, REFIID iid, Interface** factory) { + HSTRING_HEADER header; + FF_A_CLEANUP(deleteHstring) HSTRING runtimeClass = NULL; + HRESULT hr = WindowsCreateStringReference(className, (UINT32)::wcslen(className), &header, &runtimeClass); + if (FAILED(hr)) { + return hr; + } + + return RoGetActivationFactory(runtimeClass, iid, reinterpret_cast(factory)); +} + +template +static inline HRESULT ffQueryInterface(SourceAbi* source, TargetAbi** target) { + *target = NULL; + return reinterpret_cast(source)->QueryInterface(winrt::guid_of(), reinterpret_cast(target)); +} + +template +static HRESULT ffWaitForAsyncOperation(TOperationAbi* operation, TResultAbi** result) { + *result = NULL; + + IAsyncInfo* FF_AUTO_RELEASE_COM_OBJECT asyncInfo = NULL; + HRESULT hr = ffQueryInterface(operation, &asyncInfo); + if (FAILED(hr)) { + return hr; + } + + AsyncStatus status = AsyncStatus::Started; + + for (;;) { + hr = asyncInfo->get_Status(&status); + if (FAILED(hr)) { + return hr; + } + if (status == AsyncStatus::Started) { + ffTimeSleep(0); + } else { + break; + } + } + + if (status != AsyncStatus::Completed) { + HRESULT errorCode = E_FAIL; + asyncInfo->get_ErrorCode(&errorCode); + return FAILED(errorCode) ? errorCode : E_FAIL; + } + + return operation->GetResults((void**) result); +} + +static HRESULT ffSaveThumbnailToTempPath( + abi_t* thumbnail, + FFstrbuf* destination) { + abi_t>* FF_AUTO_RELEASE_COM_OBJECT openOperation = NULL; + HRESULT hr = thumbnail->OpenReadAsync(reinterpret_cast(&openOperation)); + if (FAILED(hr)) { + return hr; + } + + abi_t* FF_AUTO_RELEASE_COM_OBJECT contentStream = NULL; + hr = ffWaitForAsyncOperation(openOperation, &contentStream); + if (FAILED(hr) || !contentStream) { + return FAILED(hr) ? hr : E_FAIL; + } + + abi_t* FF_AUTO_RELEASE_COM_OBJECT randomAccessStream = NULL; + hr = ffQueryInterface(contentStream, &randomAccessStream); + if (FAILED(hr)) { + return hr; + } + + UINT64 size = 0; + hr = randomAccessStream->get_Size(&size); + if (FAILED(hr) || size == 0) { + return FAILED(hr) ? hr : S_FALSE; + } + + if (size > 0xFFFFFFFFu) { + return HRESULT_FROM_WIN32(ERROR_FILE_TOO_LARGE); + } + + abi_t* FF_AUTO_RELEASE_COM_OBJECT bufferFactory = NULL; + hr = ffGetActivationFactory(L"Windows.Storage.Streams.Buffer", winrt::guid_of(), &bufferFactory); + if (FAILED(hr)) { + return hr; + } + + abi_t* FF_AUTO_RELEASE_COM_OBJECT buffer = NULL; + hr = bufferFactory->Create((UINT32) size, reinterpret_cast(&buffer)); + if (FAILED(hr) || !buffer) { + return FAILED(hr) ? hr : E_FAIL; + } + + abi_t* FF_AUTO_RELEASE_COM_OBJECT inputStream = NULL; + hr = ffQueryInterface(contentStream, &inputStream); + if (FAILED(hr)) { + return hr; + } + + abi_t>* FF_AUTO_RELEASE_COM_OBJECT readOperation = NULL; + hr = inputStream->ReadAsync(buffer, (UINT32) size, static_cast(winrt::Windows::Storage::Streams::InputStreamOptions::None), reinterpret_cast(&readOperation)); + if (FAILED(hr)) { + return hr; + } + + abi_t* FF_AUTO_RELEASE_COM_OBJECT readBuffer = NULL; + hr = ffWaitForAsyncOperation(readOperation, &readBuffer); + if (FAILED(hr) || !readBuffer) { + return FAILED(hr) ? hr : E_FAIL; + } + + UINT32 length = 0; + hr = readBuffer->get_Length(&length); + if (FAILED(hr) || length == 0) { + return FAILED(hr) ? hr : S_FALSE; + } + + Windows::Storage::Streams::IBufferByteAccess* FF_AUTO_RELEASE_COM_OBJECT byteAccess = NULL; + hr = reinterpret_cast(readBuffer)->QueryInterface(IID_PPV_ARGS(&byteAccess)); + if (FAILED(hr)) { + return hr; + } + + byte* bytes = NULL; + hr = byteAccess->Buffer(&bytes); + if (FAILED(hr) || !bytes) { + return FAILED(hr) ? hr : E_FAIL; + } + + wchar_t tempDirectory[MAX_PATH]; + DWORD tempLength = GetTempPathW(MAX_PATH, tempDirectory); + if (tempLength == 0 || tempLength >= MAX_PATH) { + return HRESULT_FROM_WIN32(GetLastError()); + } + + wchar_t tempFilePath[MAX_PATH]; + if (!GetTempFileNameW(tempDirectory, L"fft", 0, tempFilePath)) { + return HRESULT_FROM_WIN32(GetLastError()); + } + + HANDLE file = CreateFileW(tempFilePath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if (file == INVALID_HANDLE_VALUE) { + DeleteFileW(tempFilePath); + return HRESULT_FROM_WIN32(GetLastError()); + } + + DWORD written = 0; + BOOL writtenOk = WriteFile(file, bytes, length, &written, NULL); + DWORD writeError = writtenOk ? ERROR_SUCCESS : GetLastError(); + CloseHandle(file); + + if (!writtenOk || written != length) { + DeleteFileW(tempFilePath); + return HRESULT_FROM_WIN32(writtenOk ? ERROR_WRITE_FAULT : writeError); + } + + ffStrbufSetWS(destination, tempFilePath); + return S_OK; +} + +static const char* getMedia(FFMediaResult* result, bool saveCover) { + // RO_INIT_MULTITHREADED is required for IRandomAccessStreamReference::OpenReadAsync to work correctly + HRESULT initHr = RoInitialize(RO_INIT_MULTITHREADED); + bool shouldUninitialize = SUCCEEDED(initHr); + if (FAILED(initHr) && initHr != RPC_E_CHANGED_MODE) { + return "winrt: RoInitialize() failed"; + } + + const char* error = NULL; + + do { + abi_t* FF_AUTO_RELEASE_COM_OBJECT managerStatics = NULL; + HRESULT hr = ffGetActivationFactory(L"Windows.Media.Control.GlobalSystemMediaTransportControlsSessionManager", winrt::guid_of(), &managerStatics); + if (FAILED(hr) || !managerStatics) { + error = "winrt: RoGetActivationFactory(GlobalSystemMediaTransportControlsSessionManager) failed"; + break; + } + + abi_t>* FF_AUTO_RELEASE_COM_OBJECT managerOperation = NULL; + hr = managerStatics->RequestAsync(reinterpret_cast(&managerOperation)); + if (FAILED(hr) || !managerOperation) { + error = "winrt: RequestAsync() failed"; + break; + } + + abi_t* FF_AUTO_RELEASE_COM_OBJECT manager = NULL; + hr = ffWaitForAsyncOperation(managerOperation, &manager); + if (FAILED(hr) || !manager) { + error = "winrt: RequestAsync().GetResults() failed"; + break; + } + + abi_t* FF_AUTO_RELEASE_COM_OBJECT session = NULL; + hr = manager->GetCurrentSession(reinterpret_cast(&session)); + if (FAILED(hr) || !session) { + error = "winrt: GetCurrentSession() failed"; + break; + } + + abi_t>* FF_AUTO_RELEASE_COM_OBJECT mediaPropsOperation = NULL; + hr = session->TryGetMediaPropertiesAsync(reinterpret_cast(&mediaPropsOperation)); + if (FAILED(hr) || !mediaPropsOperation) { + error = "winrt: TryGetMediaPropertiesAsync() failed"; + break; + } + + abi_t* FF_AUTO_RELEASE_COM_OBJECT mediaProps = NULL; + hr = ffWaitForAsyncOperation(mediaPropsOperation, &mediaProps); + if (FAILED(hr) || !mediaProps) { + error = "winrt: TryGetMediaPropertiesAsync().GetResults() failed"; + break; + } + + abi_t* FF_AUTO_RELEASE_COM_OBJECT playbackInfo = NULL; + hr = session->GetPlaybackInfo(reinterpret_cast(&playbackInfo)); + if (SUCCEEDED(hr) && playbackInfo) { + int32_t playbackStatusValue = 0; + if (SUCCEEDED(playbackInfo->get_PlaybackStatus(&playbackStatusValue))) { + switch (static_cast(playbackStatusValue)) { + #define FF_MEDIA_SET_STATUS(status_code) \ + case winrt::Windows::Media::Control::GlobalSystemMediaTransportControlsSessionPlaybackStatus::status_code: \ + ffStrbufSetStatic(&result->status, #status_code); \ + break; + FF_MEDIA_SET_STATUS(Closed) + FF_MEDIA_SET_STATUS(Opened) + FF_MEDIA_SET_STATUS(Changing) + FF_MEDIA_SET_STATUS(Stopped) + FF_MEDIA_SET_STATUS(Playing) + FF_MEDIA_SET_STATUS(Paused) + #undef FF_MEDIA_SET_STATUS + } + } + } + + FF_A_CLEANUP(deleteHstring) HSTRING playerId = NULL; + hr = session->get_SourceAppUserModelId(reinterpret_cast(&playerId)); + if (FAILED(hr)) { + error = "winrt: get_SourceAppUserModelId() failed"; + break; + } + + ffStrbufSetHstring(&result->playerId, playerId); + + FF_A_CLEANUP(deleteHstring) HSTRING title = NULL; + if (SUCCEEDED(mediaProps->get_Title(reinterpret_cast(&title)))) { + ffStrbufSetHstring(&result->song, title); + } + + FF_A_CLEANUP(deleteHstring) HSTRING artist = NULL; + if (SUCCEEDED(mediaProps->get_Artist(reinterpret_cast(&artist)))) { + ffStrbufSetHstring(&result->artist, artist); + } + + FF_A_CLEANUP(deleteHstring) HSTRING album = NULL; + if (SUCCEEDED(mediaProps->get_AlbumTitle(reinterpret_cast(&album)))) { + ffStrbufSetHstring(&result->album, album); + } + + abi_t* FF_AUTO_RELEASE_COM_OBJECT appInfoStatics = NULL; + hr = ffGetActivationFactory(L"Windows.ApplicationModel.AppInfo", winrt::guid_of(), &appInfoStatics); + if (SUCCEEDED(hr) && appInfoStatics) { + abi_t* FF_AUTO_RELEASE_COM_OBJECT appInfo = NULL; + if (SUCCEEDED(appInfoStatics->GetFromAppUserModelId(reinterpret_cast(playerId), reinterpret_cast(&appInfo))) && appInfo) { + abi_t* FF_AUTO_RELEASE_COM_OBJECT displayInfo = NULL; + if (SUCCEEDED(appInfo->get_DisplayInfo(reinterpret_cast(&displayInfo))) && displayInfo) { + FF_A_CLEANUP(deleteHstring) HSTRING displayName = NULL; + if (SUCCEEDED(displayInfo->get_DisplayName(reinterpret_cast(&displayName)))) { + ffStrbufSetHstring(&result->player, displayName); + } + } + } + } + + if (result->player.length == 0) { + ffStrbufSet(&result->player, &result->playerId); + if (ffStrbufEndsWithIgnCaseS(&result->player, ".exe")) { + ffStrbufSubstrBefore(&result->player, result->player.length - 4); + } + } + + if (saveCover) { + abi_t* FF_AUTO_RELEASE_COM_OBJECT thumbnail = NULL; + hr = mediaProps->get_Thumbnail(reinterpret_cast(&thumbnail)); + if (SUCCEEDED(hr) && thumbnail) { + if (SUCCEEDED(ffSaveThumbnailToTempPath(thumbnail, &result->cover)) && result->cover.length > 0) { + result->removeCoverAfterUse = true; + } + } + } + } while (false); + + if (shouldUninitialize) { + RoUninitialize(); + } + + return error; +} +#else +static const char* getMedia(FFMediaResult* media, bool saveCover) { + FF_UNUSED(media, saveCover); + return "Fastfetch is not compiled with WinRT support"; +} +#endif // FF_HAVE_WINRT + +extern "C" void ffDetectMediaImpl(FFMediaResult* media, bool saveCover) { + const char* error = getMedia(media, saveCover); + ffStrbufAppendS(&media->error, error); +} diff --git a/src/detection/media/media_windows.dll.cpp b/src/detection/media/media_windows.dll.cpp deleted file mode 100644 index b89ced9c7..000000000 --- a/src/detection/media/media_windows.dll.cpp +++ /dev/null @@ -1,99 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -extern "C" { -#include "media_windows.dll.h" - -const char* ffWinrtDetectMedia(FFWinrtMediaResult* result, bool saveCover) { - // C++/WinRT requires Windows 8.1+ and C++ runtime (std::string, exceptions and other stuff) - // Make it a separate dll in order not to break Windows 7 support - using namespace winrt::Windows::Media::Control; - using namespace winrt::Windows::ApplicationModel; - - try { - auto manager = GlobalSystemMediaTransportControlsSessionManager::RequestAsync().get(); - if (!manager) { - return "winrt: GlobalSystemMediaTransportControlsSessionManager::RequestAsync() failed"; - } - - auto session = manager.GetCurrentSession(); - if (!session) { - return "winrt: GetCurrentSession() failed"; - } - - auto mediaProps = session - .TryGetMediaPropertiesAsync() - .get(); - if (!mediaProps) { - return "winrt: TryGetMediaPropertiesAsync() failed"; - } - - if (auto playbackInfo = session.GetPlaybackInfo()) { - switch (playbackInfo.PlaybackStatus()) { -#define FF_MEDIA_SET_STATUS(status_code) \ - case GlobalSystemMediaTransportControlsSessionPlaybackStatus::status_code: \ - result->status = #status_code; \ - break; - FF_MEDIA_SET_STATUS(Closed) - FF_MEDIA_SET_STATUS(Opened) - FF_MEDIA_SET_STATUS(Changing) - FF_MEDIA_SET_STATUS(Stopped) - FF_MEDIA_SET_STATUS(Playing) - FF_MEDIA_SET_STATUS(Paused) -#undef FF_MEDIA_SET_STATUS - } - } - - ::wcsncpy(result->playerId, session.SourceAppUserModelId().data(), FF_MEDIA_WIN_RESULT_BUFLEN); - result->playerId[FF_MEDIA_WIN_RESULT_BUFLEN - 1] = L'\0'; - ::wcsncpy(result->song, mediaProps.Title().data(), FF_MEDIA_WIN_RESULT_BUFLEN); - result->song[FF_MEDIA_WIN_RESULT_BUFLEN - 1] = L'\0'; - ::wcsncpy(result->artist, mediaProps.Artist().data(), FF_MEDIA_WIN_RESULT_BUFLEN); - result->artist[FF_MEDIA_WIN_RESULT_BUFLEN - 1] = L'\0'; - ::wcsncpy(result->album, mediaProps.AlbumTitle().data(), FF_MEDIA_WIN_RESULT_BUFLEN); - result->album[FF_MEDIA_WIN_RESULT_BUFLEN - 1] = L'\0'; - try { - // Only works for UWP apps - ::wcsncpy(result->playerName, AppInfo::GetFromAppUserModelId(session.SourceAppUserModelId()).DisplayInfo().DisplayName().data(), FF_MEDIA_WIN_RESULT_BUFLEN); - result->playerName[FF_MEDIA_WIN_RESULT_BUFLEN - 1] = L'\0'; - } catch (...) {} - - if (saveCover) { - using namespace winrt::Windows::Storage; - using namespace winrt::Windows::Storage::Streams; - if (auto thumbRef = mediaProps.Thumbnail()) { - try { - if (auto stream = thumbRef.OpenReadAsync().get()) { - if (stream.Size() > 0) { - Buffer buffer(static_cast(stream.Size())); - stream.ReadAsync(buffer, buffer.Capacity(), InputStreamOptions::None).get(); - - 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 (...) { - // Ignore thumbnail errors - } - } - } - - return NULL; - } catch (...) { - return "A C++ exception is thrown"; - } -} - -} // extern "C" diff --git a/src/detection/media/media_windows.dll.h b/src/detection/media/media_windows.dll.h deleted file mode 100644 index b9b942d74..000000000 --- a/src/detection/media/media_windows.dll.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#define FF_MEDIA_WIN_RESULT_BUFLEN 256 - -typedef struct FFWinrtMediaResult { - wchar_t playerId[FF_MEDIA_WIN_RESULT_BUFLEN]; - wchar_t playerName[FF_MEDIA_WIN_RESULT_BUFLEN]; - 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; -} FFWinrtMediaResult; - -__attribute__((__dllexport__)) -const char* -ffWinrtDetectMedia(FFWinrtMediaResult* result, bool saveCover);