Skip to content

Instantly share code, notes, and snippets.

@maestrith
Last active December 17, 2015 11:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save maestrith/5601781 to your computer and use it in GitHub Desktop.
Save maestrith/5601781 to your computer and use it in GitHub Desktop.
Nearly complete.
#SingleInstance,Force
CoordMode,ToolTip,Screen
type:=new xml("types"),OnMessage(0x03,"move")
wmp:=ComObjCreate("WMPLayer.OCX")
ComObjError(0)
global type,wmp,varlist:=[],templist
if type.ssn("//version").text!=2
type.add("version","",2),Compile()
Gui,2:Add,Edit,w800 h400 hwnddebug -Wrap
Gui,2:Show,x0 y0,Debug
aplay()
return
debug(x){
global debug
ControlSetText,,%x%,ahk_id%debug%
}
4GuiEscape:
ExitApp
return
class xml{
__New(param*){
ref:=param.1,root:=param.2,file:=param.3
file:=file?file:ref ".xml",root:=!root?ref:root
temp:=ComObjCreate("MSXML2.DOMDocument"),temp.setProperty("SelectionLanguage","XPath")
if param.4
temp.loadxml(param.4),this.xml:=temp
else
{
ifexist %file%
temp.load(file),this.xml:=temp
else
this.xml:=xml.CreateElement(temp,root)
this.file:=file
}
xml.xk({ref:ref,obj:this})
}
xk(xml=""){
static list:=[]
if IsObject(xml)
return list[xml.ref]:=xml.obj
if !xml
return list
if list[xml]
return list[xml]
}
__Get(x=""){
return this.xml.xml
}
CreateElement(doc,root){
x:=doc.CreateElement(root),doc.AppendChild(x)
return doc
}
add(path="",att="",text="",dup="",find="",under=""){
main:=this.xml.SelectSingleNode("*")
for a,b in find
if found:=main.SelectSingleNode("//" path "[@" a "='" b "']"){
for a,b in att
found.setattribute(a,b)
found.text:=text
return found
}
if under
{
p:=under
new:=this.xml.CreateElement(path),p.AppendChild(new)
for a,b in att
new.SetAttribute(a,b)
if !(text="")
new.text:=text
return new
}
if p:=this.xml.SelectSingleNode(path)
for a,b in att
p.SetAttribute(a,b)
else
{
p:=main
Loop,Parse,path,/
{
total.=A_LoopField "/"
if dup
new:=this.xml.CreateElement(A_LoopField),p.AppendChild(new)
else if !new:=p.SelectSingleNode("//" Trim(total,"/"))
new:=this.xml.CreateElement(A_LoopField),p.AppendChild(new)
p:=new
}
for a,b in att
p.SetAttribute(a,b)
if Text!=""
p.text:=text
}
return p
}
remove(){
this.xml:=""
}
save(){
this.xml.transformNodeToObject(xml.style(),this.xml)
this.xml.save(this.file)
}
transform(){
this.xml.transformNodeToObject(xml.style(),this.xml)
}
ssn(node){
return this.xml.SelectSingleNode(node)
}
sn(node){
return this.xml.SelectNodes(node)
}
style(){
static
if !IsObject(xsl){
xsl:=ComObjCreate("MSXML2.DOMDocument")
style=
(
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" encoding="UTF-8"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
<xsl:for-each select="@*">
<xsl:text></xsl:text>
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
)
xsl.loadXML(style),Style:=null
}
return xsl
}
easyatt(node,notext=""){
list:=[],nodes:=sn(node,"@*")
while,n:=nodes.item[A_Index-1]
list[n.nodename]:=n.text
if !notext
list[1]:=node.text
return list
}
}
ssn(node,path){
return node.SelectSingleNode(path)
}
sn(node,path){
return node.SelectNodes(path)
}
t(x*){
for a,b in x
list.=b "`n"
ToolTip,%list%
}
m(x*){
for a,b in x
list.=b "`n"
MsgBox,% list
}
compile(){
types:=[]
types["Audio"]:={id:"{4202947A-A563-4B05-A754-A1B4B5989849}",name:"Music in my library"}
types["Video"]:={id:"{B2D9BDDC-8E49-444B-9BA4-193ABF9C7870}",name:"Video in my library"}
types["Photo"]:={id:"{CC823400-A8E4-4081-B073-D3B6D952FE69}",name:"Pictures in my library"}
types["TV"]:={id:"{E5415A66-7763-4BDE-B97F-5557CA73C303}",name:"TV shows in my library"}
audio:=[{name:"Artist"},{name:"Album Artist",att:"WM/AlbumArtist"},{name:"Album Title",att:"WM/AlbumTitle"},{name:"Auto Rating",ap:"Effective Rating"},{name:"Bitrate"},{name:"Composer",att:"WM/Composer"},{name:"Conductor",att:"WM/Conductor"},{name:"Content Distributor",att:"WM/ContentDistributor"},{name:"Provider Genre"},{name:"Date Added",ap:"Acquisition Date"},{name:"Encoding Date"},{name:"Recording Date"},{name:"File name",ap:"SourceURL"},{name:"File size"},{name:"File Type"},{name:"Genre"},{name:"Language"},{name:"Playback Duration"},{name:"Mood"},{name:"User Rating"},{name:"Parental Rating",att:"WM/ParentalRating"},{name:"Period"},{name:"Playcount: Afternoon play totals"},{name:"Playcount: Evening play totals"},{name:"Playcount: Morning play totals"},{name:"Playcount: Night play totals"},{name:"Playcount: Total"},{name:"Playcount: Weekday play totals"},{name:"Playcount: Weekend play totals"},{name:"Playcount: Afternoon play totals"},{name:"Playcount: Evening play totals"},{name:"Playcount: Night play totals"},{name:"Provider"},{name:"Publisher",att:"WM/Publisher"},{name:"Release Date"},{name:"Subgenre"},{name:"Subtitle"},{name:"Title"},{name:"Writer"}]
video:=[{name:"Actor"},{name:"Auto Rating",ap:"Effective Rating"},{name:"Auto Rating",ap:"Effective Rating"},{name:"Bitrate"},{name:"Broadcast time",ap:"MediaOriginalBroadcastTime"},{name:"Channel",ap:"MediaOriginalChannel",att:"WM/MediaOriginalChannel"},{name:"Content Distributor",att:"WM/ContentDistributor"},{name:"Content Provider Genre",ap:"Provider Genre"},{name:"Date Added",ap:"Acquisition Date"},{name:"Encoding Date"},{name:"Recording Date"},{name:"Director"},{name:"File name",ap:"SourceURL"},{name:"File size"},{name:"File Type",ap:"FileType"},{name:"Genre"},{name:"Language"},{name:"Playback Duration"},{name:"User Rating"},{name:"Parental Rating",ap:"WM/ParentalRating"},{name:"Playcount: Afternoon play totals"},{name:"Playcount: Evening play totals"},{name:"Playcount: Morning play totals"},{name:"Playcount: Night play totals"},{name:"Playcount: Total"},{name:"Playcount: Weekday play totals"},{name:"Playcount: Weekend play totals"},{name:"Producer",att:"WM/Producer"},{name:"Provider",att:"WM/Provider"},{name:"Publisher",att:"WM/Publisher"},{name:"Release Date"},{name:"Station name",att:"WM/MediaStationName"},{name:"Subtitle"},{name:"Title"},{name:"Writer"}]
photo:=[{name:"Author"},{name:"Caption"},{name:"Date Added",ap:"Acquisition Date"},{name:"Date taken",ap:"DateTimeTaken"},{name:"File name",ap:"SourceURL"},{name:"Image height",ap:"ImageHeight",att:"WM/VideoHeight"},{name:"Image width",ap:"ImageWidth",att:"WM/VideoWidth"},{name:"Month Taken"},{name:"User Rating"},{name:"Year Taken",ap:"DateTimeTakenYear",att:"RecordingTimeYear"},{name:"File Type",ap:"FileType",att:"FileType"}]
;radio:=[{name:"Date att:"AcquisitionTimeDay"},{att:"AcquisitionTimeMonth"},{att:"AcquisitionTimeYear"},{att:"AcquisitionTimeYearMonth"},{att:"AcquisitionTimeYearMonthDay"},{att:"Author"},{att:"Bitrate"},{att:"CanonicalFileType"},{att:"FileType"},{att:"MediaType"},{att:"SourceURL"},{att:"Title"},{att:"WM/Language"},{att:"WM/Provider"}]
for a,name in ["Audio","Video","Photo"]{
current:=type.add(name),main:=""
for a,b in types[name]
current.SetAttribute(a,b)
for a,name in %name%
type.add("name",name,"",1,"",current),main.="|" name.name
type.add("list","",main,"","",current)
}
/*
for x,name in ["Audio","Video","Photo","TV"]{
}
*/
main:=[]
for a,b in ["Artist","Actor","Album Artist","Album Title","Author","Caption","Channel","Composer","Conductor","Content Distributor","Content Provider Genre","Director","Episode","File Type","Genre","Language","Mood","Parental Rating","Period","Producer","Provider","Publisher","Series","Station name","Subgenre","Subtitle","Title","Writer"]
main[b]:=[["list1"],["Equals|Does Not Equal|Is|Is Not|Contains|Does Not Contain"],["|Any string value"]]
main["Bitrate"]:=[["list2"],["Is At Least","Is No More Than","Is"],[48,64,96,128,160,192,256,300,500,750,1000,1500,3000,4500,6000,7500]]
for a,b in ["File size","Image height","Image width"]
main[b]:=[["list3"],["Is Less Than","Is Greater Than","Is","Is Not"],["Any number"]]
for a,b in ["Broadcast time","Encoding Date","Recording Date","Date taken","Release Date"]
main[b]:=[["list4"],["Is Before","Is Later Than","Is","Is Not"],["Yesterday","Last week","Last month","6 months","1 year","2 years","5 years","2000s","1990s","1980s","1970s","1960s","1950s","1940s"]]
main["Date Added"]:=[["list5"],["Is Before","Is After","Is","Is Not"],["Yesterday","Last week","Last month","6 months","1 year","2 years","5 years"]]
main["Month Taken"]:=[["list6"],["Is Before","Is More Recent Than","Is","Is Not"],[1,2,3,4,5,6,7,8,9,10,11,12,13]]
main["Year Taken"]:=[["list7"],["Is Before","Is More Recent Than","Is","Is Not"],["Any year"]]
for a,b in ["Auto Rating","User Rating"]
main[b]:=[["list8"],["Is At Least","Is No More Than","Is","Is Not"],["Unrated","1 Star","2 Stars","3 Stars","4 Stars","5 Stars"]]
main["File name"]:=[["list9"],["Contains","Does Not Contain"],["Any string"]]
main["Playback Duration"]:=[["list10"],["Is Less Than","Is Greater Than","Is","Is Not"],[30,60,120,180,240,300,360]]
for a,b in ["Playcount: Afternoon play totals","Playcount: Evening play totals","Playcount: Morning play totals","Playcount: Night play totals","Playcount: Total","Playcount: Weekday play totals","Playcount: Weekend play totals"]
main[b]:=[["list11"],["Is Less Than","Is Greater Than","Is","Is Not"],["Any number"]]
condition:=type.add("condition")
for a,b in Main{
list:=type.sn("//*[@name='" a "']"),list1:=list2:=""
while,l:=list.item(A_Index-1)
l.SetAttribute("list",b.1.1)
if !type.ssn("//condition/" b.1.1){
for a,con in b.2
list1.="|" con
for a,val in b.3
list2.="|" val
type.add(b.1.1,{condition:list1,value:list2},"","","",condition)
}
}
Loop,2
type.Transform()
type.save()
}
aplay(){
global templist,tv,aphwnd
Gui,4:+hwndaphwnd +ToolWindow
Hotkey,IfWinActive,ahk_id%aphwnd%
Hotkey,Delete,remove,On
Hotkey,BackSpace,remove,On
Gui,4:Font,s10
Gui,4:Add,Treeview,xm w680 h400 hwndtv gtv AltSubmit -0x4
Gui,4:Default
TV_Add("Click here to add Media Types")
varlist.tv:=tv
Gui,4:Add,ListView,w680 h300 NoSortHdr,Media
Gui,4:Show
x=<?wpl version="1.0"?><smil><head><title>Temporary List</title></head><body><seq><smartPlaylist title="Temporary List"></smartPlaylist></seq></body></smil>
templist:=new xml("temp","","",x)
templist.xml.save("temp.wpl")
}
remove:
Gui,4:Default
main:=templist.ssn("//*[@tv='" TV_GetSelection() "']")
TV_Delete(TV_GetSelection())
if main.nodename="sourceFilter"
main:=main.parentnode
main.parentnode.removechild(main)
templist.Transform(),debug(templist[])
return
4GuiContextMenu:
CoordMode,mouse,Screen
MouseGetPos,x,y,,Control
if control=SysListView321
{
Gui,5:Destroy
media:=playlist.item(LV_GetNext()-1)
Gui,5:Add,ListView,w800 r40 AltSubmit -ReadOnly geditatt,Media Attribute|Attribute Name
Gui,5:Default
loop,% media.attributecount(){
name:=media.getattributename(A_Index-1)
if Media.isReadOnlyItem(name)!=-1
LV_Add("",media.getiteminfo(name),name)
}
Loop,2
LV_ModifyCol(A_Index,"AutoHDR")
Gui,5:Show
;m(playlist.item(LV_GetNext()-1).name)
return
}
return
editatt:
if A_GuiEvent=Normal
{
send,{f2}
return
}
Gui,4:Default
in:=LV_GetNext()-1
Gui,5:Default
if RegExMatch(A_GuiEvent,"e"){
LV_GetText(val,LV_GetNext()),LV_GetText(att,LV_GetNext(),2)
playlist.item(in).setiteminfo(att,val)
if (att="title"){
displaylist()
}
}
return
addtype:
Gui,5:Submit
Gui,4:Default
tt:=TV_GetSelection()
in:=xml.easyatt(type.ssn("//" addtype))
root:=TV_Add(in.name)
main:=templist.ssn("//smartPlaylist"),top:=templist.add("querySet","","","","",main)
templist.add("sourceFilter",{id:in.id,name:in.name,tv:root,type:addtype},"",0,0,top)
TV_Delete(tt),TV_Add("Click here to add Media Types")
templist.Transform(),debug(templist[])
displaylist()
return
tv:
tv()
return
tv(){
global
if !(A_GuiEvent="Normal"&&TV_GetSelection())
return
if WinExist("ahk_id" sett){
Gui,5:Destroy
return
}
tv:=varlist.tv
main:=templist.ssn("//*[@tv='" tt:=TV_GetSelection() "']"),t:=ssn(main,"@type").text
WinGetPos,wx,wy,,,ahk_id%tv%
VarSetCapacity(rc,16),NumPut(TV_GetSelection(),rc)
SendMessage,0x1104,1,&rc,,ahk_id%tv%
SendMessage,0x111c,0,0,,ahk_id%tv%
height:=errorlevel,nx:=NumGet(rc,0)+wx,ny:=NumGet(rc,4)+wy
if !main
{
Gui,5:Destroy
Gui,5:-Caption
Gui,5:Margin,0,0
Gui,5:Add,DDL,Choose1 vaddtype x0 y0,Audio|Video|Photo
Gui,5:Add,Button,gaddtype x+1 Default,Add Type
Gui,5:show,x%nx% y%ny%,Add a new type
return
}
if (main.nodename="sourceFilter")
dis:="",ny+=height,psel:=""
if (main.nodename="fragment")
psel:=ssn(main,"@name").Text,dis:="Disabled"
Gui,5:Destroy
Gui,5:Default
Gui,-Caption +hwndapl +Owner4 +hwndsett
Gui,Margin,0,0
Gui,Add,ComboBox,x0 y0 vfragment %dis% gfirst w220
Gui,Add,ComboBox,x+0 w140 vcon
Gui,Add,ComboBox,x+0 w200 vval
varlist.sett:=sett
if !psel
Gui,Add,Button,x+0 gaddst Default,Add
else
Gui,Add,Button,x+0 gchange Default,Update
popcb([psel])
Gui,Show,% "x" nx "y" ny
}
change:
Gui,5:Submit
Gui,4:Default
main:=templist.ssn("//*[@tv='" TV_GetSelection() "']")
if (ssn(main,"@name").text="bitrate"&&val>1000)
val/=1000
for a,b in [con,val]
main.childnodes.item(A_Index-1).text:=b
TV_Modify(TV_GetSelection(),"",fragment " : " con " : " val)
templist.Transform(),debug(templist[])
displaylist()
return
addst:
;Create a function to test the values for this and the edit portion as well
Gui,5:Submit,Nohide
Gui,4:Default
anycon:={"any string":"value","any number":"numerical value","any year":"year value (eg: 2001)"}
ComObjError(0)
if !type.ssn("//*[@name='" fragment "']"){
m("Please choose from the list of available options")
ControlFocus,ComboBox1
return
}
ComObjError(1)
for a,b in {ComboBox2:con,ComboBox3:val}{
if (anycon[b]){
m("Please give the item a " anycon[b])
ControlFocus,%a%
return
}
}
if (fragment="bitrate"&&val>1000)
val:=Floor(val/1000)
list:=type.ssn("//*[@name='" fragment "']/@list").text
ea:=xml.easyatt(type.ssn("//" list))
main:=templist.ssn("//*[@tv='" TV_GetSelection() "']")
t:=ssn(main,"@type").text
tt:=TV_Add(fragment " : " con " : " val,ex:=ssn(main,"@tv").text)
TV_Modify(ex,"Expand")
ff:=type.ssn("//*[@name='" fragment "']/@ap").text
fragment:=ff?ff:fragment
frag:=templist.add("fragment",{name:fragment,tv:tt,type:t},"","","",main)
for a,b in {condition:con,value:val}
templist.add("argument",{name:a},b,"","",frag)
templist.Transform(),debug(templist[])
Gui,5:Destroy
displaylist()
return
displaylist(){
global templist,playlist
Gui,4:Default
templist.xml.save("temp.wpl")
f:=wmp.MediaCollection.add(A_ScriptDir "\temp.wpl")
LV_Delete(),playlist:=wmp.PlaylistCollection.getByName("Temporary List")
if playlist.count>1
Loop,% playlist.Count{
pl:=playlist.item(A_Index-1)
wmp.playlistcollection.remove(pl)
}
playlist:=wmp.PlaylistCollection.getByName("Temporary List").item(0)
loop,% playlist.count
LV_Add("",playlist.item(A_Index-1).getiteminfo("Title"))
}
first:
popcb(1)
return
popcb(x=""){
global fragment,t,templist
if IsObject(x){
name:=type.ssn("//*[@ap='" x.1 "']/@name").text
x.1:=name?name:x.1
GuiControl,5:,ComboBox1,% type.ssn("//" t "/list").text
if !x.1
GuiControl,5:Choose,ComboBox1,1
else
GuiControl,5:ChooseString,ComboBox1,% x.1
}
Gui,5:Submit,Nohide
list:=type.ssn("//" t "/*[@name='" fragment "']/@list")
rep:=type.ssn("//*[@name='" fragment "']/@att").text
rep:=rep?rep:fragment
ComObjError(0)
count:=wmp.mediacollection.getAttributeStringCollection(rep,t)
Loop,% count.count
if item:=count.item(A_Index-1)
ll.="|" item
ComObjError(1)
for a,b in {condition:2,value:3}{
ov:=ssn(list,"//" list.text "/@" a).text
nv:=A_Index=1?ov
nv:=(A_Index=2&&ll)?ll:ov
GuiControl,5:,ComboBox%b%,%nv%
GuiControl,5:Choose,ComboBox%b%,1
}
if x.1{
Gui,4:Default
main:=templist.ssn("//*[@tv='" TV_GetSelection() "']")
Gui,5:Default
while,val:=main.childnodes.item(A_Index-1){
GuiControl,5:ChooseString,% "ComboBox" A_Index+1,% val.text
if ErrorLevel
{
GuiControl,5:,ComboBox3,% "|" val.text
GuiControl,5:Choose,ComboBox3,1
}
}
}
templist.Transform()
debug(templist[])
}
5GuiEscape:
5GuiClose:
Gui,5:Destroy
return
move(a,b,c,d){
global sett
if WinExist("ahk_id" sett)
Gui,5:Destroy
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment