#!/usr/bin/env python2

# Copyright (C) 2013 Jonathan Moore Liles                                     #
#                                                                             #
# This program is free software; you can redistribute it and/or modify it     #
# under the terms of the GNU General Public License as published by the       #
# Free Software Foundation; either version 2 of the License, or (at your      #
# option) any later version.                                                  #
#                                                                             #
# This program is distributed in the hope that it will be useful, but WITHOUT #
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       #
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for   #
# more details.                                                               #
#                                                                             #
# You should have received a copy of the GNU General Public License along     #
# with This program; see the file COPYING.  If not,write to the Free Software #
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  #

import xml.etree.ElementTree as et
import random
import sys
import os
from datetime import date
import shutil

if len(sys.argv) == 1:
        print( "Usage: import-ardour-session [PATH_TO_ARDOUR_FILE] [NAME_OF_NON_TIMELINE_PROJECT]" )
        sys.exit( 1 )

Overwrite=False

i = 1;

if ( sys.argv[i] == "--overwrite" ):
        Overwrite = True
        i = i + 1

ArdourFilePath = sys.argv[i]
i = i + 1
NonTimelineProjectPath = sys.argv[i]
i = i + 1 

try:
        os.makedirs( NonTimelineProjectPath );
        os.makedirs( NonTimelineProjectPath + "/sources");
except:
        if not Overwrite:
                print( "Output path already exists!" )
                sys.exit( 1 )

try:
        tree = et.parse( ArdourFilePath );
except:
        print( "Invalid XML input" )
        sys.exit( 1 )

root = tree.getroot();

Sources = {}
DiskStreams = {}

print( "Gathering session info" )
if root.tag != "Session":
        print( "Not an Ardour session?" )
        sys.exit(1)

print( "Ardour session file version is " + root.attrib["version"] )
print( "This program is known to work with versions <= 3.0.1" )

ProjectName = root.attrib["name"]

print( "Converting Ardour session \"" + ProjectName + "\" to Non Timeline format. Please be patient." )


print( "Gathering sources." )
for node in root.findall( "./Sources/Source" ):
	Sources[node.attrib["id"]] = node;
#	print( "\tFound source " + node.attrib["name"] )

print( "Gathering version 3 diskstreams." )
for node in root.findall( "./Routes/Route/Diskstream" ):
	DiskStreams[node.attrib["id"]] = node;
	print( "\tFound diskstream " + node.attrib["name"] )

print( "Gathering version 2 diskstreams." )
for node in root.findall( "./DiskStreams/AudioDiskstream" ):
	DiskStreams[node.attrib["id"]] = node;
#	print( "\tFound diskstream " + node.attrib["name"]; )


print( "Gathering version 1 diskstreams." )
for node in root.findall( "./DiskStreams/DiskStream" ):
	DiskStreams[node.attrib["id"]] = node;
#	print( "\tFound diskstream " + node.attrib["name"]; )

LoggableID = 1;

def NewID():
        global LoggableID
        ID="0x%x" % LoggableID
        LoggableID = LoggableID + 1
        return ID


History = "{\n"

print( "Processing tempo." )

for node in root.findall("./TempoMap/Tempo"):
        TempoID = NewID()
        History += ( "\tTempo_Point " + TempoID + " create :start 0 :tempo " + node.attrib["beats-per-minute"] + "\n")

for node in root.findall("./TempoMap/Meter"):
        TimeID = NewID()
        try:
                BPB = node.attrib["beats-per-bar"]
        except:
                BPB = node.attrib["divisions-per-bar"]

        History += ( "\tTime_Point " + TimeID + " create :start 0 :beats_per_bar " + BPB + " :beat_type " + node.attrib["note-type"] + "\n")
 

print( "Processing playlists." )
for node in root.findall( "./Playlists/Playlist" ):
        
        try:
                Track = DiskStreams[node.attrib["orig_diskstream_id"]]
        except:
                try:
                        Track = DiskStreams[node.attrib["orig-track-id"]]
                except:
                        print( "\tSkipping playlist " + node.attrib["name"] + " for unknown diskstream" )
                        continue

        
        if node.attrib["name"] == Track.attrib["playlist"]:
                print( "\tFound playlist " + node.attrib["name"] )

                # for chan in range(0, int( Track.attrib["channels"] )):
                TrackID = NewID()
                SequenceID = NewID()
                # if int(Track.attrib["channels"]) > 1:
                #         TrackName = Track.attrib["name"] + "-" + ( "%i" % chan )
                # else:
                TrackName = Track.attrib["name"]
                Channels = int(Track.attrib["channels"])

                History += ( "\tTrack " + TrackID + " create :name \"" + TrackName + "\"" + ( " :sequence " + SequenceID ) + " :color " + ( "%i" % random.randint(256,123123123)) + ( " :inputs %i :outputs %i\n" % ( Channels, Channels ) ) )
                History += ( "\tAudio_Sequence " + SequenceID + " create :track " + TrackID + " :name \"" + node.attrib["name"] + "\"\n" )
                for n2 in node.findall("./Region"):
                        RegionID = NewID();
                                
                        if ( int( Track.attrib["channels"] ) > 1 ):

                                SourceList = []
                                APath1 = os.path.dirname(ArdourFilePath) + "/sounds/"
                                APath2 = os.path.dirname(ArdourFilePath) + "/interchange/" + ProjectName + "/audiofiles/"

                                for chan in range(0, int( Track.attrib["channels"] )):
                                        SourceName = Sources[n2.attrib["source-" + ( "%i" % chan )]].attrib["name"]

                                        if os.path.exists( APath1 + SourceName):
                                                SourceName = APath1 + SourceName
                                        elif os.path.exists( APath2 + SourceName ):
                                                SourceName = APath2 + SourceName
                                        else:
                                                print( "source not found!" )
                                                
                                        SourceList.append( "'" + SourceName + "'" );
                                                        
                                        s1,s2,s3 = Sources[n2.attrib["source-0"]].attrib["name"].partition( '%' )
                                        
                                        SourceName = s1 + ".wav"
                                        OutputName = NonTimelineProjectPath + "/sources/" + SourceName
     
                                if not os.path.exists( OutputName ):
                                        print( "Combining multifile source into multichannel source" )
                                        os.system( "sox -S -M " + " ".join(SourceList) + " " + "'" + OutputName + "'" )
                                        
                        else:
                                SourceName = Sources[n2.attrib["source-0"]].attrib["name"];
                                if not os.path.exists( NonTimelineProjectPath + "/sources/" + SourceName ):
                                        print( "\t\tCopying source: " + SourceName )
                                                
                                        try:
                                                shutil.copy( os.path.dirname(ArdourFilePath) + "/interchange/" + ProjectName + "/audiofiles/" + SourceName,
                                                                     NonTimelineProjectPath + "/sources/" )
                                        except:
                                                shutil.copy( os.path.dirname(ArdourFilePath) + "/sounds/" + SourceName,
                                                                     NonTimelineProjectPath + "/sources/" )


                        History +=  ("\tAudio_Region " + RegionID + 
                                       " create :source \"" + SourceName +
                                       "\" :start " + n2.attrib["position"] + 
                                       " :length " + n2.attrib["length"] +
                                       " :offset " + n2.attrib["start"] +
                                       " :sequence " + SequenceID + "\n")
        else:
                        print( "\tSkipping inactive playlist" )

History += ("}\n")                        

print( "Comitting to disk." )

with open( NonTimelineProjectPath + "/info", 'w' ) as InfoFile:
        try:
                SampleRate = root.attrib["sample-rate"]
        except:
                print( "Couldn't find sample rate... Using default." )
                SampleRate = "48000"
                
        InfoFile.write( "created by\n\tNon-Timeline 1.2.0\ncreated on\n\t" + date.today().ctime() + "\nversion\n\t2\nsample rate\n\t" + SampleRate + "\n" )

with open( NonTimelineProjectPath + "/history", 'w' ) as HistoryFile:
        HistoryFile.write( History )
	
print( "Done. You've been freed. Go make music!" )

