ESLyric / feedback

Feedback for ESLyric
12 stars 0 forks source link

Implement two fundamental ESLyric callbacks #116

Closed TT-ReBORN closed 1 year ago

TT-ReBORN commented 1 year ago

Hi ohyeah,

I need two callbacks for Georgia-ReBORN to be able to make your "Lyric Search" feature work properly when changing the lyric source in "Lyric Search" and when changing to "Next lyric" (fb.RunMainMenuCommand('View/ESLyric/Panels/Select lyric/Next lyric'); ).

For foobar themes in general, these are must have callbacks when NOT using the ESLyric panel.

To illustrate what I mean and why I need them, I show you with my code: For "Lyric Search", I'm using this code:

const esl = new ActiveXObject('eslyric');
/** Changes current lyrics when changing the lyrics source, only used for ESLyric "Lyric search". */
const changeLyrics = () => {
    fb.RunMainMenuCommand('View/ESLyric/Panels/Save lyric');
    setTimeout(() => {
        initLyrics();
    }, 1000);
};
esl.SetPlayingLyricChangedCallback(changeLyrics); // Start ESLyric callback listener when lyrics change

/**
 * Checks if the lyrics file exists at path+filename and sets this.fileName if it does.
 * @param {string} path
 * @param {string} filename
 */
checkLyrics(path, filename) {
    const lrcFile = `${path + filename}.lrc`;
    const txtFile = `${path + filename}.txt`;
    this.fileName = IsFile(lrcFile) ? lrcFile : IsFile(txtFile) ? txtFile : null;
    return Boolean(this.fileName);
}

The problem is the checkLyrics method does not work properly when using "Lyric Search" and I need the new ESLyric callback, lets name the new callback "esl.GetLyricTypeCallback()"

The new esl.GetLyricTypeCallback() will return a string value of 'lrc' or 'txt'

Then I can implement the new callback like this and the "Lyric Search" will work properly:

let getLyricType;
const changeLyrics = () => {
    getLyricType = esl.GetLyricTypeCallback(); // Will return 'lrc' or 'txt'
    fb.RunMainMenuCommand('View/ESLyric/Panels/Save lyric');
    setTimeout(() => {
        initLyrics();
    }, 1000);
};

checkLyrics(path, filename) {
    const currentFile = `${path + filename}.${getLyricType}`;
    const lrcFile = `${path + filename}.lrc`;
    const txtFile = `${path + filename}.txt`;
    this.fileName = IsFile(currentFile) ? currentFile : IsFile(lrcFile) ? lrcFile : IsFile(txtFile) ? txtFile : null;
    return Boolean(this.fileName);
}

Now the lyric will load the correct lyrics from "Lyric Search" and will not return only synced lyrics.


For the "Next lyric" I have this code, when clicked it will change to the next lyric source via context menu:

let lyricsSrc = 0;
lyricsMenu.addItem('Next lyric', false, () => {
    fb.RunMainMenuCommand('View/ESLyric/Panels/Delete lyric');
    const nextLyricSource = ((() => {
        const nextSrc = () => fb.RunMainMenuCommand('View/ESLyric/Panels/Select lyric/Next lyric');
        return () => {
            lyricsSrc++;
            RepeatFunc(() => { nextSrc(); }, lyricsSrc);
            if (lyricsSrc > 9) lyricsSrc = 0;
            return lyricsSrc;
        };
    })());
    nextLyricSource();
    setTimeout(() => { fb.RunMainMenuCommand('View/ESLyric/Panels/Save lyric'); }, 1000);
    setTimeout(() => { initLyrics(); on_playback_seek(); }, 1000);
});

This does not work properly because I have limited the lyricsSrc to have maximum 8 sources. To be able to make it work, I would need to have a new callback, lets name it esl.GetLyricSearchResultsCountCallback() This callback would return the search results of all lyric sources as a number, example: Artistname123 - Trackname123 was found in 20 lyric sources, esl.GetLyricSearchResultsCountCallback() would return number 20

Then I can make the "Next lyric" function work properly:

let lyricsSrc = 0;
let getLyricSearchResultsCount;
lyricsMenu.addItem('Next lyric', false, () => {
    getLyricSearchResultsCount = esl.GetLyricSearchResultsCountCallback(); // Get the lyric search results count
    fb.RunMainMenuCommand('View/ESLyric/Panels/Delete lyric');
    const nextLyricSource = ((() => {
        const nextSrc = () => fb.RunMainMenuCommand('View/ESLyric/Panels/Select lyric/Next lyric');
        return () => {
            lyricsSrc++;
            RepeatFunc(() => { nextSrc(); }, lyricsSrc);
            if (lyricsSrc > getLyricSearchResultsCount) lyricsSrc = 0;
            return lyricsSrc;
        };
    })());
    nextLyricSource();
    setTimeout(() => { fb.RunMainMenuCommand('View/ESLyric/Panels/Save lyric'); }, 1000);
    setTimeout(() => { initLyrics(); on_playback_seek(); }, 1000);
});

These two callbacks should be pretty easy to implement on your side, I would really appreciate if you can do that as it would benefit all foobar theme developers, big thanks!

-Tom

ESLyric commented 1 year ago

You can get the playing lyric info through the callback which be set via SetPlayingLyricChangedCallback, I think its all right if you get lyric text from the passed lyric.

function on_playing_lyric_changed(meta)
{
    fb.trace(meta.lyricText);
    fb.trace(meta.title); 
}
TT-ReBORN commented 1 year ago

This does not work, fb.trace() is not a function in the Spider Monkey Panel. This trace method is also not listed in the Spider Monkey Panel documentation: https://theqwertiest.github.io/foo_spider_monkey_panel/assets/generated_files/docs/html/fb.html I have googled it and it seems this was possible in the WSH.

The issue is that my checkLyrics method is checking for lyrics on hard disk by existing filetype (top priority is lrc when found) and then it loads the existing lyrics ( which were saved to hard disk ) from the hard disk:

checkLyrics(path, filename) {
    const lrcFile = `${path + filename}.lrc`;
    const txtFile = `${path + filename}.txt`;
    this.fileName = IsFile(lrcFile) ? lrcFile : IsFile(txtFile) ? txtFile : null;
    return Boolean(this.fileName);
}

When you implement the new esl.GetLyricTypeCallback() which returns lrc or txt based on current displayed lyrics I can make this work properly like this:

///// NEW CODE let getLyricType;
const esl = new ActiveXObject('eslyric');

const changeLyrics = () => {
    ///// NEW CODE  getLyricType = esl.GetLyricTypeCallback(); // Check current lyric file type, will return 'lrc' or 'txt
    fb.RunMainMenuCommand('View/ESLyric/Panels/Save lyric');
    setTimeout(() => {
        initLyrics();
    }, 1000);
};
checkLyrics(path, filename) {
    ///// NEW CODE const currentFile = `${path + filename}.${getLyricType}`;**
    const lrcFile = `${path + filename}.lrc`;
    const txtFile = `${path + filename}.txt`;
    ///// NEW CODE this.fileName = IsFile(currentFile) ? currentFile : IsFile(lrcFile) ? lrcFile : IsFile(txtFile) ? txtFile : null;
    return Boolean(this.fileName);
}

Now the checkLyrics method will return the current displayed lyrics because it correctly loads the lyric filetype from getLyricType -> changeLyrics -> esl.GetLyricTypeCallback() when changing lyric source in "Lyric Search". That means I can changed between synced lyrics ('lrc) or unsynced lyrics ('txt') when using "Lyric Search".


And for the "Next lyric" fb.RunMainMenuCommand('View/ESLyric/Panels/Select lyric/Next lyric'); which would be also nice to have, I would need the lyric source results count as a number value from the search query as already described in the first post.

-Tom

ESLyric commented 1 year ago

The fb.trace just a example, you can get now playing lyric from the lyricText field, then you can parse and display lyric yourself. You dont need save it first then read again.

TT-ReBORN commented 1 year ago

Yes, meta.lyricText was my first thought but I can not get this to work in SMP. Example:

export let currentLyricText; // Will pass the current lyrics

export function getLyrics(meta, man) {
    request(settings, (err, res, body) => {
            // previous code...
        lyricMeta.lyricText = lyricText;
        lyricMeta.location = url;
        man.addLyric(lyricMeta);

        currentLyricText = lyricText; // Lyrics saved
        console.log(currentLyricText); // And correctly printed
    });
}

In my lyrics script file I try to import the variable: import { currentLyricText } from '../../../../eslyric-data/scripts/searcher/azlyrics.js';

I get this error message:

include failed:
import declarations may only appear at top level of a module

but import is already at the top, bummer :-( , nothing I can do about it...


This method is also not optional because I would need to declare a new variable var currentLyricText; in EVERY lyric source, which is not good...


So how do I access, meta.lyricText then? Am I missing something? If you would implement a new callback esl.GetLyricTextCallback() that would get the value/lyrics of meta.lyricText it would work without problems.

-Tom

ESLyric commented 1 year ago

I mean you can access the 'meta.lyricText' directly from the callback:

const esl = new ActiveXObject('eslyric');
/** Changes current lyrics when changing the lyrics source, only used for ESLyric "Lyric search". */
// This callback will called when lyric changed. e.g. set/unset playing lyric, playback stop etc.
const changeLyrics = (meta) => {
        // validate meta, meta == null when there is nothing to display.
    parseAndDisplayLyric(meta.lyricText);
};
esl.SetPlayingLyricChangedCallback(changeLyrics); // Start ESLyric callback listener when lyrics change
TT-ReBORN commented 1 year ago

Great, it does work good! Thanks for this ohyeah =)

const esl = new ActiveXObject('eslyric');
/** Changes current lyrics when changing the lyrics source, only used for ESLyric "Lyric search". */
const changeLyrics = (meta) => {
    let rawLyrics = [];
    if (meta == null) return;
    else rawLyrics = [meta.lyricText];
    this.loadLyrics(rawLyrics);
};
esl.SetPlayingLyricChangedCallback(changeLyrics); // Start ESLyric callback listener when lyrics change

It was a misunderstanding from my side, I have thought you would need a ESLyric callback to get access to meta.lyricText property :sweat_smile: Well I do not know the structure of ESLyric internals and how the interface is linked with JavaScript and your ESLyric component, so please excuse me.


Ok, the last thing is the "Next lyric" feature I need to make work properly, this feature cycles through all available lyric sources found search results:

Currently my code is this:

let lyricsSrc = 0;
lyricsMenu.addItem('Next lyric', false, () => {
    fb.RunMainMenuCommand('View/ESLyric/Panels/Delete lyric');
    const nextLyricSource = ((() => {
        const nextSrc = () => fb.RunMainMenuCommand('View/ESLyric/Panels/Select lyric/Next lyric');
        return () => {
            lyricsSrc++;
            RepeatFunc(() => { nextSrc(); }, lyricsSrc);
            if (lyricsSrc > 9) lyricsSrc = 0;
            return lyricsSrc;
        };
    })());
    nextLyricSource();
    setTimeout(() => { fb.RunMainMenuCommand('View/ESLyric/Panels/Save lyric'); }, 1000);
    setTimeout(() => { initLyrics(); on_playback_seek(); }, 1000);
});

As you see lyricsSrc is only limited to 9 sources, that means if cycling though lyric sources has reached 9, it will reset to 0, meaning it will go back to the first lyric source and display the lyric.

I have thought if I had a ESLyric callback esl.GetLyricSearchResultsCountCallback(); // Get the lyric search results count I could make this and it work properly ( dynamic available lyric source search results number ):

getLyricSearchResultsCount = esl.GetLyricSearchResultsCountCallback(); // Get the lyric search results count
lyricsSrc++;
RepeatFunc(() => { nextSrc(); }, lyricsSrc);
if (lyricsSrc > getLyricSearchResultsCount) lyricsSrc = 0;
return lyricsSrc;

What do you think?

-Tom

ESLyric commented 1 year ago

just run the Next lyric command:

fb.RunMainMenuCommand('View/ESLyric/Panels/Select lyric/Next lyric');

ESLyric will also cycle lyrics and call your changeLyrics callback when change to the 'next' lyric.

TT-ReBORN commented 1 year ago

Yes, I'm already using the fb.RunMainMenuCommand('View/ESLyric/Panels/Select lyric/Next lyric'); command as seen in the code snippet I've posted before.

Actually I didn't even need the esl.GetLyricSearchResultsCountCallback(); I have refactored my lyrics code and I needed to changed this ESLyric option: When found lyric: Automatically to Choose the best matched lyric currently Took me a half day to figure it out, maybe it should be better documented...

Anyways both "Lyric search" and "Next lyric" features now work properly in my theme. Gonna release Georgia-ReBORN RC-2, this was the last TODO for this release =)

Thanks for the help ohyeah!

Cheers

-Tom

TT-ReBORN commented 1 year ago

@ESLyric, I have one last question.

I have reordered all lyric sources in foobar's Preferences > Tools > ESLyric > Lyric Option > Lyric Sources They are saved as absolute file paths in the foo_uie_eslyric.dll.cfg config file.

The problem is that this preconfigured config file is included in my theme to make life easier for the end user, but if I make a new portable installation that has a different name then the one in the config file foo_uie_eslyric.dll.cfg All lyric source orders in foobar's Preferences > Tools > ESLyric > Lyric Option > Lyric Sources are resetted. This of course also will happen for Georgia-ReBORN users because they will install and name their portable/standard foobar to a different name and install file location.

So I thought if it is possible that you can make relative file paths?

Example as it is now in the foo_uie_eslyric.dll.cfg file when you open it:

$F2D646CB-8DD6-4E5C-99C4-4C77395C708D]C:\Users\Administrator\Desktop\foobar2000\profile\eslyric-data\scripts\searcher\musixmatch.js2�
$AEE2639A-EC0E-413B-AAE0-9B1E76E493AC]C:\Users\Administrator\Desktop\foobar2000\profile\eslyric-data\scripts\searcher\minilyrics.js2�
$6385F5F6-2E1D-4C0C-9819-5E8025555009XC:\Users\Administrator\Desktop\foobar2000\profile\eslyric-data\scripts\searcher\kugou.js2�
$407C7FC7-3344-4596-9F31-A4C4B8D40AD2ZC:\Users\Administrator\Desktop\foobar2000\profile\eslyric-data\scripts\searcher\qqmusic.js2�
$9814C5D4-F87C-4B5A-B760-428603D37213]C:\Users\Administrator\Desktop\foobar2000\profile\eslyric-data\scripts\searcher\netease_en.js2�
$16705E69-8232-4066-BF3F-3CEEF7DF96C7ZC:\Users\Administrator\Desktop\foobar2000\profile\eslyric-data\scripts\searcher\netease.js2�
$CDF7A25D-1ED2-481B-9C62-F7FE794742F1YC:\Users\Administrator\Desktop\foobar2000\profile\eslyric-data\scripts\searcher\genius.js2�
$E720F510-7FC5-4BD1-B286-5C570B185373[C:\Users\Administrator\Desktop\foobar2000\profile\eslyric-data\scripts\searcher\azlyrics.js2�
$D7C58009-37B6-4A64-969F-47F511BC5D3E[C:\Users\Administrator\Desktop\foobar2000\profile\eslyric-data\scripts\searcher\bandcamp.js2�
$750B284B-F7F8-4872-8A0B-B1604D0078DD]C:\Users\Administrator\Desktop\foobar2000\profile\eslyric-data\scripts\searcher\songlyrics.js2�
$8B183376-0C4A-4A85-A7C6-FA2F7BCBDD17^C:\Users\Administrator\Desktop\foobar2000\profile\eslyric-data\scripts\searcher\chartlyrics.js2�
$572C6E40-8AE2-4258-8BD5-920B73374037^C:\Users\Administrator\Desktop\foobar2000\profile\eslyric-data\scripts\searcher\lyricsmania.js2�
$D56BB536-6F94-4605-8AC5-49D1D736CFF1]C:\Users\Administrator\Desktop\foobar2000\profile\eslyric-data\scripts\searcher\lyricsmode.js2�
$59A73EC5-8FA7-4B3B-A42B-D933D8A127C5aC:\Users\Administrator\Desktop\foobar2000\profile\eslyric-data\scripts\searcher\absolutelyrics.js2�
$34C18934-5BB3-4D91-99F2-430B688A0B8CYC:\Users\Administrator\Desktop\foobar2000\profile\eslyric-data\scripts\searcher\letras.js2�
$22BBE118-E16D-4BA8-AFF8-ACB6DE7384E2ZC:\Users\Administrator\Desktop\foobar2000\profile\eslyric-data\scripts\searcher\elyrics.js2�
$9D1EB772-5AAD-4266-8FE8-91ED576AB5B3]C:\Users\Administrator\Desktop\foobar2000\profile\eslyric-data\scripts\searcher\darklyrics.js2�
$DFEA5E72-3C26-4893-9074-6188B7CC4AC7ZC:\Users\Administrator\Desktop\foobar2000\profile\eslyric-data\scripts\searcher\plyrics.js2�
$F7178902-D359-4B41-B0C5-CA731076A2BD[C:\Users\Administrator\Desktop\foobar2000\profile\eslyric-data\scripts\searcher\stlyrics.js2�
$727C7DE9-D74E-49D5-96DD-F11A48E70500^C:\Users\Administrator\Desktop\foobar2000\profile\eslyric-data\scripts\searcher\oldielyrics.js2�
$57676FE5-558A-460F-AC27-F4C9FCC0B0A0bC:\Users\Administrator\Desktop\foobar2000\profile\eslyric-data\scripts\searcher\lyricstranslate.js2�
$53D19BDE-02F7-4C81-8DA4-D190ECE9B002eC:\Users\Administrator\Desktop\foobar2000\profile\eslyric-data\scripts\searcher\lyricalnonsense_en.js2�
$8168FD71-4FC8-4132-9678-4647AF0A1DDCbC:\Users\Administrator\Desktop\foobar2000\profile\eslyric-data\scripts\searcher\lyricalnonsense.js9

with relative file paths (i.e fb.profilePath ) it would be like this:

$F2D646CB-8DD6-4E5C-99C4-4C77395C708D]fb.profilePath\eslyric-data\scripts\searcher\musixmatch.js2�
$AEE2639A-EC0E-413B-AAE0-9B1E76E493AC]fb.profilePath\eslyric-data\scripts\searcher\minilyrics.js2�
$6385F5F6-2E1D-4C0C-9819-5E8025555009Xfb.profilePath\eslyric-data\scripts\searcher\kugou.js2�
$407C7FC7-3344-4596-9F31-A4C4B8D40AD2Zfb.profilePath\eslyric-data\scripts\searcher\qqmusic.js2�
$9814C5D4-F87C-4B5A-B760-428603D37213]fb.profilePath\eslyric-data\scripts\searcher\netease_en.js2�
$16705E69-8232-4066-BF3F-3CEEF7DF96C7Zfb.profilePath\eslyric-data\scripts\searcher\netease.js2�
$CDF7A25D-1ED2-481B-9C62-F7FE794742F1Yfb.profilePath\eslyric-data\scripts\searcher\genius.js2�
$E720F510-7FC5-4BD1-B286-5C570B185373[fb.profilePath\eslyric-data\scripts\searcher\azlyrics.js2�
$D7C58009-37B6-4A64-969F-47F511BC5D3E[fb.profilePath\eslyric-data\scripts\searcher\bandcamp.js2�
$750B284B-F7F8-4872-8A0B-B1604D0078DD]fb.profilePath\eslyric-data\scripts\searcher\songlyrics.js2�
$8B183376-0C4A-4A85-A7C6-FA2F7BCBDD17^fb.profilePath\eslyric-data\scripts\searcher\chartlyrics.js2�
$572C6E40-8AE2-4258-8BD5-920B73374037^fb.profilePath\eslyric-data\scripts\searcher\lyricsmania.js2�
$D56BB536-6F94-4605-8AC5-49D1D736CFF1]fb.profilePath\eslyric-data\scripts\searcher\lyricsmode.js2�
$59A73EC5-8FA7-4B3B-A42B-D933D8A127C5afb.profilePath\eslyric-data\scripts\searcher\absolutelyrics.js2�
$34C18934-5BB3-4D91-99F2-430B688A0B8CYfb.profilePath\eslyric-data\scripts\searcher\letras.js2�
$22BBE118-E16D-4BA8-AFF8-ACB6DE7384E2Zfb.profilePath\eslyric-data\scripts\searcher\elyrics.js2�
$9D1EB772-5AAD-4266-8FE8-91ED576AB5B3]fb.profilePath\eslyric-data\scripts\searcher\darklyrics.js2�
$DFEA5E72-3C26-4893-9074-6188B7CC4AC7Zfb.profilePath\eslyric-data\scripts\searcher\plyrics.js2�
$F7178902-D359-4B41-B0C5-CA731076A2BD[fb.profilePath\eslyric-data\scripts\searcher\stlyrics.js2�
$727C7DE9-D74E-49D5-96DD-F11A48E70500^fb.profilePath\eslyric-data\scripts\searcher\oldielyrics.js2�
$57676FE5-558A-460F-AC27-F4C9FCC0B0A0bfb.profilePath\eslyric-data\scripts\searcher\lyricstranslate.js2�
$53D19BDE-02F7-4C81-8DA4-D190ECE9B002efb.profilePath\eslyric-data\scripts\searcher\lyricalnonsense_en.js2�
$8168FD71-4FC8-4132-9678-4647AF0A1DDCbfb.profilePath\eslyric-data\scripts\searcher\lyricalnonsense.js9

Then it could work, is it possible to do that with C++ ?

-Tom

ESLyric commented 1 year ago

It should be possible to use relative path. I need review my code to see how it works. and make changes if applicable.

a1waysbeta commented 1 year ago

https://github.com/ESLyric/release/releases/tag/0.5.4.1011

TT-ReBORN commented 1 year ago

Damn, just right after I released RC2... 😅

ESLyric commented 1 year ago

Damn, just right after I released RC2... 😅

@TT-ReBORN Uploaded a hotfix version.

TT-ReBORN commented 1 year ago

Thanks! Working good with the latest version, lyric source search orders are now saved.