-
Notifications
You must be signed in to change notification settings - Fork 13
/
namDHC.ahk
2527 lines (2083 loc) · 96.1 KB
/
namDHC.ahk
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#singleInstance off
#noEnv
#Persistent
detectHiddenWindows On
setTitleMatchmode 3
SetWorkingDir %a_ScriptDir%
#Include SelectFolderEx.ahk
#Include ClassImageButton.ahk
#Include ConsoleClass.ahk
#Include JSON.ahk
VER_HISTORY =
(
v1.00
- Initial release
v1.01
- Added ISO input media support
- Minor fixes
v1.02
- Removed superfluous code
- Some spelling mistakes fixed
- Minor GUI changes
v1.03
- Fixed Cancel all jobs button
- Fixed output folder editfield allowing invalid characters
- Fixed files only being removed from listview after successful operation (when selected)
- Minor GUI bugs fixed
- GUI changes
- Added time elapsed to report
- Changed about window
v1.05
- Added update functionality
- GUI changes
- More GUI changes
- Fixed issue extracting or creating all formats instead of selected
- Fixed JSON issues
- Bug fixes
v1.06
- Allows creation of multiple formats during a single job.
Formats will be added to the file and directory names in parenthesis.
Example of files from a PSX game with both TOC and CUE formats selected for output:
PSXGAME (TOC).toc
PSXGAME (TOC).bin
PSXGAME (CUE).bin
PSXGAME (CUE).cue
- User will be prompted to rename any duplicate output files
- Changed the finished job sound to play media instead of just beeps
- Fixed main menu not hiding during job processes
- Updater wont automatically update even when selecting no
- Bugfixes, GUI changes n' stuff
v1.07
- Added zip file support
NOTE: Folders & multiple formats within zip files are unsupported.
namDHC will only uncompress the first supported file that it finds within in each zipfile
- Changed quit routine
- Changed error handling for output chd files that already exist
- Changed file read functions
- Fixed namDHC won't ask about duplicate files when verifying or getting info from CHD's
- Fixed Folder and file browsing shows input extensions that aren't actually selected
- Fixed timeout monitoring
- Fixed some race conditions
- GUI changes n' stuff
- Changed JSON library again (hopefully last time)
- Having issues with script pausing/hanging after cancel command is sent to thread
v1.08
- Fixed Verify option
- No need to hit enter to confirm a new output folder
- Limit output folder name to 255 characters
- Removed Add/Remove metadata indefinitely
v1.09
- Fixed select output folder button not launching explorer window
- Fixed sometimes showing multiple jobs in one progress slot
- Re-enabled Autohotkey 'speedups'
- Fixed line character being misrepresented in report
v1.10
- Possible fix crashing and slowdown on some machines (Removed Autohotkey speedups :P)
- Fixed namDHC sometimes deleting the output file if it already existed
- Fixed a possible chdman timeout issue
- Fixed reporting to not show old reports from previous jobs
v1.11
- Possible crash fixes (?)
- Fixed zip files not being cleared from list after a successful job
- Slight speed improvement and (hopefully) improved reliability when cancelling jobs
v1.12
- Added an option to force no DPI scaling for people who are having issues with options being cut off in window (Thanks TFWol)
- Fixed quit routine
v1.13
- Final report shows size savings when compressing to CHD
- Fixed output folder being cleared if cancel was clicked in the select folder helper
- Removed close button on console windows
- Some cleanup
)
; Default global values
; ---------------------
CURRENT_VERSION := "1.13"
CHECK_FOR_UPDATES_STARTUP := "yes"
CHDMAN_FILE_LOC := a_scriptDir "\chdman.exe"
DIR_TEMP := a_Temp "\namDHC"
CHDMAN_VERSION_ARRAY := ["0.239", "0.240", "0.241", "0.249"]
GITHUB_REPO_URL := "https://api.github.com/repos/umageddon/namDHC/releases/latest"
APP_MAIN_NAME := "namDHC"
APP_VERBOSE_NAME := APP_MAIN_NAME " - Verbose"
APP_RUN_JOB_NAME := APP_MAIN_NAME " - Job"
APP_RUN_CHDMAN_NAME := APP_RUN_JOB_NAME " - chdman"
APP_RUN_CONSOLE_NAME := APP_RUN_JOB_NAME " - Console"
APP_NO_DPI_SCALE := "no"
TIMEOUT_SEC := 20
WAIT_TIME_CONSOLE_SEC := 1
JOB_QUEUE_SIZE := 3
JOB_QUEUE_SIZE_LIMIT := 10
OUTPUT_FOLDER := a_workingDir
PLAY_SONG_FINISHED := "yes"
REMOVE_FILE_ENTRY_AFTER_FINISH := "yes"
SHOW_JOB_CONSOLE := "no"
SHOW_VERBOSE_WINDOW := "no"
APP_VERBOSE_WIN_HEIGHT := 400
APP_VERBOSE_WIN_WIDTH := 800
APP_VERBOSE_WIN_POS_X := 775
APP_VERBOSE_WIN_POS_Y := 150
APP_MAIN_WIN_POS_X := 800
APP_MAIN_WIN_POS_Y := 100
; Read ini to write over globals if changed previously
;-------------------------------------------------------------
ini("read"
,["JOB_QUEUE_SIZE","OUTPUT_FOLDER","SHOW_JOB_CONSOLE","SHOW_VERBOSE_WINDOW","PLAY_SONG_FINISHED","REMOVE_FILE_ENTRY_AFTER_FINISH", "APP_NO_DPI_SCALE"
,"APP_MAIN_WIN_POS_X","APP_MAIN_WIN_POS_Y","APP_VERBOSE_WIN_WIDTH","APP_VERBOSE_WIN_HEIGHT","APP_VERBOSE_WIN_POS_X","APP_VERBOSE_WIN_POS_Y","CHECK_FOR_UPDATES_STARTUP"])
if ( !fileExist(CHDMAN_FILE_LOC) ) {
msgbox 16, % "Fatal Error", % "CHDMAN.EXE not found!`n`nMake sure the chdman executable is located in the same directory as namDHC and try again.`n`nThe following chdman verions are supported:`n" arrayToString(CHDMAN_VERSION_ARRAY)
exitApp
}
; Run a chdman thread
; Will be called when running chdman - As to allow for a one file executable
;-------------------------------------------------------------
if ( a_args[1] == "threadMode" ) {
#include threads.ahk
}
; Kill all processes so only one instance is running
;-------------------------------------------------------------
killAllProcess()
; Set working job variables
;-------------------------------------------------------------
job := {workTally:{}, msgData:[], availPSlots:[], workQueue:[], scannedFiles:{}, queuedMsgData:[], InputExtTypes:[], OutputExtType:[], selectedOutputExtTypes:[], selectedInputExtTypes:[]}
; Set GUI variables
;-------------------------------------------------------------
GUI := { chdmanOpt:{}, dropdowns:{job:{}, media:{}}, buttons:{normal:[], hover:[], clicked:[], disabled:[]}, menu:{namesOrder:[], File:[], Settings:[], About:[]} }
GUI.dropdowns.job := { create: {pos:1,desc:"Create CHD files from media"}
,extract: {pos:2,desc:"Extract images from CHD files"}
,info: {pos:3, desc:"Get info from CHD files"}
,verify: {pos:4, desc:"Verify CHD files"}}
/*
,addMeta: {pos:5, desc:"Add metadata to CHD files"}
,delMeta: {pos:6, desc:"Delete metadata from CHD files"}
*/
GUI.dropdowns.media := { cd:"CD image", hd:"Hard disk image", ld:"LaserDisc image", raw:"Raw image" }
GUI.buttons.default := {normal:[0, 0xFFCCCCCC, "", "", 3], hover:[0, 0xFFBBBBBB, "", 0xFF555555, 3], clicked:[0, 0xFFCFCFCF, "", 0xFFAAAAAA, 3], disabled:[0, 0xFFE0E0E0, "", 0xFFAAAAAA, 3] }
GUI.buttons.cancel := {normal:[0, 0xFFFC6D62, "", "White", 3], hover:[0, 0xFFff8e85, "", "White", 3], clicked:[0, 0xFFfad5d2, "", "White", 3], disabled:[0, 0xFFfad5d2, "", "White", 3]}
GUI.buttons.start := {normal:[0, 0xFF74b6cc, "", 0xFF444444, 3], hover:[0, 0xFF84bed1, "", "White", 3], clicked:[0, 0xFFa5d6e6, "", "White", 3], disabled:[0, 0xFFd3dde0, "", 0xFF888888, 3] }
; Set menu variables
;-------------------------------------------------------------
GUI.menu["namesOrder"] := ["File", "Settings", "About"]
GUI.menu.File[1] := {name:"Quit", gotolabel:"quitApp", saveVar:""}
GUI.menu.About[1] := {name:"About", gotolabel:"menuSelected", saveVar:""}
GUI.menu.Settings[1] := {name:"Check for updates automatically", gotolabel:"menuSelected", saveVar:"CHECK_FOR_UPDATES_STARTUP"}
GUI.menu.Settings[2] := {name:"Number of jobs to run concurrently", gotolabel:":SubSettingsConcurrently", saveVar:""}
GUI.menu.Settings[3] := {name:"Show a verbose window", gotolabel:"menuSelected", saveVar:"SHOW_VERBOSE_WINDOW", Fn:"showVerbose"}
GUI.menu.Settings[4] := {name:"Show a console window for each new job", gotolabel:"menuSelected", saveVar:"SHOW_JOB_CONSOLE"}
GUI.menu.Settings[5] := {name:"Play a sound when finished jobs", gotolabel:"menuSelected", saveVar:"PLAY_SONG_FINISHED"}
GUI.menu.Settings[6] := {name:"Remove file entry from list on success", gotolabel:"menuSelected", saveVar:"REMOVE_FILE_ENTRY_AFTER_FINISH"}
GUI.menu.Settings[7] := {name:"No DPI scaling - May help with cut off options", gotolabel:"menuSelected", saveVar:"APP_NO_DPI_SCALE", Fn: "msgNeedARestart"}
; misc GUI variables
;-------------------------------------------------------------
GUI.HDtemplate := { ddList: "" ; Hard drive template dropdown list
. "|Conner CFA170A - 163MB||"
. "Rodime R0201 - 5MB|"
. "Rodime R0202 - 10MB|"
. "Rodime R0203 - 15MB|"
. "Rodime R0204 - 20MB|"
. "Seagate ST-213 - 10MB|"
. "Segate ST-225 - 20MB|"
. "Seagate ST-251 - 40MB|"
. "Seagate ST-3600N - 487MB|"
. "Maxtor LXT-213S - 238MB|"
. "Maxtor LXT-340S - 376MB|"
. "Maxtor MXT-540SL - 733MB|"
. "Micropolis 1528 - 1272MB|"
, values : [0,1,2,3,4,5,6,7,8,9,10,11,12]}
GUI.CPUCores := procCountDDList()
/*
GUI CHDMAN options
Format:
;-------------------------------------------------------------
name: String - Friendly name of option - used as a reference
paramString: String - String used in actual chdman command
description: String - String used to describe option in the GUI
editField: String - Creates an editfield for the option containting the string supplied
- useQuotes: Boolean - TRUE will add quotes around the users editfield when submitting to chdman - only used with editField
dropdownOptions: String - Creates a dropdown with the options supplied. Must be in autohotkey format (ie- seperated by '|')
- dropdownValues: Array - Used with dropdownOptions - Supplies a different set of values to submit when selecting a dropdown option
hidden: Boolean - TRUE to hide the option in the GUI
masterOf: String - Supply the element name this 'masters over' - the 'subordinate' option will only be enabled when this option is checked
xInset: Number - Number to pixels move option right in the GUI
checked: Boolean - TRUE if checkbox is checked by default
*/
GUI.chdmanOpt.force := {name: "force", paramString: "f", description: "Force overwriting an existing output file"}
GUI.chdmanOpt.verbose := {name: "verbose", paramString: "v", description: "Verbose output", hidden: true}
GUI.chdmanOpt.outputBin := {name: "outputbin", paramString: "ob", description: "Output filename for binary data", editField: "filename.bin", useQuotes:true}
GUI.chdmanOpt.inputParent := {name: "inputparent", paramString: "ip", description: "Input Parent", editField: "filename.ext", useQuotes:true}
GUI.chdmanOpt.inputStartFrame := {name: "inputstartframe", paramString: "isf", description: "Input Start Frame", editField: 0}
GUI.chdmanOpt.inputFrames := {name: "inputframes", paramString: "if", description: "Effective length of input in frames", editField: 0}
GUI.chdmanOpt.inputStartByte := {name: "inputstartbyte", paramString: "isb", description: "Starting byte offset within the input", editField: 0}
GUI.chdmanOpt.outputParent := {name: "outputparent", paramString: "op", description: "Output parent file for CHD", editField: "filename.chd", useQuotes:true}
GUI.chdmanOpt.hunkSize := {name: "hunksize", paramString: "hs", description: "Size of each hunk (in bytes)", editField: 19584}
GUI.chdmanOpt.inputStartHunk := {name: "inputstarthunk", paramString: "ish", description: "Starting hunk offset within the input", editField: 0}
GUI.chdmanOpt.inputBytes := {name: "inputBytes", paramString: "ib", description: "Effective length of input (in bytes)", editField: 0}
GUI.chdmanOpt.compression := {name: "compression", paramString: "c", description: "Compression codecs to use", editField: "cdlz,cdzl,cdfl"}
GUI.chdmanOpt.inputHunks := {name: "inputhunks", paramString: "ih", description: "Effective length of input (in hunks)", editField: 0}
GUI.chdmanOpt.numProcessors := {name :"numprocessors", paramString: "np", description: "Max number of CPU threads to use", dropdownOptions: GUI.CPUCores}
GUI.chdmanOpt.template := {name: "template", paramString: "tp", description: "Hard drive template to use", dropdownOptions: GUI.HDtemplate.ddList, dropdownValues:GUI.HDtemplate.values}
GUI.chdmanOpt.chs := {name: "chs", paramString: "chs", description: "CHS Values [cyl, heads, sectors]", editField: "332,16,63"}
GUI.chdmanOpt.ident := {name: "ident", paramString: "id", description: "Name of ident file for CHS info", editField: "filename.chs", useQuotes:true}
GUI.chdmanOpt.size := {name: "size", paramString: "s", description: "Size of output file (in bytes)", editField: 0}
GUI.chdmanOpt.unitSize := {name: "unitsize", paramString: "us", description: "Size of each unit (in bytes)", editField: 0}
GUI.chdmanOpt.sectorSize := {name: "sectorsize", paramString: "ss", description: "Size of each hard disk sector (in bytes)", editField: 512}
GUI.chdmanOpt.deleteInputFiles := {name: "deleteInputFiles", description: "Delete input files after completing job", masterOf: "deleteInputDir"}
GUI.chdmanOpt.deleteInputDir := {name: "deleteInputDir", description: "Also delete input directory (if empty)", xInset:10}
GUI.chdmanOpt.createSubDir := {name: "createSubDir", description: "Create a directory for each job"}
GUI.chdmanOpt.keepIncomplete := {name: "keepIncomplete", description: "Keep failed or cancelled output files"}
; Create Main GUI and its elements
;-------------------------------------------------------------
createMainGUI()
createProgressBars()
createMenus()
showVerbose(SHOW_VERBOSE_WINDOW) ; Check or uncheck item "Show verbose window" and show the window
selectJob() ; Select 1st selection in job dropdown list and trigger refreshGUI()
if ( CHECK_FOR_UPDATES_STARTUP == "yes" )
checkForUpdates()
onMessage(0x03, "moveGUIWin") ; If windows are moved, save positions in moveGUIWin()
sleep 25 ; Needed (?) to allow window to be detected
mainAppHWND := winExist(APP_MAIN_NAME)
log(APP_MAIN_NAME " ready.")
return
;-------------------------------------------------------------------------------------------------------------------------
; A Menu item was selected
;-------------------------------------------------------------
menuSelected()
{
global
local selMenuObj, varName, fn
switch a_ThisMenu {
case "SettingsMenu":
selMenuObj := GUI.menu.settings[a_ThisMenuItemPos] ; Reference menu setting
varName := selMenuObj.saveVar ; Get variable name
%varName% := (%varName% == "no")? "yes":"no" ; Toggle variable setting
menu, SettingsMenu, % ((%varName% == "yes")? "Check":"UnCheck"), % selMenuObj.name ; Check or uncheck in menu
ini("write", varName) ; Write new setting
if ( isFunc(selMenuObj.Fn) ) { ; Check if function needs to be called
fn := selMenuObj.Fn
%fn%(%varName%) ; Call function
}
case "SubSettingsConcurrently": ; Menu: Settings: User selected number of jobs to run concurrently
loop % JOB_QUEUE_SIZE_LIMIT ; Uncheck all
menu, SubSettingsConcurrently, UnCheck, % a_index
menu, SubSettingsConcurrently, Check, % A_ThisMenuItemPos ; Check selected
JOB_QUEUE_SIZE := A_ThisMenuItemPos ; Set variable
ini("write", "JOB_QUEUE_SIZE")
log("Saved JOB_QUEUE_SIZE")
case "AboutMenu": ; Menu: About
guiToggle("disable", "all")
gui 1:+OwnDialogs
gui 4: destroy
gui 4: margin, 20 20
gui 4: font, s15 Q5 w700 c000000
gui 4: add, text, x10 y10, % APP_MAIN_NAME
gui 4: font, s10 Q5 w700 c000000
gui 4: add, text, x100 y17, % " v" CURRENT_VERSION
gui 4: font, s10 Q5 w400 c000000
gui 4: add, text, x10 y35, % "A Windows frontend for the MAME CHDMAN tool"
gui 4: add, button, x10 y65 w130 h22 gcheckForUpdates, % "Check for updates"
gui 4: add, text, x10 y100, % "History"
gui 4: add, edit, x10 y120 h200 w775, % VER_HISTORY
gui 4: add, link, x10 y340, Github: <a href="https://github.com/umageddon/namDHC">https://github.com/umageddon/namDHC</a>
gui 4: add, link, x10 y360, MAME Info: <a href="https://www.mamedev.org/">https://www.mamedev.org/</a>
gui 4: font, s9 Q5 w400 c000000
gui 4: add, text, x10 y390, % "(C) Copyright 2022 Umageddon"
gui 4: show, w800 center, About
Gui 4:+LastFound +AlwaysOnTop +ToolWindow
controlFocus,, About ; Removes outline around html anchor
return
}
}
4GuiClose()
{
gui 4:destroy
refreshGUI()
return
}
msgNeedARestart() {
msgbox, 16, % "", % "You will need to restart to see any changes"
}
; Job selection
;-------------------------------------------------------------
selectJob()
{
global
gui 1:submit, nohide
gui 1:+ownDialogs
; Changes depending on job selected
switch dropdownJob {
case GUI.dropdowns.job.create.desc:
newStartButtonLabel := "CREATE CHD"
guiCtrl({dropdownMedia:"|" GUI.dropdowns.media.cd "|" GUI.dropdowns.media.hd "|" GUI.dropdowns.media.ld "|" GUI.dropdowns.media.raw})
case GUI.dropdowns.job.extract.desc:
newStartButtonLabel := "EXTRACT MEDIA"
guiCtrl({dropdownMedia:"|" GUI.dropdowns.media.cd "|" GUI.dropdowns.media.hd "|" GUI.dropdowns.media.ld "|" GUI.dropdowns.media.raw})
case GUI.dropdowns.job.info.desc:
newStartButtonLabel := "GET INFO"
guiCtrl({dropdownMedia:"|CHD Files"})
case GUI.dropdowns.job.verify.desc:
guiToggle("enable", "all")
newStartButtonLabel := "VERIFY CHD"
guiCtrl({dropdownMedia:"|CHD Files"})
case GUI.dropdowns.job.addMeta.desc:
newStartButtonLabel := "ADD METADATA"
guiCtrl({dropdownMedia:"|CHD Files"})
msgbox 64, % "", % "Option not implemented yet"
case GUI.dropdowns.job.delMeta.desc:
newStartButtonLabel := "DELETE METADATA"
guiCtrl({dropdownMedia:"|CHD Files"})
msgbox 64, % "", % "Option not implemented yet"
}
guiCtrl({buttonStartJobs:newStartButtonLabel}) ; New start button label to reflect new job
imageButton.create(startButtonHWND, GUI.buttons.start.normal, GUI.buttons.start.hover, GUI.buttons.start.clicked, GUI.buttons.start.disabled) ; Default button colors, must be set after changing button text
guiCtrl("choose", {dropdownMedia:"|1"}) ; Choose first item in media dropdown and fire the selection
}
; Media selection
;-------------------------------------------------------------
selectMedia()
{
global
local mediaSel, key, opt, val, idx, optNum, checkOpt, changeOpt, changeOptVal, ctrlY, x, y, gPos, file
local optPerSide:=9, ctrlH:=25
gui 1:submit, nohide
gui 1:+ownDialogs
; User selected media
switch dropdownMedia {
case GUI.dropdowns.media.cd: mediaSel := "cd"
case GUI.dropdowns.media.hd: mediaSel := "hd"
case GUI.dropdowns.media.ld: mediaSel := "ld"
case GUI.dropdowns.media.raw: mediaSel := "raw"
default: mediaSel := "chd"
}
; Assign job variables according to media
switch dropdownJob {
case GUI.dropdowns.job.create.desc: job.Cmd := "create" mediaSel, job.Desc := "Create CHD from a " stringUpper(mediaSel) " image", job.FinPreTxt := "Jobs created"
case GUI.dropdowns.job.extract.desc: job.Cmd := "extract" mediaSel, job.Desc := "Extract a " stringUpper(mediaSel) " image from CHD", job.FinPreTxt := "Jobs extracted"
case GUI.dropdowns.job.info.desc: job.Cmd := "info", job.Desc := "Get info from CHD", job.FinPreTxt := "Read info from jobs"
case GUI.dropdowns.job.verify.desc: job.Cmd := "verify", job.Desc := "Verify CHD", job.FinPreTxt := "Jobs verified"
case GUI.dropdowns.job.addMeta.desc: job.Cmd := "addmeta", job.Desc := "Add Metadata to CHD", job.FinPreTxt := "Jobs with metadata added to"
case GUI.dropdowns.job.delMeta.desc: job.Cmd := "delmeta", job.Desc := "Delete Metadata from CHD", job.FinPreTxt := "Jobs with metadata deleted from"
}
; Assign rest of job variables according to job
switch job.Cmd {
case "extractcd": job.InputExtTypes := ["chd"], job.OutputExtTypes := ["cue", "toc", "gdi"], job.Options := [GUI.chdmanOpt.force, GUI.chdmanOpt.createSubDir, GUI.chdmanOpt.deleteInputFiles, GUI.chdmanOpt.keepIncomplete, GUI.chdmanOpt.outputBin, GUI.chdmanOpt.inputParent]
case "extractld": job.InputExtTypes := ["chd"], job.OutputExtTypes := ["raw"], job.Options := [GUI.chdmanOpt.force, GUI.chdmanOpt.createSubDir, GUI.chdmanOpt.deleteInputFiles, GUI.chdmanOpt.keepIncomplete, GUI.chdmanOpt.inputParent, GUI.chdmanOpt.inputStartFrame, GUI.chdmanOpt.inputFrames]
case "extracthd": job.InputExtTypes := ["chd"], job.OutputExtTypes := ["img"], job.Options := [GUI.chdmanOpt.force, GUI.chdmanOpt.createSubDir, GUI.chdmanOpt.deleteInputFiles, GUI.chdmanOpt.keepIncomplete, GUI.chdmanOpt.inputParent, GUI.chdmanOpt.inputStartByte, GUI.chdmanOpt.inputStartHunk, GUI.chdmanOpt.inputBytes, GUI.chdmanOpt.inputHunks]
case "extractraw": job.InputExtTypes := ["chd"], job.OutputExtTypes := ["img", "raw"], job.Options := [GUI.chdmanOpt.force, GUI.chdmanOpt.createSubDir, GUI.chdmanOpt.deleteInputFiles, GUI.chdmanOpt.keepIncomplete, GUI.chdmanOpt.inputParent, GUI.chdmanOpt.inputStartByte, GUI.chdmanOpt.inputStartHunk, GUI.chdmanOpt.inputBytes, GUI.chdmanOpt.inputHunks]
case "createcd": job.InputExtTypes := ["cue", "toc", "gdi", "iso", "zip"], job.OutputExtTypes := ["chd"], job.Options := [GUI.chdmanOpt.force, GUI.chdmanOpt.createSubDir, GUI.chdmanOpt.deleteInputFiles, GUI.chdmanOpt.deleteInputDir, GUI.chdmanOpt.keepIncomplete, GUI.chdmanOpt.numProcessors, GUI.chdmanOpt.outputParent, GUI.chdmanOpt.hunkSize, GUI.chdmanOpt.compression]
case "createld": job.InputExtTypes := ["raw", "zip"], job.OutputExtTypes := ["chd"], job.Options := [GUI.chdmanOpt.force, GUI.chdmanOpt.createSubDir, GUI.chdmanOpt.deleteInputFiles, GUI.chdmanOpt.deleteInputDir, GUI.chdmanOpt.keepIncomplete, GUI.chdmanOpt.numProcessors, GUI.chdmanOpt.outputParent, GUI.chdmanOpt.inputStartFrame, GUI.chdmanOpt.inputFrames, GUI.chdmanOpt.hunkSize, GUI.chdmanOpt.compression]
case "createhd": job.InputExtTypes := ["img", "zip"], job.OutputExtTypes := ["chd"], job.Options := [GUI.chdmanOpt.force, GUI.chdmanOpt.createSubDir, GUI.chdmanOpt.deleteInputFiles, GUI.chdmanOpt.deleteInputDir, GUI.chdmanOpt.keepIncomplete, GUI.chdmanOpt.numProcessors, GUI.chdmanOpt.compression, GUI.chdmanOpt.outputParent, GUI.chdmanOpt.size, GUI.chdmanOpt.inputStartByte, GUI.chdmanOpt.inputStartHunk, GUI.chdmanOpt.inputBytes, GUI.chdmanOpt.inputHunks, GUI.chdmanOpt.hunkSize, GUI.chdmanOpt.ident, GUI.chdmanOpt.template, GUI.chdmanOpt.chs, GUI.chdmanOpt.sectorSize]
case "createraw": job.InputExtTypes := ["img", "raw", "zip"], job.OutputExtTypes := ["chd"], job.Options := [GUI.chdmanOpt.force, GUI.chdmanOpt.createSubDir, GUI.chdmanOpt.deleteInputFiles, GUI.chdmanOpt.deleteInputDir, GUI.chdmanOpt.keepIncomplete, GUI.chdmanOpt.numProcessors, GUI.chdmanOpt.outputParent, GUI.chdmanOpt.inputStartByte, GUI.chdmanOpt.inputStartHunk, GUI.chdmanOpt.inputBytes, GUI.chdmanOpt.inputHunks, GUI.chdmanOpt.hunkSize, GUI.chdmanOpt.unitSize, GUI.chdmanOpt.compression]
case "info": job.InputExtTypes := ["chd", "zip"], job.OutputExtTypes := [], job.Options := []
case "verify": job.InputExtTypes := ["chd", "zip"], job.OutputExtTypes := [], job.Options := []
case "addmeta": job.InputExtTypes := ["chd"], job.OutputExtTypes := [], job.Options := []
case "delmeta": job.InputExtTypes := ["chd"], job.OutputExtTypes := [], job.Options := []
}
; Hide and uncheck ALL options
for key, opt in GUI.chdmanOpt {
guiToggle("hide", [opt.name "_checkbox", opt.name "_edit", opt.name "_dropdown"])
guiCtrl({(opt.name "_checkbox"):0})
}
; Show checkbox options depending on media selected
if ( job.Options.length() ) {
guiToggle("show", "groupboxOptions")
gPos := guiGetCtrlPos("groupboxOptions") ; Assign x & y values to groupbox x & y positions
idx := 0, ctrlY := 0, x := gPos.x+10, y := gPos.y
for optNum, opt in job.Options { ; Show appropriate options according to selected type of job and media type
if ( !opt || opt.hidden )
continue
if ( idx == optPerSide ) ; We've run out of vertical room to show more chdman options so new options go into next column
x += 400, y := gPos.y, ctrlY := 1, idx := 0 ; Set initial control/checkbox positions
else
ctrlY++, idx++ ; Add to Y position for next control
checkOpt := opt.name "_checkbox"
guiCtrl({(checkOpt):" " (opt.description? opt.description : opt.name)}) ; Label the checkbox -- Default to using the chdman opt.name parameter if no description
guiCtrl("moveDraw", {(checkOpt):"x" x + (opt.xInset? opt.xInset:0) " y" y+(ctrlY*ctrlH)}) ; Move the chdman checkbox
if ( opt.hasKey("editField") ) { ; The option can have either a dropdown or editfield
changeOpt := opt.name "_edit"
guiCtrl({(changeOpt):opt.editField}) ; Populate editfield from GUI.chdmanOpt array
}
else if ( opt.hasKey("dropdownOptions") ) {
changeOpt := opt.name "_dropdown"
guiCtrl({(changeOpt):opt.dropdownOptions}) ; Populate option dropdown from GUI.chdmanOpt array
}
guiCtrl("moveDraw", {(changeOpt):"x" x+210 " y" y +(ctrlY*ctrlH)-3}) ; Move the option editfield or dropdown into place
guiToggle("show", [checkOpt, changeOpt]) ; Show the option and its coresponding editfield or dropdownlist
guiCtrl({(checkOpt):opt.checked ? 1:0}) ; Check it if by default it's on
}
guiCtrl("moveDraw", {groupboxOptions:"h" ceil((optNum >optPerSide ? optPerSide : optNum)*ctrlH)+30}) ; Resize options groupbox height to fit all options
}
else { ; If no options to show for this selection ...
guiToggle("hide", "groupboxOptions") ; ... then hide the groupbox
guiCtrl("moveDraw", {groupboxOptions:"h0"}) ; and resize the groupbox height for no options
}
; Reset extension menus
menuExtHandler(true)
; Populate listview
gui 1: listView, listViewInputFiles
LV_delete() ; Delete all listview entries
for idx, file in job.scannedFiles[job.Cmd]
LV_add("", file) ; Re-populate listview with scanned files
controlFocus, SysListView321, % APP_MAIN_NAME ; Focus on listview to stop one item being selected
refreshGUI()
}
; Refreshes GUI to reflect current settings
;-------------------------------------------------------------
refreshGUI()
{
global
local opt, key, optNum
static selectedJob
gui 1:submit, nohide
; By default, enable all elements
guiToggle("enable", "all")
; Show the main menu
toggleMainMenu("show")
; Changes to elements depending on job selected
switch dropdownJob {
case GUI.dropdowns.job.create.desc:
case GUI.dropdowns.job.extract.desc:
case GUI.dropdowns.job.info.desc:
guiToggle("disable", ["dropdownMedia", "buttonOutputExtType", "buttonInputExtType", "editOutputFolder", "buttonBrowseOutput"])
case GUI.dropdowns.job.verify.desc:
guiToggle("disable", ["dropdownMedia", "buttonOutputExtType", "buttonInputExtType", "editOutputFolder", "buttonBrowseOutput", "buttonBrowseOutput"])
case GUI.dropdowns.job.addMeta.desc:
guiToggle("disable", "all")
guiToggle("enable", "dropdownJob")
case GUI.dropdowns.job.delMeta.desc:
guiToggle("disable", "all")
guiToggle("enable", "dropdownJob")
}
; Enable chdman option checkboxes depending on job selected
for optNum, opt in job.Options
guiToggle("enable", opt.name "_checkbox")
; Checked option: enable or disable chdman option editfields, dropdowns or slave options
for optNum, opt in job.Options
guiToggle((guiCtrlGet(opt.name "_checkbox") ? "enable":"disable"), [opt.name "_dropdown", opt.name "_edit", opt.masterOf "_checkbox", opt.masterOf "_dropdown", opt.masterOf "_edit"]) ; If checked, enable or disable dropdown or editfields
; Hide progress bars, progress text & progress groupbox
guiToggle("hide", ["progressAll", "progressTextAll", "groupBoxProgress"])
loop % JOB_QUEUE_SIZE_LIMIT
guiToggle("hide", ["progress" a_index, "progressText" a_index, "progressCancelButton" a_index])
; Trigger listview() to refresh selection buttons
listViewInputFiles()
; Set status text
SB_SetText(job.scannedFiles[job.Cmd].length()? job.scannedFiles[job.Cmd].length() " jobs in the " stringUpper(job.Cmd) " queue. Ready to start!" : "Add files to the job queue to start", 1)
; Make sure main button is showing
guiToggle("hide", "buttonCancelAllJobs")
guiToggle("show", "buttonStartJobs")
guiToggle((job.scannedFiles[job.Cmd].length()>0 ? "enable":"disable"), ["buttonStartJobs", "buttonselectAllInputFiles"]) ; Enable start button if there are jobs in the listview
; Show and resize main GUI
gui 1:show, autosize x%APP_MAIN_WIN_POS_X% y%APP_MAIN_WIN_POS_Y%, % APP_MAIN_NAME
; Select main listview
gui 1: listView, listViewInputFiles
}
; User pressed input or output files button
; Show Ext menu
;-------------------------------------------------------------
buttonExtSelect()
{
switch a_guicontrol {
case "buttonInputExtType":
menu, InputExtTypes, Show, 873, 172 ; Hardcoded because x,y position returns from function are wonky
case "buttonOutputExtType":
menu, OutputExtTypes, Show, 873, 480
}
}
; User selected an extension from the input/output extension menu
;-------------------------------------------------------------
menuExtHandler(init:=false)
{
global job
if ( init == true ) { ; Create and populate extension menu lists
for idx, type in ["InputExtTypes", "OutputExtTypes"] {
menu, % type, deleteAll ; Clear all old Input & Output menu items
job["selected" type] := [] ; Clear global Array of selected Input & Output extensions
for idx2, ext in job[type] { ; Parse through job.InputExtTypes & job.OutputExtTypes
if ( !ext )
continue
menu, % type, add, % ext, % "menuExtHandler" ; Add extension item to the menu
if ( dropdownJob == GUI.dropdowns.job.extract.desc && type == "OutputExtTypes" && idx2 > 1 )
continue ; By default, only check one extension of the Output menu if we are extracting an image
else {
menu, % type, Check, % ext ; Otherwise, check all extension menu items
job["selected" type].push(ext) ; Then add it to the input & output global selected extension array
}
}
}
}
else if ( a_ThisMenu ) { ; An extension menu was selected
selectedExtList := "selected" strReplace(a_ThisMenu, "extTypes", "") "ExtTypes"
job[selectedExtList] := [] ; Re-build either of these Arrays: job.selectedOutputExtTypes[] or job.selectedInputExtTypes[]
switch a_ThisMenu { ; a_ThisMenu is either 'InputExtTypes' or 'OutputExtTypes'
case "OutputExtTypes": ; Only one output extension is allowed to be checked
;for idx, val in job.OutputExtTypes
;menu, OutputExtTypes, Uncheck, % val ; Uncheck all menu items,
;menu, OutputExtTypes, Check, % a_ThisMenuItem ; Then check what was clicked, so only one is ever checked
menu, OutputExtTypes, Togglecheck, % a_ThisMenuItem ; Toggle checking item
case "InputExtTypes":
menu, InputExtTypes, Togglecheck, % a_ThisMenuItem ; Toggle checking item
}
for idx, val in job[a_ThisMenu]
if ( isMenuChecked(a_ThisMenu, idx) ) {
job[selectedExtList].push(val) ; Add checked extension item(s) to the global array for reference later
}
if ( job[selectedExtList].length() == 0 ) {
menu, % a_ThisMenu, check, % a_ThisMenuItem ; Make sure at least one item is checked
job[selectedExtList].push(a_ThisMenuItem)
}
}
for idx, type in ["InputExtTypes", "OutputExtTypes"] ; Redraw input & output extension lists
guiCtrl({(type) "Text": arrayToString(job["selected" type])})
}
; Scan files and add to queue
;-------------------------------------------------------------
addFolderFiles()
{
global job, APP_MAIN_NAME
newFiles := [], extList := "", numAdded := 0
gui 1:submit, nohide
gui 1:+OwnDialogs
guiToggle("disable", "all")
if ( !isObject(job.scannedFiles[job.Cmd]) )
job.scannedFiles[job.Cmd] := []
switch ( a_GuiControl ) {
case "buttonAddFiles":
for idx, ext in job.selectedInputExtTypes
extList .= "*." ext "; "
fileSelectFile, newInputList, M3, % "::{20d04fe0-3aea-1069-a2d8-08002b30309d}", % "Select files", % extList
if ( !errorLevel )
loop, parse, newInputList, % "`n"
{
if ( a_index == 1 )
path := regExReplace(a_Loopfield, "\\$")
else
newFiles.push(path "\" a_Loopfield)
}
case "buttonAddFolder":
inputFolder := selectFolderEx("", "Select a folder containing " arrayToString(job.selectedInputExtTypes) " type files.", winExist(APP_MAIN_NAME))
if ( inputFolder.SelectedDir ) {
inputFolder := regExReplace(inputFolder.SelectedDir, "\\$")
for idx, thisExt in job.selectedInputExtTypes {
loop, Files, % inputFolder "\*." thisExt, FR
newFiles.push(a_LoopFileLongPath)
}
}
}
if ( newFiles.length() ) {
for idx, thisFile in newFiles {
addFile := true, msg := "", fileParts := splitPath(thisFile)
if ( !inArray(fileParts.ext, job.selectedInputExtTypes) )
addFile := false ;,msg := "Skip adding " thisFile " - Not a selected format"
else if ( inArray(thisFile, job.scannedFiles[job.Cmd]) )
addFile := false, msg := "Skip adding " thisFile " - Already in queue"
else if ( fileParts.ext == "zip" ) { ; If its a zipfile, check to see if user extensions are contained within it
addFile := false, msg := "Skip adding " thisFile " - No selected formats found in zipfile" ; By default we assume zipfile dosent cantain a selected format
for idx, fileInZip in readZipFile(thisFile) {
zipFileExt := splitPath(fileInZip).ext
if ( inArray(zipFileExt, job.selectedInputExtTypes) && zipFileExt <> "zip" ) { ; Only add file inside the zipfile if it is in the selected extension list and it's not another zipfile within a zipfile
addFile := true
continue
}
}
}
if ( addFile ) {
numAdded++
msg := "Adding " (fileInZip ? thisFile " --> " fileInZip : thisFile)
LV_add("", thisFile)
job.scannedFiles[job.Cmd].push(thisFile)
}
log(msg)
SB_SetText(msg, 1, 1)
}
}
reportQueuedFiles()
refreshGUI()
}
; The listview containting the current input files was clicked
;-------------------------------------------------------------
listViewInputFiles()
{
global
local suffx, idx, val
if ( a_guievent == "I" )
return
if ( LV_GetCount("S") > 0 ) {
suffx := (LV_GetCount("S") > 1) ? "s" : ""
guiCtrl({buttonRemoveInputFiles:"Remove file" suffx, buttonclearInputFiles:"Clear selection" suffx})
for idx, val in [4,6] ; Apply buttons 'Remove selections' and 'Clear selections' skin after changing text
imageButton.create(GUIbutton%val%, GUI.buttons.default.normal, GUI.buttons.default.hover, GUI.buttons.default.clicked, GUI.buttons.default.disabled) ; Default button colors
guiToggle("enable", ["buttonRemoveInputFiles", "buttonclearInputFiles"])
}
else
guiToggle("disable", ["buttonclearInputFiles", "buttonRemoveInputFiles"])
guiToggle((LV_GetCount()>0?"enable":"disable"), ["buttonselectAllInputFiles"])
}
; Select file(s) from current input listview
; ------------------------------------------
selectInputFiles()
{
global job
row := 0, removeThese := []
gui 1:submit, nohide
gui 1:+OwnDialogs
gui 1: listView, listViewInputFiles ; Select the listview for manipulation
if ( inStr(a_GuiControl, "SelectAll") ) {
LV_Modify(0, "Select")
}
else if ( inStr(a_GuiControl, "Clear") ) {
LV_Modify(0, "-Select")
}
else if ( inStr(a_GuiControl, "Remove") ) {
guiToggle("disable", "all")
loop {
row := LV_GetNext(row) ; Get selected download from list and move to next
if ( !row ) ; Break if no more selected
break
removeThese.push(row)
}
while ( removeThese.length() ) {
row := removeThese.pop()
LV_GetText(removeThisFile, row , 1)
LV_Delete(row)
removeFromArray(removeThisFile, job.scannedFiles[job.Cmd])
log("Removed '" removeThisFile "' from the " stringUpper(job.Cmd) " queue")
SB_setText("Removed '" removeThisFile "' from the " stringUpper(job.Cmd) " queue", 1)
}
reportQueuedFiles()
}
refreshGUI()
controlFocus, SysListView321, %APP_MAIN_NAME%
}
; Report Queued files to the bottom info bar
; ------------------------------------------
reportQueuedFiles()
{
global job
log( job.scannedFiles[job.Cmd].length()? job.scannedFiles[job.Cmd].length() " jobs in the " stringUpper(job.Cmd) " queue. Ready to start!" : "No jobs in the " stringUpper(job.Cmd) " file queue" )
SB_setText( job.scannedFiles[job.Cmd].length()? job.scannedFiles[job.Cmd].length() " jobs in the " stringUpper(job.Cmd) " queue. Ready to start!" : "No jobs in the " stringUpper(job.Cmd) " file queue" )
}
; Select output folder
; --------------------
editOutputFolder()
{
setTimer checkNewOutputFolder, -500
return
}
; Check new inputted folder
; -------------------------
checkNewOutputFolder()
{
global editOutputFolder, OUTPUT_FOLDER
gui 1:submit, nohide
gui 1:+ownDialogs
if ( a_guiControl == "buttonBrowseOutput" ) {
selectFolder := selectFolderEx(OUTPUT_FOLDER, "Select a folder to save converted files to", mainAppHWND)
if ( selectFolder.selectedDir )
guiCtrl({editOutputFolder:selectFolder.selectedDir}) ; Assign to edit field if user selected
}
newFolder := editOutputFolder
if ( !newFolder || newFolder == OUTPUT_FOLDER ) {
newFolder := OUTPUT_FOLDER ; Return to old value if no change or no value given
return
}
badChar := false
for idx, val in ["*", "?", "<", ">", "/", "|", """"] { ; Validate folder name
if ( inStr(newfolder, val) ) {
badChar := true
break
}
}
folderChk := splitPath(newFolder)
if ( !folderChk.drv || !folderChk.dir || badChar || strlen(newFolder) > 255 ) { ; Make sure newFolder is a valid directory string
msgBox % "Invalid output folder"
guiCtrl({editOutputFolder:OUTPUT_FOLDER}) ; Edit reverts back to old value if new value invalid
} else {
OUTPUT_FOLDER := normalizePath(regExReplace(newFolder, "\\$")) ; 'Sanitize' new folder name
log("'" OUTPUT_FOLDER "' selected as output folder")
SB_SetText("'" OUTPUT_FOLDER "' selected as new output folder" , 1)
ini("write", "OUTPUT_FOLDER")
refreshGUI()
controlFocus,, %APP_MAIN_NAME%
}
}
; A chdman option checkbox was clicked
; ---------------------------------
checkboxOption(ctrl:="")
{
global GUI
gui 1:submit, nohide
opt := strReplace(a_guicontrol?a_guicontrol:ctrl, "_checkbox")
guiToggle((%a_guiControl%? "enable":"disable"), [opt "_dropdown", opt "_edit"]) ; Enable or disable corepsnding dropdown or editfield according to checked status
if ( GUI.chdmanOpt[opt].hasKey("masterOf") ) { ; Disable the 'slave' checkbox if masterOf is set as an option
guiToggle((%a_guiControl%? "enable":"disable"), [GUI.chdmanOpt[opt].masterOf "_checkbox", GUI.chdmanOpt[opt].masterOf "_dropdown", GUI.chdmanOpt[opt].masterOf "_edit"])
guiCtrl({(GUI.chdmanOpt[opt].masterOf "_checkbox"):0})
}
}
; Convert job button - Start the jobs!
; ------------------------------------
buttonStartJobs()
{
global
local fnMsg, runCmd, thisJob, gPos, y, file, filefull, dir, x1, x2, y, cmd, x, qsToDo
static CHDInfoFileNum
gui 1:submit, nohide
gui 1:+ownDialogs
switch job.Cmd {
; Create media
case "createcd", "createhd", "createraw", "createld", "extractcd", "extracthd", "extractraw", "extractld":
SB_SetText("Creating " stringUpper(job.Cmd) " work queue" , 1)
log("Creating " stringUpper(job.Cmd) " work queue" )
job.workQueue := createjob(job.Cmd, job.Options, job.selectedOutputExtTypes, job.selectedInputExtTypes, job.scannedFiles[job.Cmd]) ; Create a queue (object) of files to process
; Verify CHD
case "verify":
SB_SetText("Verifying CHD's" , 1)
log("Starting Verify CHD's" )
job.workQueue := createjob("verify", "", "", job.selectedInputExtTypes, job.scannedFiles["verify"])
; Show info for CHD
case "info":
SB_SetText("Info for CHD's" , 1)
log("Getting info from CHD's" )
guiToggle("disable", "all")
CHDInfoFileNum := 1, x1 := 20, x2:= 150, y := 20
gui 3: destroy
gui 3: margin, 20, 20
gui 3: font, s11 Q5 w750 c000000
gui 3: add, text, x20 y%y% w700 vtextCHDInfoTitle, % ""
y += 40
loop 12 {
gui 3: font, s9 Q5 w700 c000000
gui 3: add, text, x%x1% y%y% w100 vtextCHDInfo_%a_index%, % ""
gui 3: font, s9 Q5 w400 c000000
gui 3: add, edit, x%x2% y+-13 w615 veditCHDInfo_%a_index% readonly, % ""
y += 23
}
y += 30
gui 3: font, s9 Q5 w700 c000000
gui 3: add, text, x%x1% y%y%, % "Hunks"
gui 3: add, text, x130 y%y%, % "Type"
gui 3: add, text, x260 y%y%, % "Percent"
gui 3: font, s9 Q5 w400 c000000
loop 4 {
y += 20
gui 3: add, text, x%x1% y%y% w150 vtextCHDInfoHunks_%a_index%, % ""
gui 3: add, text, x130 y%y% w150 vtextCHDInfoType_%a_index%, % "" ; recombine words that were seperated with strSplit
gui 3: add, text, x260 y%y% w150 vtextCHDInfoPercent_%a_index%, % ""
}
y += 40
gui 3: font, s9 Q5 w700 c000000
gui 3: add, text, x%x1% y%y% w150, % "Metadata"
gui 3: font, s8 Q5 w400 c000000, % "Consolas"
y += 20
gui 3: add, edit, x%x1% y%y% w750 h250 veditMetadata readonly, % ""
y+= 270
gui 3: font, s9 Q5 w400 c000000
gui 3: add, button, x20 w120 y%y% h30 gselectCHDInfo vbuttonCHDInfoLeft hwndbuttonCHDInfoPrevHWND disabled, % "< Prev file"
imageButton.create(buttonCHDInfoPrevHWND, GUI.buttons.default.normal, GUI.buttons.default.hover, GUI.buttons.default.clicked, GUI.buttons.default.disabled) ; Default button colors
y+=5
gui 3: add, dropdownlist, x160 y%y% w475 vdropdownCHDInfo gselectCHDInfo altsubmit, % getDDCHDInfoList()
y-=5
gui 3: font, s9 Q5 w400 c000000
gui 3: add, button, x+15 y%y% w120 h30 gselectCHDInfo vbuttonCHDInfoRight hwndbuttonCHDInfoNextHWND, % " Next file >"
imageButton.create(buttonCHDInfoNextHWND, GUI.buttons.default.normal, GUI.buttons.default.hover, GUI.buttons.default.clicked, GUI.buttons.default.disabled) ; Default button colors
gui 3: font, s12 Q5 w750 c000000
gui 3: add, text, x285 y350 w200 center border vtextCHDInfoLoading, % "`nLoading...`n"
gui 3: font, s9 Q5 w400 c000000
Gui 3:+LastFound +AlwaysOnTop +ToolWindow
gui 3:show, autosize, % "CHD Info"
selectCHDInfo:
gui 3:submit, nohide
switch a_guiControl {
case "buttonCHDInfoLeft":
CHDInfoFileNum--
case "buttonCHDInfoRight":
CHDInfoFileNum++
case "dropdownCHDInfo":
CHDInfoFileNum := dropdownCHDInfo
}
setTimer, showCHDInfoLoading, -1000 ; Show loading message and disable all elemnts while loading - only if loading is taking longer then normal
if ( showCHDInfo(job.scannedFiles["info"][CHDInfoFileNum], CHDInfoFileNum, job.scannedFiles["info"].length(), 3) == false ) { ; Func returned nothing, clear the title
guiCtrl({textCHDInfoTitle:""})
guiToggle("hide", "textCHDInfoLoading", 3)
setTimer, showCHDInfoLoading, off
return
}
setTimer, showCHDInfoLoading, off
guiToggle("hide", "textCHDInfoLoading", 3) ; Hide loading message
guiToggle("enable", ["dropdownCHDInfo", "buttonCHDInfoLeft", "buttonCHDInfoRight"], 3) ; Enable info elements
guiCtrl("choose", {dropdownCHDInfo:CHDInfoFileNum}, 3) ; Choose dropdown to match newly selected item in CHD info
controlFocus, ComboBox1, % "CHD Info" ; Keep focus on dropdown to allow arrow keys to also select next and previous files
if ( CHDInfoFileNum == 1 ) ; Then disable the appropriate button according to selection number (first or last in list)
guiToggle("disable", "buttonCHDInfoLeft", 3)
else if ( CHDInfoFileNum == job.scannedFiles["info"].length() )
guiToggle("disable", "buttonCHDInfoRight", 3)
return
3GUIClose:
gui 3: destroy
refreshGUI()
return
case "addMeta":
case "delMeta":
case default:
}
if ( !job.workQueue || job.workQueue.length() == 0 ) { ; Nothing to do!
log("No jobs found in the work queue")
msgbox, 16, % "Error", % "No jobs in the work queue!"
return
}