#!/usr/bin/env python
# -*- coding: utf-8 -*-

# pebsaq: a poor synthesizer
# Copyright (C) 2010, 2012  Niels G. W. Serup

# This file is part of pebsaq.
#
# pebsaq 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 3 of the License, or
# (at your option) any later version.
#
# pebsaq 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 pebsaq.  If not, see <http://www.gnu.org/licenses/>.

##[ Name        ]## scripts.pebsaq
##[ Maintainer  ]## Niels G. W. Serup <ns@metanohi.name>
##[ Description ]## Runs pebsaq

import sys
import os.path
from optparse import OptionParser

try:
    import pebsaq.various
    # If this script has been called by pebsaq-local, it is
    # already set. Only set it if it is not set.
    if 'INSTALLED' not in dir():
        INSTALLED = True
except ImportError:
    # pebsaq is not installed, trying an ugly fix. Considering that
    # this executable is in the scripts/ directory, appending the
    # directory one level up to sys.path should make importing possible.
    basedir = os.path.split(os.path.dirname(os.path.realpath(__file__)))[0]
    sys.path.insert(0, basedir)
    INSTALLED = False

import pebsaq.various as various
from pebsaq.utility import Utility
import pebsaq.generalinformation as ginfo

try:
    from setproctitle import setproctitle
except ImportError:
    setproctitle = lambda *args: None

class NewOptionParser(OptionParser):
    def format_epilog(self, formatter):
        return self.epilog
    
    def error(self, msg, done=False, **kwds):
        various.error(msg, done, self.prog + ': error', **kwds)

parser = NewOptionParser(
    prog=ginfo.program_name,
    usage='Usage: %prog [OPTION]...',
    description=ginfo.program_description,
    version=ginfo.version_info,
    epilog='''
pebsaq is a synthesizer with no filters and with only three tone
generators: sine, triangle and square. If you run pebsaq without any
options, it will start in interactive mode where you can use your
computer keyboard to play tones.

Note that the strengths of the three waves are relative to each other.

Instead of specifying options on the command-line, you can save your
settings in config files. Ordinarily, your config file should be named
`.pebsaq.conf' and be located in your home directory (although you can
change that). Entries should be newline-separated `property = value'
pairs (e.g. `frequency = 420').
''')
parser.add_option('-I', '--not-interactive', dest='interactive',
                  action='store_false',
                  help='do not start in interactive mode (named \
"interactive" in your config file)'),
parser.add_option('-n', '--config-file', dest='config_file_path',
                  metavar='PATH',
                  help='set the path to your config file',
                  default=os.path.expanduser('~/.pebsaq.conf'))
parser.add_option('-f', '--frequency', dest='frequency',
                  metavar='Hz', type='int',
                  help='set the frequency at which the waves will flow \
(defaults to 220 Hz, named "frequency" in your config file)')
parser.add_option('-a', '--amplitude', dest='amplitude',
                  metavar='0--1', type='float',
                  help='set the relative amplitude \
(defaults to 0.5, named "amplitude" in your config file)')
parser.add_option('-c', '--channels', dest='channels',
                  metavar='NUMBER', type='int',
                  help='set the number of channels (default to 1 \
(mono), named "channels" in your config file)')
parser.add_option('-s', '--sample-size', dest='sample_size',
                  metavar='NUMBER', type='int',
                  help='set the number of bytes in a sample (defaults \
to 2 (16 bits), named "sample size" in your config file)')
parser.add_option('-r', '--frame-rate', dest='frame_rate',
                  metavar='Hz', type='int',
                  help='set the frame rate (defaults to 44100, named \
"frame rate" in your config file)')
parser.add_option('-A', '--sine-strength', dest='sine_strength',
                  metavar='NUMBER', type='int',
                  help='set the strength of the sine wave (defaults \
to 1, named "sine strength" in your config file)')
parser.add_option('-B', '--square-strength', dest='square_strength',
                  metavar='NUMBER', type='int',
                  help='set the strength of the square wave (defaults \
to 1, named "square strength" in your config file)')
parser.add_option('-C', '--triangle-strength', dest='triangle_strength',
                  metavar='NUMBER', type='int',
                  help='set the strength of the triangle wave (defaults \
to 1, named "triangle strength" in your config file)')
parser.add_option('-m', '--mute', dest='mute',
                  action='store_true',
                  help='mute all sound (named "mute" in your config file)'),
parser.add_option('-l', '--cache-length', dest='cache_length',
                  metavar='NUMBER', type='int',
                  help='set the length (in samples) of the cache \
(defaults to none, named "cache length" in your config file). When \
this is not set, the cache size will be changed whenever a new \
frequency is set. On some systems this might not work, which is why \
you can use this option. It\'s probably best to use a value between \
32 and 4096, depending on your frame rate. NOTE: Currently, this \
does not work very well, but it does create strange sounds.')
parser.add_option('-q', '--quiet', dest='term_verbose',
                  action='store_false',
                  help='do not print error and status messages \
(named "verbose" in your config file)')
parser.add_option('--no-colored-text', dest='term_colored_text',
                  action='store_false',
                  help='do not attempt to color error and status \
messages from pebsaq (named "colored text" in your config file)')

options, args = parser.parse_args()
options = eval(str(options))
options['error_function'] = parser.error

setproctitle(parser.prog)

# Create and run
u = Utility(**options)
try:
    u.start()
except (EOFError, KeyboardInterrupt):
    pass
except Exception:
    import traceback
    traceback.print_exc()
