This commit is contained in:
visionmercer 2026-06-10 10:35:36 +02:00
commit 46cdaf4e63

550
cimp.bas
View file

@ -1,4 +1,4 @@
declare library "terminkey"
declare library"terminkey"
function terminkey%()
sub echooff()
sub echoon()
@ -7,18 +7,18 @@ end declare
$console:only
on error goto quit
const KEY_UP = 1001
const KEY_DOWN = 1002
const KEY_RIGHT = 1003
const KEY_LEFT = 1004
const key_up=1001
const key_down=1002
const key_right=1003
const key_left=1004
$if WIN then
Shell "chcp 65001 > nul"
$if win then
shell"chcp 65001 > nul"
$end if
redim file(0) as string
if command$ = "" then
print "please specify file to play."
if command$=""then
print"please specify file to play."
goto quit
end if
@ -32,7 +32,7 @@ dim shuffle as integer
dim nooutput as integer
dim timevis as integer
dim nyan as integer
dim marqueeOffset as integer
dim marqueeoffset as integer
dim i as integer
dim musichandle as long
@ -46,17 +46,17 @@ dim progress as string
dim progressbar as string
dim tw as integer
dim fixedWidth as integer
dim maxTitleWidth as integer
dim visibleTitle as string
dim currentSongWidth as integer
dim paddedTitle as string
dim paddedLength as integer
dim fixedwidth as integer
dim maxtitlewidth as integer
dim visibletitle as string
dim currentsongwidth as integer
dim paddedtitle as string
dim paddedlength as integer
dim idx as integer
dim addedWidth as integer
dim charIdx as integer
dim nextChar as string
dim marqueeFrame as integer
dim addedwidth as integer
dim charidx as integer
dim nextchar as string
dim marqueeframe as integer
volume=1
repeat=0
@ -64,17 +64,17 @@ shuffle=0
nooutput=0
timevis=1
nyan=0
marqueeOffset=0
marqueeoffset=0
for i=1 to _commandcount
select case command$(i)
case "-v", "--volume"
case "-v","--volume"
i=i+1
volume=val(command$(i)) / 100
volume=val(command$(i))/100
case "-s","--shuffle"
shuffle=-1
case "-r","--repeat"
if command$(i+1)="1" then
if command$(i+1)="1"then
repeat=1
else
repeat=-1
@ -85,8 +85,8 @@ for i=1 to _commandcount
nyan=-1
case else
if _fileexists(command$(i)) then
if lcase$(right$(command$(i), 4))=".m3u" then
ParseM3U command$(i),file()
if lcase$(right$(command$(i),4))=".m3u"then
parsem3u command$(i),file()
else
file(ubound(file))=command$(i)
redim _preserve file(ubound(file)+1)
@ -99,163 +99,163 @@ redim _preserve file(ubound(file)-1)
if shuffle=-1 then shufflearray file()
i=0
musichandle = _sndopen(file(i))
if musichandle = 0 then
print "Error: could not open file "; file(i)
musichandle=_sndopen(file(i))
if musichandle=0 then
print"Error: could not open file "; file(i)
goto quit
end if
_sndvol musichandle, volume
_sndvol musichandle,volume
_sndplay musichandle
state = "playing "
songname = beforelast(".", afterlast("/", file(i)))
state="playing "
songname=beforelast(".",afterlast("/",file(i)))
while keyin <> 27
keyin = terminkey
while keyin<>27
keyin=terminkey
select case keyin
case KEY_UP
volume = volume + (0.01 + (volume / 10))
if volume > 1 then volume = 1
_sndvol musichandle, volume
case KEY_DOWN
volume = volume - (0.01 + (volume / 10))
if volume < 0 then volume = 0
_sndvol musichandle, volume
case KEY_RIGHT
if _sndgetpos(musichandle) + 5 < _sndlen(musichandle) then
_sndsetpos musichandle, _sndgetpos(musichandle) + 5
case key_up
volume=volume+(0.01+(volume/10))
if volume>1 then volume=1
_sndvol musichandle,volume
case key_down
volume=volume-(0.01+(volume/10))
if volume<0 then volume=0
_sndvol musichandle,volume
case key_right
if _sndgetpos(musichandle)+5<_sndlen(musichandle) then
_sndsetpos musichandle,_sndgetpos(musichandle)+5
else
playnext = 1
playnext=1
end if
case KEY_LEFT
if _sndgetpos(musichandle) - 5 > 0 then
_sndsetpos musichandle, _sndgetpos(musichandle) - 5
case key_left
if _sndgetpos(musichandle)-5>0 then
_sndsetpos musichandle,_sndgetpos(musichandle)-5
else
playnext = -1
playnext=-1
end if
case asc("q")
keyin = 27
keyin=27
case asc("z")
if _sndgetpos(musichandle) > 2 then
_sndsetpos musichandle, 0
if _sndgetpos(musichandle)>2 then
_sndsetpos musichandle,0
else
playnext = -1
playnext=-1
end if
case asc("x")
if _sndplaying(musichandle) then
_sndsetpos musichandle, 0
_sndsetpos musichandle,0
else
_sndplay musichandle
end if
case asc("c"), asc(" ")
case asc("c"),asc(" ")
if _sndplaying(musichandle) then
_sndpause musichandle
state = "paused "
state="paused "
else
_sndplay musichandle
state = "playing "
state="playing "
end if
case asc("v")
_sndstop musichandle
state = "stopped "
state="stopped "
case asc("b")
playnext = 1
playnext=1
case asc("t")
timevis = -timevis
timevis=-timevis
case asc("s")
shufflearray file()
end select
if _sndgetpos(musichandle) = _sndlen(musichandle) then playnext = 1
if playnext <> 0 then
oldhandle = musichandle
if repeat = 1 and playnext = 1 then
playnext = 0
else
i = i + playnext
if i > ubound(file) then
if repeat = -1 then
i = 0
else
goto quit
end if
elseif i < lbound(file) then
if repeat = -1 then
i = ubound(file)
else
i = lbound(file)
end if
if _sndgetpos(musichandle)=_sndlen(musichandle) then playnext=1
if playnext<>0 then
oldhandle=musichandle
if repeat=1 and playnext=1 then
playnext=0
else
i=i+playnext
if i>ubound(file) then
if repeat=-1 then
i=0
else
goto quit
end if
elseif i<lbound(file) then
if repeat=-1 then
i=ubound(file)
else
i=lbound(file)
end if
end if
musichandle = _sndopen(file(i))
if musichandle <> 0 then
_sndvol musichandle, volume
_sndplay musichandle
_sndstop oldhandle
_sndclose oldhandle
state = "playing "
songname = beforelast(".", afterlast("/", file(i)))
playnext = 0
else
musichandle = oldhandle
end if
end if
if timevis = 1 then
progress = " -" + timeleft(musichandle)
else
progress = " " + timeelapsed(musichandle)
musichandle=_sndopen(file(i))
if musichandle<>0 then
_sndvol musichandle,volume
_sndplay musichandle
_sndstop oldhandle
_sndclose oldhandle
state="playing "
songname=beforelast(".",afterlast("/",file(i)))
playnext=0
else
musichandle=oldhandle
end if
end if
if nooutput = 0 then
tw = termwidth
fixedWidth = UWidth(state) + UWidth(progress)
maxTitleWidth = tw - fixedWidth - 2
currentSongWidth = UWidth(songname)
if currentSongWidth > maxTitleWidth and maxTitleWidth > 4 then
paddedTitle = songname + " "
paddedLength = ulen(paddedTitle)
visibleTitle = ""
addedWidth = 0
idx = 0
while addedWidth < maxTitleWidth
charIdx = ((marqueeOffset + idx) mod paddedLength) + 1
nextChar = umid(paddedTitle, charIdx, 1)
if addedWidth + UWidth(nextChar) > maxTitleWidth then exit while
visibleTitle = visibleTitle + nextChar
addedWidth = addedWidth + UWidth(nextChar)
idx = idx + 1
wend
if addedWidth < maxTitleWidth then
visibleTitle = visibleTitle + space$(maxTitleWidth - addedWidth)
end if
marqueeFrame = marqueeFrame + 1
if marqueeFrame mod 4 = 0 then
marqueeOffset = marqueeOffset + 1
if marqueeOffset >= paddedLength then marqueeOffset = 0
end if
else
' Terminal is wide enough, no scrolling needed
visibleTitle = songname
marqueeOffset = 0
if timevis=1 then
progress=" -"+timeleft(musichandle)
else
progress=" "+timeelapsed(musichandle)
end if
if nooutput=0 then
tw=termwidth
fixedwidth=uwidth(state)+uwidth(progress)
maxtitlewidth=tw-fixedwidth-2
currentsongwidth=uwidth(songname)
if currentsongwidth>maxtitlewidth and maxtitlewidth>4 then
paddedtitle=songname+" "
paddedlength=ulen(paddedtitle)
visibletitle=""
addedwidth=0
idx=0
while addedwidth<maxtitlewidth
charidx=((marqueeoffset+idx) mod paddedlength)+1
nextchar=umid(paddedtitle,charidx,1)
if addedwidth+uwidth(nextchar)>maxtitlewidth then exit while
visibletitle=visibletitle+nextchar
addedwidth=addedwidth+uwidth(nextchar)
idx=idx+1
wend
if addedwidth<maxtitlewidth then
visibletitle=visibletitle+space$(maxtitlewidth-addedwidth)
end if
' Reset marquee offset if song changes
if playnext <> 0 then marqueeOffset = 0
' Print the text line
if nyan = -1 then
print termcolor(7); state; AnimatedRainbowText(visibleTitle); termcolor(7); progress; clearrest
else
print termcolor(7); state; termcolor(3); visibleTitle; termcolor(7); progress; clearrest
marqueeframe=marqueeframe+1
if marqueeframe mod 4=0 then
marqueeoffset=marqueeoffset+1
if marqueeoffset>=paddedlength then marqueeoffset=0
end if
' Generate and print progress bar matching the layout width
progressbar = bar(UWidth(state) + UWidth(visibleTitle) + UWidth(progress), (_sndgetpos(musichandle) / _sndlen(musichandle)) * 100, 11, 7)
print progressbar; clearrest; cursorback;
else
' Terminal is wide enough, no scrolling needed
visibletitle=songname
marqueeoffset=0
end if
' Reset marquee offset if song changes
if playnext<>0 then marqueeoffset=0
' Print the text line
if nyan=-1 then
print termcolor(7); state; animatedrainbowtext(visibletitle); termcolor(7); progress; clearrest
else
print termcolor(7); state; termcolor(3); visibletitle; termcolor(7); progress; clearrest
end if
' Generate and print progress bar matching the layout width
progressbar=bar(uwidth(state)+uwidth(visibletitle)+uwidth(progress),(_sndgetpos(musichandle)/_sndlen(musichandle))*100,11,7)
print progressbar; clearrest; cursorback;
end if
_limit 30
if _exit then goto quit
wend
@ -265,43 +265,43 @@ _sndclose musichandle
print clearrest
print clearrest;
print cursorback;
print chr$(27) + "[0m";
print chr$(27)+"[0m";
cursoron
echoon
system
sub shufflearray (stringarray() as string)
randomize timer
dim n as long, j as long
for n = ubound(stringarray) to 1 step -1
j = int(rnd * n)
swap stringarray(n), stringarray(j)
dim n as long,j as long
for n=ubound(stringarray) to 1 step -1
j=int(rnd*n)
swap stringarray(n),stringarray(j)
next
end sub
sub ParseM3U (filename$, array$())
dim i as long, f as long, count as long
dim basePath$, l$, resolvedPath$
for i = len(filename$) to 1 step -1
if mid$(filename$, i, 1) = "/" or mid$(filename$, i, 1) = "\" then
basePath$ = left$(filename$, i)
sub parsem3u (filename$,array$())
dim i as long,f as long,count as long
dim basepath$,l$,resolvedpath$
for i=len(filename$) to 1 step -1
if mid$(filename$,i,1)="/"or mid$(filename$,i,1)="\"then
basepath$=left$(filename$,i)
exit for
end if
next
f = freefile
f=freefile
open filename$ for input as #f
count = 0
count=0
do until eof(f)
line input #f, l$
l$ = _trim$(l$)
if len(l$) > 0 and left$(l$, 1) <> "#" then
resolvedPath$ = l$
if not _fileexists(resolvedPath$) then
resolvedPath$ = basePath$ + l$
line input #f,l$
l$=_trim$(l$)
if len(l$)>0 and left$(l$,1)<>"#"then
resolvedpath$=l$
if not _fileexists(resolvedpath$) then
resolvedpath$=basepath$+l$
end if
if _fileexists(resolvedPath$) then
array$(ubound(array$)) = resolvedPath$
redim _preserve array$(ubound(array$) + 1)
if _fileexists(resolvedpath$) then
array$(ubound(array$))=resolvedpath$
redim _preserve array$(ubound(array$)+1)
end if
end if
loop
@ -310,189 +310,189 @@ end sub
function timeleft$ (handle&)
dim seconds as integer
seconds = _sndlen(handle&) - _sndgetpos(handle&)
if seconds < 0 then seconds = 0
timeleft$ = right$("0" + ltrim$(str$(seconds \ 60)), 2) + ":" + right$("0" + ltrim$(str$(seconds mod 60)), 2)
seconds=_sndlen(handle&)-_sndgetpos(handle&)
if seconds<0 then seconds=0
timeleft$=right$("0"+ltrim$(str$(seconds \ 60)),2)+":"+right$("0"+ltrim$(str$(seconds mod 60)),2)
end function
function timeelapsed$ (handle&)
dim seconds as integer
seconds = _sndgetpos(handle&)
if seconds < 0 then seconds = 0
timeelapsed$ = right$("0" + ltrim$(str$(seconds \ 60)), 2) + ":" + right$("0" + ltrim$(str$(seconds mod 60)), 2)
seconds=_sndgetpos(handle&)
if seconds<0 then seconds=0
timeelapsed$=right$("0"+ltrim$(str$(seconds \ 60)),2)+":"+right$("0"+ltrim$(str$(seconds mod 60)),2)
end function
function termcolor$ (colorvalue as _unsigned long)
select case colorvalue
case 0 to 7
termcolor = chr$(27) + "[0;3" + _trim$(str$(colorvalue)) + "m"
termcolor=chr$(27)+"[0;3"+_trim$(str$(colorvalue))+"m"
case 8 to 15
termcolor = chr$(27) + "[1;3" + _trim$(str$(colorvalue - 8)) + "m"
termcolor=chr$(27)+"[1;3"+_trim$(str$(colorvalue-8))+"m"
case 16 to 255
termcolor = chr$(27) + "[38;5;" + _trim$(str$(colorvalue)) + "m"
case is > 255
termcolor = chr$(27) + "[38;2;" + _trim$(str$(_red32(colorvalue))) + ";" + _trim$(str$(_green32(colorvalue))) + ";" + _trim$(str$(_blue32(colorvalue))) + "m"
termcolor=chr$(27)+"[38;5;"+_trim$(str$(colorvalue))+"m"
case is>255
termcolor=chr$(27)+"[38;2;"+_trim$(str$(_red32(colorvalue)))+";"+_trim$(str$(_green32(colorvalue)))+";"+_trim$(str$(_blue32(colorvalue)))+"m"
end select
end function
function cursorback$ ()
cursorback = chr$(27) + "[F"
cursorback=chr$(27)+"[F"
end function
function clearline$
clearline = chr$(27) + "[2K"
clearline=chr$(27)+"[2K"
end function
function clearrest$
clearrest = chr$(27) + "[K"
clearrest=chr$(27)+"[K"
end function
sub cursoroff ()
print chr$(27); "[?25l";
print chr$(27);"[?25l";
end sub
sub cursoron ()
print chr$(27); "[?25h";
print chr$(27);"[?25h";
end sub
function bar$ (length as integer, percent as integer, color1 as long, color2 as long)
function bar$ (length as integer,percent as integer,color1 as long,color2 as long)
dim done as string
dim notdone as string
dim i as integer
for i = 1 to int((percent / 100) * length)
done = done + "━"
for i=1 to int((percent/100)*length)
done=done+"━"
next i
for i = 1 to length - int((percent / 100) * length)
notdone = notdone + "━"
for i=1 to length-int((percent/100)*length)
notdone=notdone+"━"
next i
bar$ = termcolor(color1) + done + termcolor(color2) + notdone
bar$=termcolor(color1)+done+termcolor(color2)+notdone
end function
function afterlast$ (delim as string, strng as string)
afterlast = mid$(strng, _instrrev(strng, delim) + 1)
function afterlast$ (delim as string,strng as string)
afterlast=mid$(strng,_instrrev(strng,delim)+1)
end function
function beforelast$ (delim as string, strng as string)
beforelast = left$(strng, _instrrev(strng, delim) - 1)
function beforelast$ (delim as string,strng as string)
beforelast=left$(strng,_instrrev(strng,delim)-1)
end function
function AnimatedRainbowText$ (text$)
function animatedrainbowtext$ (text$)
static offset as double
dim result as string
dim L as long, i as long
dim r as integer, g as integer, b as integer
dim hue as double, f as double
dim sector as integer, v as integer, p as integer, q as integer, t as integer
dim rgbPart$
dim l as long,i as long
dim r as integer,g as integer,b as integer
dim hue as double,f as double
dim sector as integer,v as integer,p as integer,q as integer,t as integer
dim rgbpart$
L = ulen(text$)
if L = 0 then exit function
offset = offset + 5.0
if offset >= 360 then offset = offset - 360
l=ulen(text$)
if l=0 then exit function
offset=offset+5.0
if offset>=360 then offset=offset-360
for i = 1 to L
hue = MOD_Double(offset + ((i - 1) / L) * 360, 360)
sector = int(hue / 60)
f = (hue / 60) - sector
v = 255: p = 0: q = 255 * (1 - f): t = 255 * f
for i=1 to l
hue=mod_double(offset+((i-1)/l)*360,360)
sector=int(hue/60)
f=(hue/60)-sector
v=255:p=0:q=255*(1-f):t=255*f
select case sector
case 0: r = v: g = t: b = p
case 1: r = q: g = v: b = p
case 2: r = p: g = v: b = t
case 3: r = p: g = q: b = v
case 4: r = t: g = p: b = v
case 5: r = v: g = p: b = q
case 0:r=v:g=t:b=p
case 1:r=q:g=v:b=p
case 2:r=p:g=v:b=t
case 3:r=p:g=q:b=v
case 4:r=t:g=p:b=v
case 5:r=v:g=p:b=q
end select
rgbPart$ = _trim$(str$(r)) + ";" + _trim$(str$(g)) + ";" + _trim$(str$(b))
result = result + chr$(27) + "[38;2;" + rgbPart$ + "m" + umid$(text$, i, 1)
rgbpart$=_trim$(str$(r))+";"+_trim$(str$(g))+";"+_trim$(str$(b))
result=result+chr$(27)+"[38;2;"+rgbpart$+"m"+umid$(text$,i,1)
next i
AnimatedRainbowText$ = result + chr$(27) + "[0m"
animatedrainbowtext$=result+chr$(27)+"[0m"
end function
function MOD_Double (value as double, m as double)
MOD_Double = value - (m * int(value / m))
function mod_double (value as double,m as double)
mod_double=value-(m*int(value/m))
end function
function ulen% (txt$)
dim count%, i%, b%
count% = 0
for i% = 1 to len(txt$)
b% = asc(txt$, i%)
if (b% and &H80) = 0 or (b% and &HC0) = &HC0 then
count% = count% + 1
dim count%,i%,b%
count%=0
for i%=1 to len(txt$)
b%=asc(txt$,i%)
if (b% and &h80)=0 or (b% and &hc0)=&hc0 then
count%=count%+1
end if
next
ulen% = count%
ulen%=count%
end function
function umid$ (txt$, startChar%, numChars%)
if startChar% < 1 or numChars% <= 0 or txt$ = "" then exit function
function umid$ (txt$,startchar%,numchars%)
if startchar%<1 or numchars%<=0 or txt$=""then exit function
dim byteIdx%, charCount%, startByte%, endByte%, b%
byteIdx% = 1
charCount% = 0
dim byteidx%,charcount%,startbyte%,endbyte%,b%
byteidx%=1
charcount%=0
while byteIdx% <= len(txt$)
b% = asc(txt$, byteIdx%)
if (b% and &H80) = 0 or (b% and &HC0) = &HC0 then
charCount% = charCount% + 1
if charCount% = startChar% then startByte% = byteIdx%
while byteidx%<=len(txt$)
b%=asc(txt$,byteidx%)
if (b% and &h80)=0 or (b% and &hc0)=&hc0 then
charcount%=charcount%+1
if charcount%=startchar% then startbyte%=byteidx%
end if
if startByte% > 0 then exit while
byteIdx% = byteIdx% + 1
if startbyte%>0 then exit while
byteidx%=byteidx%+1
wend
if startByte% = 0 then exit function
if startbyte%=0 then exit function
byteIdx% = startByte%
dim charsFound%
charsFound% = 0
while byteIdx% <= len(txt$)
b% = asc(txt$, byteIdx%)
if (b% and &H80) = 0 or (b% and &HC0) = &HC0 then
charsFound% = charsFound% + 1
byteidx%=startbyte%
dim charsfound%
charsfound%=0
while byteidx%<=len(txt$)
b%=asc(txt$,byteidx%)
if (b% and &h80)=0 or (b% and &hc0)=&hc0 then
charsfound%=charsfound%+1
end if
if charsFound% > numChars% then exit while
byteIdx% = byteIdx% + 1
if charsfound%>numchars% then exit while
byteidx%=byteidx%+1
wend
umid$ = mid$(txt$, startByte%, byteIdx% - startByte%)
umid$=mid$(txt$,startbyte%,byteidx%-startbyte%)
end function
function UWidth% (txt$)
dim totalWidth%, i%, char$, cp&
totalWidth% = 0
for i% = 1 to ulen(txt$)
char$ = umid(txt$, i%, 1)
cp& = GetCodePoint&(char$)
function uwidth% (txt$)
dim totalwidth%,i%,char$,cp&
totalwidth%=0
for i%=1 to ulen(txt$)
char$=umid(txt$,i%,1)
cp&=getcodepoint&(char$)
if cp& > &H1100 then
totalWidth% = totalWidth% + 2
if cp&>&h1100 then
totalwidth%=totalwidth%+2
else
totalWidth% = totalWidth% + 1
totalwidth%=totalwidth%+1
end if
next
UWidth% = totalWidth%
uwidth%=totalwidth%
end function
function GetCodePoint& (utf8Char$)
dim lLength as integer
lLength = len(utf8Char$)
dim b1 as _unsigned _byte, b2 as _unsigned _byte
dim b3 as _unsigned _byte, b4 as _unsigned _byte
function getcodepoint& (utf8char$)
dim llength as integer
llength=len(utf8char$)
dim b1 as _unsigned _byte,b2 as _unsigned _byte
dim b3 as _unsigned _byte,b4 as _unsigned _byte
select case lLength
select case llength
case 1
GetCodePoint& = asc(utf8Char$, 1)
getcodepoint&=asc(utf8char$,1)
case 2
b1 = asc(utf8Char$, 1): b2 = asc(utf8Char$, 2)
GetCodePoint& = (b1 and &H1F) * 64 + (b2 and &H3F)
b1=asc(utf8char$,1):b2=asc(utf8char$,2)
getcodepoint&=(b1 and &h1f)*64+(b2 and &h3f)
case 3
b1 = asc(utf8Char$, 1): b2 = asc(utf8Char$, 2): b3 = asc(utf8Char$, 3)
GetCodePoint& = (b1 and &H0F) * 4096 + (b2 and &H3F) * 64 + (b3 and &H3F)
b1=asc(utf8char$,1):b2=asc(utf8char$,2):b3=asc(utf8char$,3)
getcodepoint&=(b1 and &h0f)*4096+(b2 and &h3f)*64+(b3 and &h3f)
case 4
b1 = asc(utf8Char$, 1): b2 = asc(utf8Char$, 2): b3 = asc(utf8Char$, 3): b4 = asc(utf8Char$, 4)
GetCodePoint& = (b1 and &H07) * 262144 + (b2 and &H3F) * 4096 + (b3 and &H3F) * 64 + (b4 and &H3F)
b1=asc(utf8char$,1):b2=asc(utf8char$,2):b3=asc(utf8char$,3):b4=asc(utf8char$,4)
getcodepoint&=(b1 and &h07)*262144+(b2 and &h3f)*4096+(b3 and &h3f)*64+(b4 and &h3f)
end select
end function