ID3v1 Tagging Monster
View: Screenshot
Download: WinBatch Dialog Constants Extender "dlgc34i.dll"
;######################################################################################################################
; CAUTION:   NOT A FINAL RELEASE VERSION  ***  EXPERIMENTAL VERSION  *** MAN AT WORK  ***  TRY IT AT YOUR OWN RISK  ***
;######################################################################################################################


;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfDisplayPropertiesSheet (sFilename)

slpVerb="properties" ; verbs are "open", "print", "edit" etc.
hBBlpVerb=BinaryAlloc(StrLen(slpVerb)+1)
BinaryPokeStr(hBBlpVerb,0,slpVerb)
pBBlpVerb=IntControl(42,hBBlpVerb,0,0,0)

slpFile=sFilename
hBBlpFile=BinaryAlloc(StrLen(slpFile)+1)
BinaryPokeStr(hBBlpFile,0,slpFile)
pBBlpFile=IntControl(42,hBBlpFile,0,0,0)

SEE_MASK_INVOKEIDLIST   = 12   ; &HC
SEE_MASK_NOCLOSEPROCESS = 64   ; &H40
SEE_MASK_FLAG_NO_UI     = 1024 ; &H400
SW_SHOWNORMAL           = 1

hBBSEI=BinaryAlloc(60)
BinaryPoke4(hBBSEI,00,60)
BinaryPoke4(hBBSEI,04,SEE_MASK_INVOKEIDLIST|SEE_MASK_NOCLOSEPROCESS|SEE_MASK_FLAG_NO_UI)
;BinaryPoke4(hBBSEI,08,DllHwnd(WinGetActive())) ; Not used.
;BinaryPoke4(hBBSEI,08,Hwnd)                    ; Not used.
BinaryPoke4(hBBSEI,08,0)
BinaryPoke4(hBBSEI,12,pBBlpVerb)
BinaryPoke4(hBBSEI,16,pBBlpFile)
;BinaryPoke4(hBBSEI,20,0)                       ; Not used.
;BinaryPoke4(hBBSEI,24,0)                       ; Not used.
BinaryPoke4(hBBSEI,28,SW_SHOWNORMAL)
;BinaryPoke4(hBBSEI,32,0)                       ; Not used.
;BinaryPoke4(hBBSEI,36,0)                       ; Not used.
;BinaryPoke4(hBBSEI,40,0)                       ; Not used.
;BinaryPoke4(hBBSEI,44,0)                       ; Not used.
;BinaryPoke4(hBBSEI,48,0)                       ; Not used.
;BinaryPoke4(hBBSEI,52,0)                       ; Not used.
;BinaryPoke4(hBBSEI,56,0)                       ; Not used.

shell32=StrCat(DirWindows(1),"SHELL32.DLL")
iResult=DllCall(shell32,long:"ShellExecuteExA",lpbinary:hBBSEI)
hInstApp=BinaryPeek4(hBBSEI,32)
If iResult<>0
   WAIT_TIMEOUT=258
   hHandle=BinaryPeek4(hBBSEI,56)
   kernel32=StrCat(DirWindows(1),"KERNEL32.DLL")
   While WAIT_TIMEOUT==DllCall(kernel32,long:"WaitForSingleObject",long:hHandle,long:0)
      TimeDelay(1)
   EndWhile
EndIf

BinaryFree(hBBSEI)
BinaryFree(hBBlpFile)
BinaryFree(hBBlpVerb)

Return (hInstApp)
;..........................................................................................................................................
;   typedef struct _SHELLEXECUTEINFO {
;       DWORD  cbSize;                          ;    cbSize        As Long
;       ULONG  fMask;                           ;    fMask         As Long
;       HWND  hwnd;                             ;    hwnd          As Long
;       LPCTSTR  lpVerb;                        ;    lpVerb        As String
;       LPCTSTR  lpFile;                        ;    lpFile        As String
;       LPCTSTR  lpParameters;                  ;    lpParameters  As String
;       LPCTSTR  lpDirectory;                   ;    lpDirectory   As String
;       int  nShow;                             ;    nShow         As Long
;       HINSTANCE  hInstApp;                    ;    hInstApp      As Long
;       LPVOID  lpIDList;                       ;    lpIDList      As Long     'Optional
;       LPCTSTR  lpClass;                       ;    lpClass       As String   'Optional
;       HKEY  hkeyClass;                        ;    hkeyClass     As Long     'Optional
;       DWORD  dwHotKey;                        ;    dwHotKey      As Long     'Optional
;       union {                                 ;    hIcon         As Long     'Optional
;           HANDLE  hIcon;                      ;
;           HANDLE  hMonitor;                   ;
;       } DUMMYUNIONNAME;                       ;
;       HANDLE  hProcess;                       ;    hProcess      As Long     'Optional
;   } SHELLEXECUTEINFO, *LPSHELLEXECUTEINFO;
;..........................................................................................................................................
;   ; SHELLEXECUTEINFO fMask-Konstanten
;   SEE_MASK_CLASSKEY       = 3    ; &H3    ; Struktur wird mit dem Handle des Registry - Schluessels fuer die Klasse gefuellt
;   SEE_MASK_CLASSNAME      = 1    ; &H1    ; Struktur wird mit dem Klassennamen oder GUID gefuellt der die Datei beschreibt
;   SEE_MASK_CONNECTNETDRV  = 128  ; &H80   ; Struktur verbindet den PC mit einem Netzlaufwerk falls noetig, lpFile muss der UNC-Pfadname in dem Netzwerk sein
;   SEE_MASK_DOENVSUBST     = 512  ; &H200  ; Struktur wird mit Umgebungsvariablen des Programms gefuellt, diese werden in lpDirectory oder lpFile gepackt
;   SEE_MASK_FLAG_DDEWAIT   = 256  ; &H100  ; die Funktion wartet, dass die DDE ihre Vorgaenge abgeschlossen hat und kehrt dann erst zurueck
;   SEE_MASK_FLAG_NO_UI     = 1024 ; &H400  ; die Funktion zeigt keine Fehler-Dialogboxen an
;   SEE_MASK_HOTKEY         = 32   ; &H20   ; dwHotkey wird gefuellt
;   SEE_MASK_ICON           = 16   ; &H10   ; hIcon wird gefuellt mit dem Icon-Handle des Standard-Icons der Anwendung
;   SEE_MASK_IDLIST         = 4    ; &H4    ; benutzt die lpIDLIST-Option um das Programm zu starten, das in ihr beschrieben ist
;   SEE_MASK_INVOKEIDLIST   = 12   ; &HC    ; benutzt die lpIDLIST-Option um das Programm zu starten, das in ihr beschrieben ist
;   SEE_MASK_NOCLOSEPROCESS = 64   ; &H40   ; fuellt die Struktur-Option hProcess  mit dem Process-Handle der gestarteten Anwendung
;..........................................................................................................................................
;   ; SHELLEXECUTEINFO nShow-Konstanten
;   SW_HIDE                 = 0    ; versteckt das Fenster
;   SW_MAXIMIZE             = 3    ; maximiert das Fenster
;   SW_MINIMIZE             = 6    ; minimiert das Fenster
;   SW_RESTORE              = 9    ; stellt das Fenster wieder her
;   SW_SHOW                 = 5    ; zeigt das Fenster an
;   SW_SHOWMAXIMIZED        = 3    ; zeigt das Fenster maximiert an
;   SW_SHOWMINIMIZED        = 2    ; zeigt das Fenster minimiert an
;   SW_SHOWMINNOACTIVE      = 7    ; zeigt das Fenster minimiert an, aber aktiviert es nicht
;   SW_SHOWNA               = 8    ; zeigt das Fenster an, aber aktiviert es nicht
;   SW_SHOWNOACTIVATE       = 4    ; zeigt das Fenster in der besten Groeße und Position an, aber aktiviert es nicht
;   SW_SHOWNORMAL           = 1    ; zeigt das Fenster normal an
;..........................................................................................................................................
;   ; SHELLEXECUTEINFO hInstApp Rueckgabe-Konstanten
;   SE_ERR_ACCESSDENIED     = 5    ; Zugriff verweigert
;   SE_ERR_ASSOCINCOMPLETE  = 27   ; Dateityp ist nicht ausreichend assoziiert
;   SE_ERR_DDEBUSY          = 30   ; DDE konnte nicht gestartet werden
;   SE_ERR_DDEFAIL          = 29   ; DDE ist gescheitert
;   SE_ERR_DDETIMEOUT       = 28   ; DDE-Zeitlimit wurde ereicht
;   SE_ERR_DLLNOTFOUND      = 32   ; eine benoetigte Dll wurde nicht gefunden
;   SE_ERR_FNF              = 2    ; Datei wurde nicht gefunden
;   SE_ERR_NOASSOC          = 31   ; Dateityp ist nicht assoziiert
;   SE_ERR_OOM              = 8    ; nicht genuegend Speicher verfuegbar
;   SE_ERR_PNF              = 3    ; Pfad wurde nicht gefunden
;   SE_ERR_SHARE            = 26   ; Datei konnte nicht geoeffnet werden, da sie bereits verwendet wird
;..........................................................................................................................................
;   ; SHELLEXECUTEINFO dwHotKey-Konstanten
;   HOTKEYF_ALT             = 4    ; &H4  ; benutzt ALT fuer den Hotkey
;   HOTKEYF_CONTROL         = 2    ; &H2  ; benutzt STRG fuer den Hotkey
;   HOTKEYF_EXT             = 8    ; &H8  ; benutzt den Extendend-Key fuer den Hotkey
;   HOTKEYF_SHIFT           = 1    ; &H1  ; benutzt Shift fuer den Hotkey
;..........................................................................................................................................
;   ; WaitForSingleObject dwMillisecond-Konstante
;   INFINITE                = 65535; &HFFFF ; unendlich warten
;..........................................................................................................................................
;   ; WaitForSingleObject Rueckgabe-Konstanten
;   WAIT_ABANDONED          = 128  ; &H80        ; Der Mutex, der in hHandle angegeben ist, wird nicht freigegeben, solange der Eltern-Thread zerstoert ist.
;                                                ; Der Mutex ist nun Bestandteil des aufrufenden Threads und ist nicht mehr im signalisierenden Status.
;   WAIT_FAILED             = -1   ; &HFFFFFFFF  ; Die Funktion ist gescheitert.
;   WAIT_OBJECT_0           = 0    ; &H0         ; Das Objekt. das in hHandle spezifiziert ist, ist in einem signalisierendem Status.
;   WAIT_TIMEOUT            = 258  ; &H102       ; Das Zeitlimit fuer eine Aenderung des Thread-Status ist abgelaufen.
;..........................................................................................................................................
;   Reference: VB API Helpline; vb@rchiv © 2000-2003 Dieter Otter
;
; Detlev Dalitz.20030129
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------


;------------------------------------------------------------------------------------------------------------------------------------------
;ToolTip control
;Guido 09/2002 - Made into UDF's Iain Dickason 1/2003
;Baloon tooltips Guido 01/03
;http://msdn.microsoft.com/library/en-us/shellcc/platform/commctls/tooltip/reflist.asp
;FUNCTIONS
;==========================================================================
;=SetupToolTips - Needs to be run before AddToolTip can be called         =
;=dlghandle - wil dialog handle                                           =
;=balloon - @true baloon tooltips (COMCTL32.DLL v.5.8 Internet Explorer 5)=
;           @false normal tooltips                                        =
;=Returns - tool window handle                                            =
;==========================================================================
#DefineFunction SetupToolTips(dlghandle,balloon)
If balloon Then TTS_BALLOON=64
   Else TTS_BALLOON=0

ICC_BAR_CLASSES=4
WM_USER=1024
WS_POPUP=2147483648
WS_EX_TOPMOST=8
HWND_TOPMOST=-1
ICC_BAR_CLASSES=4
USEDEFAULT=2147483648
TTS_ALWAYSTIP=1
TTS_NOPREFIX=2
TTF_SUBCLASS=16
TTF_IDISHWND=1
TTM_ADDTOOL=WM_USER+4
SWP_NOSIZE=1
SWP_NOMOVE=2
SWP_NOACTIVATE=16

user32=DllLoad(StrCat(DirWindows(1),"USER32.DLL"))
hinst=DllHinst("")

;init common controls
COMMONCONTROLSEX=BinaryAlloc(8)
BinaryPoke4(COMMONCONTROLSEX,0,8)
BinaryPoke4(COMMONCONTROLSEX,4,ICC_BAR_CLASSES)
comctl32=StrCat(DirWindows(1),"COMCTL32.DLL")
r=DllCall(comctl32,long:"InitCommonControlsEx",lpbinary:COMMONCONTROLSEX)
BinaryFree(COMMONCONTROLSEX)

;create toolwindow
htt=DllCall(user32,long:"CreateWindowExA",long:WS_EX_TOPMOST,lpstr:"tooltips_class32",lpstr:"",long:WS_POPUP|TTS_NOPREFIX|TTS_ALWAYSTIP|TTS_BALLOON,long:USEDEFAULT,long:USEDEFAULT,long:USEDEFAULT,long:USEDEFAULT,long:dlghandle,long:0,long:hinst,long:0)
DllCall(user32,long:"SetWindowPos",long:htt,long:HWND_TOPMOST,long:0,long:0,long:0,long:0,long:SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE)
DllFree(user32)
Return htt
#EndFunction

;========================================================================
;=AddToolTip - Used to add a tooltip to a control                       =
;= htt - tool window handle returned by SetupToolTips()                 =
;= dlghandle - the handle of the dialog (passed from the dialog callback=
;= ctrlid - real control id obtained with roboscripter                  =
;= text - the text to display as the tooltip                            =
;= IconType=0 - No icon.                                                =
;= IconType=1 - Blue info on white bubble.                              =
;= IconType=2 - Exclamation mark on triangle.                           =
;= IconType=3 - White cross on red circle.                              =
;========================================================================
;#DefineFunction AddToolTip(htt,dlghandle,ctrlid,icontype,text)
#DefineFunction AddToolTip(htt,dlghandle,ctrlid,text)
WM_USER=1024
TTM_ADDTOOL=WM_USER+4
TTF_SUBCLASS=16
TTM_SETTITLE=WM_USER+32

;icontype=Min(Max(0,icontype),3)

user32=DllLoad(StrCat(DirWindows(1),"USER32.DLL"))
hinst=DllHinst("")

RECT=BinaryAlloc(16)

;get control handle
ctrhandle=DllCall(user32,long:"GetDlgItem",long:dlghandle,long:ctrlid)

;get button location
DllCall(user32,long:"GetClientRect",long:ctrhandle,lpbinary:RECT)
;tooltip text
textbuf=BinaryAlloc(StrLen(text)+1)
BinaryPokeStr(textbuf,0,text)
textad=IntControl(42,textbuf,0,0,0)

;fill structure
TOOLINFO=BinaryAlloc(44)
BinaryPoke4(TOOLINFO,0,44) ;cbSize
BinaryPoke4(TOOLINFO,4,TTF_SUBCLASS) ;uFlags
BinaryPoke4(TOOLINFO,8,ctrhandle) ;hwnd
BinaryPoke4(TOOLINFO,12,0) ;uId

BinaryPoke4(TOOLINFO,16,BinaryPeek4(RECT,0)) ;rect.left
BinaryPoke4(TOOLINFO,20,BinaryPeek4(RECT,4)) ;rect.top
BinaryPoke4(TOOLINFO,24,BinaryPeek4(RECT,8)) ;rect.right
BinaryPoke4(TOOLINFO,28,BinaryPeek4(RECT,12));rect.bottom

BinaryPoke4(TOOLINFO,32,hinst)  ;hinst
BinaryPoke4(TOOLINFO,36,textad) ;lpszText
BinaryPoke4(TOOLINFO,40,0) ;lParam

;add tooltip
r=DllCall(user32,long:"SendMessageA",long:htt,long:TTM_ADDTOOL,long:0,lpbinary:TOOLINFO)
;If icontype Then r=DllCall(user32,long:"SendMessageA",long:htt,long:TTM_SETTITLE,long:IconType,lpbinary:TOOLINFO)
DllFree(user32)
BinaryFree(textbuf)
BinaryFree(RECT)
BinaryFree(TOOLINFO)
Return r
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------


;------------------------------------------------------------------------------------------------------------------------------------------
#DefineSubRoutine  udsInitTooltips()
; --- Tooltips by Guido ---
; DialogProcOptions(handle,2,1) ;Push buttons
; This needs to be called before the AddToolTips can be used.
htt=SetupToolTips(hDlg,0) ; Normal rectangle.
;htt=SetupToolTips(hDlg,1) ; Balloon.

AddToolTip(htt,hDlg,119,"Remove top Title Item.")
AddToolTip(htt,hDlg,121,"Remove top Artist Item.")
AddToolTip(htt,hDlg,123,"Remove top Album Item.")
AddToolTip(htt,hDlg,125,"Remove top Comment Item.")
AddToolTip(htt,hDlg,127,"Remove top Year Item.")
AddToolTip(htt,hDlg,129,"Remove top Track Item.")
AddToolTip(htt,hDlg,131,"Remove top Reserved Item.")
AddToolTip(htt,hDlg,133,"Remove top Genre Item.")

AddToolTip(htt,hDlg,120,"Remove Title Itemlist.")
AddToolTip(htt,hDlg,122,"Remove Artist Itemlist.")
AddToolTip(htt,hDlg,124,"Remove Album Itemlist.")
AddToolTip(htt,hDlg,126,"Remove Comment Itemlist.")
AddToolTip(htt,hDlg,128,"Remove Year Itemlist.")
AddToolTip(htt,hDlg,130,"Remove Track Itemlist.")
AddToolTip(htt,hDlg,132,"Remove Reserved Itemlist.")
AddToolTip(htt,hDlg,134,"Remove Genre Itemlist.")

AddToolTip(htt,hDlg,103,"Copy Memo Title to ID3Tag.")
AddToolTip(htt,hDlg,104,"Copy Memo Artist to ID3Tag.")
AddToolTip(htt,hDlg,105,"Copy Memo Album to ID3Tag.")
AddToolTip(htt,hDlg,107,"Copy Memo Comment to ID3Tag.")
AddToolTip(htt,hDlg,109,"Copy Memo Year to ID3Tag.")
AddToolTip(htt,hDlg,111,"Copy Memo Track to ID3Tag.")
AddToolTip(htt,hDlg,113,"Copy Memo Reserved to ID3Tag.")
AddToolTip(htt,hDlg,115,"Copy Memo Genre to ID3Tag.")

AddToolTip(htt,hDlg,169,"Copy ID3Tag Title to Memo.")
AddToolTip(htt,hDlg,170,"Copy ID3Tag Artist to Memo.")
AddToolTip(htt,hDlg,171,"Copy ID3Tag Album to Memo.")
AddToolTip(htt,hDlg,172,"Copy ID3Tag Comment to Memo.")
AddToolTip(htt,hDlg,173,"Copy ID3Tag Year to Memo.")
AddToolTip(htt,hDlg,174,"Copy ID3Tag Track to Memo.")
AddToolTip(htt,hDlg,175,"Copy ID3Tag Reserved to Memo.")
AddToolTip(htt,hDlg,176,"Copy ID3Tag Genre to Memo.")

AddToolTip(htt,hDlg,180,"Add one Filename to BatchList.")
AddToolTip(htt,hDlg,181,"Add all Filenames to BatchList.")
AddToolTip(htt,hDlg,182,"Remove one Item from BatchList.")
AddToolTip(htt,hDlg,183,"Remove all Items from BatchList.")

AddToolTip(htt,hDlg,184,"Run associated MP3 Player.")
AddToolTip(htt,hDlg,185,"Display File Properties Sheet.")

AddToolTip(htt,hDlg,186,"BatchList. DoubleClick to remove Filename from BatchList.")
AddToolTip(htt,hDlg,187,"Check to use BatchMode.")

AddToolTip(htt,hDlg,179,"FileList. DoubleClick to add Filename to BatchList.")
AddToolTip(htt,hDlg,190,"Push Button to tag highlighted File.")
AddToolTip(htt,hDlg,191,"Current Filename in use.")

AddToolTip(htt,hDlg,160,"Reset all Tag Checkmarks.")
AddToolTip(htt,hDlg,150,"Set all Tag Checkmarks.")
#EndSubRoutine
;------------------------------------------------------------------------------------------------------------------------------------------


;------------------------------------------------------------------------------------------------------------------------------------------
#DefineSubRoutine udsMemoFromIniRead(sFilenameMemo)
If (FileSizeEx(sFilenameMemo) == 0)
   ; No file available. Handle Error here.
   Return
EndIf

DialogControlSet(hDlg,DROPLBOX_MEMO_TITLE   ,DCSET_REPLACE_LIST,@TAB)
iCount = ItemCount(IniItemizePvt(SECTION_MEMO_TITLE   ,sFilenameMemo),@TAB)
For iKey=1 To iCount
   DialogControlSet(hDlg,DROPLBOX_MEMO_TITLE   ,DCSET_ADD_ITEM_SORT,IniReadPvt(SECTION_MEMO_TITLE   ,iKey,"",sFilenameMemo))
Next

DialogControlSet(hDlg,DROPLBOX_MEMO_ARTIST  ,DCSET_REPLACE_LIST,@TAB)
iCount = ItemCount(IniItemizePvt(SECTION_MEMO_ARTIST  ,sFilenameMemo),@TAB)
For iKey=1 To iCount
   DialogControlSet(hDlg,DROPLBOX_MEMO_ARTIST  ,DCSET_ADD_ITEM_SORT,IniReadPvt(SECTION_MEMO_ARTIST  ,iKey,"",sFilenameMemo))
Next

DialogControlSet(hDlg,DROPLBOX_MEMO_ALBUM   ,DCSET_REPLACE_LIST,@TAB)
iCount = ItemCount(IniItemizePvt(SECTION_MEMO_ALBUM   ,sFilenameMemo),@TAB)
For iKey=1 To iCount
   DialogControlSet(hDlg,DROPLBOX_MEMO_ALBUM   ,DCSET_ADD_ITEM_SORT,IniReadPvt(SECTION_MEMO_ALBUM   ,iKey,"",sFilenameMemo))
Next

DialogControlSet(hDlg,DROPLBOX_MEMO_COMMENT ,DCSET_REPLACE_LIST,@TAB)
iCount = ItemCount(IniItemizePvt(SECTION_MEMO_COMMENT ,sFilenameMemo),@TAB)
For iKey=1 To iCount
   DialogControlSet(hDlg,DROPLBOX_MEMO_COMMENT ,DCSET_ADD_ITEM_SORT,IniReadPvt(SECTION_MEMO_COMMENT ,iKey,"",sFilenameMemo))
Next

DialogControlSet(hDlg,DROPLBOX_MEMO_YEAR    ,DCSET_REPLACE_LIST,@TAB)
iCount = ItemCount(IniItemizePvt(SECTION_MEMO_YEAR    ,sFilenameMemo),@TAB)
For iKey=1 To iCount
   DialogControlSet(hDlg,DROPLBOX_MEMO_YEAR    ,DCSET_ADD_ITEM_SORT,IniReadPvt(SECTION_MEMO_YEAR    ,iKey,"",sFilenameMemo))
Next

DialogControlSet(hDlg,DROPLBOX_MEMO_TRACK   ,DCSET_REPLACE_LIST,@TAB)
iCount = ItemCount(IniItemizePvt(SECTION_MEMO_TRACK   ,sFilenameMemo),@TAB)
For iKey=1 To iCount
   DialogControlSet(hDlg,DROPLBOX_MEMO_TRACK   ,DCSET_ADD_ITEM_SORT,IniReadPvt(SECTION_MEMO_TRACK   ,iKey,"",sFilenameMemo))
Next

DialogControlSet(hDlg,DROPLBOX_MEMO_RESERVED,DCSET_REPLACE_LIST,@TAB)
iCount = ItemCount(IniItemizePvt(SECTION_MEMO_RESERVED,sFilenameMemo),@TAB)
For iKey=1 To iCount
   DialogControlSet(hDlg,DROPLBOX_MEMO_RESERVED,DCSET_ADD_ITEM_SORT,IniReadPvt(SECTION_MEMO_RESERVED,iKey,"",sFilenameMemo))
Next

DialogControlSet(hDlg,DROPLBOX_MEMO_GENRE   ,DCSET_REPLACE_LIST,@TAB)
iCount = ItemCount(IniItemizePvt(SECTION_MEMO_GENRE   ,sFilenameMemo),@TAB)
For iKey=1 To iCount
   DialogControlSet(hDlg,DROPLBOX_MEMO_GENRE   ,DCSET_ADD_ITEM_SORT,IniReadPvt(SECTION_MEMO_GENRE   ,iKey,"",sFilenameMemo))
Next
Drop(iCount,iKey)
#EndSubRoutine
;------------------------------------------------------------------------------------------------------------------------------------------


;------------------------------------------------------------------------------------------------------------------------------------------
#DefineSubRoutine udsMemoToIniWrite (sFilenameMemo)
sMemoList = ""

sMemoList = DialogControlGet(hDlg,DROPLBOX_MEMO_TITLE    ,DCGET_ITEMLIST)
iCount = ItemCount(sMemoList,@TAB)
For iKey=1 To iCount
   IniWritePvt (SECTION_MEMO_TITLE   ,iKey,ItemExtract(iKey,sMemoList,@TAB),sFilenameMemo)
Next

sMemoList = DialogControlGet(hDlg,DROPLBOX_MEMO_ARTIST   ,DCGET_ITEMLIST)
iCount = ItemCount(sMemoList,@TAB)
For iKey=1 To iCount
   IniWritePvt (SECTION_MEMO_ARTIST  ,iKey,ItemExtract(iKey,sMemoList,@TAB),sFilenameMemo)
Next

sMemoList = DialogControlGet(hDlg,DROPLBOX_MEMO_ALBUM    ,DCGET_ITEMLIST)
iCount = ItemCount(sMemoList,@TAB)
For iKey=1 To iCount
   IniWritePvt (SECTION_MEMO_ALBUM   ,iKey,ItemExtract(iKey,sMemoList,@TAB),sFilenameMemo)
Next

sMemoList = DialogControlGet(hDlg,DROPLBOX_MEMO_COMMENT  ,DCGET_ITEMLIST)
iCount = ItemCount(sMemoList,@TAB)
For iKey=1 To iCount
   IniWritePvt (SECTION_MEMO_COMMENT ,iKey,ItemExtract(iKey,sMemoList,@TAB),sFilenameMemo)
Next

sMemoList = DialogControlGet(hDlg,DROPLBOX_MEMO_YEAR     ,DCGET_ITEMLIST)
iCount = ItemCount(sMemoList,@TAB)
For iKey=1 To iCount
   IniWritePvt (SECTION_MEMO_YEAR    ,iKey,ItemExtract(iKey,sMemoList,@TAB),sFilenameMemo)
Next

sMemoList = DialogControlGet(hDlg,DROPLBOX_MEMO_RESERVED,DCGET_ITEMLIST)
iCount = ItemCount(sMemoList,@TAB)
For iKey=1 To iCount
   IniWritePvt (SECTION_MEMO_RESERVED,iKey,ItemExtract(iKey,sMemoList,@TAB),sFilenameMemo)
Next

sMemoList = DialogControlGet(hDlg,DROPLBOX_MEMO_TRACK   ,DCGET_ITEMLIST)
iCount = ItemCount(sMemoList,@TAB)
For iKey=1 To iCount
   IniWritePvt (SECTION_MEMO_TRACK   ,iKey,ItemExtract(iKey,sMemoList,@TAB),sFilenameMemo)
Next

sMemoList = DialogControlGet(hDlg,DROPLBOX_MEMO_GENRE   ,DCGET_ITEMLIST)
iCount = ItemCount(sMemoList,@TAB)
For iKey=1 To iCount
   IniWritePvt (SECTION_MEMO_GENRE   ,iKey,ItemExtract(iKey,sMemoList,@TAB),sFilenameMemo)
Next

IniWritePvt ("","","",sFilenameMemo) ; Flush IniFile.
Drop(iCount,iKey,sMemoList)
#EndSubRoutine
;------------------------------------------------------------------------------------------------------------------------------------------


;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfFileToItemList (sFilename, sDelimiter)
iBBSize = FileSize(sFilename)
If (iBBSize==0) Then Return ("")
hBB = BinaryAlloc(iBBSize)
BinaryRead(hBB,sFilename)
sItemList = BinaryPeekStr(hBB,0,iBBSize)
BinaryFree(hBB)
sItemList = StrReplace(sItemList,@CRLF,@CR)
sItemList = StrReplace(sItemList,@LF,@CR)
sItemList = StrReplace(sItemList,@CR,sDelimiter)
Return (sItemList)
; Create itemlist from txtfile with EOL=CR or EOL=LF or EOL=CRLF.
; Example: MyItemList = udfFileToItemList(myfile,@TAB).
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------


;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfItemListToFile (sItemList, sDelimiter, sFilename)
If (sItemList=="") Then Return (0)
sItemList = StrReplace(sItemList,sDelimiter,@CRLF)
hBB = BinaryAlloc(StrLen(sItemList))
BinaryPokeStr(hBB,0,sItemList)
iResult = BinaryWrite(hBB,sFilename)
BinaryFree(hBB)
Return (iResult)
; Create txtfile with EOL=CRLF from ItemList.
; Example: ItemListToFile(mylist,@tab,myfile).
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------


;------------------------------------------------------------------------------------------------------------------------------------------
#DefineSubRoutine udsMemoIniWrite ()
iResult = -1
sFolderNow = DirGet()
;..........................................................................................................................................
AFN_SAVE=0
AFN_OPEN=1
AFN_OPEN_MULTI=2
AFN_SAVE_NOREPLACE=3
;..........................................................................................................................................
AFN_Title     = "Write Memo"
AFN_Folder    = Environment("temp")
AFN_FileTypes = "INI Files|*.ini|All Files|*.*"
AFN_Flag      = AFN_SAVE
AFN_Filename  = "ID3MEMO.INI"
AFN_List      = AskFilename(AFN_Title,AFN_Folder,AFN_FileTypes,AFN_Filename,AFN_Flag)
;..........................................................................................................................................
iResult = udsMemoToIniWrite (AFN_List)
:CANCEL
DirChange(sFolderNow)
DropWild("AFN_*")
Drop(sFolderNow)
Return (iResult)
;..........................................................................................................................................
#EndSubRoutine
;------------------------------------------------------------------------------------------------------------------------------------------


;------------------------------------------------------------------------------------------------------------------------------------------
#DefineSubRoutine udsMemoIniRead ()
iResult = -1
sFolderNow = DirGet()
;..........................................................................................................................................
AFN_SAVE=0
AFN_OPEN=1
AFN_OPEN_MULTI=2
AFN_SAVE_NOREPLACE=3
;..........................................................................................................................................
AFN_Title     = "Read Memo"
AFN_Folder    = Environment("temp")
AFN_FileTypes = "INI Files|*.ini|All Files|*.*"
AFN_Flag      = AFN_OPEN
AFN_Filename  = "ID3MEMO.INI"
AFN_List      = AskFilename(AFN_Title,AFN_Folder,AFN_FileTypes,AFN_Filename,AFN_Flag)
;..........................................................................................................................................
iResult = udsMemoFromIniRead (AFN_List)
:CANCEL
DirChange(sFolderNow)
DropWild("AFN_*")
Drop(sFolderNow)
Return (iResult)
;..........................................................................................................................................
#EndSubRoutine
;------------------------------------------------------------------------------------------------------------------------------------------


;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfBatchListWrite (sItemList)
iResult = -1
sFolderNow = DirGet()
;..........................................................................................................................................
AFN_SAVE=0
AFN_OPEN=1
AFN_OPEN_MULTI=2
AFN_SAVE_NOREPLACE=3
;..........................................................................................................................................
AFN_Title     = "Save List"
AFN_Folder    = Environment("temp")
AFN_FileTypes = "TXT Files|*.txt|All Files|*.*"
AFN_Flag      = AFN_SAVE
AFN_Filename  = "ID3MONSTER.TXT"
AFN_List      = AskFilename(AFN_Title,AFN_Folder,AFN_FileTypes,AFN_Filename,AFN_Flag)
;..........................................................................................................................................
iResult =  udfItemListToFile (sItemList, @TAB, AFN_List)
:CANCEL
DirChange(sFolderNow)
DropWild("AFN_*")
Drop(sFolderNow)
Return (iResult)
;..........................................................................................................................................
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------


;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfBatchListRead()
sResult = ""
sFolderNow = DirGet()
;..........................................................................................................................................
AFN_SAVE=0
AFN_OPEN=1
AFN_OPEN_MULTI=2
AFN_SAVE_NOREPLACE=3
;..........................................................................................................................................
AFN_Title     = "Select File to process ID3v1 Batch Tagging"
AFN_Folder    = Environment("temp")
AFN_FileTypes = "TXT Files|*.txt|All Files|*.*"
AFN_Flag      = AFN_OPEN
AFN_Filename  = "ID3MONSTER.TXT"
AFN_List      = AskFilename(AFN_Title,AFN_Folder,AFN_FileTypes,AFN_Filename,AFN_Flag)
;..........................................................................................................................................
sResult =  udfFileToItemList (AFN_List, @TAB)
:CANCEL
DirChange(sFolderNow)
DropWild("AFN_*")
Drop(sFolderNow)
Return (sResult)
;..........................................................................................................................................
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------



;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfID3Read (sFilename, hBBID3)
iFileSize=FileSizeEx(sFilename)
If (BinaryReadEx(hBBID3,0,sFilename,Max(0,iFileSize-128),128) < 128) Then Return (0)
If (BinaryPeekStr(hBBID3,0,3)=="TAG") Then Return (2)
BinaryXor(hBBID3,0,hBBID3,0,BinaryEodGet(hBBID3)) ; Fill the buffer with zeroes.
Return (1)
;..........................................................................................................................................
; This Function "udfID3Read" returns a tristate value (0,1,2), which indicates,
; if the given input file is invalid (0), or has a valid ID3 "TAG" identifier (2) or not (1).
; In case of 0 or 1 the content of the hBBID3 binary buffer is filled with zero bytes.
; In case of 2 the hiBBID3 binary buffer contains the captured ID3 tag.
;
; sFilename  ... Is a valid ID3 tag-able music file.
; hBBID3  ...... Must be a 128-byte binary buffer to hold extracted ID3 data structure.
;
; Detlev Dalitz.20030121
;..........................................................................................................................................
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------


;------------------------------------------------------------------------------------------------------------------------------------------
#DefineFunction udfID3Write (sFilename, hBBID3, iForce)
iFileSize  = FileSizeEx(sFilename)

hBBID3tmp  = BinaryAlloc(128)
iSizeError = (BinaryReadEx(hBBID3tmp,0,sFilename,Max(0,iFileSize-128),128) < 128)
iTagExist  = (BinaryPeekStr(hBBID3tmp,0,3)=="TAG")
BinaryFree(hBBID3tmp)

If iSizeError Then Return (-1)           ; Input file too small.

iEod = iFileSize-(128*iTagExist)
sFileTime = FileTimeGetEx(sFilename,2)   ; Get File last modified.
sFileAttr = FileAttrGet(sFilename)
If !!StrIndex(sFileAttr,"R",1,@FWDSCAN)
   If !!iForce Then FileAttrSet(sFilename,"r") ; Allow overwrite.
      Else Return (-1) ; File is ReadOnly. Let caller handle what to do.
EndIf
iEod = 32*((iEod/32)+((iEod mod 32)>0))  ; Align the data.

iLastErrorMode = ErrorMode(@OFF)
LastError()
iResult = BinaryWriteEx(hBBID3,0,sFilename,iEod,BinaryEodGet(hBBID3))
iLastError = LastError()
ErrorMode(iLastErrorMode)
; Terminate(iLastError,"Abort.",StrCat("Error while 'BinaryWriteEx'",@LF,iLastError,@LF,sFilename))

FileTimeSetEx(sFilename,sFileTime,2)     ; Set File last modified.
FileAttrSet(sFilename,sFileAttr)         ; Set attributes back.
:CANCEL
Return (iLastError==0)
;..........................................................................................................................................
; This Function "udfID3Write" returns a boolean value, which indicates,
; if the ID3 tagging process was done successfully (1=@TRUE) or not (0=@FALSE).
; If targetfile has set the readonly attribute, then the function returns -1, which can be handled by the caller.
;
; sFilename  ... Is the filename of the music file to tag.
; hBBID3  ...... Must be a 128-byte binary buffer, which contains a valid ID3 structure tag.
; iForce  ...... Boolean value @FALSE..TRUE (0..1), which allows overwriting of readonly files without permission.
;
; Detlev Dalitz.20030121
;..........................................................................................................................................
#EndFunction
;------------------------------------------------------------------------------------------------------------------------------------------


;------------------------------------------------------------------------------------------------------------------------------------------
#DefineSubRoutine udsGet_DLG_ID3_FromBuffer ()
DLG_ID3_Tag      = BinaryPeekStr(hBBID3,000,03)        ; (03) The letters "TAG" indicating that an ID3 tag is present.
DLG_ID3_Title    = BinaryPeekStr(hBBID3,003,30)        ; (30) The title of the song.
DLG_ID3_Artist   = BinaryPeekStr(hBBID3,033,30)        ; (30) The song's artist.
DLG_ID3_Album    = BinaryPeekStr(hBBID3,063,30)        ; (30) The album from which the song was taken.
DLG_ID3_Year     = BinaryPeekStr(hBBID3,093,04)        ; (04) The year the song is from.
DLG_ID3_Comment  = BinaryPeekStr(hBBID3,097,28)        ; (28) A brief comment about the song.
DLG_ID3_Reserved = BinaryPeek   (hBBID3,125)           ; (01) A wasted empty character.
DLG_ID3_Track    = BinaryPeek   (hBBID3,126)           ; (01) The track number.
DLG_ID3_Genre    = BinaryPeek   (hBBID3,127)           ; (01) The genre of the song.
;                                                      ; =128
#EndSubRoutine
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineSubRoutine udsPut_DLG_ID3_ToBuffer ()
BinaryXor(hBBID3,0,hBBID3,0,BinaryEodGet(hBBID3))          ; Fill the buffer with zeroes.
DLG_ID3_Tag = "TAG"
BinaryPokeStr(hBBID3,000,StrSub(DLG_ID3_Tag    ,1,03))     ; (03) The letters "TAG" indicating that an ID3 tag is present.
BinaryPokeStr(hBBID3,003,StrSub(DLG_ID3_Title  ,1,30))     ; (30) The title of the song.
BinaryPokeStr(hBBID3,033,StrSub(DLG_ID3_Artist ,1,30))     ; (30) The song's artist.
BinaryPokeStr(hBBID3,063,StrSub(DLG_ID3_Album  ,1,30))     ; (30) The album from which the song was taken.
BinaryPokeStr(hBBID3,093,StrSub(DLG_ID3_Year   ,1,04))     ; (04) The year the song is from.
BinaryPokeStr(hBBID3,097,StrSub(DLG_ID3_Comment,1,28))     ; (28) A brief comment about the song.
BinaryPoke   (hBBID3,125,Min(Max(DLG_ID3_Reserved,0),255)) ; (01) A wasted empty character.
BinaryPoke   (hBBID3,126,Min(Max(DLG_ID3_Track   ,0),255)) ; (01) The track number.
BinaryPoke   (hBBID3,127,Min(Max(DLG_ID3_Genre   ,0),255)) ; (01) The genre of the song.
;                                                          ; =128
#EndSubRoutine
;------------------------------------------------------------------------------------------------------------------------------------------
;
;      Excerpt from "http://www.cs.swarthmore.edu/~richardw/cs21/id3.html"
;
;      1.
;      The strings stored in the ID3 file may not be null terminated, as
;      they would have been in C. (In other words, they don't end in '\0').
;      If the string takes up less space than allocated, the null character
;      exists. For example, the album may be 30 characters long. If the
;      album is only 20 characters long, the end of the string is marked
;      with a '\0'. However, if the album is exactly 30 characters long,
;      there is no '\0'. This means that when you read them, you can not use
;      the format string "%s".
;
;      2.
;      While the year is stored in 4 bytes and an integer is 4 bytes, the
;      year is not stored as an integer. Instead, it is stored a 4
;      characters. This means that to properly store the year as an integer
;      you must first read in the 4 characters representing the year, and
;      then use the atoi function to convert the year into an integer.
;
;      3.
;      Similarly, while the track number and the genre both represent
;      numbers, they are stored as a single value from 0-255. In other
;      words, these are unsigned chars. I have created a new type called
;      Byte which will be the same as the type unsigned char and have
;      included this in the file you can download below.
;
;      4.
;      Finally, there is a wasted byte in between the comment and the track.
;      In the proper MP3 ID3 v.1.1 format, this byte should always be '\0'.
;      You should write a check to make sure that this value is actually
;      '\0'. After that, you can throw this value away.
;------------------------------------------------------------------------------------------------------------------------------------------


;------------------------------------------------------------------------------------------------------------------------------------------
#DefineSubRoutine udsInit_DLG_MODIFY ()
DLG_MODIFY_Title    = 0
DLG_MODIFY_Artist   = 0
DLG_MODIFY_Album    = 0
DLG_MODIFY_Comment  = 0
DLG_MODIFY_Year     = 0
DLG_MODIFY_Reserved = 0
DLG_MODIFY_Track    = 0
DLG_MODIFY_Genre    = 0
DLG_MODIFY_ReadOnly = 0
#EndSubRoutine
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineSubRoutine udsSet_DLG_MODIFY_ON ()
DialogControlSet(hDlg,CHECKBOX_MODIFY_TITLE   ,DCSET_VALUE,1)
DialogControlSet(hDlg,CHECKBOX_MODIFY_ARTIST  ,DCSET_VALUE,1)
DialogControlSet(hDlg,CHECKBOX_MODIFY_ALBUM   ,DCSET_VALUE,1)
DialogControlSet(hDlg,CHECKBOX_MODIFY_YEAR    ,DCSET_VALUE,1)
DialogControlSet(hDlg,CHECKBOX_MODIFY_COMMENT ,DCSET_VALUE,1)
DialogControlSet(hDlg,CHECKBOX_MODIFY_RESERVED,DCSET_VALUE,1)
DialogControlSet(hDlg,CHECKBOX_MODIFY_TRACK   ,DCSET_VALUE,1)
DialogControlSet(hDlg,CHECKBOX_MODIFY_GENRE   ,DCSET_VALUE,1)
DialogControlSet(hDlg,CHECKBOX_MODIFY_READONLY,DCSET_VALUE,1)
#EndSubRoutine
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineSubRoutine udsSet_DLG_MODIFY_OFF ()
DialogControlSet(hDlg,CHECKBOX_MODIFY_TITLE   ,DCSET_VALUE,0)
DialogControlSet(hDlg,CHECKBOX_MODIFY_ARTIST  ,DCSET_VALUE,0)
DialogControlSet(hDlg,CHECKBOX_MODIFY_ALBUM   ,DCSET_VALUE,0)
DialogControlSet(hDlg,CHECKBOX_MODIFY_YEAR    ,DCSET_VALUE,0)
DialogControlSet(hDlg,CHECKBOX_MODIFY_COMMENT ,DCSET_VALUE,0)
DialogControlSet(hDlg,CHECKBOX_MODIFY_RESERVED,DCSET_VALUE,0)
DialogControlSet(hDlg,CHECKBOX_MODIFY_TRACK   ,DCSET_VALUE,0)
DialogControlSet(hDlg,CHECKBOX_MODIFY_GENRE   ,DCSET_VALUE,0)
DialogControlSet(hDlg,CHECKBOX_MODIFY_READONLY,DCSET_VALUE,0)
#EndSubRoutine
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineSubRoutine udsGet_DLG_MODIFY ()
DLG_MODIFY_Title    = DialogControlGet(hDlg,CHECKBOX_MODIFY_TITLE   ,DCGET_VALUE)
DLG_MODIFY_Artist   = DialogControlGet(hDlg,CHECKBOX_MODIFY_ARTIST  ,DCGET_VALUE)
DLG_MODIFY_Album    = DialogControlGet(hDlg,CHECKBOX_MODIFY_ALBUM   ,DCGET_VALUE)
DLG_MODIFY_Year     = DialogControlGet(hDlg,CHECKBOX_MODIFY_YEAR    ,DCGET_VALUE)
DLG_MODIFY_Comment  = DialogControlGet(hDlg,CHECKBOX_MODIFY_COMMENT ,DCGET_VALUE)
DLG_MODIFY_Genre    = DialogControlGet(hDlg,CHECKBOX_MODIFY_GENRE   ,DCGET_VALUE)
DLG_MODIFY_Track    = DialogControlGet(hDlg,CHECKBOX_MODIFY_TRACK   ,DCGET_VALUE)
DLG_MODIFY_Reserved = DialogControlGet(hDlg,CHECKBOX_MODIFY_RESERVED,DCGET_VALUE)

If DLG_MODIFY_Title     Then Return (1)
If DLG_MODIFY_Artist    Then Return (1)
If DLG_MODIFY_Album     Then Return (1)
If DLG_MODIFY_Year      Then Return (1)
If DLG_MODIFY_Comment   Then Return (1)
If DLG_MODIFY_Genre     Then Return (1)
If DLG_MODIFY_Track     Then Return (1)
If DLG_MODIFY_Reserved  Then Return (1)
Return (0)
#EndSubRoutine
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineSubRoutine udsApply_DLG_MODIFY ()
; If one member has not to modify, then re-read the unchanged part from the input buffer.
If !DLG_MODIFY_Title     Then DLG_ID3_Title    = BinaryPeekStr(hBBID3,003,30) ; (30) The title of the song.
If !DLG_MODIFY_Artist    Then DLG_ID3_Artist   = BinaryPeekStr(hBBID3,033,30) ; (30) The song's artist.
If !DLG_MODIFY_Album     Then DLG_ID3_Album    = BinaryPeekStr(hBBID3,063,30) ; (30) The album from which the song was taken.
If !DLG_MODIFY_Year      Then DLG_ID3_Year     = BinaryPeekStr(hBBID3,093,04) ; (04) The year the song is from.
If !DLG_MODIFY_Comment   Then DLG_ID3_Comment  = BinaryPeekStr(hBBID3,097,28) ; (28) A brief comment about the song.
If !DLG_MODIFY_Reserved  Then DLG_ID3_Reserved = BinaryPeek   (hBBID3,125)    ; (01) A wasted empty character.
If !DLG_MODIFY_Track     Then DLG_ID3_Track    = BinaryPeek   (hBBID3,126)    ; (01) The track number.
If !DLG_MODIFY_Genre     Then DLG_ID3_Genre    = BinaryPeek   (hBBID3,127)    ; (01) The genre of the song.
#EndSubRoutine
;------------------------------------------------------------------------------------------------------------------------------------------


;------------------------------------------------------------------------------------------------------------------------------------------
#DefineSubRoutine udsInit_DLG_MEMO ()
DLG_MEMO_Title    = ""
DLG_MEMO_Artist   = ""
DLG_MEMO_Album    = ""
DLG_MEMO_Comment  = ""
DLG_MEMO_Year     = ""
DLG_MEMO_Reserved = ""
DLG_MEMO_Track    = ""
DLG_MEMO_Genre    = ""
DLG_MEMO_Genre2   = ""
#EndSubRoutine
;------------------------------------------------------------------------------------------------------------------------------------------


;------------------------------------------------------------------------------------------------------------------------------------------
#DefineSubRoutine udsInit_DLG_ID3 ()
DLG_ID3_Title    = ""
DLG_ID3_Artist   = ""
DLG_ID3_Album    = ""
DLG_ID3_Year     = ""
DLG_ID3_Comment  = ""
DLG_ID3_Reserved = ""
DLG_ID3_Track    = ""
If IsDefined(DLG_ID3_Genre) Then DLG_ID3_Genre = 0
   Else DLG_ID3_Genre = StrCat("-1|",1+ID3_Genre_Max,"|1") ; Allows wrapping for spinner.
DLG_ID3_Genre2   = IniReadPvt(SECTION_GENRE_PREDEFINED,DLG_ID3_Genre,DLG_GENRE_DEFINED_NO,sFilenameGenre)
#EndSubRoutine
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineSubRoutine udsSet_DLG_ID3 ()
DialogControlSet(hDlg,EDITBOX_ID3_TITLE   ,DCSET_REPLACE_TEXT ,DLG_ID3_Title   )
DialogControlSet(hDlg,EDITBOX_ID3_ARTIST  ,DCSET_REPLACE_TEXT ,DLG_ID3_Artist  )
DialogControlSet(hDlg,EDITBOX_ID3_ALBUM   ,DCSET_REPLACE_TEXT ,DLG_ID3_Album   )
DialogControlSet(hDlg,EDITBOX_ID3_YEAR    ,DCSET_REPLACE_TEXT ,DLG_ID3_Year    )
DialogControlSet(hDlg,EDITBOX_ID3_COMMENT ,DCSET_REPLACE_TEXT ,DLG_ID3_Comment )
DialogControlSet(hDlg,SPINNER_ID3_GENRENUMBER   ,DCSET_SPINNER_VALUE,DLG_ID3_Genre   )
DialogControlSet(hDlg,SPINNER_ID3_TRACK   ,DCSET_SPINNER_VALUE,DLG_ID3_Track   )
DialogControlSet(hDlg,SPINNER_ID3_RESERVED,DCSET_SPINNER_VALUE,DLG_ID3_Reserved)
DLG_ID3_Genre2 = IniReadPvt(SECTION_GENRE_PREDEFINED,DLG_ID3_Genre,DLG_GENRE_DEFINED_NO,sFilenameGenre)
DialogControlSet(hDlg,DROPLBOX_ID3_GENRENAME ,DCSET_ITEM_SELECTED,DLG_ID3_Genre2)
#EndSubRoutine
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineSubRoutine udsGet_DLG_ID3 ()
DLG_ID3_Title    = DialogControlGet(hDlg,EDITBOX_ID3_TITLE   ,DCGET_TEXT )
DLG_ID3_Artist   = DialogControlGet(hDlg,EDITBOX_ID3_ARTIST  ,DCGET_TEXT )
DLG_ID3_Album    = DialogControlGet(hDlg,EDITBOX_ID3_ALBUM   ,DCGET_TEXT )
DLG_ID3_Year     = DialogControlGet(hDlg,EDITBOX_ID3_YEAR    ,DCGET_TEXT )
DLG_ID3_Comment  = DialogControlGet(hDlg,EDITBOX_ID3_COMMENT ,DCGET_TEXT )
DLG_ID3_Genre    = DialogControlGet(hDlg,SPINNER_ID3_GENRENUMBER   ,DCGET_SPINNER_VALUE)
DLG_ID3_Track    = DialogControlGet(hDlg,SPINNER_ID3_TRACK   ,DCGET_SPINNER_VALUE)
DLG_ID3_Reserved = DialogControlGet(hDlg,SPINNER_ID3_RESERVED,DCGET_SPINNER_VALUE)
#EndSubRoutine
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineSubRoutine udsSet_DLG_ID3_TAGEXIST (iValue)
Select iValue
Case 0
Case 1
   DialogControlSet(hDlg,VARYTEXT_ID3_TAGEXIST,DCSET_REPLACE_TITLE,DLG_TAGEXIST_NO)
   Break
Case 2
   DialogControlSet(hDlg,VARYTEXT_ID3_TAGEXIST,DCSET_REPLACE_TITLE,DLG_TAGEXIST_YES)
   Break
EndSelect
#EndSubRoutine
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineSubRoutine udsSet_DLG_ID3_READONLY (iValue)
Select iValue
Case 1
   DialogControlSet(hDlg,CHECKBOX_MODIFY_READONLY,DCSET_VALUE,DLG_READONLY_YES)
   Break
Case 0
   DialogControlSet(hDlg,CHECKBOX_MODIFY_READONLY,DCSET_VALUE,DLG_READONLY_NO)
   Break
EndSelect
#EndSubRoutine
;------------------------------------------------------------------------------------------------------------------------------------------


;------------------------------------------------------------------------------------------------------------------------------------------
#DefineSubRoutine udsDefineDialogConstants ()
;------------------------------------------------------------------------------------------------------------------------------------------
; DialogProcOptions(dialog-handle, event-code, on-off-time)
;   (i) dialog-handle  handle to dialog
;   (i) event-code     event code for event that produces call to UDC
;   (i) on-off-time : 1 - enable; 0 - disable; -1 - previous setting;  n - time in milliseconds
; Returns: (i) previous setting for event-code
;..........................................................................................................................................
DPO_DIALOG_INIT               = 0    ; Dialog has been created but not displayed.  This event is only generated once pre dialog session.
DPO_TIMER_EVENT               = 1    ; Set a Timer event.
;                                    ; (i) > 0 - milliseconds between callbacks; 0 - turn off timer; -1 - return current setting
DPO_PUSHBUTTON_PUSHED         = 2    ; User has pressed a PUSHBUTTON or PICTUREBUTTON control.
;                                    ; (i) 1 - turn on event callback; 0 - turn off callback; -1 - return current setting
DPO_RADIOBUTTON_SELECTED      = 3    ; Radiobutton Selected: User has selected a RADIOBUTTON.
DPO_CHECKBOX_CHANGED          = 4    ; Checkbox Checked/Unchecked: User has checked or unchecked a CHECKBOX control.
DPO_EDITBOX_TEXTCHANGED       = 5    ; Changed text in Editbox or Multilinebox: User has changed the text in an EDITBOX or MULTILINEBOX control.
DPO_MULTILINEBOX_TEXTCHANGED  = 5    ; Changed text in Editbox or Multilinebox: User has changed the text in an EDITBOX or MULTILINEBOX control.
DPO_FILELISTBOX_FILESELECTED  = 6    ; User has selected a file in a FILELISTBOX control.
DPO_ITEMBOX_ITEMSELECTED      = 7    ; User has selected one or more items in a ITEMBOX control.
DPO_DROPLISTBOX_ITEMCHANGED   = 8    ; User has changed the text appearing at the top of a DROPLISTBOX.
;                                    ; This event can be triggered by the user picking a new item from the list portion of the control
;                                    ; or by the user typing new text into the control.
DPO_CALENDAR_DATECHANGED      = 9    ; Calendar Date Change: User has selected a new date in a CALENDAR control.
;                                    ; Note: cycling the month with the right and left arrows does not produce a callback.
;                                    ; The user must click on a specific day of the month.
DPO_SPINNER_NUMBERCHANGED     = 10   ; User has changed the value of a SPINNER control.
DPO_CLOSE                     = 11   ; User has selected the Close command from the system menu.
;                                    ; This event only applies to dialog's with system menus enabled by a call to IntControl 49.
DPO_FILELISTBOX_DOUBLECLICKED = 12   ; The user has used the mouse to double-click an item in an FILELISTBOX.
DPO_ITEMBOX_DOUBLECLICKED     = 13   ; The user has used the mouse to double-click an item in an ITEMBOX
DPO_DIALOG_DISABLE            = 1000 ; Grey the dialog's title bar and redraw dialog as necessary.  Optionally, display the system's "wait cursor".
;                                    ; (i) 1 - disable dialog; 2 - disable and wait cursor; 0 - enable dialog ; -1 - return current setting.
DPO_BACKGROUND_CHANGED        = 1001 ; Change the dialog's background bitmap or color.
;                                      (s) bitmap file name or RBG color string(i); -1 - return current background.
;------------------------------------------------------------------------------------------------------------------------------------------

;------------------------------------------------------------------------------------------------------------------------------------------
; DialogControlGet(dialog-handle,  control-number, request-code)
;..........................................................................................................................................
DCGET_VALUE                  = 1
DCGET_TEXT                   = 3
DCGET_ITEMLIST               = 5
DCGET_ITEM                   = 6
DCGET_SPINNER_VALUE          = 8
;------------------------------------------------------------------------------------------------------------------------------------------
; DialogControlSet(dialog-handle, control-number, set-request-code, set-info)
;..........................................................................................................................................
DCSET_VALUE                  = 1
DCSET_REPLACE_TEXT           = 3
DCSET_REPLACE_TITLE          = 4
DCSET_REPLACE_LIST           = 5
DCSET_ITEM_SELECTED          = 6
DCSET_SPINNER_VALUE          = 8
DCSET_ADD_ITEM_SORT          = 14
DCSET_REMOVE_ITEM            = 15
;------------------------------------------------------------------------------------------------------------------------------------------
; DialogControlState(dialog-handle,  control-number, request-code, style)
;..........................................................................................................................................
DCSTATE_NULL                 = 0    ; Dummy.
DCSTATE_SET_FOCUS            = 1    ; Give a control the input focus.
DCSTATE_QUERY_STYLE          = 2    ; Query a control's style.
DCSTATE_ADD_STYLE            = 3    ; Add one or more styles to a control.
DCSTATE_REMOVE_STYLE         = 4    ; Remove styles from a control.
DCSTATE_GET_FOCUS            = 5    ; Get control that has focus
;..........................................................................................................................................
; Style
DCSTYLE_INVISIBLE            = 1    ; Control is invisible.
DCSTYLE_DISABLED             = 2    ; Control has disabled appearance and does not accept any user input, if would otherwise accept input.
DCSTYLE_LISTONLY             = 4    ; Control will only accept values already in the drop down list portion of the control.
DCSTYLE_BLOCKINPUT           = 8    ; The controls text cannot be change by typing in new text when the control has the input focus.
;                                   ; (Note: The user can still change the value in a SPINNER controls by using the up and down arrows.
DCSTYLE_ASTERISK             = 16   ; Displays all characters as an asterisk (*) as they are typed into the control.
DCSTYLE_DEFAULT              = 32   ; A button with this style is the default button when no push or picture button has the input focus.
DCSTYLE_DIGITS               = 64   ; Allows only digits to be entered into the edit type controls. Note: even with this set, it is still possible to paste non-digits into the edit control.
DCSTYLE_FLAT                 = 128  ; Creates a button with a flat appearance.
;------------------------------------------------------------------------------------------------------------------------------------------
#EndSubRoutine
;------------------------------------------------------------------------------------------------------------------------------------------


;------------------------------------------------------------------------------------------------------------------------------------------
#DefineSubRoutine udsCreateDroplistHash (sIniSection, sIniFilename)
; Create Lookup table for Genre Names.
; Create ItemList for the DropList-Control.
oDroplistKey  = ObjectOpen("Scripting.Dictionary")
oDroplistData = ObjectOpen("Scripting.Dictionary")
;   vbBinaryCompare=0
;   vbTextCompare=1
;   vbDatabaseCompare=2
;   oDroplistKey.CompareMode  = vbTextCompare
;   oDroplistData.CompareMode = vbTextCompare
sDroplist = ""
sKeyList = IniItemizePvt(sIniSection,sIniFilename)
iCount = ItemCount(sKeyList,@TAB)
iLow  = 1
iHigh = iCount
For iKey=iLow To iHigh
   sKey  = ItemExtract(iKey,sKeyList,@TAB)
   sData = IniReadPvt(sIniSection,sKey,@NOTAVAILABLE,sIniFilename)
   oDroplistKey.add(sKey,sData)
   oDroplistData.add(sData,sKey)
   If (sData<>@NOTAVAILABLE) Then sDroplist = ItemInsert(sData,-1,sDroplist,@TAB)
Next
sDroplist=ItemSort(sDroplist,@TAB)
sDroplist=ItemInsert(@NOTAVAILABLE,0,sDroplist,@TAB)
Drop(iCount,iHigh,iKey,iLow,sData,sKey,sKeyList)
#EndSubRoutine
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineSubRoutine udsReleaseDroplistHash ()
ObjectClose(oDroplistKey)
ObjectClose(oDroplistData)
#EndSubRoutine
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineSubRoutine udsGetSpinnerValue (iDroplistItem)
iSpinnerValue=SPINNER_MAX
If oDroplistData.Exists(iDroplistItem) Then iSpinnerValue=oDroplistData.Item(iDroplistItem)
Return (iSpinnerValue)
#EndSubRoutine
;------------------------------------------------------------------------------------------------------------------------------------------
#DefineSubRoutine udsGetDroplistItem (iSpinnerValue)
iDroplistItem = @NOTAVAILABLE
If oDroplistKey.Exists(iSpinnerValue) Then iDroplistItem=oDroplistKey.Item(iSpinnerValue)
Return (iDroplistItem)
#EndSubRoutine
;------------------------------------------------------------------------------------------------------------------------------------------



;------------------------------------------------------------------------------------------------------------------------------------------
#DefineSubRoutine udsDroplistBoxSpinner (hDlg, DlgEventCode, DlgControlNum, Res4, Res5)
;>>> Dialog Template --- DroplistBox combined with Spinner.

Select DlgEventCode

Case DPO_DIALOG_INIT  ; Init
   DialogProcOptions(hDlg,10,1) ; Enable Spinner changes.
   DialogProcOptions(hDlg, 8,1) ; Enable Droplist changes.

   udsCreateDroplistHash(sSectionGenrePredefined,sFilenameGenre)

   ; Set upper limit for spinner accordingly to lookup count.
   ; SPINNER_MAX = ItemCount(DialogControlGet(hDlg,DROPLBOX_ID3_GENRENAME,DCGET_ITEMLIST),@TAB)-1

   ; Set spinner area.
   SPINNER_MAX = "255" ; Vartype=String (because Datatype in Dictionary)
   SPINNER_MIN = "0"   ; Vartype=String (because Datatype in Dictionary)

   ; Load Data into Droplist.
   DialogControlSet (hDlg,DROPLBOX_ID3_GENRENAME,DCSET_REPLACE_LIST,sDroplist)

   ; Set Droplist to first item.
   DialogControlSet (hDlg,DROPLBOX_ID3_GENRENAME,DCSET_ITEM_SELECTED,ItemExtract(1,sDroplist,@TAB))

   ; Set Spinner to lookup entry.
   DialogControlSet (hDlg,SPINNER_ID3_GENRENUMBER,DCSET_SPINNER_VALUE,udsGetSpinnerValue(DialogControlGet(hDlg,DROPLBOX_ID3_GENRENAME,DCGET_ITEM)))
   Break

Case DPO_DROPLISTBOX_ITEMCHANGED
   iSpinnerValue = udsGetSpinnerValue(DialogControlGet(hDlg,DROPLBOX_ID3_GENRENAME,DCGET_ITEM))
   DialogControlSet (hDlg,SPINNER_ID3_GENRENUMBER,DCSET_SPINNER_VALUE,iSpinnerValue)
   Return(-1)
   Break

Case DPO_SPINNER_NUMBERCHANGED
   iSpinnerValue = DialogControlGet(hDlg,SPINNER_ID3_GENRENUMBER,DCGET_SPINNER_VALUE)
   If (iSpinnerValue < SPINNER_MIN)
      iSpinnerValue = SPINNER_MAX
      DialogControlSet (hDlg,SPINNER_ID3_GENRENUMBER,DCSET_SPINNER_VALUE,iSpinnerValue)
   EndIf
   If (iSpinnerValue > SPINNER_MAX)
      iSpinnerValue = SPINNER_MIN
      DialogControlSet (hDlg,SPINNER_ID3_GENRENUMBER,DCSET_SPINNER_VALUE,iSpinnerValue)
   EndIf
   DialogControlSet(hDlg,DROPLBOX_ID3_GENRENAME,DCSET_ITEM_SELECTED,udsGetDroplistItem(DialogControlGet(hDlg,SPINNER_ID3_GENRENUMBER,DCGET_SPINNER_VALUE)))
   Return(-1)
   Break

EndSelect
;<<< Dialog Template --- DroplistBox combined with Spinner.
#EndSubRoutine
;------------------------------------------------------------------------------------------------------------------------------------------


;------------------------------------------------------------------------------------------------------------------------------------------
#DefineSubRoutine udsProcessOneFile(sFilename)
If (FileSizeEx(sFilename) == 0) Then Return (-1) ; Let caller handle error.
If (FileExtension(sFilename) <> "mp3") Then Return (-2) ; Let caller handle error.

If !udsGet_DLG_MODIFY() Then Return (-3) ; Let caller handle error.

udsGet_DLG_ID3()
udsApply_DLG_MODIFY()
udsPut_DLG_ID3_ToBuffer()
If (udfID3Write(sFilename,hBBID3,1) <> 1)
   Message("Error in udfID3Write",StrCat("Cannot write ID3 tag to file:",@LF,sFilename))
EndIf
#EndSubRoutine
;------------------------------------------------------------------------------------------------------------------------------------------


;------------------------------------------------------------------------------------------------------------------------------------------
#DefineSubRoutine udsDispatchPUSHBUTTON (hDlg, DlgEventCode, DlgControlNum, Res4, Res5)
Select DlgEventCode
Case DPO_DIALOG_INIT
   DialogProcOptions(hDlg,DPO_PUSHBUTTON_PUSHED,1)
   Break
Case DPO_PUSHBUTTON_PUSHED
   Select DlgControlNum

   Case PUSHBTTN_OK
      Break

   Case PUSHBTTN_CANCEL
      Break

   Case PUSHBTTN_WRITE
      Select DialogControlGet(hDlg,CHECKBOX_DLG_BATCHMODE,DCGET_VALUE)
      Case 0
         ; DirectMode
         Select iListFocus
         Case FILELBOX_FILELIST
            sItem = DialogControlGet(hDlg,FILELBOX_FILELIST,DCGET_ITEM)
            Break
         Case ITEMBOX_WORKLIST
            sItem = DialogControlGet(hDlg,ITEMBOX_WORKLIST,DCGET_ITEM)
            Break
         EndSelect
         sItem = ItemExtract(1,sItem,@TAB) ; Multi files not allowed.
         If (sItem>"")
            iModify=@TRUE
            If !!StrIndex(FileAttrGet(sItem),"R",1,@FWDSCAN)
               iModify=@FALSE
               iModify=(@YES==AskYesNo("ID3 Tag Writing",StrCat("File is write protected:",@LF,sItem,@LF,@LF,"Modify it anyway?")))
            EndIf
            If !iModiFy
               udsSet_DLG_ID3_READONLY(!!StrIndex(FileAttrGet(sItem),"R",1,@FWDSCAN))
            Else
               iResult = udsProcessOneFile(sItem)
               If (DialogControlGet(hDlg,CHECKBOX_MODIFY_READONLY,DCGET_VALUE))
                  FileAttrSet(sItem,"R")
               Else
                  FileAttrSet(sItem,"r")
               EndIf
               If udfID3Read(sItem,hBBID3) ; Read back.
                  udsGet_DLG_ID3_FromBuffer()
                  udsSet_DLG_ID3()
               Else
                  ; Handle Read or Write error here.
               EndIf
            EndIf
         EndIf
         Break
      Case 1
         ; BatchMode
         DialogControlSet(hDlg,EDITBOX_WORKFILE,DCSET_REPLACE_TEXT,"")
         sItemList = DialogControlGet(hDlg,ITEMBOX_WORKLIST,DCGET_ITEMLIST)
         iCount = ItemCount(sItemList,@TAB)
         For i=1 To iCount
            sItem = ItemExtract(i,sItemList,@TAB)
            If (sItem=="") Then Continue

            If udfID3Read(sItem,hBBID3)
               udsGet_DLG_ID3_FromBuffer()
               ; udsSet_DLG_ID3()
            Else
               ; Handle Read or Write error here.
            EndIf

            iModify=@TRUE
            If !!StrIndex(FileAttrGet(sItem),"R",1,@FWDSCAN)
               iModify=@FALSE
               iModify=(@YES==AskYesNo("ID3 Tag Writing",StrCat("File is write protected:",@LF,sItem,@LF,@LF,"Modify it anyway?")))
            EndIf
            If !iModiFy Then Continue

            iResult = udsProcessOneFile(sItem)
            If (DialogControlGet(hDlg,CHECKBOX_MODIFY_READONLY,DCGET_VALUE))
               FileAttrSet(sItem,"R")
            Else
               FileAttrSet(sItem,"r")
            EndIf
            ; DialogControlSet(hDlg,ITEMBOX_WORKLIST,ITEMBOX_REMOVE_ITEM,sItem)
            DialogControlSet(hDlg,ITEMBOX_WORKLIST,DCSET_REPLACE_LIST,StrCat("Processing # ",iCount," / ",i,@TAB,sItem))
         Next
         DialogControlSet(hDlg,ITEMBOX_WORKLIST,DCSET_REPLACE_LIST,"Ready.")
         TimeDelay(1)
         DialogControlSet(hDlg,ITEMBOX_WORKLIST,DCSET_REPLACE_LIST,sItemList)
         Break
      EndSelect

      Drop(sItem,iModify)
      Break

   Case PUSHBTTN_TO_MEMO_TITLE
      DLG_ID3_Title    = DialogControlGet(hDlg,EDITBOX_ID3_TITLE,DCGET_TEXT)
      If (DLG_ID3_Title > "")  Then DialogControlSet(hDlg,DROPLBOX_MEMO_TITLE,DCSET_ITEM_SELECTED,DLG_ID3_Title)
      Break

   Case PUSHBTTN_TO_MEMO_ARTIST
      DLG_ID3_Artist   = DialogControlGet(hDlg,EDITBOX_ID3_ARTIST,DCGET_TEXT)
      If (DLG_ID3_Artist > "") Then DialogControlSet(hDlg,DROPLBOX_MEMO_ARTIST,DCSET_ITEM_SELECTED,DLG_ID3_Artist)
      Break

   Case PUSHBTTN_TO_MEMO_ALBUM
      DLG_ID3_Album    = DialogControlGet(hDlg,EDITBOX_ID3_ALBUM,DCGET_TEXT)
      If (DLG_ID3_Album > "")  Then DialogControlSet(hDlg,DROPLBOX_MEMO_ALBUM,DCSET_ITEM_SELECTED,DLG_ID3_Album)
      Break

   Case PUSHBTTN_TO_MEMO_YEAR
      DLG_ID3_Year     = DialogControlGet(hDlg,EDITBOX_ID3_YEAR,DCGET_TEXT)
      If (DLG_ID3_Year > "")   Then DialogControlSet(hDlg,DROPLBOX_MEMO_YEAR,DCSET_ITEM_SELECTED,DLG_ID3_Year)
      Break

   Case PUSHBTTN_TO_MEMO_COMMENT
      DLG_ID3_Comment  = DialogControlGet(hDlg,EDITBOX_ID3_COMMENT,DCGET_TEXT)
      If (DLG_ID3_Comment > "") Then DialogControlSet(hDlg,DROPLBOX_MEMO_COMMENT,DCSET_ITEM_SELECTED,DLG_ID3_Comment)
      Break

   Case PUSHBTTN_TO_MEMO_RESERVED
      DLG_ID3_Reserved  = DialogControlGet(hDlg,SPINNER_ID3_RESERVED,DCGET_SPINNER_VALUE)
      DialogControlSet(hDlg,DROPLBOX_MEMO_RESERVED,DCSET_ITEM_SELECTED,DLG_ID3_Reserved)
      Break

   Case PUSHBTTN_TO_MEMO_TRACK
      DLG_ID3_Track = DialogControlGet(hDlg,SPINNER_ID3_TRACK,DCGET_SPINNER_VALUE)
      DialogControlSet(hDlg,DROPLBOX_MEMO_TRACK,DCSET_ITEM_SELECTED,DLG_ID3_Track)
      Break

   Case PUSHBTTN_TO_MEMO_GENRE
      DLG_ID3_Genre = DialogControlGet(hDlg,SPINNER_ID3_GENRENUMBER,DCGET_SPINNER_VALUE)
      DialogControlSet(hDlg,DROPLBOX_MEMO_GENRE,DCSET_ITEM_SELECTED,DLG_ID3_Genre)
      DLG_ID3_Genre2 = DialogControlGet(hDlg,DROPLBOX_ID3_GENRENAME,DCGET_ITEM)
      DialogControlSet(hDlg,EDITBOX_MEMO_GENRE2,DCSET_REPLACE_TEXT,DLG_ID3_Genre2)
      Break

   Case PUSHBTTN_ADD_WORK_FILE
      sItem = DialogControlGet(hDlg,FILELBOX_FILELIST,DCGET_ITEM)
      If (FileSizeEx(sItem) > 0)
         sItem = FileFullname(sItem)
         sItem = FileNameLong(sItem)
         If !ItemLocate(sItem,DialogControlGet(hDlg,ITEMBOX_WORKLIST,DCGET_ITEMLIST),@TAB)
            DialogControlSet(hDlg,ITEMBOX_WORKLIST,DCSET_ADD_ITEM_SORT,sItem)
         EndIf
      EndIf
      Drop (sItem)
      Break

   Case PUSHBTTN_ADD_WORK_FILES
      sItemList = FileItemize("*.mp3")
      iCount = ItemCount(sItemList,@TAB)
      For i=1 To iCount
         sItem = ItemExtract(i,sItemList,@TAB)
         If (FileSizeEx(sItem) > 0)
            sItem = FileFullname(sItem)
            sItem = FileNameLong(sItem)
            If !ItemLocate(sItem,DialogControlGet(hDlg,ITEMBOX_WORKLIST,DCGET_ITEMLIST),@TAB)
               DialogControlSet(hDlg,ITEMBOX_WORKLIST,DCSET_ADD_ITEM_SORT,sItem)
            EndIf
         EndIf
      Next
      Drop (i,iCount,sItem,sItemList)
      Break

   Case PUSHBTTN_FROM_MEMO_TITLE
      DLG_ID3_Title    = DialogControlGet(hDlg,DROPLBOX_MEMO_TITLE,DCGET_ITEM)
      DialogControlSet(hDlg,EDITBOX_ID3_TITLE,DCSET_REPLACE_TEXT,DLG_ID3_Title)
      Break

   Case PUSHBTTN_FROM_MEMO_ARTIST
      DLG_ID3_Artist   = DialogControlGet(hDlg,DROPLBOX_MEMO_ARTIST,DCGET_ITEM)
      DialogControlSet(hDlg,EDITBOX_ID3_ARTIST,DCSET_REPLACE_TEXT,DLG_ID3_Artist)
      Break

   Case PUSHBTTN_FROM_MEMO_ALBUM
      DLG_ID3_Album    = DialogControlGet(hDlg,DROPLBOX_MEMO_ALBUM,DCGET_ITEM)
      DialogControlSet(hDlg,EDITBOX_ID3_ALBUM,DCSET_REPLACE_TEXT,DLG_ID3_Album)
      Break

   Case PUSHBTTN_FROM_MEMO_YEAR
      DLG_ID3_Year     = DialogControlGet(hDlg,DROPLBOX_MEMO_YEAR,DCGET_ITEM)
      DialogControlSet(hDlg,EDITBOX_ID3_YEAR,DCSET_REPLACE_TEXT,DLG_ID3_Year)
      Break

   Case PUSHBTTN_FROM_MEMO_COMMENT
      DLG_ID3_Comment  = DialogControlGet(hDlg,DROPLBOX_MEMO_COMMENT,DCGET_ITEM)
      DialogControlSet(hDlg,EDITBOX_ID3_COMMENT,DCSET_REPLACE_TEXT,DLG_ID3_Comment)
      Break

   Case PUSHBTTN_FROM_MEMO_RESERVED
      DLG_ID3_Reserved  = DialogControlGet(hDlg,DROPLBOX_MEMO_RESERVED,DCGET_ITEM)
      DialogControlSet(hDlg,SPINNER_ID3_RESERVED,DCSET_SPINNER_VALUE,DLG_ID3_Reserved)
      Break

   Case PUSHBTTN_FROM_MEMO_TRACK
      DLG_ID3_Track  = DialogControlGet(hDlg,DROPLBOX_MEMO_TRACK,DCGET_ITEM)
      DialogControlSet(hDlg,SPINNER_ID3_TRACK,DCSET_SPINNER_VALUE,DLG_ID3_Track)
      Break

   Case PUSHBTTN_FROM_MEMO_GENRE
      DLG_ID3_Genre  = DialogControlGet(hDlg,DROPLBOX_MEMO_GENRE,DCGET_ITEM)
      DialogControlSet(hDlg,SPINNER_ID3_GENRENUMBER,DCSET_SPINNER_VALUE,DLG_ID3_Genre)
      DLG_ID3_Genre2 = DialogControlGet(hDlg,EDITBOX_MEMO_GENRE2,DCGET_TEXT)
      DialogControlSet(hDlg,DROPLBOX_ID3_GENRENAME,DCSET_ITEM_SELECTED,DLG_ID3_Genre2)
      Break

   Case PUSHBTTN_REMOVE_WORK_FILE
      sItem = DialogControlGet(hDlg,ITEMBOX_WORKLIST,DCGET_ITEM)
      If (sItem > "") Then DialogControlSet(hDlg,ITEMBOX_WORKLIST,DCSET_REMOVE_ITEM,sItem)
      Drop (sItem)
      Break

   Case PUSHBTTN_REMOVE_WORK_FILES
      DialogControlSet(hDlg,ITEMBOX_WORKLIST,DCSET_REPLACE_LIST,"")
      Break

   Case PUSHBTTN_REMOVE_LIST_TITLE
      DialogControlSet(hDlg,DROPLBOX_MEMO_TITLE   ,DCSET_REPLACE_LIST,@TAB)
      Break

   Case PUSHBTTN_REMOVE_LIST_ARTIST
      DialogControlSet(hDlg,DROPLBOX_MEMO_ARTIST  ,DCSET_REPLACE_LIST,@TAB)
      Break

   Case PUSHBTTN_REMOVE_LIST_ALBUM
      DialogControlSet(hDlg,DROPLBOX_MEMO_ALBUM   ,DCSET_REPLACE_LIST,@TAB)
      Break

   Case PUSHBTTN_REMOVE_LIST_COMMENT
      DialogControlSet(hDlg,DROPLBOX_MEMO_COMMENT ,DCSET_REPLACE_LIST,@TAB)
      Break

   Case PUSHBTTN_REMOVE_LIST_YEAR
      DialogControlSet(hDlg,DROPLBOX_MEMO_YEAR    ,DCSET_REPLACE_LIST,@TAB)
      Break

   Case PUSHBTTN_REMOVE_LIST_TRACK
      DialogControlSet(hDlg,DROPLBOX_MEMO_TRACK   ,DCSET_REPLACE_LIST,@TAB)
      Break

   Case PUSHBTTN_REMOVE_LIST_RESERVED
      DialogControlSet(hDlg,DROPLBOX_MEMO_RESERVED,DCSET_REPLACE_LIST,@TAB)
      Break

   Case PUSHBTTN_REMOVE_LIST_GENRE
      DialogControlSet(hDlg,DROPLBOX_MEMO_GENRE   ,DCSET_REPLACE_LIST,@TAB)
      DialogControlSet(hDlg,EDITBOX_MEMO_GENRE2   ,DCSET_REPLACE_TEXT,"")
      Break

   Case PUSHBTTN_REMOVE_ITEM_TITLE
      sItem = DialogControlGet(hDlg,DROPLBOX_MEMO_TITLE   ,DCGET_ITEM)
      DialogControlSet(hDlg,DROPLBOX_MEMO_TITLE   ,DCSET_REMOVE_ITEM,sItem)
      Break

   Case PUSHBTTN_REMOVE_ITEM_ARTIST
      sItem = DialogControlGet(hDlg,DROPLBOX_MEMO_ARTIST  ,DCGET_ITEM)
      DialogControlSet(hDlg,DROPLBOX_MEMO_ARTIST  ,DCSET_REMOVE_ITEM,sItem)
      Break

   Case PUSHBTTN_REMOVE_ITEM_ALBUM
      sItem = DialogControlGet(hDlg,DROPLBOX_MEMO_ALBUM   ,DCGET_ITEM)
      DialogControlSet(hDlg,DROPLBOX_MEMO_ALBUM   ,DCSET_REMOVE_ITEM,sItem)
      Break

   Case PUSHBTTN_REMOVE_ITEM_COMMENT
      sItem = DialogControlGet(hDlg,DROPLBOX_MEMO_COMMENT ,DCGET_ITEM)
      DialogControlSet(hDlg,DROPLBOX_MEMO_COMMENT ,DCSET_REMOVE_ITEM,sItem)
      Break

   Case PUSHBTTN_REMOVE_ITEM_YEAR
      sItem = DialogControlGet(hDlg,DROPLBOX_MEMO_YEAR    ,DCGET_ITEM)
      DialogControlSet(hDlg,DROPLBOX_MEMO_YEAR    ,DCSET_REMOVE_ITEM,sItem)
      Break

   Case PUSHBTTN_REMOVE_ITEM_TRACK
      sItem = DialogControlGet(hDlg,DROPLBOX_MEMO_TRACK   ,DCGET_ITEM)
      DialogControlSet(hDlg,DROPLBOX_MEMO_TRACK   ,DCSET_REMOVE_ITEM,sItem)
      Break

   Case PUSHBTTN_REMOVE_ITEM_RESERVED
      sItem = DialogControlGet(hDlg,DROPLBOX_MEMO_RESERVED,DCGET_ITEM)
      DialogControlSet(hDlg,DROPLBOX_MEMO_RESERVED,DCSET_REMOVE_ITEM,sItem)
      Break

   Case PUSHBTTN_REMOVE_ITEM_GENRE
      sItem = DialogControlGet(hDlg,DROPLBOX_MEMO_GENRE   ,DCGET_ITEM)
      DialogControlSet(hDlg,DROPLBOX_MEMO_GENRE   ,DCSET_REMOVE_ITEM,sItem)
      DialogControlSet(hDlg,EDITBOX_MEMO_GENRE2   ,DCSET_REPLACE_TEXT,"")
      Break

   Case PUSHBTTN_SET_MODIFY_ON
      udsSet_DLG_MODIFY_ON()
      Break

   Case PUSHBTTN_SET_MODIFY_OFF
      udsSet_DLG_MODIFY_OFF()
      Break

   Case PUSHBTTN_PLAY
      sItem = ""
      Select iListFocus
      Case FILELBOX_FILELIST
         sItem = DialogControlGet(hDlg,FILELBOX_FILELIST,DCGET_ITEM)
         Break
      Case ITEMBOX_WORKLIST
         sItem = DialogControlGet(hDlg,ITEMBOX_WORKLIST,DCGET_ITEM)
         Break
      EndSelect
      If (sItem > "")
         DirChange(DirGet()) ; Trick for FileFullName to get ready accomplished.
         sItem = FileFullname(sItem)
         Run(sItem,"") ; Start standard application.
      EndIf
      Drop(sItem)
      Break

   Case PUSHBTTN_BATCH_SAVE
      iResult = udfBatchListWrite(DialogControlGet(hDlg,ITEMBOX_WORKLIST,DCGET_ITEMLIST))
      Break

   Case PUSHBTTN_BATCH_OPEN
      sItemList = udfBatchListRead()
      If (sItemList > "") Then DialogControlSet(hDlg,ITEMBOX_WORKLIST,DCSET_REPLACE_LIST,sItemList)
      Break

   Case PUSHBTTN_MEMO_OPEN
      iResult = udsMemoIniRead()
      Break

   Case PUSHBTTN_MEMO_SAVE
      iResult = udsMemoIniWrite()
      Break

   Case PUSHBTTN_PROPERTIES
      sItem = ""
      Select iListFocus
      Case FILELBOX_FILELIST
         sItem = DialogControlGet(hDlg,FILELBOX_FILELIST,DCGET_ITEM)
         Break
      Case ITEMBOX_WORKLIST
         sItem = DialogControlGet(hDlg,ITEMBOX_WORKLIST,DCGET_ITEM)
         Break
      EndSelect
      If (sItem>"")
         DirChange(DirGet()) ; Trick for FileFullName to get ready accomplished.
         sItem = FileFullname(sItem)
         udfDisplayPropertiesSheet(sItem)
      EndIf
      Drop(sItem)
      Break

   EndSelect
   Break
EndSelect

:CANCEL
IntControl(72, 2, 0, 0, 0) ; Gosub the label :CANCEL
Return
#EndSubRoutine
;------------------------------------------------------------------------------------------------------------------------------------------


;------------------------------------------------------------------------------------------------------------------------------------------
#DefineSubRoutine DlgCallback_ID3Dialog (hDlg, DlgEventCode, DlgControlNum, Res4, Res5)

Select DlgEventCode

Case DPO_DIALOG_INIT
   ; This case is executed only once when the dialog is just created.
   udsDispatchPUSHBUTTON (hDlg, DlgEventCode, DlgControlNum, Res4, Res5)
   udsDroplistBoxSpinner (hDlg, DlgEventCode, DlgControlNum, Res4, Res5)
   DialogProcOptions(hDlg,DPO_FILELISTBOX_FILESELECTED ,1)
   DialogProcOptions(hDlg,DPO_FILELISTBOX_DOUBLECLICKED,1)
   DialogProcOptions(hDlg,DPO_DROPLISTBOX_ITEMCHANGED  ,1)
   DialogProcOptions(hDlg,DPO_ITEMBOX_DOUBLECLICKED    ,1)
   DialogProcOptions(hDlg,DPO_CHECKBOX_CHANGED         ,1)
   DialogProcOptions(hDlg,DPO_ITEMBOX_ITEMSELECTED     ,1)
   DialogProcOptions(hDlg,DPO_TIMER_EVENT              ,2000)

   udsInitTooltips()
   udsGet_DLG_ID3_FromBuffer () ; At this time the buffer should be pretty clean.
   udsSet_DLG_ID3()
   udsMemoFromIniRead(sFilenameMemo)
   udsSet_DLG_MODIFY_OFF ()
   iListFocus = FILELBOX_FILELIST
   Break

Case DPO_TIMER_EVENT
   sWorkCount = ""
   iWorkCount = ItemCount(DialogControlGet(hDlg,ITEMBOX_WORKLIST,DCGET_ITEMLIST),@TAB)
   If (iWorkCount > 0) Then sWorkCount = StrFixLeft(iWorkCount,"0",6)
   DialogControlSet(hDlg,VARYTEXT_WORKCOUNT,DCSET_REPLACE_TITLE,sWorkCount)
   Break

Case DPO_PUSHBUTTON_PUSHED
   DirChange(DirGet()) ; Trick for FileFullName to get ready accomplished.
   udsDispatchPUSHBUTTON (hDlg, DlgEventCode, DlgControlNum, Res4, Res5)
   Return (-2)
   Break

Case DPO_FILELISTBOX_FILESELECTED
   DirChange(DirGet()) ; Trick for FileFullName to get ready accomplished.
   Select DlgControlNum
   Case FILELBOX_FILELIST
      iListFocus = FILELBOX_FILELIST
      DialogControlSet(hDlg,ITEMBOX_WORKLIST,DCSET_ITEM_SELECTED,"")
      sItem = DialogControlGet(hDlg,FILELBOX_FILELIST,DCGET_ITEM)
      sItem = ItemExtract(1,sItem,@TAB) ; Multi files not allowed.
      If (sItem > "")
         If (FileSizeEx(sItem)>0)
            If (FileExtension(sItem)=="mp3")
               sItem = FileFullname(sItem)
               sItem = FileNameLong(sItem)
               DialogControlSet(hDlg,EDITBOX_WORKFILE,DCSET_REPLACE_TEXT,sItem)
               udsInit_DLG_ID3()
               iResult = udfID3Read(sItem,hBBID3)
               udsSet_DLG_ID3_TAGEXIST(iResult)
               udsSet_DLG_ID3_READONLY(!!StrIndex(FileAttrGet(sItem),"R",1,@FWDSCAN))
               If (iResult == 2) Then  udsGet_DLG_ID3_FromBuffer()
                  Else udsInit_DLG_ID3()
               udsSet_DLG_ID3()
            Else
               DialogControlSet(hDlg,EDITBOX_WORKFILE,DCSET_REPLACE_TEXT,"")
            EndIf
         Else
            DialogControlSet(hDlg,EDITBOX_WORKFILE,DCSET_REPLACE_TEXT,"")
            udsInit_DLG_ID3()
            udsSet_DLG_ID3()
            udsSet_DLG_MODIFY_OFF ()
         EndIf
      Else
         DialogControlSet(hDlg,EDITBOX_WORKFILE,DCSET_REPLACE_TEXT,"")
      EndIf
      Drop(sItem)
      Break
   EndSelect
   Break

Case DPO_FILELISTBOX_DOUBLECLICKED
   DirChange(DirGet()) ; Trick for FileFullName to get ready accomplished.
   sItem = DialogControlGet(hDlg,FILELBOX_FILELIST,DCGET_ITEM)
   If (FileSizeEx(sItem) > 0)
      sItem = FileFullname(sItem)
      sItem = FileNameLong(sItem)
      DialogControlSet(hDlg,EDITBOX_WORKFILE,DCSET_REPLACE_TEXT,sItem)
      If !ItemLocate(sItem,DialogControlGet(hDlg,ITEMBOX_WORKLIST,DCGET_ITEMLIST),@TAB)
         DialogControlSet(hDlg,ITEMBOX_WORKLIST,DCSET_ADD_ITEM_SORT,sItem)
      EndIf
   EndIf
   Drop (sItem)
   Break

Case DPO_ITEMBOX_DOUBLECLICKED
   sItem = DialogControlGet(hDlg,ITEMBOX_WORKLIST,DCGET_ITEM)
   If (sItem > "") Then DialogControlSet(hDlg,ITEMBOX_WORKLIST,DCSET_REMOVE_ITEM,sItem)
   Drop (sItem)
   Break

Case DPO_ITEMBOX_ITEMSELECTED
   DirChange(DirGet()) ; Trick for FileFullName to get ready accomplished.
   DialogControlSet(hDlg,FILELBOX_FILELIST,DCSET_ITEM_SELECTED,"")
   iListFocus = ITEMBOX_WORKLIST
   sItem = DialogControlGet(hDlg,ITEMBOX_WORKLIST,DCGET_ITEM)
   If (sItem > "")
      sItem = ItemExtract(1,sItem,@TAB) ; Multi files not allowed.
      sItem = FileFullname(sItem)
      sItem = FileNameLong(sItem)
      DialogControlSet(hDlg,EDITBOX_WORKFILE,DCSET_REPLACE_TEXT,sItem)
      If (FileSizeEx(sItem) > 0)
         If (FileExtension(sItem) == "mp3")

            udsInit_DLG_ID3()
            iResult = udfID3Read(sItem,hBBID3)
            udsSet_DLG_ID3_TAGEXIST(iResult)
            udsSet_DLG_ID3_READONLY(!!StrIndex(FileAttrGet(sItem),"R",1,@FWDSCAN))
            If (iResult == 2) Then  udsGet_DLG_ID3_FromBuffer()
               Else udsInit_DLG_ID3()
            udsSet_DLG_ID3 ()
         EndIf
      EndIf
   EndIf
   Drop(sItem)
   Break

Case DPO_SPINNER_NUMBERCHANGED
   Select DlgControlNum
   Case SPINNER_ID3_TRACK
      DLG_ID3_Track = DialogControlGet(hDlg,SPINNER_ID3_TRACK,DCGET_SPINNER_VALUE)
      If (DLG_ID3_Track<ID3_Track_Min) Then DLG_ID3_Track=ID3_Track_Max
      If (DLG_ID3_Track>ID3_Track_Max) Then DLG_ID3_Track=ID3_Track_Min
      DialogControlSet(hDlg,SPINNER_ID3_TRACK,DCSET_SPINNER_VALUE,DLG_ID3_Track)
      Break
   Case SPINNER_ID3_RESERVED
      DLG_ID3_Reserved = DialogControlGet(hDlg,SPINNER_ID3_RESERVED,DCGET_SPINNER_VALUE)
      If (DLG_ID3_Reserved<ID3_Reserved_Min) Then DLG_ID3_Reserved=ID3_Reserved_Max
      If (DLG_ID3_Reserved>ID3_Reserved_Max) Then DLG_ID3_Reserved=ID3_Reserved_Min
      DialogControlSet(hDlg,SPINNER_ID3_RESERVED,DCSET_SPINNER_VALUE,DLG_ID3_Reserved)
      Break
   EndSelect
   Continue

Case DPO_DROPLISTBOX_ITEMCHANGED
   Select DlgControlNum
   Case DROPLBOX_MEMO_GENRE
      DLG_ID3_Genre = DialogControlGet(hDlg,DROPLBOX_MEMO_GENRE,DCGET_ITEM)
      If (DLG_ID3_Genre<ID3_Genre_Min) Then DLG_ID3_Genre=ID3_Genre_Max
      If (DLG_ID3_Genre>ID3_Genre_Max) Then DLG_ID3_Genre=ID3_Genre_Min
      DialogControlSet(hDlg,DROPLBOX_MEMO_GENRE,DCSET_ITEM_SELECTED,DLG_ID3_Genre)
      DLG_ID3_Genre2 = IniReadPvt(SECTION_GENRE_PREDEFINED,DLG_ID3_Genre,DLG_GENRE_DEFINED_NO,sFilenameGenre)
      DialogControlSet(hDlg,EDITBOX_MEMO_GENRE2,DCSET_REPLACE_TEXT,DLG_ID3_Genre2)
      Break
   EndSelect
   Continue

Case DPO_CHECKBOX_CHANGED
   Select DlgControlNum
   Case CHECKBOX_DLG_BATCHMODE
      DialogControlSet(hDlg,EDITBOX_WORKFILE,DCSET_REPLACE_TEXT,"")
      Select DialogControlGet(hDlg,CHECKBOX_DLG_BATCHMODE,DCGET_VALUE)
      Case 1
         DialogControlState(hDlg,FILELBOX_FILELIST,DCSTATE_ADD_STYLE,DCSTYLE_DISABLED)
         ;DialogControlState(hDlg,EDITBOX_WORKFILE ,DCSTATE_ADD_STYLE,DCSTYLE_DISABLED)
         DialogControlState(hDlg,ITEMBOX_WORKLIST, DCSTATE_REMOVE_STYLE,DCSTYLE_DISABLED)
         DialogControlSet(hDlg,PUSHBTTN_WRITE,DCSET_REPLACE_TITLE,"*** &Batch Tag ***")
         sSelected = DialogControlGet(hDlg,FILELBOX_FILELIST,DCGET_ITEM)
         DialogControlSet(hDlg,FILELBOX_FILELIST,DCSET_ITEM_SELECTED,"")
         Break
      Case 0
         DialogControlState(hDlg,FILELBOX_FILELIST,DCSTATE_REMOVE_STYLE,DCSTYLE_DISABLED)
         ;DialogControlState(hDlg,EDITBOX_WORKFILE ,DCSTATE_REMOVE_STYLE,DCSTYLE_DISABLED)
         DialogControlSet(hDlg,PUSHBTTN_WRITE,DCSET_REPLACE_TITLE,"Tag &Now !")
         DialogControlSet(hDlg,ITEMBOX_WORKLIST,DCSET_ITEM_SELECTED,"")
         DialogControlSet(hDlg,FILELBOX_FILELIST,DCSET_ITEM_SELECTED,sSelected)
         Break
      EndSelect
      Break
   EndSelect
   Break
EndSelect

Select DlgControlNum
Case DROPLBOX_ID3_GENRENAME
   Return (udsDroplistBoxSpinner (hDlg, DlgEventCode, DlgControlNum, Res4, Res5))
   Break
Case SPINNER_ID3_GENRENUMBER
   Return (udsDroplistBoxSpinner (hDlg, DlgEventCode, DlgControlNum, Res4, Res5))
   Break
EndSelect

Return (-1)
#EndSubRoutine
;------------------------------------------------------------------------------------------------------------------------------------------


#DefineSubRoutine udsDefineMyControls ()
;------------------------------------------------------------------------------------------------------------------------------------------
; Controls
;------------------------------------------------------------------------------------------------------------------------------------------
PUSHBTTN_OK                   = 001
PUSHBTTN_CANCEL               = 002
PUSHBTTN_WRITE                = 003
PUSHBTTN_PLAY                 = 083

PUSHBTTN_TO_MEMO_TITLE        = 004
PUSHBTTN_TO_MEMO_ARTIST       = 005
PUSHBTTN_TO_MEMO_ALBUM        = 006
PUSHBTTN_TO_MEMO_YEAR         = 007
PUSHBTTN_TO_MEMO_COMMENT      = 008
PUSHBTTN_TO_MEMO_RESERVED     = 009
PUSHBTTN_TO_MEMO_TRACK        = 010
PUSHBTTN_TO_MEMO_GENRE        = 011

PUSHBTTN_ADD_WORK_FILE        = 012
PUSHBTTN_ADD_WORK_FILES       = 084

PUSHBTTN_FROM_MEMO_TITLE      = 013
PUSHBTTN_FROM_MEMO_ARTIST     = 014
PUSHBTTN_FROM_MEMO_ALBUM      = 015
PUSHBTTN_FROM_MEMO_YEAR       = 016
PUSHBTTN_FROM_MEMO_COMMENT    = 017
PUSHBTTN_FROM_MEMO_RESERVED   = 018
PUSHBTTN_FROM_MEMO_TRACK      = 019
PUSHBTTN_FROM_MEMO_GENRE      = 020

PUSHBTTN_REMOVE_WORK_FILE     = 021
PUSHBTTN_REMOVE_WORK_FILES    = 085

EDITBOX_ID3_TITLE             = 022
EDITBOX_ID3_ARTIST            = 023
EDITBOX_ID3_ALBUM             = 024
EDITBOX_ID3_YEAR              = 025
EDITBOX_ID3_COMMENT           = 026

DROPLBOX_ID3_GENRENAME        = 027
SPINNER_ID3_GENRENUMBER       = 028

SPINNER_ID3_TRACK             = 029
SPINNER_ID3_RESERVED          = 030

DROPLBOX_MEMO_TITLE           = 041
DROPLBOX_MEMO_ARTIST          = 042
DROPLBOX_MEMO_ALBUM           = 043
DROPLBOX_MEMO_COMMENT         = 044
DROPLBOX_MEMO_YEAR            = 045
DROPLBOX_MEMO_TRACK           = 046
DROPLBOX_MEMO_RESERVED        = 047
DROPLBOX_MEMO_GENRE           = 048
EDITBOX_MEMO_GENRE2           = 049

FILELBOX_FILELIST             = 050
ITEMBOX_WORKLIST              = 051
EDITBOX_WORKFILE              = 053

CHECKBOX_MODIFY_TITLE         = 054
CHECKBOX_MODIFY_ARTIST        = 055
CHECKBOX_MODIFY_ALBUM         = 056
CHECKBOX_MODIFY_YEAR          = 057
CHECKBOX_MODIFY_COMMENT       = 058
CHECKBOX_MODIFY_RESERVED      = 059
CHECKBOX_MODIFY_TRACK         = 060
CHECKBOX_MODIFY_GENRE         = 061

PUSHBTTN_REMOVE_ITEM_TITLE    = 070
PUSHBTTN_REMOVE_ITEM_ARTIST   = 071
PUSHBTTN_REMOVE_ITEM_ALBUM    = 072
PUSHBTTN_REMOVE_ITEM_COMMENT  = 073
PUSHBTTN_REMOVE_ITEM_YEAR     = 074
PUSHBTTN_REMOVE_ITEM_TRACK    = 075
PUSHBTTN_REMOVE_ITEM_RESERVED = 076
PUSHBTTN_REMOVE_ITEM_GENRE    = 077

PUSHBTTN_REMOVE_LIST_TITLE    = 062
PUSHBTTN_REMOVE_LIST_ARTIST   = 063
PUSHBTTN_REMOVE_LIST_ALBUM    = 064
PUSHBTTN_REMOVE_LIST_COMMENT  = 065
PUSHBTTN_REMOVE_LIST_YEAR     = 066
PUSHBTTN_REMOVE_LIST_TRACK    = 067
PUSHBTTN_REMOVE_LIST_RESERVED = 068
PUSHBTTN_REMOVE_LIST_GENRE    = 069

PUSHBTTN_SET_MODIFY_ON        = 078
PUSHBTTN_SET_MODIFY_OFF       = 079

VARYTEXT_ID3_TAGEXIST         = 081

CHECKBOX_DLG_BATCHMODE        = 082

VARYTEXT_WORKCOUNT            = 086

PUSHBTTN_BATCH_OPEN           = 087
PUSHBTTN_BATCH_SAVE           = 088

PUSHBTTN_MEMO_OPEN            = 089
PUSHBTTN_MEMO_SAVE            = 090

CHECKBOX_MODIFY_REMOVETAG     = 091
CHECKBOX_MODIFY_READONLY      = 092

PUSHBTTN_PROPERTIES           = 093
;------------------------------------------------------------------------------------------------------------------------------------------
#EndSubRoutine


;------------------------------------------------------------------------------------------------------------------------------------------
#DefineSubRoutine udsDefineMyDialog ()
MyDialogFormat=`WWWDLGED,6.1`
MyDialogCaption=`ID3v1 Tagging Monster  v1.01  20030202  (c)20030123 Detlev Dalitz`
MyDialogX=-01
MyDialogY=100
MyDialogWidth=430
MyDialogHeight=267
MyDialogNumControls=093
MyDialogProcedure=`DlgCallback_ID3Dialog`
MyDialogFont=`DEFAULT`
MyDialogTextColor=`DEFAULT`
MyDialogBackground=`DEFAULT,0|128|192`
MyDialogConfig=1
MyDialog001=`287,251,036,012,PUSHBUTTON,DEFAULT,"OK",1,1,3,"System|6656|70|34","0|0|0",DEFAULT`
MyDialog002=`339,251,036,012,PUSHBUTTON,DEFAULT,"Cancel",0,2,3,"System|6656|70|34","0|0|0",DEFAULT`
MyDialog003=`045,143,168,012,PUSHBUTTON,DEFAULT,"Tag &now !",11,71,0,"System|9728|70|34","0|0|0","240|236|192"`
MyDialog004=`213,037,008,012,PUSHBUTTON,DEFAULT,">",31,21,DEFAULT,"System|6656|70|34","0|0|0","192|192|208"`
MyDialog005=`213,051,008,012,PUSHBUTTON,DEFAULT,">",32,22,DEFAULT,"System|6656|70|34","0|0|0","192|192|208"`
MyDialog006=`213,065,008,012,PUSHBUTTON,DEFAULT,">",33,23,DEFAULT,"System|6656|70|34","0|0|0","192|192|208"`
MyDialog007=`071,093,008,012,PUSHBUTTON,DEFAULT,">",34,25,DEFAULT,"System|6656|70|34","0|0|0","192|192|208"`
MyDialog008=`213,079,008,012,PUSHBUTTON,DEFAULT,">",35,24,DEFAULT,"System|6656|70|34","0|0|0","192|192|208"`
MyDialog009=`213,093,008,012,PUSHBUTTON,DEFAULT,">",36,27,DEFAULT,"System|6656|70|34","0|0|0","192|192|208"`
MyDialog010=`137,093,008,012,PUSHBUTTON,DEFAULT,">",37,26,DEFAULT,"System|6656|70|34","0|0|0","192|192|208"`
MyDialog011=`213,107,008,012,PUSHBUTTON,DEFAULT,">",38,28,DEFAULT,"System|6656|70|34","0|0|0","192|192|208"`
MyDialog012=`211,189,012,012,PUSHBUTTON,DEFAULT,">",51,62,DEFAULT,"System|6656|70|34","0|0|0",DEFAULT`
MyDialog013=`409,037,008,012,PUSHBUTTON,DEFAULT,"<",41,31,DEFAULT,"System|6656|70|34","0|0|0","192|192|208"`
MyDialog014=`409,051,008,012,PUSHBUTTON,DEFAULT,"<",42,32,DEFAULT,"System|6656|70|34","0|0|0","192|192|208"`
MyDialog015=`409,065,008,012,PUSHBUTTON,DEFAULT,"<",43,33,DEFAULT,"System|6656|70|34","0|0|0","192|192|208"`
MyDialog016=`273,093,008,012,PUSHBUTTON,DEFAULT,"<",44,35,DEFAULT,"System|6656|70|34","0|0|0","192|192|208"`
MyDialog017=`409,079,008,012,PUSHBUTTON,DEFAULT,"<",45,34,DEFAULT,"System|6656|70|34","0|0|0","192|192|208"`
MyDialog018=`409,093,008,012,PUSHBUTTON,DEFAULT,"<",46,37,DEFAULT,"System|6656|70|34","0|0|0","192|192|208"`
MyDialog019=`345,093,008,012,PUSHBUTTON,DEFAULT,"<",47,36,DEFAULT,"System|6656|70|34","0|0|0","192|192|208"`
MyDialog020=`409,107,008,012,PUSHBUTTON,DEFAULT,"<",48,38,DEFAULT,"System|6656|70|34","0|0|0","192|192|208"`
MyDialog021=`211,219,012,012,PUSHBUTTON,DEFAULT,"<",61,64,DEFAULT,"System|6656|70|34","0|0|0",DEFAULT`
MyDialog022=`045,037,166,012,EDITBOX,"DLG_ID3_Title",DEFAULT,DEFAULT,10,DEFAULT,"Courier New|6656|70|49","0|0|0","255|255|240"`
MyDialog023=`045,051,166,012,EDITBOX,"DLG_ID3_Artist",DEFAULT,DEFAULT,11,DEFAULT,"Courier New|6656|70|49","0|0|0","255|255|240"`
MyDialog024=`045,065,166,012,EDITBOX,"DLG_ID3_Album",DEFAULT,DEFAULT,12,DEFAULT,"Courier New|6656|70|49","0|0|0","255|255|240"`
MyDialog025=`045,093,024,012,EDITBOX,"DLG_ID3_Year",DEFAULT,DEFAULT,14,DEFAULT,"Courier New|6656|70|49","0|0|0","255|255|240"`
MyDialog026=`045,079,166,012,EDITBOX,"DLG_ID3_Comment",DEFAULT,DEFAULT,13,DEFAULT,"Courier New|6656|70|49","0|0|0","255|255|240"`
MyDialog027=`045,107,140,054,DROPLISTBOX,"DLG_ID3_Genre2",DEFAULT,DEFAULT,17,4,"Courier New|6656|70|49","0|0|0","255|255|240"`
MyDialog028=`185,107,026,012,SPINNER,"DLG_ID3_Genre",0,DEFAULT,18,DEFAULT,"Courier New|6656|70|49","0|0|0","255|255|240"`
MyDialog029=`109,093,026,012,SPINNER,"DLG_ID3_Track",0,DEFAULT,15,DEFAULT,"Courier New|6656|70|49","0|0|0","255|255|240"`
MyDialog030=`185,093,026,012,SPINNER,"DLG_ID3_Reserved",0,DEFAULT,16,10,"Courier New|6656|70|49","0|0|0","255|255|240"`
MyDialog031=`023,039,012,008,STATICTEXT,DEFAULT,"&Title",DEFAULT,11,DEFAULT,DEFAULT,"255|255|240",DEFAULT`
MyDialog032=`021,053,014,008,STATICTEXT,DEFAULT,"&Artist",DEFAULT,11,DEFAULT,DEFAULT,"255|255|240",DEFAULT`
MyDialog033=`019,067,016,008,STATICTEXT,DEFAULT,"Albu&m",DEFAULT,11,DEFAULT,DEFAULT,"255|255|240",DEFAULT`
MyDialog034=`023,095,012,008,STATICTEXT,DEFAULT,"&Year",DEFAULT,11,DEFAULT,DEFAULT,"255|255|240",DEFAULT`
MyDialog035=`011,081,024,008,STATICTEXT,DEFAULT,"&Comment",DEFAULT,11,DEFAULT,DEFAULT,"255|255|240",DEFAULT`
MyDialog036=`151,095,024,008,STATICTEXT,DEFAULT,"&Reserved",DEFAULT,11,2,DEFAULT,"255|255|240",DEFAULT`
MyDialog037=`083,095,016,008,STATICTEXT,DEFAULT,"Trac&k",DEFAULT,11,DEFAULT,DEFAULT,"255|255|240",DEFAULT`
MyDialog038=`019,109,016,008,STATICTEXT,DEFAULT,"&Genre",DEFAULT,11,DEFAULT,DEFAULT,"255|255|240",DEFAULT`
MyDialog039=`007,017,218,106,GROUPBOX,DEFAULT,"ID3v1 Tag",DEFAULT,21,DEFAULT,"MS Sans Serif|6656|70|34","0|0|0","255|255|240"`
MyDialog040=`227,017,194,106,GROUPBOX,DEFAULT,"Memo",DEFAULT,20,DEFAULT,"MS Sans Serif|6656|70|34","0|0|128","192|192|208"`
MyDialog041=`231,037,168,114,DROPLISTBOX,"DLG_MEMO_Title",DEFAULT,DEFAULT,33,DEFAULT,"Courier New|6656|70|49","0|0|128","192|192|208"`
MyDialog042=`231,051,168,100,DROPLISTBOX,"DLG_MEMO_Artist",DEFAULT,DEFAULT,34,DEFAULT,"Courier New|6656|70|49","0|0|128","192|192|208"`
MyDialog043=`231,065,168,086,DROPLISTBOX,"DLG_MEMO_Album",DEFAULT,DEFAULT,35,DEFAULT,"Courier New|6656|70|49","0|0|128","192|192|208"`
MyDialog044=`231,079,168,072,DROPLISTBOX,"DLG_MEMO_Comment",DEFAULT,DEFAULT,36,DEFAULT,"Courier New|6656|70|49","0|0|128","192|192|208"`
MyDialog045=`231,093,032,058,DROPLISTBOX,"DLG_MEMO_Year",DEFAULT,DEFAULT,37,DEFAULT,"Courier New|6656|70|49","0|0|128","192|192|208"`
MyDialog046=`303,093,032,058,DROPLISTBOX,"DLG_MEMO_Track",DEFAULT,DEFAULT,38,DEFAULT,"Courier New|6656|70|49","0|0|128","192|192|208"`
MyDialog047=`367,093,032,054,DROPLISTBOX,"DLG_MEMO_Reserved",DEFAULT,DEFAULT,39,0,"Courier New|6656|70|49","0|0|128","192|192|208"`
MyDialog048=`367,107,032,046,DROPLISTBOX,"DLG_MEMO_Genre",DEFAULT,DEFAULT,40,DEFAULT,"Courier New|6656|70|49","0|0|128","192|192|208"`
MyDialog049=`231,107,136,012,EDITBOX,"DLG_MEMO_Genre2",DEFAULT,DEFAULT,71,8,"Courier New|6656|70|49","0|0|128","192|192|208"`
MyDialog050=`007,169,200,080,FILELISTBOX,"sFilelist",DEFAULT,DEFAULT,61,DEFAULT,DEFAULT,DEFAULT,DEFAULT`
MyDialog051=`227,169,194,080,ITEMBOX,"sWorklist",DEFAULT,DEFAULT,67,DEFAULT,DEFAULT,DEFAULT,DEFAULT`
MyDialog052=`007,245,202,014,VARYTEXT,"sFilelist",DEFAULT,DEFAULT,42,DEFAULT,DEFAULT,"255|255|240",DEFAULT`
MyDialog053=`007,125,414,010,EDITBOX,"sWorkfile",DEFAULT,DEFAULT,71,DEFAULT,DEFAULT,DEFAULT,"255|255|240"`
MyDialog054=`037,037,008,012,CHECKBOX,"DLG_MODIFY_Title",DEFAULT,1,2,DEFAULT,DEFAULT,DEFAULT,DEFAULT`
MyDialog055=`037,051,008,012,CHECKBOX,"DLG_MODIFY_Artist",DEFAULT,1,3,DEFAULT,DEFAULT,DEFAULT,DEFAULT`
MyDialog056=`037,065,008,012,CHECKBOX,"DLG_MODIFY_Album",DEFAULT,1,4,DEFAULT,DEFAULT,DEFAULT,DEFAULT`
MyDialog057=`037,093,008,012,CHECKBOX,"DLG_MODIFY_Year",DEFAULT,1,6,DEFAULT,DEFAULT,DEFAULT,DEFAULT`
MyDialog058=`037,079,008,012,CHECKBOX,"DLG_MODIFY_Comment",DEFAULT,1,5,DEFAULT,DEFAULT,DEFAULT,DEFAULT`
MyDialog059=`177,093,008,012,CHECKBOX,"DLG_MODIFY_Reserved",DEFAULT,1,9,2,DEFAULT,DEFAULT,DEFAULT`
MyDialog060=`101,093,008,012,CHECKBOX,"DLG_MODIFY_Track",DEFAULT,1,8,DEFAULT,DEFAULT,DEFAULT,DEFAULT`
MyDialog061=`037,107,008,012,CHECKBOX,"DLG_MODIFY_Genre",DEFAULT,1,7,DEFAULT,DEFAULT,DEFAULT,DEFAULT`
MyDialog062=`401,043,006,006,PUSHBUTTON,DEFAULT,DEFAULT,81,42,DEFAULT,"MS Sans Serif|5632|40|34","0|0|0","255|0|128"`
MyDialog063=`401,057,006,006,PUSHBUTTON,DEFAULT,DEFAULT,82,44,DEFAULT,"MS Sans Serif|5632|40|34","0|0|0","255|0|128"`
MyDialog064=`401,071,006,006,PUSHBUTTON,DEFAULT,DEFAULT,83,46,DEFAULT,"MS Sans Serif|5632|40|34","0|0|0","255|0|128"`
MyDialog065=`401,085,006,006,PUSHBUTTON,DEFAULT,DEFAULT,84,48,DEFAULT,"MS Sans Serif|5632|40|34","0|0|0","255|0|128"`
MyDialog066=`265,099,006,006,PUSHBUTTON,DEFAULT,DEFAULT,85,50,DEFAULT,"MS Sans Serif|5632|40|34","0|0|0","255|0|128"`
MyDialog067=`337,099,006,006,PUSHBUTTON,DEFAULT,DEFAULT,86,52,DEFAULT,"MS Sans Serif|5632|40|34","0|0|0","255|0|128"`
MyDialog068=`401,099,006,006,PUSHBUTTON,DEFAULT,DEFAULT,87,54,DEFAULT,"MS Sans Serif|5632|40|34","0|0|0","255|0|128"`
MyDialog069=`401,113,006,006,PUSHBUTTON,DEFAULT,DEFAULT,88,56,DEFAULT,"MS Sans Serif|5632|40|34","0|0|0","255|0|128"`
MyDialog070=`401,037,006,006,PUSHBUTTON,DEFAULT,DEFAULT,91,41,DEFAULT,"MS Sans Serif|5632|40|34","0|0|0","128|0|255"`
MyDialog071=`401,051,006,006,PUSHBUTTON,DEFAULT,DEFAULT,92,43,DEFAULT,"MS Sans Serif|5632|40|34","0|0|0","128|0|255"`
MyDialog072=`401,065,006,006,PUSHBUTTON,DEFAULT,DEFAULT,93,45,DEFAULT,"MS Sans Serif|5632|40|34","0|0|0","128|0|255"`
MyDialog073=`401,079,006,006,PUSHBUTTON,DEFAULT,DEFAULT,94,47,DEFAULT,"MS Sans Serif|5632|40|34","0|0|0","128|0|255"`
MyDialog074=`265,093,006,006,PUSHBUTTON,DEFAULT,DEFAULT,95,49,0,"MS Sans Serif|5632|40|34","0|0|0","128|0|255"`
MyDialog075=`337,093,006,006,PUSHBUTTON,DEFAULT,DEFAULT,96,51,DEFAULT,"MS Sans Serif|5632|40|34","0|0|0","128|0|255"`
MyDialog076=`401,093,006,006,PUSHBUTTON,DEFAULT,DEFAULT,97,53,DEFAULT,"MS Sans Serif|5632|40|34","0|0|0","128|0|255"`
MyDialog077=`401,107,006,006,PUSHBUTTON,DEFAULT,DEFAULT,98,55,DEFAULT,"MS Sans Serif|5632|40|34","0|0|0","128|0|255"`
MyDialog078=`185,025,018,010,PUSHBUTTON,DEFAULT,"Set",102,10,0,"MS Sans Serif|5632|40|34","0|0|0","255|255|240"`
MyDialog079=`203,025,018,010,PUSHBUTTON,DEFAULT,"Clear",103,11,0,"MS Sans Serif|5632|40|34","0|0|0","255|255|240"`
MyDialog080=`159,027,024,008,STATICTEXT,DEFAULT,"Modif&y all",DEFAULT,11,DEFAULT,DEFAULT,"255|255|240",DEFAULT`
MyDialog081=`007,135,034,008,VARYTEXT,"DLG_ID3_TAGEXIST",DEFAULT,DEFAULT,42,DEFAULT,DEFAULT,"0|255|255",DEFAULT`
MyDialog082=`229,159,040,008,CHECKBOX,"DLG_BATCHMODE","&Batch Mode",1,68,DEFAULT,DEFAULT,"255|255|240",DEFAULT`
MyDialog083=`209,171,016,012,PUSHBUTTON,DEFAULT,"Play",4,66,32,"MS Sans Serif|5632|40|34","255|255|255","0|0|0"`
MyDialog084=`211,201,012,012,PUSHBUTTON,DEFAULT,">>",52,63,DEFAULT,"System|6656|70|34","0|0|0",DEFAULT`
MyDialog085=`211,231,012,012,PUSHBUTTON,DEFAULT,"<<",62,65,DEFAULT,"System|6656|70|34","0|0|0",DEFAULT`
MyDialog086=`399,245,024,008,VARYTEXT,"WORKCOUNT",DEFAULT,DEFAULT,78,DEFAULT,"Courier New|5632|40|49","255|255|240",DEFAULT`
MyDialog087=`389,157,016,010,PUSHBUTTON,DEFAULT,"Open",111,69,0,"MS Sans Serif|5632|40|34","255|255|255","0|128|128"`
MyDialog088=`405,157,016,010,PUSHBUTTON,DEFAULT,"Save",112,70,0,"MS Sans Serif|5632|40|34","255|255|255","0|128|128"`
MyDialog089=`385,025,016,010,PUSHBUTTON,DEFAULT,"Open",121,57,0,"MS Sans Serif|5632|40|34","255|255|255","0|128|128"`
MyDialog090=`401,025,016,010,PUSHBUTTON,DEFAULT,"Save",122,58,0,"MS Sans Serif|5632|40|34","255|255|255","0|128|128"`
MyDialog091=`037,027,042,008,CHECKBOX,"DLG_MODIFY_RemoveTag","Remo&ve Tag",131,1,2,DEFAULT,"255|255|240",DEFAULT`
MyDialog092=`101,027,036,008,CHECKBOX,"DLG_MODIFY_ReadOnly","Read &Only",132,1,0,DEFAULT,"255|255|240",DEFAULT`
MyDialog093=`209,249,038,012,PUSHBUTTON,DEFAULT,"File Properties",5,66,0,"MS Sans Serif|5632|40|34","255|255|255","0|0|0"`
MyDialogButtonPushed=Dialog("MyDialog")
#EndSubRoutine
;------------------------------------------------------------------------------------------------------------------------------------------




;------------------------------------------------------------------------------------------------------------------------------------------
; --- MAIN --- starts here ---
;------------------------------------------------------------------------------------------------------------------------------------------
BoxOpen("ID3v1 Tagging Monster  v1.01  20030202  (c)20030123 Detlev Dalitz","Loading ...")
BoxText("Initializing ...")
;..........................................................................................................................................
SECTION_MEMO_TITLE       = "ID3V1 MEMO TITLE"
SECTION_MEMO_ARTIST      = "ID3V1 MEMO ARTIST"
SECTION_MEMO_ALBUM       = "ID3V1 MEMO ALBUM"
SECTION_MEMO_COMMENT     = "ID3V1 MEMO COMMENT"
SECTION_MEMO_YEAR        = "ID3V1 MEMO YEAR"
SECTION_MEMO_RESERVED    = "ID3V1 MEMO RESERVED"
SECTION_MEMO_TRACK       = "ID3V1 MEMO TRACK"
SECTION_MEMO_GENRE       = "ID3V1 MEMO GENRE"
SECTION_GENRE_PREDEFINED = "ID3V1 GENRE PREDEFINED"
;..........................................................................................................................................
ID3_Genre_Min = 0
ID3_Genre_Max = 255
ID3_Track_Min = 0
ID3_Track_Max = 255
ID3_Reserved_Min = 0
ID3_Reserved_Max = 255
;..........................................................................................................................................
sTempFolder = Environment("temp")
sFilenameMemo  = StrCat(sTempFolder,"\ID3V1.MEMO.EMPTY.INI")
sFilenameGenre = StrCat(sTempFolder,"\ID3V1.GENRE.INI")
sSectionGenrePredefined = "ID3V1 GENRE PREDEFINED"
sFilelist = "*.mp3"
sWorkList = ""
;..........................................................................................................................................
@NOTAVAILABLE = "*N/A*"
DLG_GENRE_DEFINED_NO  = @NOTAVAILABLE
DLG_GENRE_DEFINED_YES = ""
DLG_TAGEXIST_NO  = "[No Tag]"
DLG_TAGEXIST_YES = ""
DLG_READONLY_NO  = 0
DLG_READONLY_YES = 1
;..........................................................................................................................................
hBBID3 = BinaryAlloc(128) ; The ID3 Tag binary buffer.
;..........................................................................................................................................
; Inits for the Dialog.
udsInit_DLG_MODIFY ()
udsInit_DLG_MEMO()
udsInit_DLG_ID3()
DLG_ID3_Genre = "-1|256|1"
;..........................................................................................................................................
;udsDefineDialogConstants ()
AddExtender("DLGC34I.DLL") ; Load Alan Kreutzer's Extender containing my Dialog Constants.
BoxText(StrCat("Using Dialog Constants, Version ",dlgcversion()))
TimeDelay(1)
udsDefineMyControls ()
;..........................................................................................................................................
BoxShut()
WinHide("")
;..........................................................................................................................................
IntControl (49,1,0,0,0) ; Add system menu to dialog window.
udsDefineMyDialog()
;..........................................................................................................................................
:CANCEL
BoxShut()
BinaryFree(hBBID3)
udsReleaseDroplistHash()
Exit
;------------------------------------------------------------------------------------------------------------------------------------------
;*EOF*