From 315ef7e858c960c4ab811160d61c718c8cf60699 Mon Sep 17 00:00:00 2001 From: umageddon Date: Wed, 23 Mar 2022 14:50:33 -0600 Subject: [PATCH] Add files via upload --- JSON2.ahk | 68 ++++++++++++++++++++++++ namDHC.ahk | 147 ++++++++++++++++++++++++++++++++++++++++++++-------- threads.ahk | 4 +- 3 files changed, 196 insertions(+), 23 deletions(-) create mode 100644 JSON2.ahk diff --git a/JSON2.ahk b/JSON2.ahk new file mode 100644 index 0000000..8eaa975 --- /dev/null +++ b/JSON2.ahk @@ -0,0 +1,68 @@ +/* +Thanks Bentschi +https://www.autohotkey.com/board/topic/91700-funktion-json-encode-und-decode/ +*/ + +json2(i) +{ + ;ENCODE + if (isobject(i)) + { + o := "", a := 1, x := 1 + for k,v in i + { + if (k!=x) + a := 0, break + x += 1 + } + o .= (a) ? "[" : "{", f := 1 + for k,v in i + o .= ((f) ? "" : ",")((a) ? "" : """" k """:")((isobject(v)) ? json2(v) : ((v+0=v) ? v : """" v """")), f := 0 + return o ((a) ? "]" : "}") + } + ;DECODE + if (regexmatch(i, "s)^__chr(A|W):(.*)", m)) + { + VarSetCapacity(b, 4, 0), NumPut(m2, b, 0, "int") + return StrGet(&b, 1, (m1="A") ? "cp28591" : "utf-16") + } + if (regexmatch(i, "s)^__str:((\\""|[^""])*)", m)) + { + str := m1 + for p,r in {b:"`b", f:"`f", n:"`n", 0:"", r:"`r", t:"`t", v:"`v", "'":"'", """":"""", "/":"/"} + str := regexreplace(str, "\\" p, r) + while (regexmatch(str, "s)^(.*?)\\x([0-9a-fA-F]{2})(.*)", m)) + str := m1 json2("__chrA:0x" m2) m3 + while (regexmatch(str, "s)^(.*?)\\u([0-9a-fA-F]{4})(.*)", m)) + str := m1 json2("__chrW:0x" m2) m3 + while (regexmatch(str, "s)^(.*?)\\([0-9]{1,3})(.*)", m)) + str := m1 json2("__chrA:" m2) m3 + return regexreplace(str, "\\\\", "\") + } + str := [], obj := [] + while (RegExMatch(i, "s)^(.*?[^\\])""((\\""|[^""])*?[^\\]|)""(.*)$", m)) + str.insert(json2("__str:" m2)), i := m1 "__str<" str.maxIndex() ">" m4 + while (RegExMatch(RegExReplace(i, "\s+", ""), "s)^(.*?)(\{|\[)([^\{\[\]\}]*?)(\}|\])(.*)$", m)) + { + a := (m2="{") ? 0 : 1, c := m3, i := m1 "__obj<" ((obj.maxIndex()+1) ? obj.maxIndex()+1 : 1) ">" m5, tmp := [] + while (RegExMatch(c, "^(.*?),(.*)$", m)) + tmp.insert(m1), c := m2 + tmp.insert(c), tmp2 := {}, obj.insert(cobj := {}) + for k,v in tmp + { + if (RegExMatch(v, "^(.*?):(.*)$", m)) + tmp2[m1] := m2 + else + tmp2.insert(v) + } + for k,v in tmp2 + { + for x,y in str + k := RegExReplace(k, "__str<" x ">", y), v := RegExReplace(v, "__str<" x ">", y) + for x,y in obj + v := RegExMatch(v, "^__obj<" x ">$") ? y : v + cobj[k] := v + } + } + return obj[obj.maxIndex()] +} \ No newline at end of file diff --git a/namDHC.ahk b/namDHC.ahk index c7e6165..b187fcc 100644 --- a/namDHC.ahk +++ b/namDHC.ahk @@ -27,24 +27,25 @@ SetControlDelay, -1 - GUI changes - Added time elapsed to report - Changed about window - + + v1.04 - Added update functionality */ #Include SelectFolderEx.ahk #Include ClassImageButton.ahk #Include ConsoleClass.ahk #Include JSON.ahk - -starttime := a_tickcount - +#Include JSON2.ahk onExit("quitApp", 1) ; Default global values ; --------------------- -mainAppVersion := "1.03" +currentAppVersion := "1.04" +checkForUpdatesAtStartup := "yes" chdmanLocation := a_scriptDir "\chdman.exe" chdmanVerArray := ["0.236", "0.237", "0.238", "0.239", "0.240"] +githubRepoURL := "https://api.github.com/repos/umageddon/namDHC/releases/62394694" mainAppName := "namDHC" mainAppNameVerbose := mainAppName " - Verbose" runAppName := mainAppName " - Job" @@ -80,7 +81,8 @@ ini("read", ["jobQueueSize" ,"verboseWinPosW" ,"verboseWinPosH" ,"verboseWinPosX" - ,"verboseWinPosY"]) + ,"verboseWinPosY" + ,"checkForUpdatesAtStartup"]) if ( !fileExist(chdmanLocation) ) { 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(chdmanVerArray) @@ -117,11 +119,13 @@ GUI.buttons["start"] := {normal:[0, 0xFF74b6cc, "", 0xFF444444, 3], hover:[0, 0 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:"Number of jobs to run concurrently", gotolabel:":SubSettingsConcurrently", saveVar:""} -GUI.menu.Settings[2] := {name:"Show verbose window", gotolabel:"menuSelected", saveVar:"showVerboseWin", Fn:"showVerboseWindow"} -GUI.menu.Settings[3] := {name:"Show a console for each job", gotolabel:"menuSelected", saveVar:"showJobConsole"} -GUI.menu.Settings[4] := {name:"Play sounds when finished job queue", gotolabel:"menuSelected", saveVar:"playFinishedSong"} -GUI.menu.Settings[5] := {name:"Remove file entry from list when successful", gotolabel:"menuSelected", saveVar:"removeFileEntryAfterFinish"} +GUI.menu.Settings[1] := {name:"Check for updates automatically", gotolabel:"menuSelected", saveVar:"checkForUpdatesAtStartup"} +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:"showVerboseWin", Fn:"showVerboseWindow"} +GUI.menu.Settings[4] := {name:"Show a console window for each new job", gotolabel:"menuSelected", saveVar:"showJobConsole"} +GUI.menu.Settings[5] := {name:"Play a sound when finished jobs", gotolabel:"menuSelected", saveVar:"playFinishedSong"} +GUI.menu.Settings[6] := {name:"Remove entry from list when successful", gotolabel:"menuSelected", saveVar:"removeFileEntryAfterFinish"} + ; Set misc GUI variables ; ------------------------- @@ -196,6 +200,10 @@ mainAppHWND := winExist(mainAppName) mainAppMenuGet := DllCall("GetMenu", "uint", mainAppHWND) ; Save menu to retrieve later mainMenuVisible := true + +if ( checkForUpdatesAtStartup == "yes" ) + checkForUpdates() + onMessage(0x03, "moveGUIWin") ; If windows are moved, save positions in moveGUIWin() onMessage(0x004A, "receiveData") ; Receive messages from threads @@ -249,22 +257,24 @@ menuSelected() gui 4: margin, 20 20 gui 4: font, s15 Q5 w700 c000000 gui 4: add, text, x10 y10, % mainAppName + gui 4: font, s10 Q5 w700 c000000 - gui 4: add, text, x100 y17, % " v" mainAppVersion + gui 4: add, text, x100 y17, % " v" currentAppVersion gui 4: font, s10 Q5 w400 c000000 - gui 4: add, text, x10 y40, % "A Windows frontend for the MAME CHDMAN tool" - gui 4: add, link, x10 y100, Updates and bug reports: https://github.com/umageddon/namDHC - gui 4: add, link, x10 y120, MAME Info: https://www.mamedev.org/ + gui 4: add, text, x10 y35, % "A Windows frontend for the MAME CHDMAN tool" + + gui 4: add, button, x10 y70 w130 h22 gcheckForUpdates, % "Check for updates" + + gui 4: add, link, x10 y110, Github: https://github.com/umageddon/namDHC + gui 4: add, link, x10 y130, MAME Info: https://www.mamedev.org/ gui 4: font, s9 Q5 w400 c000000 - gui 4: add, text, x170 y145, % "(C) Copyright 2022 Umageddon" + gui 4: add, text, x10 y165, % "(C) Copyright 2022 Umageddon" gui 4: show, w500 center, About Gui 4:+LastFound +AlwaysOnTop +ToolWindow controlFocus,, About ; Removes outline around html anchor return - - } } @@ -855,7 +865,7 @@ createMainGUI() gui 1:add, statusBar SB_SetParts(640, 175) - SB_SetText(" namDHC v" mainAppVersion " for CHDMAN", 2) + SB_SetText(" namDHC v" currentAppVersion " for CHDMAN", 2) gui 1:add, groupBox, x5 w800 h425 vgroupboxJob, Job @@ -1437,14 +1447,14 @@ getFilesFromCUEGDITOC(inputFiles) ; Log messages and send to verbose window ; -------------------------------------- -log(newMsg:="", newline:=true, clear:=false) +log(newMsg:="", newline:=true, clear:=false, timestamp:=true) { global mainAppNameVerbose, editVerbose if ( !newMsg ) return false - newMsg := "[" a_Hour ":" a_Min ":" a_Sec "] " newMsg + newMsg := timestamp ? "[" a_Hour ":" a_Min ":" a_Sec "] " newMsg : newMsg msg := clear? newMsg : guiCtrlGet("editVerbose", 2) . newMsg guiCtrl({editVerbose:msg (newline? "`n" : "")}, 2) @@ -2007,6 +2017,101 @@ millisecToTime(msec) } +; Thanks maestrith +; https://www.autohotkey.com/board/topic/88685-download-a-url-to-a-variable/ +URLDownloadToVar(url){ + try { + hObject:=ComObjCreate("WinHttp.WinHttpRequest.5.1") + hObject.Open("GET",url) + hObject.Send() + return hObject.ResponseText + } +} + + +checkForUpdates(wParam:="", userClicked:=false) +{ + global currentAppVersion, mainAppName, githubRepoURL + gui 4:+OwnDialogs + + log("Checking for updates ... ") + + if ( !a_isCompiled ) { + if ( userClicked ) + msgbox 16, % "Error", % "Can only update compiled binaries" + log("Error updating: Can only update compiled binaries") ; no time-stamp + return + } + + /* + obj.tag_name = version (ie-"namDHCv1.03") + obj.body = version changes + obj.assets[1].browser_download_url = URL *should* point to chdman.exe + obj.assets[2].browser_download_url = URL *should* point to namDHC.exe + obj.assets[3].browser_download_url = URL *should* point to namDHC_vx.xx.zip + obj.created_at = date created + */ + JSON := URLDownloadToVar(githubRepoURL) + obj := json2(JSON) ; Previous JSON library cant read github API properly, this JSON library has issues with thread communication + + if ( !isObject(obj) ) + log("Error updating: Update info invalid") + + else if ( obj.message && inStr(obj.message, "limit exceeded") ) + log("Error updating: Github API limit exceeded") + + else if ( !obj.tag_name ) + log("Error updating: Update info invalid") + + else { + newVersion := strReplace(obj.tag_name, "namDHCv", "") + + if ( newVersion == currentAppVersion ) { + if ( userClicked ) + msgbox 64, % "No new updates found", % "You are running the current version" + log("No new updates found. You are running the current version") + return + } + + else if ( newVersion < currentAppVersion ) { + if ( userClicked ) + msgbox 16, % "Error", % "Your version is newer then the current release!" + log("Your version is newer then the current release!") + } + else if ( newVersion > currentAppVersion ) { + log("An update was found: v" newVersion) + msgBox, 68, % "Update available", % "A new version of " mainAppName " is available!`n`nCurrent version: v" currentAppVersion "`nLatest version: v" newVersion "`n`nChanges:`n" strReplace(obj.body, "-", " -") "`n`nDo you want to update?" + ifmsgbox Yes + { + for idx, asset in obj.assets { + if ( inStr(asset.browser_download_url, "namDHC.exe") ) + thisBinURL := asset.browser_download_url + } + if ( !thisBinURL ) { + msgbox 16, % "Error", % "Error downloading update!" + log("Error updating: Update binary couldn't be found in the repo!") + return + } + tempDir := a_Temp "\namDHC" + fileCreateDir, % tempDir + tempEXEFullFile := tempDir "\namDHC.exe" + urlDownloadToFile, % thisBinURL, % tempEXEFullFile + if ( !fileExist(tempEXEFullFile) ) { + msgbox 16, % "Error", % "Error downloading update!" + log("Error updating: There was an error downloading the update") + return + } + batchFile := tempDir "\update.bat" + fileDelete(batchFile, 5, 10) + batchText := "@timeout /t 1 /nobreak > NUL`r`n@del """ a_ScriptFullPath """ > NUL`r`n@copy """ tempEXEFullFile """ """ a_ScriptFullPath """ > NUL`r`n@start " a_ScriptFullPath "`r`n@exit 0`r`n" + fileAppend, % batchText, % batchFile + sleep 25 + run % batchFile + exitApp + } + } + } +} ; Close App ; --------- diff --git a/threads.ahk b/threads.ahk index ed736b0..00ef049 100644 --- a/threads.ahk +++ b/threads.ahk @@ -216,7 +216,7 @@ thread_sendData(msg:="") if ( msg == false ) return msg := (msg=="") ? sendData : msg - sendAppMessage(json(msg), mainAppName " ahk_id " mainAppHWND) ; Send back the data we've recieved plus any other new info + sendAppMessage(toJSON(msg), mainAppName " ahk_id " mainAppHWND) ; Send back the data we've recieved plus any other new info sendData.log := "" sendData.status := "" sendData.report := "" @@ -249,7 +249,7 @@ thread_receiveData(wParam, ByRef lParam) global recvData stringAddress := numGet(lParam + 2*A_PtrSize) - recvData := json(strGet(stringAddress,, "utf-8")) + recvData := fromJSON(strGet(stringAddress,, "utf-8")) if ( recvData.kill == "true" ) ; User has requested this job to be cancelled thread_killProcess()