Location: PHPKode > projects > XRNS-PHP > xrns_sort_instruments.php
<?php

/*

Requires: PHP5 and Info-Zip (http://www.info-zip.org/)
Usage: `php xrns_sort_instruments.php /path/to/file1.xrns file2.xrns`
Will output resulting file to current working directory

Public Domain, last modified December 31st, 2008
Coded by Dac Chartrand of http://www.trotch.com/

*/

// ----------------------------------------------------------------------------
// Variables
// ----------------------------------------------------------------------------

$tmp_dir = '/tmp';

// ----------------------------------------------------------------------------
// Requires
// ----------------------------------------------------------------------------

require_once('xrns_functions.php');

// ----------------------------------------------------------------------------
// Functions
// ----------------------------------------------------------------------------

function dirsize($dirname) {

    if (!is_dir($dirname) || !is_readable($dirname)) {
        return false;
    }

    $dirname_stack[] = $dirname;
    $size = 0;

    do {
        $dirname = array_shift($dirname_stack);
        $handle = opendir($dirname);
        while (false !== ($file = readdir($handle))) {
            if ($file != '.' && $file != '..' && is_readable($dirname . '/' . $file)) {
                if (is_dir($dirname . '/' . $file)) {
                    $dirname_stack[] = $dirname . '/' . $file;
                }
                $size += filesize($dirname . '/' . $file);
            }
        }
        closedir($handle);
    } while (count($dirname_stack) > 0);

    return $size;
}

// ----------------------------------------------------------------------------
// Check Variables
// ----------------------------------------------------------------------------

// get filename component of path
$argv[0] = basename($argv[0]);
if (!is_dir($tmp_dir)) {
    $tmp_dir = get_temp_dir();
    if (!$tmp_dir) die("Error: Please set \$tmp_dir in $argv[0] to an existing directory.\n");
}

// ----------------------------------------------------------------------------
// Check User Input
// ----------------------------------------------------------------------------

if ($argc != 3) {
    echo "Error: $argv[0] expects 2 parameters.\n";
    echo "Usage: `php $argv[0] /path/to/file1.xrns file2.xrns`\n";
    echo "$argv[0] will output resulting file (file2.xrns) to current working directory.\n";
    die();
}

if (!file_exists($argv[1])) die("Error: The file $argv[1] was not found.\n");
if (!(preg_match('/(\.zip$|\.xrns$)/i', $argv[2]))) {
    die("Error: The filename $argv[2] is invalid, use .xrns (or .zip)\n");
}

$song1 = $argv[1];
$song2 = $argv[2];

// ----------------------------------------------------------------------------
// Unpack
// ----------------------------------------------------------------------------

echo "---------------------------------------\n";
echo "$argv[0] is working...\n";
echo date("D M j G:i:s T Y\n");
echo "---------------------------------------\n";

echo "Using temporary directory: $tmp_dir\n";

// Create a unique directory
$unzip1 = $tmp_dir . '/xrns_sort_instruments_' . md5(uniqid(mt_rand(), true)) . '_Track01/';

// Unzip song1
$result = UnzipAllFiles($song1, $unzip1);
if($result === FALSE) {
    echo "Error: There was a problem unzipping the first file.\n";
    die();
}


// Load XML
$sx1 = simplexml_load_file($unzip1 . 'Song.xml');


// ----------------------------------------------------------------------------
// Do the dirty
// ----------------------------------------------------------------------------

$sort_me = array();
$size_me = array();
$i = 0;
foreach ($sx1->Instruments->Instrument as $inst) {

    // Store Instrument nodes
    $sort_me[$i] = $inst;

    // Store instrument sizes
    $size = dirsize($unzip1 . 'SampleData/Instrument' . str_pad(($i), 2, '0', STR_PAD_LEFT) . ' (' . trim($inst->Name) . ')');
    $size_me[$i] = $size;

    ++$i;
}

arsort($size_me); // Sort
// print_r($size_me); // Debug

// Make a new directory to avoid overwriting instruments with the same name
mkdir($unzip1 .'SampleDataNew');

$sorted = array();
$dupe_dir = array();
$search_replace = array();
$i = 0;
foreach($size_me as $key => $val) {

    // We need to clone otherwise the nodes, which are references by default,
    // disapear when we delete them
    $sorted[$i] = clone $sort_me[$key];

    // Keep track of instruments in order to swap them later
    $tmp = sprintf("%02X", $key);
    $search_replace[$tmp] = sprintf("%02X", $i);

    // Move the files
    if ($val !== false) {

        $name = trim($sort_me[$key]->Name);
        $dirname1 = $unzip1 . 'SampleData/Instrument' . str_pad(($key), 2, '0', STR_PAD_LEFT) . " ($name)";
        $dirname2 = $unzip1 . 'SampleDataNew/Instrument' . str_pad(($i), 2, '0', STR_PAD_LEFT) . " ($name)";

        dircopy($dirname1, $dirname2);

        // Debug
        // echo "Source: $dirname1 \n";
        // echo "Dest: $dirname2 \n\n";

    }

    ++$i;

}

// Put humpty back together again
obliterate_directory($unzip1 . 'SampleData');
mkdir($unzip1 .'SampleData');
dircopy($unzip1 . 'SampleDataNew', $unzip1 . 'SampleData');

// print_r($search_replace); // Debug
// Search and replace
foreach ($sx1->PatternPool->Patterns->Pattern as $p) {
    foreach ($p->Tracks->PatternTrack as $x) if ($x->Lines->Line) {
        foreach ($x->Lines->Line as $y) if ($y->NoteColumns->NoteColumn) {
            foreach ($y->NoteColumns->NoteColumn as $z) if ($z->Instrument) {

                $tmp = $z->Instrument . ''; // Stringify
                if(isset($search_replace[$tmp]))
                    $z->Instrument = $search_replace[$tmp];

            }
        }
    }
}

// Delete stuff
$total = count($sx1->Instruments->Instrument);
for($i = $total - 1; $i >= 0; --$i) {
    unset($sx1->Instruments->Instrument[$i]);
}

// Append stuff
foreach($sorted as $inst) {
    simplexml_append($sx1->Instruments, $inst);
}


// ----------------------------------------------------------------------------
// Validate
// ----------------------------------------------------------------------------

if (!xrns_xsd_check($sx1, (int)$sx1['doc_version'])) {

    echo "Error: XML is invalid!\n";
    obliterate_directory($unzip1);
    die();

}

// ----------------------------------------------------------------------------
// Replace Song.xml
// ----------------------------------------------------------------------------

unlink($unzip1 . 'Song.xml') or die("Error: There was a problem deleting a file.\n");

file_put_contents($unzip1 . 'Song.xml', $sx1->asXML());

// Zip song
$result = ZipAllFiles($song2, $unzip1);
if($result === FALSE) {
    echo "Error: There was a problem zipping the final file.\n";
    die();
}

// ----------------------------------------------------------------------------
// Remove temp directories
// ----------------------------------------------------------------------------

obliterate_directory($unzip1);

echo "---------------------------------------\n";
echo "$argv[0] is done!\n";
echo date("D M j G:i:s T Y\n");
echo "---------------------------------------\n";

?>
Return current item: XRNS-PHP