Jump to content

RazerM

Active Members
  • Posts

    1,211
  • Joined

  • Last visited

1 Follower

About RazerM

  • Birthday 05/26/1991

Profile Information

  • Member Title
    cowinkeedenky - coincidence?
  • Location
    Scotland

Recent Profile Visitors

811 profile views

RazerM's Achievements

Universalist

Universalist (7/7)

1

Reputation

  1. I have a script that behaves differently when run from the 'Run Script' context menu compared with running through SciTE or typing "Autoit.exe script.au3" in to the command line. I've looked in the registry to see a %* parameter is added after the scriptname. Running from the commandline with the added %* parameter causes the script to behave as it does through the context menu. What does it do?
  2. I placed the fix at the top of the script before WM_NOTIFY has been registered. Then replace the $tag... variables with the custom ones. $tNMHDR = DllStructCreate($sNMHDR, $ilParam) $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom")) $iIDFrom = DllStructGetData($tNMHDR, "IDFrom") $iCode = DllStructGetData($tNMHDR, "Code") Switch $hWndFrom Case $hWndListView Switch $iCode Case $NM_CLICK ; Sent by a list-view control when the user clicks an item with the left mouse button $tInfo = DllStructCreate($sNMITEMACTIVATE, $ilParam)
  3. Make sure you are running the 64 bit version of AutoIt.
  4. I've played about with the $tagNMHDR and $tagNMITEMACTIVATE structs. changing 'CODE' in $tagNMHDR to INT64 makes everything work as expected but not sure where I would find if that's the correct thing to do. For now I'll be using this If @AutoItX64 Then $sNMHDR = "hwnd hWndFrom;uint_ptr IDFrom;INT64 Code" Else $sNMHDR = "hwnd hWndFrom;uint_ptr IDFrom;int Code" EndIf
  5. Using the example code below, I would expect that clicking row 1, column 1 would give Index 0, SubItem 0 (which it does). But clicking row 1, column 2 gives Index 0, SubItem 0 also. I then looked at the NewState variable. After clicking all 9 row/column combinations it seems that SubItem is giving the index, and newState is giving the subitem. (Index stays 0 throughout) Apart from the clearly named variables msdn also states the behaviour I would expect. I am running the lastest stable release on Windows 7 64-bit. A table of my results: Row Clicked |Col Clicked |Index |SubItem |NewState | 1 |1 |0 |0 |0 | 1 |2 |0 |0 |1 | 1 |3 |0 |0 |2 | 2 |1 |0 |1 |0 | 2 |2 |0 |1 |1 | 2 |3 |0 |1 |2 | 3 |1 |0 |2 |0 | 3 |2 |0 |2 |1 | 3 |3 |0 |2 |2 | #AutoIt3Wrapper_au3check_parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 #include <GuiConstantsEx.au3> #include <GuiListView.au3> #include <GuiImageList.au3> #include <WindowsConstants.au3> Opt('MustDeclareVars', 1) $Debug_LV = False ; Check ClassName being passed to ListView functions, set to True and use a handle to another control to see it work Global $hListView _Main() Func _Main() Local $hImage ; Create GUI GUICreate("ListView Click Item", 400, 300) $hListView = GUICtrlCreateListView("", 2, 2, 394, 268) _GUICtrlListView_SetUnicodeFormat($hListView, False) GUISetState() GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY") ; Load images $hImage = _GUIImageList_Create() _GUIImageList_Add($hImage, _GUICtrlListView_CreateSolidBitMap(GUICtrlGetHandle($hListView), 0xFF0000, 16, 16)) _GUIImageList_Add($hImage, _GUICtrlListView_CreateSolidBitMap(GUICtrlGetHandle($hListView), 0x00FF00, 16, 16)) _GUIImageList_Add($hImage, _GUICtrlListView_CreateSolidBitMap(GUICtrlGetHandle($hListView), 0x0000FF, 16, 16)) _GUICtrlListView_SetImageList($hListView, $hImage, 1) ; Add columns _GUICtrlListView_InsertColumn($hListView, 0, "Column 1", 100) _GUICtrlListView_InsertColumn($hListView, 1, "Column 2", 100) _GUICtrlListView_InsertColumn($hListView, 2, "Column 3", 100) ; Add items _GUICtrlListView_AddItem($hListView, "Row 1: Col 1", 0) _GUICtrlListView_AddItem($hListView, "Row 2: Col 1", 1) _GUICtrlListView_AddItem($hListView, "Row 3: Col 1", 2) _GUICtrlListView_AddSubItem($hListView, 0, "Row 1: Col 2", 1) _GUICtrlListView_AddSubItem($hListView, 1, "Row 2: Col 2", 1) _GUICtrlListView_AddSubItem($hListView, 2, "Row 3: Col 2", 1) _GUICtrlListView_AddSubItem($hListView, 0, "Row 1: Col 3", 2) _GUICtrlListView_AddSubItem($hListView, 1, "Row 2: Col 3", 2) _GUICtrlListView_AddSubItem($hListView, 2, "Row 3: Col 3",2) ; Loop until user exits Do Until GUIGetMsg() = $GUI_EVENT_CLOSE GUIDelete() EndFunc ;==>_Main Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam) #forceref $hWnd, $iMsg, $iwParam Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR, $hWndListView, $tInfo $hWndListView = $hListView If Not IsHWnd($hListView) Then $hWndListView = GUICtrlGetHandle($hListView) $tNMHDR = DllStructCreate($tagNMHDR, $ilParam) $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom")) $iIDFrom = DllStructGetData($tNMHDR, "IDFrom") $iCode = DllStructGetData($tNMHDR, "Code") Switch $hWndFrom Case $hWndListView Switch $iCode Case $NM_CLICK ; Sent by a list-view control when the user clicks an item with the left mouse button $tInfo = DllStructCreate($tagNMITEMACTIVATE, $ilParam) _DebugPrint("$NM_CLICK" & @LF & "--> hWndFrom:" & @TAB & $hWndFrom & @LF & _ "-->IDFrom:" & @TAB & $iIDFrom & @LF & _ "-->Code:" & @TAB & $iCode & @LF & _ "-->Index:" & @TAB & DllStructGetData($tInfo, "Index") & @LF & _ "-->SubItem:" & @TAB & DllStructGetData($tInfo, "SubItem") & @LF & _ "-->NewState:" & @TAB & DllStructGetData($tInfo, "NewState") & @LF & _ "-->OldState:" & @TAB & DllStructGetData($tInfo, "OldState") & @LF & _ "-->Changed:" & @TAB & DllStructGetData($tInfo, "Changed") & @LF & _ "-->ActionX:" & @TAB & DllStructGetData($tInfo, "ActionX") & @LF & _ "-->ActionY:" & @TAB & DllStructGetData($tInfo, "ActionY") & @LF & _ "-->lParam:" & @TAB & DllStructGetData($tInfo, "lParam") & @LF & _ "-->KeyFlags:" & @TAB & DllStructGetData($tInfo, "KeyFlags")) ; No return value EndSwitch EndSwitch Return $GUI_RUNDEFMSG EndFunc ;==>WM_NOTIFY Func _DebugPrint($s_text, $line = @ScriptLineNumber) ConsoleWrite( _ "!===========================================================" & @LF & _ "+======================================================" & @LF & _ "-->Line(" & StringFormat("%04d", $line) & "):" & @TAB & $s_text & @LF & _ "+======================================================" & @LF) EndFunc ;==>_DebugPrint
  6. Unfortunately I forget who made the ModernMenu.au3 file, but it wasn't me. It's great though and I use it a lot.
  7. It's called AInstall, and it generates a .au3 script, compiles it, then packs it into a .exe file with iexpress. (Enter 'iexpress' in your run window to see what it is) It's not finished but I started it ages ago and never finished it, I just wondered if someone would benefit from it and/or further its development. Anyone can have a go and keep it as theirs. I've attached files so that you can open an AInstall setup file (*.ais) and compile an installer immediately to see how it works. In the Example.zip file is a folder called 'Notabilis', it contains a notepad-like program I created recently, it will be the program that we create an installer file for. Extract the zip file to the C:\ drive so that you have C:\Notabilis\ (AInstall uses hard paths for creating an installer) Now extract the AInstall.zip file to anywhere on your computer and run AInstall\AInstall.au3 (runs on both AutoIt v3.3.0.0 and v3.3.1.0). Choose File>Open and browse to C:\Notabilis\Notabilis.ais then click Open. Now choose Tools>Compile & Run and the installer will be compiled, once it starts you can do a test install, (this installer doesn't write any registry entries so can be deleted easily), and you can see that the result is pretty streamlined. The resulting (standalone I might add, all files are embedded) file will be at 'C:\Notabilis\Setup\Notabilis_Setup.exe' if you feel like running the installer manually. Example.zip (498.9K) Number of downloads: AInstall.zip (254.1K) Number of downloads: Detailed Notes: - You don't need to understand this to try out AInstall. In AInstall\ you'll notice three related files: GUI.au3, MakeGen.au3 and GenScript.au3 GUI.au3 You use this to edit the way the compiled installer will look.You can run this file directly to 'try out' the installer without installing anything.You'll notice a bunch of "#=" and "##=" lines, see MakeGen.au3 belowMakeGen.au3 This processes GUI.au3 to create GenScript.au3, which is used by AInstall to create the resulting compiled installer.#= lines in GUI.au3 are inserted into GenScript.au3 but do not execute when GUI.au3 is running.##= lines in GUI.au3 are inserted into GenScript.au3 exactly as they appear, for things like deciding whether the resulting Installer requires a EULA.
  8. Ok, it's just that I've installed a revision-based system that saves files within certain directories when they are saved, i'll limit to 1 then.
  9. On vista here, I have the config file as C:\Program Files\AutoIt3\SciTE\Tidy\Tidy.ini Tidy seems to be ignoring this file as I have removed the KeepNVersions line completely and it still backs up the file. Any ideas?
  10. Sounds great. About the volume function, only vcr and digitalvideo devices 'officially' support the 'setaudio <etc>' command. (from MSDN docs) Therefore I'm not sure it's good practise to add it in as we are dealing with waveform-audio devices. I'll submit the sound.au3 for release in next beta, and the volume function can be on hold until we discuss it more.
  11. Thanks Melba23, I've updated post #47 with the changes mentioned in the post above.
  12. New beta: #include <Date.au3> #include <File.au3> #include <String.au3> ;=============================================================================== ; ; Function Name: _SoundOpen ; Description:: Opens a sound file for use with other _Sound functions ; Parameter(s): $sFile - The sound file, $sAlias[optional] - a name such as sound1, ; if you do not specify one it is randomly generated ; Requirement(s): AutoIt 3.2 ++ ; Return Value(s): string(the sound id) - Success, 0 - Failure ; @extended <> 0 - open failed, @error = 2 - File doesn't exist, ; @error = 3 - alias contains whitespace ; Author(s): RazerM, Melba23, some code by Simucal, PsaltyDS ; ;=============================================================================== ; Func _SoundOpen($sFile, $sAlias = "") ;Declare variables Local $aSndID[3], $sSndID, $iCurrentPos, $iRet, $asAlias, $fTryNextMethod = False, $hFile Local $szDrive, $szDir, $szFName, $szExt, $iSndLenMs, $iSndLenMin, $iSndLenHour, $iSndLenSecs, $sSndLenFormat Local $sSndDirName, $sSndFileName, $sSndDirShortName, $oShell, $oShellDir, $oShellDirFile, $sRaw, $aInfo Local $sTrackLength, $iSoundTicks, $iActualTicks, $iVBRRatio, $aiTime ;check for file If Not FileExists($sFile) Then Return SetError(2, 0, 0) ;search for whitespace by character $asAlias = StringSplit($sAlias, "") For $iCurrentPos = 1 To $asAlias[0] If StringIsSpace($asAlias[$iCurrentPos]) Then Return SetError(3, 0, 0) Next ;create random alias if one is not supplied If $sAlias = "" Then $sSndID = __RandomStr(10) Else $sSndID = $sAlias EndIf If StringInStr($sSndID, '!') Then Return SetError(3, 0, 0) ;invalid file/alias $aSndID[0] = $sSndID _PathSplit($sFile, $szDrive, $szDir, $szFName, $szExt) If $szDrive = "" Then $sSndDirName = @WorkingDir & "\" Else $sSndDirName = $szDrive & $szDir EndIf $sSndFileName = $szFName & $szExt $sSndDirShortName = FileGetShortName($sSndDirName, 1) ;open file $iRet = __mciSendString("open " & FileGetShortName($sFile) & " alias " & $aSndID[0]) $oShell = ObjCreate("shell.application") If IsObj($oShell) Then $oShellDir = $oShell.NameSpace ($sSndDirShortName) If IsObj($oShellDir) Then $oShellDirFile = $oShellDir.Parsename ($sSndFileName) If IsObj($oShellDirFile) Then $sRaw = $oShellDir.GetDetailsOf ($oShellDirFile, -1) $aInfo = StringRegExp($sRaw, ": ([0-9]{2}:[0-9]{2}:[0-9]{2})", 3) If Not IsArray($aInfo) Then $fTryNextMethod = True Else $sTrackLength = $aInfo[0] EndIf Else $fTryNextMethod = True EndIf Else $fTryNextMethod = True EndIf Else $fTryNextMethod = True EndIf If $fTryNextMethod Then $fTryNextMethod = False If $szExt = ".mp3" Then $hFile = FileOpen(FileGetShortName($sSndDirName & $sSndFileName), 4) $sTag = FileRead($hFile, 5156) FileClose($hFile) $sTrackLength = __ReadXingFromMP3($sTag) If @error Then $fTryNextMethod = True Else $fTryNextMethod = True EndIf EndIf If $fTryNextMethod Then $fTryNextMethod = False If $szExt = ".mp3" Then $sTrackLength = __ReadTLENFromMP3($sTag) If @error Then $fTryNextMethod = True Else $fTryNextMethod = True EndIf EndIf FileClose($hFile) If $fTryNextMethod Then $fTryNextMethod = False ;tell mci to use time in milliseconds __mciSendString("set " & $aSndID[0] & " time format miliseconds") ;receive length of sound $iSndLenMs = __mciSendString("status " & $aSndID[0] & " length", 255) ;assign modified data to variables _TicksToTime($iSndLenMs, $iSndLenHour, $iSndLenMin, $iSndLenSecs) ;assign formatted data to $sSndLenFormat $sTrackLength = StringFormat("%02i:%02i:%02i", $iSndLenHour, $iSndLenMin, $iSndLenSecs) EndIf ; Convert Track_Length to mSec $aiTime = StringSplit($sTrackLength, ":") $iActualTicks = _TimeToTicks($aiTime[1], $aiTime[2], $aiTime[3]) ;tell mci to use time in milliseconds __mciSendString("set " & $aSndID[0] & " time format miliseconds") ;;Get estimated length $iSoundTicks = __mciSendString("status " & $aSndID[0] & " length", 255) ;Compare to actual length If Abs($iSoundTicks - $iActualTicks) < 1000 Then ;Assume CBR, as our track length from shell.application is only accurate within 1000ms $iVBRRatio = 0 Else ;Set correction ratio for VBR operations $iVBRRatio = $iSoundTicks / $iActualTicks EndIf $aSndID[1] = $iVBRRatio $aSndID[2] = 0 Return SetError(0, $iRet, $aSndID) EndFunc ;==>_SoundOpen ;=============================================================================== ; ; Function Name: _SoundClose ; Description:: Closes a sound ; Parameter(s): $sSndID - Sound ID returned by _SoundOpen ; Requirement(s): AutoIt 3.2 ++ ; Return Value(s): 1 - Success, 0 and @error = 1 - Failure ; Author(s): RazerM, Melba23 ; ;=============================================================================== ; Func _SoundClose($aSndID) If Not IsArray($aSndID) Then Return SetError(3, 0, 0) ; invalid file/alias If StringInStr($aSndID[0], '!') Then Return SetError(3, 0, 0) ; invalid file/alias If __mciSendString("close " & $aSndID[0]) = 0 Then Return 1 Else Return SetError(1, 0, 0) EndIf EndFunc ;==>_SoundClose ;=============================================================================== ; ; Function Name: _SoundPlay ; Description:: Plays a sound from the current position (beginning is the default) ; Parameter(s): $sSndID - Sound ID returned by _SoundOpen or sound file ; $fWait - If set to 1 the script will wait for the sound to finish before continuing ; - If set to 0 the script will continue while the sound is playing ; Requirement(s): AutoIt 3.2 ++ ; Return Value(s): 1 - Success, 0 - Failure ; @error = 2 - $fWait is invalid, @error = 1 - play failed ; Author(s): RazerM, Melba23 ; ;=============================================================================== ; Func _SoundPlay($aSndID, $fWait = 0) ;Declare variables Local $iRet, $vTemp ;validate $fWait If $fWait <> 0 And $fWait <> 1 Then Return SetError(2, 0, 0) If Not IsArray($aSndID) Then If Not FileExists($aSndID) Then Return SetError(3, 0, 0) ; invalid file/alias $vTemp = FileGetShortName($aSndID) Dim $aSndID[1] = [$vTemp] EndIf If StringInStr($aSndID[0], '!') Then Return SetError(3, 0, 0) ; invalid file/alias ;if sound has finished, seek to start If _SoundPos($aSndID, 2) = _SoundLength($aSndID, 2) Then __mciSendString("seek " & $aSndID[0] & " to start") ;If $fWait = 1 then pass wait to mci If $fWait = 1 Then $iRet = __mciSendString("play " & $aSndID[0] & " wait") Else $iRet = __mciSendString("play " & $aSndID[0]) EndIf ;return If $iRet = 0 Then Return 1 Else Return SetError(1, 0, 0) EndIf EndFunc ;==>_SoundPlay ;=============================================================================== ; ; Function Name: _SoundStop ; Description:: Stops the sound ; Parameter(s): $sSndID - Sound ID returned by _SoundOpen or sound file ; Requirement(s): AutoIt 3.2 ++ ; Return Value(s): 1 - Success, 0 and @error = 1 - Failure, ; Author(s): RazerM, Melba23 ; ;=============================================================================== ; Func _SoundStop($aSndID) ;Declare variables Local $iRet, $iRet2, $vTemp If Not IsArray($aSndID) Then If Not FileExists($aSndID) Then Return SetError(3, 0, 0) ; invalid file/alias $vTemp = FileGetShortName($aSndID) Dim $aSndID[1] = [$vTemp] EndIf If StringInStr($aSndID[0], '!') Then Return SetError(3, 0, 0) ; invalid file/alias ;seek to start $iRet = __mciSendString("seek " & $aSndID[0] & " to start") ;stop $iRet2 = __mciSendString("stop " & $aSndID[0]) ;return If $iRet = 0 And $iRet2 = 0 Then Return 1 Else Return SetError(1, 0, 0) EndIf EndFunc ;==>_SoundStop ;=============================================================================== ; ; Function Name: _SoundPause ; Description:: Pauses the sound ; Parameter(s): $sSndID - Sound ID returned by _SoundOpen or sound file ; Requirement(s): AutoIt 3.2 ++ ; Return Value(s): 1 - Success, 0 and @error = 1 - Failure, ; Author(s): RazerM, Melba23 ; ;=============================================================================== ; Func _SoundPause($aSndID) ;Declare variables Local $iRet, $vTemp If Not IsArray($aSndID) Then If Not FileExists($aSndID) Then Return SetError(3, 0, 0) ; invalid file/alias $vTemp = FileGetShortName($aSndID) Dim $aSndID[1] = [$vTemp] EndIf If StringInStr($aSndID[0], '!') Then Return SetError(3, 0, 0) ; invalid file/alias ;pause sound $iRet = __mciSendString("pause " & $aSndID[0]) ;return If $iRet = 0 Then Return 1 Else Return SetError(1, 0, 0) EndIf EndFunc ;==>_SoundPause ;=============================================================================== ; ; Function Name: _SoundResume ; Description:: Resumes the sound after being paused ; Parameter(s): $sSndID - Sound ID returned by _SoundOpen or sound file ; Requirement(s): AutoIt 3.2 ++ ; Return Value(s): 1 - Success, 0 and @error = 1 - Failure, ; Author(s): RazerM, Melba23 ; ;=============================================================================== ; Func _SoundResume($aSndID) ;Declare variables Local $iRet, $vTemp If Not IsArray($aSndID) Then If Not FileExists($aSndID) Then Return SetError(3, 0, 0) ; invalid file/alias $vTemp = FileGetShortName($aSndID) Dim $aSndID[1] = [$vTemp] EndIf If StringInStr($aSndID[0], '!') Then Return SetError(3, 0, 0) ; invalid file/alias ;resume sound $iRet = __mciSendString("resume " & $aSndID[0]) ;return If $iRet = 0 Then Return 1 Else Return SetError(1, 0, 0) EndIf EndFunc ;==>_SoundResume ;=============================================================================== ; ; Function Name: _SoundLength ; Description:: Returns the length of the sound in the format hh:mm:ss ; Parameter(s): $sSndID - Sound ID returned by _SoundOpen or sound file, ; $iMode = 1 - hh:mm:ss, $iMode = 2 - milliseconds ; Requirement(s): AutoIt 3.2 ++ ; Return Value(s): Length of the sound - Success, 0 and @error = 1 - $iMode is invalid ; Author(s): RazerM, Melba23 ; Mofified: jpm ; ;=============================================================================== ; Func _SoundLength($aSndID, $iMode = 1) ;Declare variables Local $iSndLenMs, $iSndLenMin, $iSndLenHour, $iSndLenSecs, $sSndLenFormat, $vTemp = "" ;validate $iMode If $iMode <> 1 And $iMode <> 2 Then Return SetError(1, 0, 0) If Not IsArray($aSndID) Then If Not FileExists($aSndID) Then Return SetError(3, 0, 0) ; invalid file/alias $vTemp = FileGetShortName($aSndID) Dim $aSndID[3] $aSndID = _SoundOpen($vTemp) EndIf If StringInStr($aSndID[0], '!') Then Return SetError(3, 0, 0) ; invalid file/alias ;tell mci to use time in milliseconds __mciSendString("set " & $aSndID[0] & " time format miliseconds") ;receive length of sound $iSndLenMs = __mciSendString("status " & $aSndID[0] & " length", 255) If $aSndID[1] <> 0 Then $iSndLenMs = Round($iSndLenMs / $aSndID[1]) If $vTemp <> "" Then _SoundClose($aSndID) ;if user called _SoundLength with a filename ;assign modified data to variables _TicksToTime($iSndLenMs, $iSndLenHour, $iSndLenMin, $iSndLenSecs) ;assign formatted data to $sSndLenFormat $sSndLenFormat = StringFormat("%02i:%02i:%02i", $iSndLenHour, $iSndLenMin, $iSndLenSecs) ;return correct variable If $iMode = 1 Then Return $sSndLenFormat If $iMode = 2 Then Return $iSndLenMs EndFunc ;==>_SoundLength ;=============================================================================== ; ; Function Name: _SoundSeek ; Description:: Seeks the sound to a specified time ; Parameter(s): $sSndID - Sound ID returned by _SoundOpen (must NOT be a file), $iHour, $iMin, $iSec ; Requirement(s): AutoIt 3.2 ++ ; Return Value(s): 1 - Success, 0 and @error = 1 - Failure, ; Author(s): RazerM, Melba23 ; ;=============================================================================== ; Func _SoundSeek(ByRef $aSndID, $iHour, $iMin, $iSec) ;Declare variables Local $iMs = 0, $iRet, $vTemp If Not IsArray($aSndID) Then If Not FileExists($aSndID) Then Return SetError(3, 0, 0) ; invalid file/alias $vTemp = FileGetShortName($aSndID) Dim $aSndID[1] = [$vTemp] EndIf If StringInStr($aSndID[0], '!') Then Return SetError(3, 0, 0) ; invalid file/alias ;prepare mci to receive time in milliseconds __mciSendString("set " & $aSndID[0] & " time format miliseconds") ;modify the $iHour, $iMin and $iSec parameters to be in milliseconds ;and add to $iMs $iMs += $iSec * 1000 $iMs += $iMin * 60 * 1000 $iMs += $iHour * 60 * 60 * 1000 If $aSndID[1] <> 0 Then $aSndID[2] = Round($iMs * $aSndID[1]) - $iMs $iMs = Round($iMs * $aSndID[1]) EndIf ; seek sound to time ($iMs) $iRet = __mciSendString("seek " & $aSndID[0] & " to " & $iMs) If _SoundPos($aSndID, 2) < 0 Then $aSndID[2] = 0 ;return If $iRet = 0 Then Return 1 Else Return SetError(1, 0, 0) EndIf EndFunc ;==>_SoundSeek ;=============================================================================== ; ; Function Name: _SoundStatus ; Description:: All devices can return the "not ready", "paused", "playing", and "stopped" values. ; Some devices can return the additional "open", "parked", "recording", and "seeking" values.(MSDN) ; Parameter(s): $sSndID - Sound ID returned by _SoundOpen or sound file ; Requirement(s): AutoIt 3.2 ++ ; Return Value(s): Sound Status ; Author(s): RazerM, Melba23 ; ;=============================================================================== ; Func _SoundStatus($aSndID) Local $vTemp If Not IsArray($aSndID) Then If Not FileExists($aSndID) Then Return SetError(3, 0, 0) ; invalid file/alias $vTemp = FileGetShortName($aSndID) Dim $aSndID[1] = [$vTemp] EndIf If StringInStr($aSndID[0], '!') Then Return SetError(3, 0, 0) ; invalid file/alias ;return status Return __mciSendString("status " & $aSndID[0] & " mode", 255) EndFunc ;==>_SoundStatus ;=============================================================================== ; ; Function Name: _SoundPos ; Description:: Returns the current position of the song ; Parameter(s): $sSndID - Sound ID returned by _SoundOpen or sound file, ; $iMode = 1 - hh:mm:ss, $iMode = 2 - milliseconds ; Requirement(s): AutoIt 3.2 ++ ; Return Value(s): Current Position - Success, @error = 1 - $iMode is invalid ; Author(s): RazerM, Melba23 ; ;=============================================================================== ; Func _SoundPos($aSndID, $iMode = 1) ;Declare variables Local $iSndPosMs, $iSndPosMin, $iSndPosHour, $iSndPosSecs, $sSndPosFormat, $vTemp ;validate $iMode If $iMode <> 1 And $iMode <> 2 Then Return SetError(1, 0, 0) If Not IsArray($aSndID) Then If Not FileExists($aSndID) Then Return SetError(3, 0, 0) ; invalid file/alias $vTemp = FileGetShortName($aSndID) Dim $aSndID[1] = [$vTemp] EndIf If StringInStr($aSndID[0], '!') Then Return SetError(3, 0, 0) ; invalid file/alias ;tell mci to use time in milliseconds __mciSendString("set " & $aSndID[0] & " time format miliseconds") ;receive position of sound $iSndPosMs = __mciSendString("status " & $aSndID[0] & " position", 255) If $aSndID[1] <> 0 Then $iSndPosMs -= $aSndID[2] EndIf ;modify data and assign to variables _TicksToTime($iSndPosMs, $iSndPosHour, $iSndPosMin, $iSndPosSecs) ;assign formatted data to $sSndPosFormat $sSndPosFormat = StringFormat("%02i:%02i:%02i", $iSndPosHour, $iSndPosMin, $iSndPosSecs) ;return correct variable If $iMode = 1 Then Return $sSndPosFormat If $iMode = 2 Then Return $iSndPosMs EndFunc ;==>_SoundPos ;internal functions Func __mciSendString($string, $iLen = 0) Local $iRet $iRet = DllCall("winmm.dll", "int", "mciSendStringA", "str", $string, "str", "", "long", $iLen, "long", 0) If Not @error Then Return $iRet[2] EndFunc ;==>__mciSendString Func __RandomStr($LEN) Local $string For $iCurrentPos = 1 To $LEN $string &= Chr(Random(97, 122, 1)) Next Return $string EndFunc ;==>__RandomStr ;=============================================================================== ; ; Function Name: [private] __ReadTLENFromMP3 ; Description:: Used internally within this file, not for general use ; Parameter(s): $sTag - >= 1024 bytes from 'read raw' mode. ; Requirement(s): File must be an mp3 AFAIK ; Return Value(s): Sound length (hh:mm:ss) - Success, 0 and @error = 1 - Failure ; Author(s): Melba23 ; Modified: RazerM ; ;=============================================================================== ; Func __ReadTLENFromMP3($sTag) Local $iTemp, $sTemp, $iLengthMs, $iLengthHour, $iLengthMin, $iLengthSecs ; Check that an ID3v2.3 tag is present If StringLeft($sTag, 10) <> "0x49443303" Then Return SetError(1, 0, 0) $iTemp = StringInStr($sTag, "544C454E") + 21 $sTag = StringTrimLeft($sTag, $iTemp) $sTemp = "" For $i = 1 To 32 Step 2 If StringMid($sTag, $i, 2) = "00" Then ExitLoop Else $sTemp &= StringMid($sTag, $i, 2) EndIf Next $iLengthMs = Number(_HexToString($sTemp)) If $iLengthMs > 0 Then _TicksToTime($iLengthMs, $iLengthHour, $iLengthMin, $iLengthSecs) ;Convert to hh:mm:ss and return Return StringFormat("%02i:%02i:%02i", $iLengthHour, $iLengthMin, $iLengthSecs) Else Return SetError(1, 0, 0) EndIf EndFunc ;==>__ReadTLENFromMP3 ;=============================================================================== ; ; Function Name: [private] __ReadXingFromMP3 ; Description:: Used internally within this file, not for general use ; Parameter(s): $sTag - first 5156 bytes from 'read raw' mode. ; Requirement(s): File must be an mp3 AFAIK ; Return Value(s): Sound length (hh:mm:ss) - Success, 0 and @error = 1 - Failure ; Author(s): Melba23 ; Modified: RazerM ; ;=============================================================================== ; Func __ReadXingFromMP3($sTag) Local $iXingPos, $iFlags, $iFrames, $sHeader, $iMPEGByte, $iFreqByte, $iMPEGVer, $iLayerNum, $iSamples, $iFreqNum, $iFrequency, $iLengthMs, $iLengthHours, $iLengthMins, $iLengthSecs $iXingPos = StringInStr($sTag, "58696E67") If $iXingPos = 0 Then Return SetError(1, 0, 0) ; Read fields flag $iFlags = Number("0x" & StringMid($sTag, $iXingPos + 14, 2)) If BitAND($iFlags, 1) = 1 Then $iFrames = Number("0x" & StringMid($sTag, $iXingPos + 16, 8)) Else Return SetError(1, 0, 0); No frames field EndIf ; Now to find Samples per frame & Sampling rate ; Go back to the frame header start $sHeader = StringMid($sTag, $iXingPos - 72, 8) ; Read the relevant bytes $iMPEGByte = Number("0x" & StringMid($sHeader, 4, 1)) $iFreqByte = Number("0x" & StringMid($sHeader, 6, 1)) ; Decode them ; 8 = MPEG-1, 0 = MPEG-2 $iMPEGVer = BitAND($iMPEGByte, 8) ; 2 = Layer III, 4 = Layer II, 6 = Layer I $iLayerNum = BitAND($iMPEGByte, 6) Switch $iLayerNum Case 6 $iSamples = 384 Case 4 $iSamples = 1152 Case 2 Switch $iMPEGVer Case 8 $iSamples = 1152 Case 0 $iSamples = 576 Case Else $iSamples = 0 EndSwitch Case Else $iSamples = 0 EndSwitch ; If not valid return If $iSamples = 0 Then Return SetError(1, 0, 0) ; 0 = bit 00, 4 = Bit 01, 8 = Bit 10 $iFreqNum = BitAND($iFreqByte, 12) Switch $iFreqNum Case 0 $iFrequency = 44100 Case 4 $iFrequency = 48000 Case 8 $iFrequency = 32000 Case Else $iFrequency = 0 EndSwitch ; If not valid return If $iFrequency = 0 Then Return SetError(1, 0, 0) ; MPEG-2 halves the value If $iMPEGVer = 0 Then $iFrequency = $iFrequency / 2 ; Duration in secs = No of frames * Samples per frame / Sampling freq $iLengthMs = Int(($iFrames * $iSamples / $iFrequency) * 1000) ; Convert to hh:mm:ss and return _TicksToTime($iLengthMs, $iLengthHours, $iLengthMins, $iLengthSecs) Return StringFormat("%02i:%02i:%02i", $iLengthHours, $iLengthMins, $iLengthSecs) EndFunc ;==>__ReadXingFromMP3 Changes: Changed order of sound-length methods.Optimised routine for TLEN and Xing by only reading in data once.Some bug fixes.Edit: Updated with a few minor bug fixes outlined by Melba23
  13. Thanks, I never thought that through. Will be fixed soon. This will also be fixed. I don't entirely understand what is happening here , so thanks for the help. 1. Yes that makes more sense, I shall change it to pass the file handle into the helper functions. 2. I did this because Xing and TLEN are set especially to cater for this purpose, but it does make more sense with file properties first now that you mention the hit it would have on CBR files.
  14. New beta: #include <Date.au3> #include <File.au3> #include <String.au3> ;=============================================================================== ; ; Function Name: _SoundOpen ; Description:: Opens a sound file for use with other _Sound functions ; Parameter(s): $sFile - The sound file, $sAlias[optional] - a name such as sound1, ; if you do not specify one it is randomly generated ; Requirement(s): AutoIt 3.2 ++ ; Return Value(s): string(the sound id) - Success, 0 - Failure ; @extended <> 0 - open failed, @error = 2 - File doesn't exist, ; @error = 3 - alias contains whitespace ; Author(s): RazerM, Melba23, some code by Simucal, PsaltyDS ; ;=============================================================================== ; Func _SoundOpen($sFile, $sAlias = "") ;Declare variables Local $aSndID[3], $sSndID, $iCurrentPos, $iRet, $asAlias, $fTryNextMethod = False Local $szDrive, $szDir, $szFName, $szExt, $iSndLenMs, $iSndLenMin, $iSndLenHour, $iSndLenSecs, $sSndLenFormat Local $sSndDirName, $sSndFileName, $sSndDirShortName, $oShell, $oShellDir, $oShellDirFile, $sRaw, $aInfo Local $sTrackLength, $iSoundTicks, $iActualTicks, $iVBRRatio, $aiTime ;check for file If Not FileExists($sFile) Then Return SetError(2, 0, 0) ;search for whitespace by character $asAlias = StringSplit($sAlias, "") For $iCurrentPos = 1 To $asAlias[0] If StringIsSpace($asAlias[$iCurrentPos]) Then Return SetError(3, 0, 0) Next ;create random alias if one is not supplied If $sAlias = "" Then $sSndID = __RandomStr(10) Else $sSndID = $sAlias EndIf If StringInStr($sSndID, '!') Then Return SetError(3, 0, 0) ;invalid file/alias $aSndID[0] = $sSndID _PathSplit($sFile, $szDrive, $szDir, $szFName, $szExt) If $szDrive = "" Then $sSndDirName = @WorkingDir & "\" Else $sSndDirName = $szDrive & $szDir EndIf $sSndFileName = $szFName & $szExt $sSndDirShortName = FileGetShortName($sSndDirName, 1) ;open file $iRet = __mciSendString("open " & FileGetShortName($sFile) & " alias " & $aSndID[0]) If $szExt = ".mp3" Then $sTrackLength = __ReadXingFromMP3(FileGetShortName($sSndDirName & $sSndFileName)) If @error Then $fTryNextMethod = True Else $fTryNextMethod = True EndIf If $fTryNextMethod And $szExt = ".mp3" Then $sTrackLength = __ReadTLENFromMP3(FileGetShortName($sSndDirName & $sSndFileName)) If @error Then $fTryNextMethod = True Else $fTryNextMethod = True EndIf If $fTryNextMethod Then $fTryNextMethod = False $oShell = ObjCreate("shell.application") If IsObj($oShell) Then $oShellDir = $oShell.NameSpace ($sSndDirShortName) If IsObj($oShellDir) Then $oShellDirFile = $oShellDir.Parsename ($sSndFileName) If IsObj($oShellDirFile) Then $sRaw = $oShellDir.GetDetailsOf ($oShellDirFile, -1) $aInfo = StringRegExp($sRaw, ": ([0-9]{2}:[0-9]{2}:[0-9]{2})", 3) If Not IsArray($aInfo) Then $fTryNextMethod = True Else $sTrackLength = $aInfo[0] EndIf Else $fTryNextMethod = True EndIf Else $fTryNextMethod = True EndIf Else $fTryNextMethod = True EndIf EndIf If $fTryNextMethod Then ;tell mci to use time in milliseconds __mciSendString("set " & $aSndID[0] & " time format miliseconds") ;receive length of sound $iSndLenMs = __mciSendString("status " & $aSndID[0] & " length", 255) ;assign modified data to variables _TicksToTime($iSndLenMs, $iSndLenHour, $iSndLenMin, $iSndLenSecs) ;assign formatted data to $sSndLenFormat $sTrackLength = StringFormat("%02i:%02i:%02i", $iSndLenHour, $iSndLenMin, $iSndLenSecs) $fTryNextMethod = False EndIf ; Convert Track_Length to mSec $aiTime = StringSplit($sTrackLength, ":") $iActualTicks = _TimeToTicks($aiTime[1], $aiTime[2], $aiTime[3]) ;tell mci to use time in milliseconds __mciSendString("set " & $aSndID[0] & " time format miliseconds") ;;Get estimated length $iSoundTicks = __mciSendString("status " & $aSndID[0] & " length", 255) ;Compare to actual length If Abs($iSoundTicks - $iActualTicks) < 1000 Then ;Assume CBR, as our track length from shell.application is only accurate within 1000ms $iVBRRatio = 0 Else ;Set correction ratio for VBR operations $iVBRRatio = $iSoundTicks / $iActualTicks EndIf $aSndID[1] = $iVBRRatio $aSndID[2] = 0 Return SetError(0, $iRet, $aSndID) EndFunc ;==>_SoundOpen ;=============================================================================== ; ; Function Name: _SoundClose ; Description:: Closes a sound ; Parameter(s): $sSndID - Sound ID returned by _SoundOpen ; Requirement(s): AutoIt 3.2 ++ ; Return Value(s): 1 - Success, 0 and @error = 1 - Failure ; Author(s): RazerM, Melba23 ; ;=============================================================================== ; Func _SoundClose($aSndID) If Not IsArray($aSndID) Then Return SetError(3, 0, 0) ; invalid file/alias If StringInStr($aSndID[0], '!') Then Return SetError(3, 0, 0) ; invalid file/alias If __mciSendString("close " & $aSndID[0]) = 0 Then Return 1 Else Return SetError(1, 0, 0) EndIf EndFunc ;==>_SoundClose ;=============================================================================== ; ; Function Name: _SoundPlay ; Description:: Plays a sound from the current position (beginning is the default) ; Parameter(s): $sSndID - Sound ID returned by _SoundOpen or sound file ; $fWait - If set to 1 the script will wait for the sound to finish before continuing ; - If set to 0 the script will continue while the sound is playing ; Requirement(s): AutoIt 3.2 ++ ; Return Value(s): 1 - Success, 0 - Failure ; @error = 2 - $fWait is invalid, @error = 1 - play failed ; Author(s): RazerM, Melba23 ; ;=============================================================================== ; Func _SoundPlay($aSndID, $fWait = 0) ;Declare variables Local $iRet, $vTemp ;validate $fWait If $fWait <> 0 And $fWait <> 1 Then Return SetError(2, 0, 0) If Not IsArray($aSndID) Then If Not FileExists($aSndID) Then Return SetError(3, 0, 0) ; invalid file/alias $vTemp = FileGetShortName($aSndID) Dim $aSndID[1] = [$vTemp] EndIf If StringInStr($aSndID[0], '!') Then Return SetError(3, 0, 0) ; invalid file/alias ;if sound has finished, seek to start If _SoundPos($aSndID, 2) = _SoundLength($aSndID, 2) Then __mciSendString("seek " & $aSndID[0] & " to start") ;If $fWait = 1 then pass wait to mci If $fWait = 1 Then $iRet = __mciSendString("play " & $aSndID[0] & " wait") Else $iRet = __mciSendString("play " & $aSndID[0]) EndIf ;return If $iRet = 0 Then Return 1 Else Return SetError(1, 0, 0) EndIf EndFunc ;==>_SoundPlay ;=============================================================================== ; ; Function Name: _SoundStop ; Description:: Stops the sound ; Parameter(s): $sSndID - Sound ID returned by _SoundOpen or sound file ; Requirement(s): AutoIt 3.2 ++ ; Return Value(s): 1 - Success, 0 and @error = 1 - Failure, ; Author(s): RazerM, Melba23 ; ;=============================================================================== ; Func _SoundStop($aSndID) ;Declare variables Local $iRet, $iRet2, $vTemp If Not IsArray($aSndID) Then If Not FileExists($aSndID) Then Return SetError(3, 0, 0) ; invalid file/alias $vTemp = FileGetShortName($aSndID) Dim $aSndID[1] = [$vTemp] EndIf If StringInStr($aSndID[0], '!') Then Return SetError(3, 0, 0) ; invalid file/alias ;seek to start $iRet = __mciSendString("seek " & $aSndID[0] & " to start") ;stop $iRet2 = __mciSendString("stop " & $aSndID[0]) ;return If $iRet = 0 And $iRet2 = 0 Then Return 1 Else Return SetError(1, 0, 0) EndIf EndFunc ;==>_SoundStop ;=============================================================================== ; ; Function Name: _SoundPause ; Description:: Pauses the sound ; Parameter(s): $sSndID - Sound ID returned by _SoundOpen or sound file ; Requirement(s): AutoIt 3.2 ++ ; Return Value(s): 1 - Success, 0 and @error = 1 - Failure, ; Author(s): RazerM, Melba23 ; ;=============================================================================== ; Func _SoundPause($aSndID) ;Declare variables Local $iRet, $vTemp If Not IsArray($aSndID) Then If Not FileExists($aSndID) Then Return SetError(3, 0, 0) ; invalid file/alias $vTemp = FileGetShortName($aSndID) Dim $aSndID[1] = [$vTemp] EndIf If StringInStr($aSndID[0], '!') Then Return SetError(3, 0, 0) ; invalid file/alias ;pause sound $iRet = __mciSendString("pause " & $aSndID[0]) ;return If $iRet = 0 Then Return 1 Else Return SetError(1, 0, 0) EndIf EndFunc ;==>_SoundPause ;=============================================================================== ; ; Function Name: _SoundResume ; Description:: Resumes the sound after being paused ; Parameter(s): $sSndID - Sound ID returned by _SoundOpen or sound file ; Requirement(s): AutoIt 3.2 ++ ; Return Value(s): 1 - Success, 0 and @error = 1 - Failure, ; Author(s): RazerM, Melba23 ; ;=============================================================================== ; Func _SoundResume($aSndID) ;Declare variables Local $iRet, $vTemp If Not IsArray($aSndID) Then If Not FileExists($aSndID) Then Return SetError(3, 0, 0) ; invalid file/alias $vTemp = FileGetShortName($aSndID) Dim $aSndID[1] = [$vTemp] EndIf If StringInStr($aSndID[0], '!') Then Return SetError(3, 0, 0) ; invalid file/alias ;resume sound $iRet = __mciSendString("resume " & $aSndID[0]) ;return If $iRet = 0 Then Return 1 Else Return SetError(1, 0, 0) EndIf EndFunc ;==>_SoundResume ;=============================================================================== ; ; Function Name: _SoundLength ; Description:: Returns the length of the sound in the format hh:mm:ss ; Parameter(s): $sSndID - Sound ID returned by _SoundOpen or sound file, ; $iMode = 1 - hh:mm:ss, $iMode = 2 - milliseconds ; Requirement(s): AutoIt 3.2 ++ ; Return Value(s): Length of the sound - Success, 0 and @error = 1 - $iMode is invalid ; Author(s): RazerM, Melba23 ; Mofified: jpm ; ;=============================================================================== ; Func _SoundLength($aSndID, $iMode = 1) ;Declare variables Local $iSndLenMs, $iSndLenMin, $iSndLenHour, $iSndLenSecs, $sSndLenFormat, $vTemp = "" ;validate $iMode If $iMode <> 1 And $iMode <> 2 Then Return SetError(1, 0, 0) If Not IsArray($aSndID) Then If Not FileExists($aSndID) Then Return SetError(3, 0, 0) ; invalid file/alias $vTemp = FileGetShortName($aSndID) Dim $aSndID[3] $aSndID = _SoundOpen($vTemp) EndIf If StringInStr($aSndID[0], '!') Then Return SetError(3, 0, 0) ; invalid file/alias ;tell mci to use time in milliseconds __mciSendString("set " & $aSndID[0] & " time format miliseconds") ;receive length of sound $iSndLenMs = __mciSendString("status " & $aSndID[0] & " length", 255) If $aSndID[1] <> 0 Then $iSndLenMs = Round($iSndLenMs / $aSndID[1]) If $vTemp <> "" Then _SoundClose($aSndID) ;if user called _SoundLength with a filename ;assign modified data to variables _TicksToTime($iSndLenMs, $iSndLenHour, $iSndLenMin, $iSndLenSecs) ;assign formatted data to $sSndLenFormat $sSndLenFormat = StringFormat("%02i:%02i:%02i", $iSndLenHour, $iSndLenMin, $iSndLenSecs) ;return correct variable If $iMode = 1 Then Return $sSndLenFormat If $iMode = 2 Then Return $iSndLenMs EndFunc ;==>_SoundLength ;=============================================================================== ; ; Function Name: _SoundSeek ; Description:: Seeks the sound to a specified time ; Parameter(s): $sSndID - Sound ID returned by _SoundOpen (must NOT be a file), $iHour, $iMin, $iSec ; Requirement(s): AutoIt 3.2 ++ ; Return Value(s): 1 - Success, 0 and @error = 1 - Failure, ; Author(s): RazerM, Melba23 ; ;=============================================================================== ; Func _SoundSeek(ByRef $aSndID, $iHour, $iMin, $iSec) ;Declare variables Local $iMs = 0, $iRet, $vTemp If Not IsArray($aSndID) Then If Not FileExists($aSndID) Then Return SetError(3, 0, 0) ; invalid file/alias $vTemp = FileGetShortName($aSndID) Dim $aSndID[1] = [$vTemp] EndIf If StringInStr($aSndID[0], '!') Then Return SetError(3, 0, 0) ; invalid file/alias ;prepare mci to receive time in milliseconds __mciSendString("set " & $aSndID[0] & " time format miliseconds") ;modify the $iHour, $iMin and $iSec parameters to be in milliseconds ;and add to $iMs $iMs += $iSec * 1000 $iMs += $iMin * 60 * 1000 $iMs += $iHour * 60 * 60 * 1000 If $aSndID[1] <> 0 Then $aSndID[2] = Round($iMs * $aSndID[1]) - $iMs $iMs = Round($iMs * $aSndID[1]) EndIf ; seek sound to time ($iMs) $iRet = __mciSendString("seek " & $aSndID[0] & " to " & $iMs) If _SoundPos($aSndID, 2) < 0 Then $aSndID[2] = 0 ;return If $iRet = 0 Then Return 1 Else Return SetError(1, 0, 0) EndIf EndFunc ;==>_SoundSeek ;=============================================================================== ; ; Function Name: _SoundStatus ; Description:: All devices can return the "not ready", "paused", "playing", and "stopped" values. ; Some devices can return the additional "open", "parked", "recording", and "seeking" values.(MSDN) ; Parameter(s): $sSndID - Sound ID returned by _SoundOpen or sound file ; Requirement(s): AutoIt 3.2 ++ ; Return Value(s): Sound Status ; Author(s): RazerM, Melba23 ; ;=============================================================================== ; Func _SoundStatus($aSndID) Local $vTemp If Not IsArray($aSndID) Then If Not FileExists($aSndID) Then Return SetError(3, 0, 0) ; invalid file/alias $vTemp = FileGetShortName($aSndID) Dim $aSndID[1] = [$vTemp] EndIf If StringInStr($aSndID[0], '!') Then Return SetError(3, 0, 0) ; invalid file/alias ;return status Return __mciSendString("status " & $aSndID[0] & " mode", 255) EndFunc ;==>_SoundStatus ;=============================================================================== ; ; Function Name: _SoundPos ; Description:: Returns the current position of the song ; Parameter(s): $sSndID - Sound ID returned by _SoundOpen or sound file, ; $iMode = 1 - hh:mm:ss, $iMode = 2 - milliseconds ; Requirement(s): AutoIt 3.2 ++ ; Return Value(s): Current Position - Success, @error = 1 - $iMode is invalid ; Author(s): RazerM, Melba23 ; ;=============================================================================== ; Func _SoundPos($aSndID, $iMode = 1) ;Declare variables Local $iSndPosMs, $iSndPosMin, $iSndPosHour, $iSndPosSecs, $sSndPosFormat, $vTemp ;validate $iMode If $iMode <> 1 And $iMode <> 2 Then Return SetError(1, 0, 0) If Not IsArray($aSndID) Then If Not FileExists($aSndID) Then Return SetError(3, 0, 0) ; invalid file/alias $vTemp = FileGetShortName($aSndID) Dim $aSndID[1] = [$vTemp] EndIf If StringInStr($aSndID[0], '!') Then Return SetError(3, 0, 0) ; invalid file/alias ;tell mci to use time in milliseconds __mciSendString("set " & $aSndID[0] & " time format miliseconds") ;receive position of sound $iSndPosMs = __mciSendString("status " & $aSndID[0] & " position", 255) If $aSndID[1] <> 0 Then $iSndPosMs -= $aSndID[2] EndIf ;modify data and assign to variables _TicksToTime($iSndPosMs, $iSndPosHour, $iSndPosMin, $iSndPosSecs) ;assign formatted data to $sSndPosFormat $sSndPosFormat = StringFormat("%02i:%02i:%02i", $iSndPosHour, $iSndPosMin, $iSndPosSecs) ;return correct variable If $iMode = 1 Then Return $sSndPosFormat If $iMode = 2 Then Return $iSndPosMs EndFunc ;==>_SoundPos ;internal functions Func __mciSendString($string, $iLen = 0) Local $iRet $iRet = DllCall("winmm.dll", "int", "mciSendStringA", "str", $string, "str", "", "long", $iLen, "long", 0) If Not @error Then Return $iRet[2] EndFunc ;==>__mciSendString Func __RandomStr($LEN) Local $string For $iCurrentPos = 1 To $LEN $string &= Chr(Random(97, 122, 1)) Next Return $string EndFunc ;==>__RandomStr ;=============================================================================== ; ; Function Name: [private] __ReadTLENFromMP3 ; Description:: Used internally within this file, not for general use ; Parameter(s): $sFile - filename of mp3 ; Requirement(s): File must be an mp3 AFAIK ; Return Value(s): Sound length (hh:mm:ss) - Success, 0 and @error = 1 - Failure ; Author(s): Melba23 ; Modified: RazerM ; ;=============================================================================== ; Func __ReadTLENFromMP3($sFile) Local $hFile, $sTag, $iLengthMs, $iLengthHour, $iLengthMin, $iLengthSecs ; Read tag info from file $hFile = FileOpen($sFile, 4) $sTag = FileRead($hFile, 1024) FileClose($hFile) ; Check that an ID3v2.3 tag is present If StringLeft($sTag, 10) <> "0x49443303" Then Return SetError(1, 0, 0) $iLengthMs = Number(_HexToString(StringTrimLeft($sTag, StringInStr($sTag, "544C454E") + 21))) If $iLengthMs > 0 Then _TicksToTime($iLengthMs, $iLengthHour, $iLengthMin, $iLengthSecs) ;Convert to hh:mm:ss and return Return StringFormat("%02i:%02i:%02i", $iLengthHour, $iLengthMin, $iLengthSecs) Else Return SetError(1, 0, 0) EndIf EndFunc ;==>__ReadTLENFromMP3 ;=============================================================================== ; ; Function Name: [private] __ReadXingFromMP3 ; Description:: Used internally within this file, not for general use ; Parameter(s): $sFile - filename of mp3 ; Requirement(s): File must be an mp3 AFAIK ; Return Value(s): Sound length (hh:mm:ss) - Success, 0 and @error = 1 - Failure ; Author(s): Melba23 ; Modified: RazerM ; ;=============================================================================== ; Func __ReadXingFromMP3($sFile) Local $hFile, $sTag, $iXingPos, $iFlags, $iFrames, $sHeader, $iMPEGByte, $iFreqByte, $iMPEGVer, $iLayerNum, $iSamples, $iFreqNum, $iFrequency, $iLengthMs, $iLengthHours, $iLengthMins, $iLengthSecs ; Read tag info from file $hFile = FileOpen($sFile, 4) $sTag = FileRead($hFile, 5156) FileClose($hFile) $iXingPos = StringInStr($sTag, "58696E67") If $iXingPos = 0 Then Return SetError(1, 0, 0) ; Read fields flag $iFlags = Number("0x" & StringMid($sTag, $iXingPos + 14, 2)) If BitAND($iFlags, 1) = 1 Then $iFrames = Number("0x" & StringMid($sTag, $iXingPos + 16, 8)) Else Return SetError(1, 0, 0); No frames field EndIf ; Now to find Samples per frame & Sampling rate ; Go back to the frame header start $sHeader = StringMid($sTag, $iXingPos - 72, 8) ; Read the relevant bytes $iMPEGByte = Number("0x" & StringMid($sHeader, 4, 1)) $iFreqByte = Number("0x" & StringMid($sHeader, 6, 1)) ; Decode them ; 8 = MPEG-1, 0 = MPEG-2 $iMPEGVer = BitAND($iMPEGByte, 8) ; 2 = Layer III, 4 = Layer II, 6 = Layer I $iLayerNum = BitAND($iMPEGByte, 6) Switch $iLayerNum Case 6 $iSamples = 384 Case 4 $iSamples = 1152 Case 2 Switch $iMPEGVer Case 8 $iSamples = 1152 Case 0 $iSamples = 576 Case Else $iSamples = 0 EndSwitch Case Else $iSamples = 0 EndSwitch ; If not valid return If $iSamples = 0 Then Return SetError(1, 0, 0) ; 0 = bit 00, 4 = Bit 01, 8 = Bit 10 $iFreqNum = BitAND($iFreqByte, 12) Switch $iFreqNum Case 0 $iFrequency = 44100 Case 4 $iFrequency = 48000 Case 8 $iFrequency = 32000 Case Else $iFrequency = 0 EndSwitch ; If not valid return If $iFrequency = 0 Then Return SetError(1, 0, 0) ; MPEG-2 halves the value If $iMPEGVer = 0 Then $iFrequency = $iFrequency / 2 ; Duration in secs = No of frames * Samples per frame / Sampling freq $iLengthMs = Int(($iFrames * $iSamples / $iFrequency) * 1000) ; Convert to hh:mm:ss and return _TicksToTime($iLengthMs, $iLengthHours, $iLengthMins, $iLengthSecs) Return StringFormat("%02i:%02i:%02i", $iLengthHours, $iLengthMins, $iLengthSecs) EndFunc ;==>__ReadXingFromMP3 Changes: _SoundPos() reporting incorrect value for long audio files._SoundLength() reports correct length with filenames now.Added Xing and TLEN methods for mp3 files.Internal functions use double underscores now.Changed variable names to improve readability.Now uses _TicksToTime() and _TimeToTicks().
×
×
  • Create New...