my AhkDJ program, mixes files nicely with tag reading etc.
I used one slider for volume on both players, you will see how it works.
Code: Select all
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory.
#SingleInstance , Force
#MaxThreads 128
#MaxThreadsBuffer On
firstime=1 ;tells queue to go ahead and load both players
overlap=6 ;eg. 6 seconds before end of song, load next song and play it, then fade first song.
WMA1 := ComObjCreate("WMPlayer.OCX") ; create individual media holders
WMA2 := ComObjCreate("WMPlayer.OCX")
iniread,volume,%A_ScriptDir%\dj.ini,settings,Volume,75 ;read in last volume setting
setbatchlines -1
x:=5
gui, +border -toolwindow -Theme
gui, Margin,5,5
Gui, Font,S10,Lucida Console
Gui, Color, 000000
Gui, Add, Slider,x%x% y10 w300 h20 range0-12000 gsetsongpos1 TickInterval10 vP1
;Gui, Add, progress,x%x% y10 w300 h20 range0-12000 TickInterval10 vP1
Gui, Add, Slider,xp y+4 w628 h25 vM1 cfff333 Altsubmit gvolume range-100-100 Page10 TickInterval10 ToolTipLeft, 0
y=60
Gui, Font,S8,Lucida Console
Gui, Add, Edit,xp y%y% w100 h20 vLength1,
if filelist
{
Gui, Add, Picture,xp+120 yp w20 h20 vpica1,aero_busy_xl.ani ;find your own ani files to put here, i got this from windows folder
}
else
{
Gui, Add, Picture,xp+120 yp w20 h20 vpica1,sync.ico
}
Gui, Add, Edit,xp+40 yp w80 h20 vremain1,
Gui, Font,S10,Lucida Console
Gui, Add, Edit,x%x% y+2 w300 h20 vTitle1,Drag & Drop files Anywhere Here
Gui, Add, Edit,xp y+2 wp h20 vArtist1,to queue them
gui, Add, Edit,xp y+2 wp h20 vtrack1,Dragging Multiple files
Gui, Add, edit,xp y+2 wp h20 Valbum1,will create a Playlist
Gui, Add, edit,xp y+2 wp h20 ValbumArtist1,
Gui, Font,S7,Lucida Console
Gui, Add, Button,xp y+2 w100 h15 vqueue1 gqueue11,Queue next Song
;Gui, Add, Button,xp+200 yp wp hp disabled ,Write Tags ;future feature
Gui, Font,S10,Lucida Console
x=333
Gui, Add, slider,x%x% y10 w300 h20 range0-12000 gsetsongpos2 vP2
y=60
Gui, Font,S8,Lucida Console
Gui, Add, Edit,xp y%y% w100 h20 vLength2,
Gui, Add, Picture,xp+120 yp w20 h20 vpica2,sync.ico
Gui, Add, Edit,xp+40 yp w80 h20 vremain2,
Gui, Font,S10,Lucida Console
Gui, Add, Edit,x%X% y+2 w300 h20 vTitle2,Drag & Drop files anywhere here
Gui, Add, Edit,xp y+2 wp h20 vArtist2, to queue them
gui, Add, Edit,xp y+2 wp h20 vtrack2,Dragging Multiple files
Gui, Add, edit,xp y+2 wp h20 Valbum2,will create a Playlist
Gui, Add, edit,xp y+2 wp h20 ValbumArtist2,
Gui, Font,S7,Lucida Console
Gui, Add, Button,xp y+2 w100 h15 vqueue2 gqueue22 ,Queue next Song
Gui, Add, Button,x+2 yp w100 h15 ggetsongs,Replace Songs
;Gui, Add, Button,xp+200 yp wp hp disabled ,Write Tags
Gui, Font,S10,Lucida Console
Gui, Add, Button,x310 Y60 w17 H60 vnextb disabled ,NEXT
Gui, Add, Button,xp Y+10 wp H60,STOP
Gui,show,y1 autosize, AhkDJ
GuiControl,,p1,1
GuiControl,,p2,1
guicontrol,,m1,-%volume%
ifexist,%A_ScriptDir%\filelist.txt
fileread,filelist,%A_ScriptDir%\filelist.txt
if filelist ;go ahead and load the last list
{
Sort,filelist,U
gosub queue1
gosub queue2
gosub volume
settimer,djtimer1,333
guicontrol,,pica1,aero_busy_xl.ani
if getremtime1
{
splitpath,getremtime1,filenname1
WinSetTitle,,sync.ico,AhkDJ - %filenname1%
}
wma1.controls.play
firstime=
}
return
;##########################################################################################
;tag
queue11: ;simple way to skip current song and load next, stick name in playedsongs
playedlist = %playedlist%%getremtime1%`n
queue1:
getremtime1=
loop, parse, filelist,`n, `r
{
t=1
if not A_LoopField
continue
getremtime11:=A_LoopField
loop,parse,playedlist,`n,`r
{
if A_LoopField = %getremtime11%
{
t=
getremtime11=
break
}
}
if t=
{
getremtime11=
continue
}
if getremtime11
{
getremtime1:=getremtime11
break
}
}
if getremtime1
{
loaded=1
read1(getremtime1,"Title,Artist,Duration,MediaType,Album,Bitrate,WM/TrackNumber,WM/AlbumArtist")
filename1:=getremtime1
wma1duration:=currentmedia1.getItemInfo("Duration")
GuiControl,,length1,% FormatSeconds(wma1duration)
GuiControl,,remain1,% FormatSeconds(wma1duration)
GuiControl,,title1,%wma1title%
GuiControl,,artist1,%wma1artist%
GuiControl,,track1,%wma1tracknumber%
GuiControl,,album1,%wma1album%
GuiControl,,albumartist1,%wma1albumartist%
r1:=Round(currentmedia1.getItemInfo("Duration"))
rem1:=Round(currentmedia1.getItemInfo("Duration")-overlap)
r1s:=Round( 12000 / r1 )
if firstime
playedlist = %playedlist%%getremtime1%`n
return
}
;if no file, clear player
r1=
rem1=
r1s=
GuiControl,,length1,
GuiControl,,remain1,
GuiControl,,title1,
GuiControl,,artist1,
GuiControl,,track1,
GuiControl,,album1,
GuiControl,,albumartist1,
loaded=3
return
;##########################################################################################
;tag
queue22:
playedlist = %playedlist%%getremtime2%`n
queue2:
getremtime2=
loop, parse, filelist,`n, `r
{
t=1
if not A_LoopField
continue
getremtime22:=A_LoopField
loop,parse,playedlist,`n,`r
{
if A_LoopField = %getremtime22%
{
t=
getremtime22=
break
}
}
if t=
{
getremtime22=
continue
}
if getremtime22
{
getremtime2:=getremtime22
break
}
}
if getremtime2
{
loaded=2
filename2:=getremtime2
read2(getremtime2,"Title,Artist,Duration,MediaType,Album,Bitrate,WM/TrackNumber,WM/AlbumArtist")
wma2duration:=currentmedia2.getItemInfo("Duration")
GuiControl,,length2,% FormatSeconds(wma2duration)
GuiControl,,remain2,% FormatSeconds(wma2duration)
GuiControl,,title2,%wma2title%
GuiControl,,artist2,%wma2artist%
GuiControl,,track2,%wma2tracknumber%
GuiControl,,album2,%wma2album%
GuiControl,,albumartist2,%wma2albumartist%
r2:=Round(currentmedia2.getItemInfo("Duration"))
rem2:=Round(currentmedia2.getItemInfo("Duration")-overlap)
r2s:=Round(12000/r2)
guicontrol,enable,nextb
return
}
;if no file, clear player
r2=
rem2=
r2s=
GuiControl,,length2,
GuiControl,,remain2,
GuiControl,,title2,
GuiControl,,artist2,
GuiControl,,track2,
GuiControl,,album2,
GuiControl,,albumartist2,
loaded=3
;guicontrol,disable,nextb
return
;##########################################################################################
;tag
buttonnext:
if loaded=2
{
if not r2 ;if no file to play return
return
settimer,volslide1,-1
settimer,djtimer2,333
guicontrol,,pica1,sync.ico
guicontrol,,pica2,aero_busy_xl.ani
stop2:=rem2
cnt2=
GuiControl,,p1,0
guicontrol,enable,queue1
guicontrol,enable,p2
guicontrol,disable,p1
guicontrol,disable,queue2
settimer,djtimer1,delete
return
}
if Loaded=1
{
if not r1
return
settimer,volslide2,-1
settimer,djtimer1,333
guicontrol,,pica2,sync.ico
stop1:=rem1
cnt1=
GuiControl,,p2,0
guicontrol,enable,queue2
guicontrol,enable,p1
guicontrol,disable,queue1
guicontrol,disable,p2
guicontrol,,pica1,aero_busy_xl.ani
settimer,djtimer2,delete
Return
}
return
;##########################################################################################
;tag
buttonstop:
wma1.controls.stop
wma2.controls.stop
guicontrol,,pica1,sync.ico
guicontrol,,pica2,sync.ico
settimer,djtimer1,delete
settimer,djtimer2,delete
return
;##########################################################################################
;tag
djtimer1:
Critical 50
if GetKeyState("LButton" , "P")
return
rteduc1:=Round(wma1.controls.currentPosition)
GuiControl,,remain1,% FormatSeconds(wma1duration-rteduc1)
r1ss:=r1s*rteduc1
GuiControl,,p1,%r1ss%
cnt1++
if rteduc1 >= %rem1%
gosub buttonnext
return
;##########################################################################################
;tag
djtimer2:
Critical 50
if GetKeyState("LButton" , "P") ;disable timer functions while left mouse button down
return
rteduc2:=Round(wma2.controls.currentPosition)
GuiControl,,remain2,% FormatSeconds(wma2duration-rteduc2)
r2ss:=r2s*rteduc2
GuiControl,,p2,%r2ss%
cnt2++
if rteduc2 >= %rem2%
gosub buttonnext
return
;##########################################################################################
;tag
setsongpos1:
guicontrolget,1pos,,p1
1sp:=Round(1pos/r1s)
if 1pos >= rem1
1sp := rem1-128
if not 1pos
1sp=1
if 1pos<12
1sp=1
wma1.controls.currentPosition:=1sp
Return
;##########################################################################################
;tag
setsongpos2:
guicontrolget,2pos,,p2
2sp:=Round(2pos/r2s)
if 2pos > rem2
2sp:= (rem2-128)
if not 2pos
2sp=1
if 2pos <= 12
2sp=1
wma2.controls.currentPosition:=2sp
Return
;##########################################################################################
;tag
volslide1: ;lowers one volume and raises other
sn= -%volume%
wma2.controls.play
playedlist = %playedlist%%getremtime2%`n
splitpath,getremtime2,filenname2
WinSetTitle,,sync.ico,AhkDJ - %filenname2%
playing2=1
playing1=
if not firstime
loop % (volume*2)
{
sn++
wma1.settings.volume:=(volume-(A_Index/2))
wma2.settings.volume:=(A_Index/2)
guicontrol,,m1,%sn%
sleep, 15
}
wma1.controls.stop
loaded=1
gosub queue1
return
;##########################################################################################
;tag
volslide2:
sn=%volume%
wma1.controls.play
playedlist = %playedlist%%getremtime1%`n
splitpath,getremtime1,filenname1
WinSetTitle,,sync.ico,AhkDJ - %filenname1%
playing1=1
playing2=
if not firsttime
loop % (volume*2)
{
sn--
wma2.settings.volume:=(volume-(A_Index/2))
wma1.settings.volume:=(A_Index/2)
guicontrol,,m1,%sn%
sleep, 15
}
else
wma1.settings.volume:=sn
wma2.controls.stop
;guicontrol,,m1,-%volume%
loaded=2
gosub queue2
return
;##########################################################################################
;tag
volume: ;set initial volumes
guicontrolget,volume,,m1
if volume<0
{
volume:=volume-(volume*2)
wma1.settings.volume:=volume
}
else
wma2.settings.volume:=volume
iniwrite,%volume%,%A_ScriptDir%\dj.ini,settings,Volume
;Notify( "[dj.ahk] `n" volume , ,5)
return
return
;##########################################################################################
;tag
GuiDropFiles:
SplitPath, A_GuiEvent ,,,OE,,
if oe not in mp3,wma,mp4,wav
{
dodis=%A_GuiEvent%\*.*
Loop files , %dodis% ,FR
{
if A_LoopFileFullPath
{
SplitPath, A_LoopFileFullPath ,,,OE,,
if oe not in mp3,wma,mp4,wav
continue
if filelist not contains %A_LoopFileFullPath%
Filelist = %filelist%%A_LoopFileFullPath%`n
}
}
}
else
Filelist = %filelist%%A_GuiEvent%`n
sort,filelist,U
if filelist
filedelete,%A_ScriptDir%\filelist.txt
sleep 300
fileappend,%filelist%`n,%A_ScriptDir%\filelist.txt
guicontrol,enable,nextb
if not playing1
if firstime
{
gosub queue1
firstime=
loaded=1
gosub buttonnext
playing1=1
playing2=
return
}
Notify( "[dj.ahk] `n" loaded , playing1 ,5)
if loaded in 1,3
if playing1=1
{
gosub queue2
firstime=
loaded=2
}
if loaded=2
if playing2=1
return
;##########################################################################################
;tag
wmaget:
return
read1(WMAName,tagname="")
{
global
wmaitemnames=AcquisitionTime,AlbumID,AlbumIDAlbumArtist,Artist,Author,AverageLevel,Bitrate,BuyNow,BuyTickets,Copyright,CurrentBitrate,Duration,FileSize,FileType,Is_Protected,IsVBR,MediaType,MoreInfo,PeakValue,ProviderLogoURL,ProviderURL,RecordingTime,Writer,RequestState,SourceURL,SyncState,Title,TrackingID,UserCustom1,UserCustom2,UserEffectiveRating,UserLastPlayedTime,UserPlayCount,UserPlaycountAfternoon,UserPlaycountEvening,UserPlaycountMorning,UserPlaycountNight,UserPlaycountWeekday,UserPlaycountWeekend,UserRating,UserServiceRating,WM/AlbumArtist,WM/AlbumTitle,WM/Category,WM/Composer,WM/Conductor,WM/ContentDistributor,WM/ContentGroupDescription,WM/Writer,WM/Genre,WM/GenreID,WM/InitialKey,WM/Language,WM/Lyrics,WM/MCDI,WM/MediaClassPrimaryID,WM/MediaClassSecondaryID,WM/Mood,WM/ParentalRating,WM/Period,WM/ProtectionType,WM/Provider,WM/ProviderRating,WM/ProviderStyle,WM/Publisher,WM/SubscriptionContentID,WM/SubTitle,WM/TrackNumber,WM/UniqueFileIdentifier,WM/WMCollectionGroupID,WM/WMCollectionID,WM/WMContentID,WM/Writer,WM/Year
data=
if not tagname
return
if not ib
{
wmA1.url:=wmaname
wma1.controls.stop
wma1.settings.volume:=1
}
currentmedia1 := wma1.newMedia( WMAName )
loop,parse,tagname,csv
{
if A_LoopField not in %wmaitemnames%
continue
stringreplace,loopname,A_LoopField,wm/ ;trim wm/ from tagname to stop errors in return value
wma1%Loopname%:=currentmedia1.getItemInfo(A_LoopField) ;read the tagname and return a global value of "wma+tagname" minus any "wm/" it finds
}
wmaitemnames=
return
}
read2(WMAName,tagname="")
{
global
wmaitemnames=AcquisitionTime,AlbumID,AlbumIDAlbumArtist,Artist,Author,AverageLevel,Bitrate,BuyNow,BuyTickets,Copyright,CurrentBitrate,Duration,FileSize,FileType,Is_Protected,IsVBR,MediaType,MoreInfo,PeakValue,ProviderLogoURL,ProviderURL,RecordingTime,Writer,RequestState,SourceURL,SyncState,Title,TrackingID,UserCustom1,UserCustom2,UserEffectiveRating,UserLastPlayedTime,UserPlayCount,UserPlaycountAfternoon,UserPlaycountEvening,UserPlaycountMorning,UserPlaycountNight,UserPlaycountWeekday,UserPlaycountWeekend,UserRating,UserServiceRating,WM/AlbumArtist,WM/AlbumTitle,WM/Category,WM/Composer,WM/Conductor,WM/ContentDistributor,WM/ContentGroupDescription,WM/Writer,WM/Genre,WM/GenreID,WM/InitialKey,WM/Language,WM/Lyrics,WM/MCDI,WM/MediaClassPrimaryID,WM/MediaClassSecondaryID,WM/Mood,WM/ParentalRating,WM/Period,WM/ProtectionType,WM/Provider,WM/ProviderRating,WM/ProviderStyle,WM/Publisher,WM/SubscriptionContentID,WM/SubTitle,WM/TrackNumber,WM/UniqueFileIdentifier,WM/WMCollectionGroupID,WM/WMCollectionID,WM/WMContentID,WM/Writer,WM/Year
data=
if not tagname
return
if not ib
{
wmA2.url:=wmaname
wma2.controls.stop
wma2.settings.volume:=1
}
currentmedia2 := wma2.newMedia( WMAName )
loop,parse,tagname,csv
{
if A_LoopField not in %wmaitemnames%
continue
stringreplace,loopname,A_LoopField,wm/ ;trim wm/ from tagname to stop errors in return value
wma2%Loopname%:=currentmedia2.getItemInfo(A_LoopField) ;read the tagname and return a global value of "wma2+tagname" minus any "wm/" it finds
}
wmaitemnames=
return
}
return
;##########################################################################################
;tag
getsongs:
if folder
FileSelectFolder, folder, *%folder% ,2, Cancel To Drag && Drop Files Onto The Player`n Or Select A Folder To Play Songs From It ; My Computer.
else
FileSelectFolder, folder, ::{20D04FE0-3AEA-1069-A2D8-08002B30309D} ,, Cancel To Drag && Drop Files Onto The Player`n Or Select A Folder To Play Songs From It ; My Computer.
Folder := RegExReplace(Folder, "\\$")
if folder
{
loop,%folder%\*.*,0,1
if A_LoopFileExt in mp3,wma,mp4
{
filelist .= A_LoopFileFullPath "`n"
scannedsongs:=A_Index
}
fileappend,%filelist%,%A_ScriptDir%\filelist.txt
}
else
fileappend,`n,%A_ScriptDir%\filelist.txt
Notify( "Found`n" scannedsongs " Songs" , ,5)
gosub queue1
gosub buttonnext
return
;##########################################################################################
;tag
!q::
guiclose:
if filelist
MsgBox, 4,Delete,Delete playlist?,30
ifmsgbox Yes
ifexist,%A_ScriptDir%\filelist.txt
filedelete,%A_ScriptDir%\filelist.txt
exitapp
return