Search code examples
javascriptituneshex

Convert HEX iTunes Persistent ID to High and Low 32-bit forms


On a Mac, I can extract the "Persistent ID" for a particular song from the "iTunes Music Library.xml" file and then use Applescript to play that song like so:

tell application "iTunes"   
    set thePersistentId to "F040658A7687B12D"
    set theSong to (some track of playlist "Music" whose persistent ID is thePersistentId)  
    play theSong with once  
end tell  

On a PC, I can extract the "Persistent ID" from the XML file in the same way. The documentation for the iTunes COM interface says the function "ItemByPersistentId" has two parameters: "highID" (The high 32 bits of the 64-bit persistent ID) and "lowID" (The low 32 bits of the 64-bit persistent ID). but I can't figure out how to convert the hex-based value to the high and low 32-bit values the ItemByPersistentId function wants.

var thePersistentId = "F040658A7687B12D";  
var iTunes = WScript.CreateObject("iTunes.Application"); 
var n = parseInt(thePersistentId);  
var high = (do something with n?);  
var low = (do something else with n?);  
iTunes.LibraryPlaylist.tracks.ItemByPersistentId(high,low).play();  

Solution

  • I don't know what the situation is on the windows script host, but some JS clients have a 32 bit int, so your var n = parseInt(thePersistentId); is doubly troublesome. You should always include the base when using parseInt (e.g. parseInt(hexValue, 16), parseInt(octValue, 8)).

    To avoid 32 bit script interpreter limitations, you can extract the lower 32 bits and upper 32 bits seperately. Each hex digit is 4 bits, so the lower 32 bits are the last 8 characters of your persistent ID, and the upper 32 bits are the remaining 8 (unless it has the 0x prefix, then it's the next rightmost chunk of 8 characters).

    var hexId = "XXXXX";   
    var iTunes = WScript.CreateObject("iTunes.Application");  
    
    //the following two statements assume you have a valid 64 bit hex, 
    //you may want to verify the length of the string
    
    //grab and parse the last 8 characters of your string
    var low = parseInt(hexId.substr(hexId.length - 8), 16);
    //grab and parse the next last 8 characters of your string
    var high = parseInt(hexId.substr(hexId.length - 16, 8), 16);
    iTunes.LibraryPlaylist.tracks.ItemByPersistentId(high,low).play(); 
    

    Edit: From what I've read in the iTuner source code, it looks like highID is actually the upper 4 bytes, and lowID the lower 4 bytes, not 8 bytes (thus discarding the middle 8 bytes of the persistentID...). Here's a modified attempt:

    //assumes hex strings with no "0x" prefix
    //grab and parse the last 4 characters of your string
    var low = parseInt(hexId.substr(hexId.length - 4), 16);
    //grab, pad and parse the first 4 characters of your string
    var high = parseInt(hexId.substr(0, 4) + "0000", 16);