<?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";
?>