Skip to content

Instantly share code, notes, and snippets.

@tillig
Created January 4, 2017 23:54
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save tillig/60138a69606729705deeb4505ee9a39d to your computer and use it in GitHub Desktop.
Save tillig/60138a69606729705deeb4505ee9a39d to your computer and use it in GitHub Desktop.
Automate running hymn against an iTunes library for removing DRM.
' M4P Backup
' by Travis Illig
' http://www.paraesthesia.com
'
' This script backs up your protected iTunes music (*.m4p) along with a
' decrypted version (*.m4a). The decryption is done using the "hymn"
' program, available at http://hymn-project.org/.
'
' Note that for "hymn" to properly decrypt your iTunes files, you may
' need to use the "FairKeys" program, available at
' http://www.nanocrew.net/software/.
'
' The script finds all *.m4p files in your Music Library. It copies those
' files, in a similar directory tree as your Music Library, into the backup
' folder specified. It then looks to see if there is a corresponding *.m4a
' file available. If there is, it copies that file into the backup folder.
' If there isn't, it runs "hymn" to decrypt the *.m4p file into the *.m4a
' file, then copies that decrypted file to the backup folder.
'
' In the below section marked "CONFIGURATION," set up the required file and
' folder paths as specified.
Option Explicit
'==============================================================================
'==============================================================================
' CONFIGURATION
' Set the following variables as noted.
Dim MUSICLIBRARYPATH, HYMNPATH, BACKUPFOLDERPATH
' Full path to "Music Library" folder, including trailing slash.
MUSICLIBRARYPATH = "F:\Music Library\"
' Full path to "hymn.exe" program.
HYMNPATH = "C:\Program Files\hymn-0.7.1\hymn.exe"
' Full path to backup folder, including trailing slash.
BACKUPFOLDERPATH = "F:\backup\Protected Music\"
'==============================================================================
'==============================================================================
'==============================================================================
' PROGRAM
' DO NOT CHANGE ANYTHING BELOW!
' Set up common objects and check for file paths
On Error Resume Next
Dim VERSION
VERSION = "1.0"
Dim fso, wshell, MusicLibraryFolder, BackupFolder
Set fso = CreateObject("Scripting.FileSystemObject")
If (Err.Number <> 0) Then
WScript.Echo "Unable to create FileSystemObject. Exiting."
WScript.Quit(1)
End If
Err.Clear
Set wshell = CreateObject("WScript.Shell")
If (Err.Number <> 0) Then
WScript.Echo "Unable to create WScript.Shell. Exiting."
WScript.Quit(1)
End If
Err.Clear
Set MusicLibraryFolder = fso.GetFolder(MUSICLIBRARYPATH)
If (Err.Number <> 0) Then
WScript.Echo "Unable to locate Music Library folder at [" & MUSICLIBRARYPATH & "]. Exiting."
WScript.Quit(1)
End If
Err.Clear
Set BackupFolder = fso.GetFolder(BACKUPFOLDERPATH)
If (Err.Number <> 0) Then
WScript.Echo "Unable to locate backup folder at [" & BACKUPFOLDERPATH & "]. Exiting."
WScript.Quit(1)
End If
Err.Clear
If (Not fso.FileExists(HYMNPATH)) Then
WScript.Echo "Unable to locate hymn.exe at [" & HYMNPATH & "]. Exiting."
WScript.Quit(1)
End If
WScript.Echo WScript.ScriptName & " " & VERSION
WScript.Echo "Music Library: " & MUSICLIBRARYPATH
WScript.Echo "Backup Folder: " & BACKUPFOLDERPATH
WScript.Echo "hymn.exe: " & HYMNPATH
WScript.Echo "Starting Backup..."
DoRecursiveBackup MusicLibraryFolder
WScript.Echo "Backup COMPLETE."
Sub DoRecursiveBackup(FolderObj)
' For all of the m4p files in the current folder...
Dim file
For Each file In FolderObj.Files
If (LCase(Right(file.Name, 4)) = ".m4p") Then
WScript.Echo "Found: " & file.Path
' Calculate the complete backup folder path
Dim newPath
newPath = Right(file.Path, Len(file.Path) - Len(MusicLibraryFolder.Path))
newPath = Left(newPath, Len(newPath) - Len(file.Name))
newPath = BackupFolder.Path & newPath
' Xcopy the m4p to the backup folder
WScript.Echo "Copying to: " & newPath
ExecuteXCopy file.Path, newPath
' Get the corresponding m4a
Dim m4aPath
m4aPath = Left(file.Path, Len(file.Path) - 4) & ".m4a"
' If it doesn't exist, run "hymn" to create it
If (Not fso.FileExists(m4aPath)) Then
ExecuteHymn file.Path
End If
' If it still doesn't exist, "hymn" didn't make it; write error message and continue
If (Not fso.FileExists(m4aPath)) Then
WScript.Echo "Decryption failed. Unable to back up decrypted version of [" & file.Path & "]. Continuing backup process..."
Else
'The M4A version exists; copy it.
ExecuteXCopy m4aPath, newPath
End If
End If
Next
' For all of the folders in the current folder, recurse
Dim folder
For Each folder In FolderObj.SubFolders
DoRecursiveBackup folder
Next
End Sub
Sub ExecuteHymn(M4PPath)
' If the M4PPath doesn't exist, exit the sub
If (Not fso.FileExists(M4PPath)) Then
WScript.Echo "Unable to locate file [" & M4PPath & "] for hymn.exe processing."
Exit Sub
End If
' Run hymn.exe to convert the M4P to M4A
WScript.Echo "Executing 'hymn.exe' to decrypt [" & M4PPath & "]"
ExecuteProgram("""" & HYMNPATH & """ """ & M4PPath & """")
End Sub
Sub ExecuteXCopy(filepath, destfolderpath)
ExecuteProgram("xcopy /y """ & filepath & """ """ & destfolderpath & """")
End Sub
Sub ExecuteProgram(CommandLine)
Dim commandexec, output
Set commandexec = wshell.Exec(CommandLine)
Do While commandexec.Status = 0
WScript.Sleep(50)
Loop
output = commandexec.StdOut.ReadAll & vbCrLf & commandexec.StdErr.ReadAll
WScript.Echo output
End Sub
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment