Skip to content

Commit ed31288

Browse files
Merge branch 'jacquesh:main' into main
2 parents 6fc77e8 + 50aa8c1 commit ed31288

File tree

10 files changed

+252
-51
lines changed

10 files changed

+252
-51
lines changed
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
name: Check pull request contents
2+
on: pull_request
3+
4+
jobs:
5+
check-changelist-modified:
6+
name: Check that the changelog has been updated
7+
runs-on: windows-2022
8+
steps:
9+
- name: Checkout
10+
uses: actions/checkout@v4
11+
12+
- name: Check what files have been modified
13+
uses: dorny/paths-filter@v3.0.2
14+
id: filter
15+
with:
16+
filters: |
17+
main:
18+
- 'src/main.cpp'
19+
20+
- name: Fail if the changelog wasn't updated
21+
if: ${{ steps.filter.outputs.main == 'false' }}
22+
run: exit 1

.github/workflows/release.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ jobs:
1616
name: Build Release
1717
runs-on: windows-latest
1818
needs: run-tests
19+
permissions:
20+
contents: write # Needed to allow creating a release
1921

2022
steps:
2123
- name: Add MSBuild to the PATH

.github/workflows/run_tests.yml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@ name: Run tests
22
on:
33
push:
44
branches: main
5+
pull_request:
56
workflow_call:
67

78
jobs:
89
print-windows-sdks:
10+
name: Log Windows SDKs
911
runs-on: windows-2022
1012
steps:
1113
- name: Print installed Windows SDK versions
@@ -14,6 +16,7 @@ jobs:
1416
run: Get-ChildItem -Name "HKLM:\SOFTWARE\Microsoft\Windows Kits\Installed Roots"
1517

1618
print-compiler-version:
19+
name: Log MSVC compiler version
1720
runs-on: windows-2022
1821
steps:
1922
- name: Add MSVC compiler to the PATH
@@ -25,8 +28,8 @@ jobs:
2528
run: cl /?
2629

2730
build-and-test-32bit:
31+
name: Build & test - x86
2832
runs-on: windows-2022
29-
name: Build and test - x86
3033
steps:
3134
- name: Add MSBuild to the PATH
3235
uses: microsoft/setup-msbuild@v2
@@ -41,8 +44,8 @@ jobs:
4144
run: build\Debug\test_foo_openlyrics.exe build\Debug\foo_openlyrics.dll
4245

4346
build-and-test-64bit:
47+
name: Build & test - x64
4448
runs-on: windows-2022
45-
name: Build and test - x64
4649
steps:
4750
- name: Add MSBuild to the PATH
4851
uses: microsoft/setup-msbuild@v2

build/foo_openlyrics.vcxproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,7 @@
301301
<ClInclude Include="..\src\resource.h" />
302302
<ClInclude Include="..\src\sources\lyric_source.h" />
303303
<ClInclude Include="..\src\stdafx.h" />
304+
<ClInclude Include="..\src\string_split.h" />
304305
<ClInclude Include="..\src\tag_util.h" />
305306
<ClInclude Include="..\src\uie_shim_panel.h" />
306307
<ClInclude Include="..\src\ui_hooks.h" />

build/foo_openlyrics.vcxproj.filters

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,9 @@
269269
<ClInclude Include="..\src\lyric_search.h">
270270
<Filter>Header Files</Filter>
271271
</ClInclude>
272+
<ClInclude Include="..\src\string_split.h">
273+
<Filter>Header Files</Filter>
274+
</ClInclude>
272275
</ItemGroup>
273276
<ItemGroup>
274277
<ResourceCompile Include="..\src\foo_openlyrics.rc">

src/PCH.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,11 @@
22

33
#define MVTF_IMPLEMENTATION
44
#include "mvtf/mvtf.h"
5+
6+
#define STRINGSPLIT_IMPLEMENTATION
7+
#ifdef MVTF_TESTS_ENABLED
8+
#define STRINGSPLIT_TESTS_ENABLED
9+
#define STRINGSPLIT_TEST MVTF_TEST
10+
#define STRINGSPLIT_ASSERT ASSERT
11+
#endif
12+
#include "string_split.h"

src/main.cpp

Lines changed: 50 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#include "stdafx.h"
22

3+
#include "mvtf/mvtf.h"
4+
35
// NOTE: We only pull in the generated header in release builds because that file gets recreated
46
// on every build, which forces every file that includes it to also be recompiled on every
57
// build. This is a significant waste of time during development.
@@ -17,17 +19,8 @@
1719
// Copied from the DECLARE_COMPONENT_VERSION(NAME,VERSION,ABOUT) macro, defined in foo_SDK/foobar2000/SDK/component_version.h
1820
namespace
1921
{
20-
class OpenLyricsVersion : public componentversion
21-
{
22-
public:
23-
void get_file_name(pfc::string_base& out) final {out = core_api::get_my_file_name();}
24-
void get_component_name(pfc::string_base & out) final {out = "OpenLyrics";}
25-
void get_component_version(pfc::string_base & out) final {out = OPENLYRICS_VERSION;}
26-
void get_about_message(pfc::string_base & out) final;
27-
};
28-
static service_factory_single_t<OpenLyricsVersion> g_openlyricsversion_factory;
29-
}
30-
void OpenLyricsVersion::get_about_message(pfc::string_base & out)
22+
23+
static void compute_about_message_string(pfc::string_base & out)
3124
{
3225
out = "foo_openlyrics " OPENLYRICS_VERSION "\n";
3326
out += "Open-source lyrics retrieval and display\n";
@@ -36,6 +29,10 @@ void OpenLyricsVersion::get_about_message(pfc::string_base & out)
3629
out += "\nChangelog:\n";
3730
// out += "Version " OPENLYRICS_VERSION " (" __DATE__ "):\n"
3831
// "\n";
32+
out += "Version " OPENLYRICS_VERSION " (" __DATE__ "):\n"
33+
"- Fix a crash when trying to show lyrics for a track with none saved\n"
34+
"- Fix letras.com returning random lyrics when a good match isn't found\n"
35+
"\n";
3936
out += "Version 1.11 (2024-09-05):\n"
4037
"- Add a source for Bandcamp.com\n"
4138
"- Fix SongLyrics.com sometimes returning lyrics saying there are no lyrics\n"
@@ -340,5 +337,47 @@ void OpenLyricsVersion::get_about_message(pfc::string_base & out)
340337
"- Initial release\n";
341338
}
342339

340+
class OpenLyricsVersion : public componentversion
341+
{
342+
public:
343+
void get_file_name(pfc::string_base& out) final {out = core_api::get_my_file_name();}
344+
void get_component_name(pfc::string_base & out) final {out = "OpenLyrics";}
345+
void get_component_version(pfc::string_base & out) final {out = OPENLYRICS_VERSION;}
346+
void get_about_message(pfc::string_base & out) final { compute_about_message_string(out); }
347+
};
348+
static service_factory_single_t<OpenLyricsVersion> g_openlyricsversion_factory;
349+
}
350+
343351
// This will prevent users from renaming your component around (important for proper troubleshooter behaviors) or loading multiple instances of it.
344352
VALIDATE_COMPONENT_FILENAME("foo_openlyrics.dll");
353+
354+
// ============
355+
// Tests
356+
// ============
357+
#ifdef MVTF_TESTS_ENABLED
358+
#include "string_split.h"
359+
360+
MVTF_TEST(changelog_isnt_empty)
361+
{
362+
pfc::string8 changelog;
363+
compute_about_message_string(changelog);
364+
ASSERT(!changelog.is_empty());
365+
}
366+
367+
MVTF_TEST(changelog_has_no_lines_long_enough_to_wrap_in_the_fb2k_about_dialog)
368+
{
369+
constexpr size_t max_non_wrapping_line_length = 76;
370+
pfc::string8 changelog_pfc;
371+
compute_about_message_string(changelog_pfc);
372+
373+
std::string_view changelog(changelog_pfc.ptr(), changelog_pfc.length());
374+
string_split split(changelog, "\n");
375+
while(!split.reached_the_end())
376+
{
377+
const std::string_view line = split.next();
378+
ASSERT(line.length() <= max_non_wrapping_line_length);
379+
}
380+
ASSERT(!split.failed());
381+
}
382+
383+
#endif

src/sources/letras.cpp

Lines changed: 32 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@ class LetrasSource : public LyricSourceRemote
1717
const GUID& id() const final { return src_guid; }
1818
std::tstring_view friendly_name() const final { return _T("letras.com"); }
1919

20-
std::string extract_lyrics_from_page(pfc::string8 page_content) const;
21-
2220
std::vector<LyricDataRaw> search(const LyricSearchParams& params, abort_callback& abort) final;
2321
bool lookup(LyricDataRaw& data, abort_callback& abort) final;
2422
};
@@ -56,22 +54,6 @@ static std::string transform_artist_for_url(const std::string_view artist)
5654
return transform_tag_for_url(artist);
5755
}
5856

59-
std::string LetrasSource::extract_lyrics_from_page(pfc::string8 page_content) const
60-
{
61-
std::string lyric_text;
62-
pugi::xml_document doc;
63-
load_html_document(page_content.c_str(), doc);
64-
65-
pugi::xpath_query query_lyricdivs("//div[@class='lyric-original']");
66-
pugi::xpath_node_set lyricdivs = query_lyricdivs.evaluate_node_set(doc);
67-
if(!lyricdivs.empty())
68-
{
69-
add_all_text_to_string(lyric_text, lyricdivs.first().node());
70-
}
71-
72-
return lyric_text;
73-
}
74-
7557
std::vector<LyricDataRaw> LetrasSource::search(const LyricSearchParams& params, abort_callback& abort)
7658
{
7759
http_request::ptr request = http_client::get()->create_request("GET");
@@ -94,25 +76,45 @@ std::vector<LyricDataRaw> LetrasSource::search(const LyricSearchParams& params,
9476
return {};
9577
}
9678

97-
const std::string lyric_text = extract_lyrics_from_page(content);
98-
if(lyric_text.empty())
79+
LyricDataRaw result = {};
80+
result.source_id = id();
81+
result.source_path = url;
82+
83+
pugi::xml_document doc;
84+
load_html_document(content.c_str(), doc);
85+
86+
std::string lyric_text;
87+
pugi::xpath_query query_lyricdivs("//div[@class='lyric-original']");
88+
pugi::xpath_node_set lyricdivs = query_lyricdivs.evaluate_node_set(doc);
89+
if(!lyricdivs.empty())
90+
{
91+
add_all_text_to_string(lyric_text, lyricdivs.first().node());
92+
result.text_bytes = string_to_raw_bytes(trim_surrounding_whitespace(lyric_text));
93+
}
94+
95+
pugi::xpath_query query_title_elem("//div[@id='js-lyricHeader']//div[@class='title-content']//h1");
96+
pugi::xpath_node_set title_element = query_title_elem.evaluate_node_set(doc);
97+
if(!title_element.empty())
98+
{
99+
add_all_text_to_string(result.title, title_element.first().node());
100+
}
101+
102+
pugi::xpath_query query_artist_elem("//div[@id='js-lyricHeader']//div[@class='title-content']//h2");
103+
pugi::xpath_node_set artist_element = query_artist_elem.evaluate_node_set(doc);
104+
if(!artist_element.empty())
105+
{
106+
add_all_text_to_string(result.artist, artist_element.first().node());
107+
}
108+
109+
if(result.text_bytes.empty() || result.artist.empty() || result.title.empty())
99110
{
100111
throw new std::runtime_error("Failed to parse lyrics, the page format may have changed");
101112
}
102113
else
103114
{
104115
LOG_INFO("Successfully retrieved lyrics from %s", url.c_str());
105-
const std::string_view trimmed_text = trim_surrounding_whitespace(lyric_text);
106-
107-
LyricDataRaw result = {};
108-
result.source_id = id();
109-
result.source_path = url;
110-
result.artist = params.artist;
111-
result.album = params.album;
112-
result.title = params.title;
113-
result.text_bytes = string_to_raw_bytes(trimmed_text);
114116

115-
const LyricData parsed = parsers::lrc::parse(result, trimmed_text);
117+
const LyricData parsed = parsers::lrc::parse(result, lyric_text);
116118
result.type = parsed.IsTimestamped() ? LyricType::Synced : LyricType::Unsynced;
117119
return {std::move(result)};
118120
}

0 commit comments

Comments
 (0)