webamp/packages/webamp-modern/assets/winamp_classic/scripts/wa2songtimer.m
Fathony Luthfillah 6a97db0a13
x2nie dev8 (Multi Skin Engines) (#1203)
* prettier

* typo

* bugfix: expect error on non supported skin format

* multiple instance, different gamma (colors)

* bugfix colortheme bg, cleanup

* prettier

* back to load single skin, del dead code

* del hack()

* trial to rename 'parse' -> skinengine_wal

* fully SkinEngine_Audio

* cleanup console warn.

* real switchSkin

* integrate WAL parser with plugable skinEngine.

* +KJofol !

* show Vis, Song,

* +WindowsMediaPlayer: Engine,Skins.

* load JS

* MMD3's header: movable

* +DialKnob

* +Button for down image that use global bmp

* preparing to Dock (layout name|mode)

* dock!

* undoc button

* +FloodLevel: kjofol seek. only ui/drag-mouse

* bugfix can't click

* +slider action.

* del dead code

* bugfix on switch kjofol skin

* call dispose() on switch skin

* bugfix Audion timer.

* bugfix loading skin*.zip, bugfix knob

* demo: loading .zip (unknown|ambiguous ext)

* just rename file

* wsz: failed to load wsz:(

* default Equalizer: missing #11,#12

* loading classic skin .wsz

* bugfix: don't stop when bitmap not found

* maximum viable.

* Replace the previous base with DeClassified

This commit aims to replace the base used for rendering Classic Skins in Webamp Modern with the latest commit of DeClassified

* added iso support for the EQ, update base skin

* working tooltips for the time display

* rename wsz_root to skin

for some reason this still doesnt make webamp modern render the skin it's given

* a bunch of things

* allow wsz_root to skin. (failed due missing files)

* prettier

* add but ignore. maybe soon be used

* temporary disabling "application.mi"

* reusing old classic code, that works

* + manifesto

* okay, lets use skin in correct way

* ren file

* redefining eq xml

* thumb background changes when mousemove

* +Pitch !

* set seek z-order to be not covering pitch.

* pitch: smooth audio effect during changes.

* bugfix normal pitch != 100%

* +Shade mode

* add objective-c syntaxt highlighter

* +Repeat, Shuffle

* Call & StrangeCall diff exploration

* +FileExtractor

* prettier.

* loading sonique for first time

* loading sonique for first time

* showing the main frame, + regional applied

* play,pause,stop

* play,pause,stop click images

* revert to using std|*.json

* show song duration (both enquee & addtrack)

* finding a correct bitrate

* +real metadata, +experiment bitRate

* show real song artist + title

* +showing real KBPS, real KHZ.

* track.id is not (can not be) required,
error on eqnueeefile()

* complete album art.

* bugfix volume onchanged

* del dead code

* lowercase key, to avoid misleading

* lowercase key, to avoid misleading

* speedup id3 parsing by Promise

* load another maki

* valid: uiRoot required for vm.

* move Track

* playlist text elipsis

* +scifi (sample skin)

* first attept to wrap text inside an irregular
shape

* reduce noise in html. => head/css.

* show cone gradient as Ring's preparation.

* show progress Ring

* both ring are now drawn.

* allow 270deg

* preparing real progress

* completing ui, no event yet

* bugfix mistaken mask

* allowing ring.action (+events)

* shuffle,repeat.

* eject

* switch to layout:NAV

* switch to layout:SMALL

* adding JetAudio support

* all bitmaps are loaded

* prevent 'undefined' id.

* show something visible :P

* preparing to load one tag with several meaning

* adding JetCowonAudio (old uib) support

* bugfix CORS issue of api.webampskins.org/graphql

* more window buttons

* add more sonique skin

* do list of ini content

* valid yarn build.

* sgf extractor

* sonique icon

* ignore 'extracted-*' folders

* add more sonique skin to load

* custom bitmap (just shown)

* just colorized

* maybe yes/no. colors is not confirmed

* not-found items (
taken from sonique install dir)

* load global png: via .ts

* show icons in circle buttons!

* exploring rgn (failed)

* can load from path (yeah, slow! :v)

* add freform/winamp

* add lineHeight to adjust font-size

* add border-bottom of menus

* prefix css (scrollbars)

* just commit, whatever.

* bugfix frequency position (not overlaped)

* +Menu ! (can only hover & mouse-down)

* still bugfix lineheight of titlebar's text

* show deprecated class

* show deprecated methods

* better on showing deprecated

* bugfix Menu.GUID

* force lowercase

* menus res

* set zero as a valid value of calcelation.

* completing Container props

* add more props, and also by retype (lowcase typo)

* pre-add

* +List, etc.

* addd more props

* rename _width -> _w & _height -> _h

* +onresize

* more detail message of too many similar error

* +ontextchanged

* log description on where the error come?

* avoid missing script id. (better debug)

* attaching WindowHolder

* my BigBento is just working (some hardcoded)

* add (my hacked) BigBento into selection.

* rename: _resizable -> _canResize. to avoid conflict
in Frame

* Frame.from = L

* a bit better. but not reflect on toggle click.

* reaching 71% of maki implementation

* mute frame border

* MUTE GRAPHQL ERROR CORS.

* dummy method: addSubMenu

* oke lah. lumayan

* implement windowholder for PL (only).

* correct align children: left & right.

* a bit better (assuring all key = lowercased)

* recompile some scripts

* bugfix thinger

* +MMD3 with thinger included (standalone)

* bugfix mono/stereo  get by text.display="songinfo"

* +winamp browser

* + Maki Explorer

* +fake implementation

* Big Bugfix: COnfig Item

* I understand, bud no found any mistake

* trial to compare string == insensitive

* trial to compare string != insensitive

* trial to case insensitive

* trial to compare string != insensitive

* bugfix triggering multi events

* set DEBUG, doesnt work :(

* more preserved guid

* mice down/up = work. but no visually.

* add undefined as fake

* implement fake Popup > open @mouse-hover

* bugfix: hover didn't work

* mute lint error

* bugfix xmlParam -> toLowerCase

* failed code to comment:

* allow bool as int

* mute console

* unhide text when not expanded | to find a text

* inpect "Class" in binary (distinct to other var)

* bugfix CORS cdn. , wait until user click demo.

* bugfix reading unicode char.

* Mad Apple Girl dancing

* Mad Apple Girl skin

* bad apple HD

* set back Text to be used by titlebar

* Completing missing classes (For better
 maki explorer / maki understanding)

* split editor to 2, for comparing up & down

* mark CLASS. by subclassing of vars identification

* Full speed animation

* add more maki: Application, File+XmlDoc

* add more maki: Application, File+XmlDoc

* more info when error (id of script)

* +global: application. +few methods

* +few methods.

* beautify (format doc), (typo)

* bugfix eris-lund: found a fatal error/program stop

* Class defintion (in maki file) is back supported.

* STUPID? mute ERROR. (don't stop)

* set back to very-simple logic

* implement alternateText

* bugfix a maki file loaded twice (multi)

* + trigger event in a class.

* mute console

* sorry, for hardcoded. ;p

* clean up uneeded dependency

* load very simple part: main.bmp + cbutton.bmp

* load main.shaded

* bitrates

* bitrates

* more classic skin

* + note & link, +full bitlist

* more classic items

* more progress.

* ++ various implementation, based on /progress

* *.WMZ region.txt is now ready !

* typo.

* integrate play/pause/stop statuses + mono|stereo

* network status

* change: wa.play.red => traffic.red (buffering)

* Volume + Pan

* EQ + PL buttons

* bugfix Text (char not found , too narrow
 bitmapfont)

* TIME text is clickable

* +Shuffle + Repeat

* better pseudo minus sign taken from "5" & "7" char

* pixel-perfect of Timer (text) of WInamp Modern.

* completing classic.player (container)

* completing VISCOLOR.txt parsing & applying values

* bugfix wrong parameter of vis

* Allow bitmap transparency by color (WMP)

* bugfix wrong parameter of vis

* Green Head is back running! (WMP)

* running WMP correctly

* running WMP correctly: background-color

* format from root dir

* format from root dir

* reduce lint complain

* del unknown file

---------

Co-authored-by: Fathony <fathony@smart-leaders.net>
Co-authored-by: Eris Lund <38136789+0x5066@users.noreply.github.com>
2023-02-23 08:41:17 -05:00

481 lines
No EOL
14 KiB
Objective-C

//Feel free to steal and/or modify.
//If you're using this from the SimpleTutorial skin, do kindly give credit to
//"Eris Lund (0x5066)" or "0x5066", or don't! I don't mind.
//This is now updated that enables it to be included within the
//skin.xml, taken from Ariszló's updated oldtimer.maki script
//Updated to include a simple menu - 22.03.2021
//This disables the shade specific checks
//If you include this, make sure your text object
//has "display="time"" (and for TTF "forcefixed="1"")
//or else you won't get the fancy formatting the
//engine applies for song timers
#include "..\..\..\lib/std.mi"
Global String currentpos, strremainder, currentpos_rev;
Global GuiObject DisplayTime/*DisplayTimeShade*/;
Global GuiObject TimerTrigger;
Global Timer timerSongTimer;
Global Timer timerSongTimerReverse;
Global Timer PauseBlinkPaused, PauseBlink, Clock;
Global int timermode;
Global int milliseconds;
Global int songlength;
Global int remainder;
Global int milliseconds_rev;
Global int i;
Global PopUpMenu clockMenu;
Function AreWePlaying();
Function InReverse();
Function TimeElapsedOrRemaining();
Function setTimer(int timermode);
Function StaticTime();
Function StaticTimeRemainder();
Function endless();
Function endlesspaused();
Function notendless();
Function notendlesspaused();
Function notendlesspaused_rev();
Function stopped();
Function initplaytimer();
Function playing();
Function playing_rev();
Function ItsBeenMuchTooLong();
System.onScriptLoaded()
{
//Group mainshade = getContainer("main").getLayout("shade");
/* Replace "timer" with "shade.time" for Winamp Classic Modern */
//DisplayTimeShade = mainshade.findObject("timer");
Group mainnormal = getScriptGroup();
/* Replace "timer" with "display.time" for Winamp Classic Modern */
DisplayTime = mainnormal.findObject("timer");
TimerTrigger = mainnormal.findObject("TimerTrigger");
//The above was taken from Ariszló's updated oldtimer.maki script
//Allows it to be included in the skin.xml file of the skin
//ints for playback
milliseconds = System.getPosition();
songlength = StringtoInteger(System.getPlayItemMetaDataString("length"));
remainder = songlength - milliseconds;
milliseconds_rev = milliseconds-songlength;
//strings for playback
currentpos = System.integerToTime(milliseconds);
strremainder = System.integerToTime(remainder);
currentpos_rev = System.integerToTime(milliseconds-songlength);
timerSongTimer = new Timer;
timerSongTimer.setDelay(50);
timerSongTimerReverse = new Timer;
timerSongTimerReverse.setDelay(50);
PauseBlink = new Timer;
PauseBlink.setDelay(50);
PauseBlinkPaused = new Timer;
PauseBlinkPaused.setDelay(50);
Clock = new Timer;
Clock.setDelay(1000);
Clock.start();
setTimer(getPrivateInt(getSkinName(), "TimerElapsedRemaining", 1));
TimeElapsedOrRemaining();
}
TimeElapsedOrRemaining()
{
int timermode = getPrivateInt(getSkinName(), "TimerElapsedRemaining", 1);
setTimer(timermode);
if(timermode == 1){ //Time elapsed
TimerTrigger.setXmlParam("tooltip", "Time Display (click to toggle elapsed/remaining)");
//DisplayTimeShade.setXmlParam("tooltip", "Time Elapsed (click to toggle remaining)");
if(songlength <= 0){ //If below 0, then run StaticTime()
StaticTime();
}
else{ //If not, also run StaticTime(), reason why is below
StaticTime(); //this actually needs to exist specifically for the pause state, dont ask me why
}
}
if (timermode == 2){ //Time remaining
//DisplayTime.setXmlParam("tooltip", "Time Remaining (click to toggle elapsed)");
//DisplayTimeShade.setXmlParam("tooltip", "Time Remaining (click to toggle elapsed)");
if(songlength <= 0){
StaticTime();
}
else{
StaticTimeRemainder(); //same
}
}
if (getStatus() == 0){ //Stopped
stopped();
}
}
Clock.onTimer(){
if(i >= 1){
i = 0;
}else{
i++;
}
}
PauseBlinkPaused.onTimer(){ //Remainder
if(i >= 1){
StaticTimeRemainder();
}else{
timerSongTimer.stop();
DisplayTime.setXmlParam("text", " : ");
//DisplayTimeShade.setXmlParam("text", " : ");
}
}
PauseBlink.onTimer(){ //Elapsed
if(i >= 1){
StaticTime();
}else{
timerSongTimer.stop();
DisplayTime.setXmlParam("text", " : ");
//DisplayTimeShade.setXmlParam("text", " : ");
}
}
TimerTrigger.onRightButtonUp (int x, int y){
int timermode = getPrivateInt(getSkinName(), "TimerElapsedRemaining", 1);
clockMenu = new PopUpMenu;
clockMenu.addcommand("Time elapsed", 1, timermode == 1,0);
clockMenu.addcommand("Time remaining", 2, timermode == 2,0);
timermode = clockMenu.popAtMouse();
setTimer(timermode);
complete;
}
/*
DisplayTimeShade.onRightButtonUp (int x, int y){
int timermode = getPrivateInt(getSkinName(), "TimerElapsedRemaining", 1);
clockMenu = new PopUpMenu;
clockMenu.addcommand("Time elapsed", 1, timermode == 1,0);
clockMenu.addcommand("Time remaining", 2, timermode == 2,0);
timermode = clockMenu.popAtMouse();
setTimer(timermode);
complete;
}
*/
TimerTrigger.onLeftButtonDown(int x, int y)
{
int timermode = getPrivateInt(getSkinName(), "TimerElapsedRemaining", 1);
timermode++;
if (timermode == 3){
timermode = 1;
}
setTimer(timermode);
complete;
}
//DisplayTimeShade.onLeftButtonDown(int x, int y)
//{
// int timermode = getPrivateInt(getSkinName(), "TimerElapsedRemaining", 1);
//
// timermode++;
//
// if (timermode == 3){
// timermode = 1;
// }
// setTimer(timermode);
// complete;
//}
//Here we run these checks every time a playback related action happens
//It's not enough to check on title change
System.onPlay(){
int timermode = getPrivateInt(getSkinName(), "TimerElapsedRemaining", 1);
TimeElapsedOrRemaining();
if (timermode == 2){
if(songlength <= 0){
endless();
//We do this to check if what we're currently playing is a stream/endless VGM track
//as trying to display the time remaining is pointless and only adds a "-", so we
//force to start the timer for the "Time Elapsed" mode if that is the case
}
else{
notendless();
//otherwise, display the time remaining
}
}
}
System.onPause(){
int timermode = getPrivateInt(getSkinName(), "TimerElapsedRemaining", 1);
TimeElapsedOrRemaining();
if (timermode == 2){
if(songlength <= 0){
endlesspaused();
}
else{
notendlesspaused_rev();
}
}
}
System.onResume(){
int timermode = getPrivateInt(getSkinName(), "TimerElapsedRemaining", 1);
TimeElapsedOrRemaining();
if (timermode == 2){
if(songlength <= 0){
endless();
}
else{
notendless();
}
}
}
System.onTitleChange(String info){
int timermode = getPrivateInt(getSkinName(), "TimerElapsedRemaining", 1);
TimeElapsedOrRemaining();
if (timermode == 2){
if(songlength <= 0){
endless();
}
else{
notendless();
}
}
}
//We stop every timer and instead display Winamp Modern's default of "00:00"
System.onStop(){
TimeElapsedOrRemaining();
stopped();
}
StaticTime(){ //Needed since the timer has a delay of 50ms and we don't want any odd flashing on loading
playing();
}
StaticTimeRemainder(){ //Needed since the timer has a delay of 50ms and we don't want any odd flashing on loading
milliseconds = System.getPosition();
songlength = StringtoInteger(System.getPlayItemMetaDataString("length"));
//The purpose of this check is to ensure we properly place
//a "0" if we happen to be below 600000ms, or 10 minutes
//If we are above 600000ms or 10 minutes, don't append a "0"
playing_rev();
//In case of plugins providing a way to play outside the song's original length
//and the user just so happened to have time remaining enabled, we want to
//ensure they still get the proper time position displayed, even if it's irrelevant.
//Winamp 2/Winamp Classic do this.
if(milliseconds > songlength){
ItsBeenMuchTooLong();
}
}
timerSongTimer.onTimer(){
currentpos = System.integerToTime(milliseconds);
//The purpose of this check is to ensure we properly place
//a "0" if we happen to be below 600000ms, or 10 minutes
//If we are above 600000ms or 10 minutes, don't append a "0"
playing();
}
timerSongTimerReverse.onTimer(){
milliseconds = System.getPosition();
songlength = StringtoInteger(System.getPlayItemMetaDataString("length"));
//The purpose of this check is to ensure we properly place
//a "0" if we happen to be below 600000ms, or 10 minutes
//If we are above 600000ms or 10 minutes, don't append a "0"
playing_rev();
//The purpose of this check is to ensure we properly place
//a "0" if we happen to be below 600000ms, or 10 minutes
//If we are above 600000ms or 10 minutes, don't append a "0"
if(milliseconds > songlength){
ItsBeenMuchTooLong();
}
}
AreWePlaying(){
//Just some sanity checks to ensure we're in the right modes
TimerTrigger.setXmlParam("tooltip", "Time Display (click to toggle elapsed/remaining)");
//DisplayTimeShade.setXmlParam("tooltip", "Time Elapsed (click to toggle remaining)");
if (getStatus() == -1){ //Paused
notendlesspaused();
}
else if (getStatus() == 0){ //Stopped
stopped();
}
else if (getStatus() == 1){ //Playing
initplaytimer();
}
}
InReverse(){
//Just some sanity checks to ensure we're in the right modes
songlength = StringtoInteger(System.getPlayItemMetaDataString("length"));
//In case of streams or VGM formats with endless playback
//We don't want the user to still be able to toggle
//between time remaining or elapsed, so we force
//the elapsed mode to run
//This has now been actually fixed
TimerTrigger.setXmlParam("tooltip", "Time Display (click to toggle elapsed/remaining)");
//DisplayTimeShade.setXmlParam("tooltip", "Time Remaining (click to toggle elapsed)");
if(songlength <= 0){
if (getStatus() == -1){ //Paused
endlesspaused();
}
else if (getStatus() == 0){ //Stopped
stopped();
}
else if (getStatus() == 1){ //Playing
endless();
}
}
else{
if (getStatus() == -1){ //Paused
notendlesspaused_rev();
}
else if (getStatus() == 0){ //Stopped
stopped();
}
else if (getStatus() == 1){ //Playing
notendless();
}
}
}
setTimer(int timermode){
if(timermode>=1 && timermode<=2){ //i fucking hate building menus
if (timermode == 1){
AreWePlaying();
}
else if (timermode == 2){
InReverse();
}
setPrivateInt(getSkinName(), "TimerElapsedRemaining", timermode);
}
}
endless(){ //Playing for endless stuff
StaticTime();
timerSongTimerReverse.stop();
PauseBlink.stop();
PauseBlinkPaused.stop();
timerSongTimer.start();
}
notendless(){ //Playing for non endless stuff
StaticTimeRemainder();
timerSongTimer.stop();
PauseBlink.stop();
PauseBlinkPaused.stop();
timerSongTimerReverse.start();
}
endlesspaused(){ //Paused for endless stuff
timerSongTimerReverse.stop();
timerSongTimer.stop();
PauseBlinkPaused.stop();
PauseBlink.start();
}
notendlesspaused(){ //Paused for non endless stuff
timerSongTimer.stop();
timerSongTimerReverse.stop();
PauseBlinkPaused.stop();
PauseBlink.start();
}
notendlesspaused_rev(){ //Paused for non endless stuff, time remaining
timerSongTimer.stop();
timerSongTimerReverse.stop();
PauseBlink.stop();
PauseBlinkPaused.start();
}
stopped(){
timerSongTimer.stop();
timerSongTimerReverse.stop();
PauseBlink.stop();
PauseBlinkPaused.stop();
DisplayTime.setXmlParam("text", " : ");
//DisplayTimeShade.setXmlParam("text", "00:00");
}
playing(){
milliseconds = System.getPosition();
currentpos = System.integerToTime(milliseconds);
if(milliseconds < 600000){
DisplayTime.setXmlParam("text", "0"+currentpos);
//DisplayTimeShade.setXmlParam("text", "0"+currentpos);
}
else{
DisplayTime.setXmlParam("text", currentpos);
//DisplayTimeShade.setXmlParam("text", currentpos);
}
}
playing_rev(){
milliseconds = System.getPosition();
songlength = StringtoInteger(System.getPlayItemMetaDataString("length"));
remainder = songlength - milliseconds;
milliseconds_rev = milliseconds-songlength;
strremainder = System.integerToTime(remainder);
currentpos_rev = System.integerToTime(milliseconds-songlength);
if(remainder < 600000){
DisplayTime.setXmlParam("text", "-0"+strremainder);
//DisplayTimeShade.setXmlParam("text", "-0"+strremainder);
}
else{
DisplayTime.setXmlParam("text", "-"+strremainder);
//DisplayTimeShade.setXmlParam("text", "-"+strremainder);
}
}
ItsBeenMuchTooLong(){ //I feel it coming on, the feeling's gettin' strong
milliseconds = System.getPosition();
songlength = StringtoInteger(System.getPlayItemMetaDataString("length"));
milliseconds_rev = milliseconds-songlength;
if(milliseconds_rev < 600000){
DisplayTime.setXmlParam("text", "-0"+currentpos_rev);
//DisplayTimeShade.setXmlParam("text", "-0"+currentpos_rev);
}
else{
DisplayTime.setXmlParam("text", "-"+currentpos_rev);
//DisplayTimeShade.setXmlParam("text", "-"+currentpos_rev);
}
}
initplaytimer(){
PauseBlink.stop();
PauseBlinkPaused.stop();
timerSongTimerReverse.stop();
StaticTime();
timerSongTimer.start();
}