# timesig.py

"""
This module is an integeral part of the program
MMA - Musical Midi Accompaniment.

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; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

Bob van der Poel <bob@mellowood.ca>

Timesig manager. All timesig stuff is here, except for the Mtrk.setTimeSig
class function. For a function which has no effect, it appears to be
a lot of code. But some sequencers and notation programs absolutely require
proper time sigs for correct operation. So, here you go.
"""

from . import gbl
import MMA.midi
from   MMA.common import *

class TimeSig:
    """ Track and set the current time signature.

        Timesigs are completely optional and are inserted into
        the MIDI file by addTimeSig(). MMA routines ignore timesig
        settings.

        NOTE: The actual func to place a timesig meta into the midi 
              stream is not here. It's part of the Mtrk() class.
    """

    def __init__(self):
        """ Initialze to null value, user will never set to this."""

        self.lastsig = (None, None)


    def create(self, nn, dd):
        """ Set timesig. If no change from last value, ignore. """

        if self.lastsig != (nn, dd):
            gbl.mtrks[0].addTimeSig(gbl.tickOffset, nn, dd, 48, 8)
            self.lastsig = (nn, dd)


    def setSig(self, ln):
        """ Set the midi time signature from parser. """

        if len(ln) == 1:
            a = ln[0].upper()
            if a == 'COMMON':
                ln = ('4', '4')
            elif a == 'CUT':
                ln = ('2', '2')
            elif '/' in ln[0]:
                ln = ln[0].split('/',1)

        if len(ln) != 2:
            error("TimeSig: Usage (numerator denominator) or ('cut' or 'common')")

        nn = stoi(ln[0])

        if nn < 1 or nn > 126:
            error("Timesig: Numerator must be 1..126")

        denominators = {'1':0, '2':1, '4':2, '8':3, '16':4, '32':5, '64':6 }
        dd = ln[1]

        if dd in denominators:
            dd = denominators[dd]

        else:
            error("Timesig: Denominator must be 1, 2, 4, 8, 16, 32 or 64, not '%s'." % dd)

        self.create(nn, dd)


    def get(self):
        """ Return existing timesig in MIDI format. """

        return self.lastsig


    def getAscii(self):
        """ Return existing timesig in readable format. """
        
        if not self.lastsig[0]:
            return "Not Set"
        n, d = self.lastsig
        return "%s/%s" % (n, ['1', '2', '4', '8',  '16', '32', '64'][d] )


timeSig = TimeSig()  # singleton 


