Skip to content

Commit

Permalink
Merge pull request #9 from stuerp/vNext
Browse files Browse the repository at this point in the history
v0.1.7.0
  • Loading branch information
stuerp authored Jul 14, 2024
2 parents a10454b + 848d4a2 commit b30d78e
Show file tree
Hide file tree
Showing 16 changed files with 382 additions and 71 deletions.
13 changes: 12 additions & 1 deletion Configuration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ void configuration_t::Reset() noexcept
_WindowSizeUnit = WindowSizeUnit::Milliseconds;
_ReactionAlignment = 0.25;

_ClearOnStartup = ClearOnStartup::All;
_ClearOnStartup = ClearOnStartup::None;
_InPrivateMode = false;
}

/// <summary>
Expand All @@ -93,6 +94,7 @@ configuration_t & configuration_t::operator=(const configuration_t & other)
_ProfileName = other._ProfileName;

_ClearOnStartup = other._ClearOnStartup;
_InPrivateMode = other._InPrivateMode;

return *this;
}
Expand Down Expand Up @@ -141,6 +143,12 @@ void configuration_t::Read(stream_reader * reader, size_t size, abort_callback &
{
uint32_t Value; reader->read_object_t(Value, abortHandler); _ClearOnStartup = (ClearOnStartup) Value;
}

// Version 6, v0.1.6.3-alpha3
if (Version >= 6)
{
reader->read_object_t(_InPrivateMode, abortHandler);
}
}
catch (exception & ex)
{
Expand Down Expand Up @@ -176,6 +184,9 @@ void configuration_t::Write(stream_writer * writer, abort_callback & abortHandle

// Version 5, v0.1.6.0
Value = (uint32_t) _ClearOnStartup; writer->write_object_t(Value, abortHandler);

// Version 6, v0.1.6.3-alpha3
writer->write_object_t(_InPrivateMode, abortHandler);
}
catch (exception & ex)
{
Expand Down
5 changes: 3 additions & 2 deletions Configuration.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

/** $VER: Configuration.h (2024.07.09) P. Stuer **/
/** $VER: Configuration.h (2024.07.10) P. Stuer **/

#pragma once

Expand Down Expand Up @@ -59,7 +59,8 @@ class configuration_t

std::wstring _ProfileName;
ClearOnStartup _ClearOnStartup;
bool _InPrivateMode;

private:
const int32_t _CurrentVersion = 5;
const int32_t _CurrentVersion = 6;
};
11 changes: 10 additions & 1 deletion HostObject.idl
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
import "oaidl.idl";
import "ocidl.idl";

[uuid(0a7a4655-5660-47d0-8a37-98ae21399e57), version(0.2)]
[uuid(0a7a4655-5660-47d0-8a37-98ae21399e57), version(0.3)]
library HostObjectLibrary
{
struct image_t
{
long Width;
long Height;
SAFEARRAY(byte) Bytes;
};

//! [AddHostObjectInterface]
[uuid(3a14c9c0-bc3e-453f-a314-4ce4a0ec81d8), object, local]
interface IHostObject : IUnknown
Expand Down Expand Up @@ -46,6 +53,8 @@ library HostObjectLibrary
[propget] HRESULT IsMuted([out, retval] bool * value);

HRESULT GetFormattedText([in] BSTR text, [out, retval] BSTR * formattedText);

HRESULT GetArtwork([in] BSTR type, [out, retval] BSTR * image);
};

[uuid(637abc45-11f7-4dde-84b4-317d62a638d3)]
Expand Down
174 changes: 173 additions & 1 deletion HostObjectImpl.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

/** $VER: HostObjectImpl.cpp (2024.07.07) P. Stuer **/
/** $VER: HostObjectImpl.cpp (2024.07.10) P. Stuer **/

#include "pch.h"

Expand All @@ -8,8 +8,11 @@
#include <pathcch.h>
#pragma comment(lib, "pathcch")

#pragma comment(lib, "crypt32")

#include "Support.h"
#include "Resources.h"
#include "Encoding.h"

#include <SDK/titleformat.h>
#include <SDK/playlist.h>
Expand Down Expand Up @@ -459,6 +462,175 @@ HRESULT HostObject::GetTrackIndex(t_size & playlistIndex, t_size & itemIndex) no
return S_OK;
}

/// <summary>
/// Gets the specified artwork of the currently selected item in the current playlist.
/// </summary>
STDMETHODIMP HostObject::GetArtwork(BSTR type, BSTR * image)
{
*image = ::SysAllocString(L""); // Return an empty string by default and in case of an error.

if (type == nullptr)
return E_INVALIDARG;

// Verify the requested artwork type.
GUID AlbumArtId;

if (::_wcsicmp(type, L"front") == 0)
{
AlbumArtId = album_art_ids::cover_front;
}
else
if (::_wcsicmp(type, L"back") == 0)
{
AlbumArtId = album_art_ids::cover_back;
}
else
if (::_wcsicmp(type, L"disc") == 0)
{
AlbumArtId = album_art_ids::disc;
}
else
if (::_wcsicmp(type, L"icon") == 0)
{
AlbumArtId = album_art_ids::icon;
}
else
if (::_wcsicmp(type, L"artist") == 0)
{
AlbumArtId = album_art_ids::artist;
}
else
return S_OK;

metadb_handle_ptr Handle;

if (!_PlaybackControl->get_now_playing(Handle))
return S_OK;

static_api_ptr_t<album_art_manager_v3> Manager;

album_art_data::ptr aad;

try
{
album_art_extractor_instance_v2::ptr Extractor = Manager->open_v3(pfc::list_single_ref_t<metadb_handle_ptr>(Handle), pfc::list_single_ref_t<GUID>(AlbumArtId), nullptr, fb2k::noAbort);

if (Extractor.is_empty())
return S_OK;

// Query the external search patterns first.
try
{
album_art_path_list::ptr Paths = Extractor->query_paths(AlbumArtId, fb2k::noAbort);

if (Paths.is_valid())
{
for (size_t i = 0; i < Paths->get_count(); ++i)
{
pfc::string Extension = pfc::io::path::getFileExtension(Paths->get_path(i));

if (!Extension.isEmpty() && ((::_stricmp(Extension.c_str(), ".jpg") == 0) || (::_stricmp(Extension.c_str(), ".png") == 0) || (::_stricmp(Extension.c_str(), ".webp") == 0) || (::_stricmp(Extension.c_str(), ".gif") == 0)))
{
::SysFreeString(*image); // Free the empty string.

*image = ::SysAllocString(::UTF8ToWide(Paths->get_path(i)).c_str());

return S_OK;
}
}
}
}
catch (...)
{
}

// Query the embedded art.
if (!Extractor->query(AlbumArtId, aad, fb2k::noAbort))
{
// Query the stub the stub path.
try
{
Extractor = Manager->open_stub(fb2k::noAbort);

if (!Extractor->query(AlbumArtId, aad, fb2k::noAbort))
return S_OK;
}
catch (std::exception & e)
{
console::print(STR_COMPONENT_BASENAME " failed to query album art stub: ", e.what());
}
}
}
catch (...)
{
// Query the stub the stub path.
try
{
album_art_extractor_instance_v2::ptr Extractor = Manager->open_stub(fb2k::noAbort);

if (!Extractor->query(AlbumArtId, aad, fb2k::noAbort))
return S_OK;
}
catch (std::exception & e)
{
console::print(STR_COMPONENT_BASENAME " failed to query album art stub: ", e.what());
}
}

if (aad.is_empty())
return S_OK;

// Convert the binary image data into a JavaScript data URI.
const WCHAR * MIMEType = nullptr;

const BYTE * p = (const BYTE *) aad->data();

// Determine the MIME type of the image data.
if ((aad->size() > 2) && p[0] == 0xFF && p[1] == 0xD8)
MIMEType = L"image/jpeg";
else
if ((aad->size() > 15) && (p[0] == 'R' && p[1] == 'I' && p[2] == 'F' && p[3] == 'F') && (::memcmp(p + 8, "WEBPVP8", 7) == 0))
MIMEType = L"image/webp";
else
if ((aad->size() > 4) && p[0] == 0x89 && p[1] == 0x50 && p[2] == 0x4E && p[3] == 0x47)
MIMEType = L"image/png";
else
if ((aad->size() > 3) && p[0] == 0x47 && p[1] == 0x49 && p[2] == 0x46)
MIMEType = L"image/gif";

if (MIMEType == nullptr)
return S_OK;

// Convert the image data to base64.
const DWORD Flags = CRYPT_STRING_BASE64 | CRYPT_STRING_NOCRLF;

DWORD Size = 0;

if (!::CryptBinaryToStringW(p, (DWORD) aad->size(), Flags, nullptr, &Size))
return S_OK;

Size += 16 + (DWORD) ::wcslen(MIMEType);

WCHAR * Base64 = new WCHAR[Size];

if (Base64 == nullptr)
return S_OK;

::swprintf_s(Base64, Size, L"data:%s;base64,", MIMEType);

// Create the result.
if (::CryptBinaryToStringW(p, (DWORD) aad->size(), Flags, Base64 + ::wcslen(Base64), &Size))
{
::SysFreeString(*image); // Free the empty string.

*image = ::SysAllocString(Base64);
}

delete[] Base64;

return S_OK;
}

#pragma region IDispatch

/// <summary>
Expand Down
38 changes: 37 additions & 1 deletion HostObjectImpl.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

/** $VER: HostObjectImpl.h (2024.07.07) P. Stuer **/
/** $VER: HostObjectImpl.h (2024.07.10) P. Stuer **/

#pragma once

Expand All @@ -21,6 +21,7 @@
#include "HostObject_h.h"

#include <SDK/playback_control.h>
#include <SDK/album_art.h>

class HostObject : public Microsoft::WRL::RuntimeClass<Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>, IHostObject, IDispatch>
{
Expand Down Expand Up @@ -80,6 +81,8 @@ class HostObject : public Microsoft::WRL::RuntimeClass<Microsoft::WRL::RuntimeCl

STDMETHODIMP GetFormattedText(BSTR text, BSTR * formattedText) override;

STDMETHODIMP GetArtwork(BSTR type, BSTR * image) override;

#pragma endregion

#pragma region IDispatch
Expand All @@ -102,4 +105,37 @@ class HostObject : public Microsoft::WRL::RuntimeClass<Microsoft::WRL::RuntimeCl
RunCallbackAsync _RunCallbackAsync;

service_ptr_t<playback_control> _PlaybackControl;

/// <summary>
/// Represents an Album Art Manager configuration to allow overriding the default configuration in this component (see album_art_manager_v3::open_v3)
/// </summary>
class album_art_manager_config_t : public album_art_manager_config
{
public:
album_art_manager_config_t() { };

album_art_manager_config_t(const album_art_manager_config_t &) = delete;
album_art_manager_config_t(const album_art_manager_config_t &&) = delete;
album_art_manager_config_t & operator=(const album_art_manager_config_t &) = delete;
album_art_manager_config_t & operator=(album_art_manager_config_t &&) = delete;

virtual ~album_art_manager_config_t() { };

virtual bool get_external_pattern(pfc::string_base & out, const GUID & albumArtType) override
{
return false;
}

virtual bool use_embedded_pictures() override
{
return true;
}

virtual bool use_fallbacks() override
{
return true;
}
};

service_ptr_t<album_art_manager_config_t> _AlbumArtManagerConfig = new service_impl_t<album_art_manager_config_t>;
};
Loading

0 comments on commit b30d78e

Please sign in to comment.