Repository navigation
Expand file tree
/
Copy pathartwork_bridge.cpp
More file actions
145 lines (120 loc) · 4.94 KB
/
Copy pathartwork_bridge.cpp
File metadata and controls
145 lines (120 loc) · 4.94 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#include "pch.h"
#include "artwork_bridge.h"
#include "preferences.h"
#include "core/control_panel_core.h"
#include <mutex>
#include <string>
// Global function pointers
pfn_foo_artwork_search g_artwork_search = nullptr;
pfn_foo_artwork_get_bitmap g_artwork_get_bitmap = nullptr;
pfn_foo_artwork_is_loading g_artwork_is_loading = nullptr;
pfn_foo_artwork_set_callback g_artwork_set_callback = nullptr;
pfn_foo_artwork_remove_callback g_artwork_remove_callback = nullptr;
// Module handle for foo_artwork
static HMODULE g_foo_artwork_module = nullptr;
// Pending artwork from callback (guarded by g_pending_mutex)
static std::mutex g_pending_mutex;
static HBITMAP g_pending_artwork_bitmap = nullptr;
static bool g_has_pending_artwork = false;
// Last requested artist & title for search deduplication
static std::string g_last_requested_artist;
static std::string g_last_requested_title;
// Callback function that receives artwork results from foo_artwork.
// Called on foo_artwork's worker thread - must synchronize and marshal to main thread.
static void artwork_result_callback(bool success, HBITMAP bitmap) {
if (success && bitmap) {
std::lock_guard<std::mutex> lock(g_pending_mutex);
g_pending_artwork_bitmap = bitmap;
g_has_pending_artwork = true;
}
// Always marshal notification to main thread so that title formats (%foo_artwork_title%, %foo_artwork_artist%)
// and UI repaints are updated even if no artwork image was found in API search
fb2k::inMainThread([]() {
nowbar::ControlPanelCore::notify_online_artwork_received();
});
}
bool init_artwork_bridge() {
// Try to get handle to already-loaded foo_artwork module
g_foo_artwork_module = GetModuleHandleW(L"foo_artwork.dll");
if (!g_foo_artwork_module) {
// foo_artwork not installed/loaded
return false;
}
// Resolve function pointers - these are extern "C" exports from foo_artwork
g_artwork_search = (pfn_foo_artwork_search)
GetProcAddress(g_foo_artwork_module, "foo_artwork_search");
g_artwork_get_bitmap = (pfn_foo_artwork_get_bitmap)
GetProcAddress(g_foo_artwork_module, "foo_artwork_get_bitmap");
g_artwork_is_loading = (pfn_foo_artwork_is_loading)
GetProcAddress(g_foo_artwork_module, "foo_artwork_is_loading");
g_artwork_set_callback = (pfn_foo_artwork_set_callback)
GetProcAddress(g_foo_artwork_module, "foo_artwork_set_callback");
g_artwork_remove_callback = (pfn_foo_artwork_remove_callback)
GetProcAddress(g_foo_artwork_module, "foo_artwork_remove_callback");
// Register our callback to receive artwork results
if (g_artwork_set_callback) {
g_artwork_set_callback(artwork_result_callback);
}
// Return true if at least the search function is available
return g_artwork_search != nullptr;
}
void shutdown_artwork_bridge() {
// Unregister our specific callback (multi-callback safe)
if (g_artwork_remove_callback) {
g_artwork_remove_callback(artwork_result_callback);
} else if (g_artwork_set_callback) {
g_artwork_set_callback(nullptr); // Fallback for older foo_artwork
}
std::lock_guard<std::mutex> lock(g_pending_mutex);
g_pending_artwork_bitmap = nullptr;
g_has_pending_artwork = false;
g_last_requested_artist.clear();
g_last_requested_title.clear();
}
void clear_pending_online_artwork() {
std::lock_guard<std::mutex> lock(g_pending_mutex);
g_pending_artwork_bitmap = nullptr;
g_has_pending_artwork = false;
g_last_requested_artist.clear();
g_last_requested_title.clear();
}
void request_online_artwork(const char* artist, const char* title) {
// Check if online artwork is enabled in preferences
if (!get_nowbar_online_artwork()) {
return;
}
// Check if bridge is available
if (!g_artwork_search) {
init_artwork_bridge();
if (!g_artwork_search) return;
}
const char* safe_artist = artist ? artist : "";
const char* safe_title = title ? title : "";
if (safe_artist[0] == '\0' && safe_title[0] == '\0') {
return;
}
// Deduplicate: If already requested this exact artist & title, don't re-issue search
{
std::lock_guard<std::mutex> lock(g_pending_mutex);
if (g_last_requested_artist == safe_artist && g_last_requested_title == safe_title) {
return;
}
g_last_requested_artist = safe_artist;
g_last_requested_title = safe_title;
g_pending_artwork_bitmap = nullptr;
g_has_pending_artwork = false;
}
// Request artwork from foo_artwork
g_artwork_search(safe_artist, safe_title);
}
bool has_pending_online_artwork() {
std::lock_guard<std::mutex> lock(g_pending_mutex);
return g_has_pending_artwork;
}
HBITMAP get_pending_online_artwork() {
std::lock_guard<std::mutex> lock(g_pending_mutex);
HBITMAP bitmap = g_pending_artwork_bitmap;
g_pending_artwork_bitmap = nullptr;
g_has_pending_artwork = false;
return bitmap;
}