| 1 | # Copyright (c) 2008, samurai-x.org |
|---|
| 2 | # All rights reserved. |
|---|
| 3 | # |
|---|
| 4 | # Redistribution and use in source and binary forms, with or without |
|---|
| 5 | # modification, are permitted provided that the following conditions are met: |
|---|
| 6 | # * Redistributions of source code must retain the above copyright |
|---|
| 7 | # notice, this list of conditions and the following disclaimer. |
|---|
| 8 | # * Redistributions in binary form must reproduce the above copyright |
|---|
| 9 | # notice, this list of conditions and the following disclaimer in the |
|---|
| 10 | # documentation and/or other materials provided with the distribution. |
|---|
| 11 | # * Neither the name of the samurai-x.org nor the |
|---|
| 12 | # names of its contributors may be used to endorse or promote products |
|---|
| 13 | # derived from this software without specific prior written permission. |
|---|
| 14 | # |
|---|
| 15 | # THIS SOFTWARE IS PROVIDED BY SAMURAI-X.ORG ``AS IS'' AND ANY |
|---|
| 16 | # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
|---|
| 17 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
|---|
| 18 | # DISCLAIMED. IN NO EVENT SHALL SAMURAI-X.ORG BE LIABLE FOR ANY |
|---|
| 19 | # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
|---|
| 20 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
|---|
| 21 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
|---|
| 22 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|---|
| 23 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
|---|
| 24 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|---|
| 25 | |
|---|
| 26 | import sys |
|---|
| 27 | import os |
|---|
| 28 | |
|---|
| 29 | import pyglet |
|---|
| 30 | pyglet.options['shadow_window'] = False |
|---|
| 31 | |
|---|
| 32 | from pyglet.window.xlib import cursorfont |
|---|
| 33 | |
|---|
| 34 | import samuraix |
|---|
| 35 | from samuraix import xhelpers |
|---|
| 36 | from samuraix import userfuncs |
|---|
| 37 | from samuraix.procutil import set_process_name |
|---|
| 38 | from samuraix.timer import Timer |
|---|
| 39 | |
|---|
| 40 | import logging |
|---|
| 41 | log = logging.getLogger(__name__) |
|---|
| 42 | |
|---|
| 43 | |
|---|
| 44 | def init_atoms(): |
|---|
| 45 | log.debug('creating atoms instance...') |
|---|
| 46 | from samuraix.atoms import Atoms |
|---|
| 47 | samuraix.atoms = Atoms() |
|---|
| 48 | |
|---|
| 49 | |
|---|
| 50 | def init_cursors(): |
|---|
| 51 | log.debug('creating cursors instance...') |
|---|
| 52 | from samuraix.cursors import Cursors |
|---|
| 53 | samuraix.cursors = Cursors() |
|---|
| 54 | samuraix.cursors['normal'] = samuraix.cursors[cursorfont.XC_left_ptr] |
|---|
| 55 | samuraix.cursors['resize'] = samuraix.cursors[cursorfont.XC_sizing] |
|---|
| 56 | samuraix.cursors['move'] = samuraix.cursors[cursorfont.XC_fleur] |
|---|
| 57 | |
|---|
| 58 | |
|---|
| 59 | def init_timer(): |
|---|
| 60 | log.debug('creating timer...') |
|---|
| 61 | from samuraix.timer import Timer |
|---|
| 62 | samuraix.timer = Timer() |
|---|
| 63 | |
|---|
| 64 | |
|---|
| 65 | def configure_logging(file_level=logging.DEBUG, console_level=logging.INFO): |
|---|
| 66 | #logging.basicConfig(level=logging.DEBUG, |
|---|
| 67 | # format='%(asctime)s %(name)s %(levelname)s %(message)s') |
|---|
| 68 | |
|---|
| 69 | from samuraix.logformatter import FDFormatter |
|---|
| 70 | |
|---|
| 71 | console = logging.StreamHandler() |
|---|
| 72 | console.setLevel(console_level) |
|---|
| 73 | # set this to True for color console output |
|---|
| 74 | if True: |
|---|
| 75 | formatter_class = FDFormatter |
|---|
| 76 | else: |
|---|
| 77 | formatter_class = logging.Formatter |
|---|
| 78 | formatter = formatter_class('[%(asctime)s %(levelname)s %(name)s] %(message)s') |
|---|
| 79 | console.setFormatter(formatter) |
|---|
| 80 | logging.getLogger('').addHandler(console) |
|---|
| 81 | |
|---|
| 82 | logfile = 'lastrun.log' |
|---|
| 83 | |
|---|
| 84 | log.info('logging everything to %s' % logfile) |
|---|
| 85 | |
|---|
| 86 | lastlog = logging.FileHandler(logfile, 'w') |
|---|
| 87 | lastlog.setLevel(file_level) |
|---|
| 88 | formatter = logging.Formatter('[%(asctime)s %(levelname)s %(name)s %(lineno)d] %(message)s') |
|---|
| 89 | lastlog.setFormatter(formatter) |
|---|
| 90 | logging.getLogger('').addHandler(lastlog) |
|---|
| 91 | |
|---|
| 92 | logging.root.setLevel(logging.DEBUG) |
|---|
| 93 | |
|---|
| 94 | |
|---|
| 95 | def load_config(config=None): |
|---|
| 96 | log.info('loading config...') |
|---|
| 97 | if config is None: |
|---|
| 98 | from samuraix.defaultconfig import config |
|---|
| 99 | |
|---|
| 100 | if callable(config): |
|---|
| 101 | config = config() |
|---|
| 102 | samuraix.config = config |
|---|
| 103 | |
|---|
| 104 | |
|---|
| 105 | def load_user_config(configfile=None): |
|---|
| 106 | if configfile is None: |
|---|
| 107 | configfile = '~/.samuraix' |
|---|
| 108 | configfile = os.path.normpath(os.path.expanduser(configfile)) |
|---|
| 109 | log.info('reading config from %s...' % configfile) |
|---|
| 110 | locals = {} |
|---|
| 111 | try: |
|---|
| 112 | execfile(configfile, {}, locals) |
|---|
| 113 | except IOError, e: |
|---|
| 114 | log.warn('failed reading config file: %s' % e) |
|---|
| 115 | return None |
|---|
| 116 | return locals['config'] |
|---|
| 117 | |
|---|
| 118 | |
|---|
| 119 | def parse_options(args=None): |
|---|
| 120 | log.debug('parsing options...') |
|---|
| 121 | |
|---|
| 122 | from optparse import OptionParser |
|---|
| 123 | |
|---|
| 124 | parser = OptionParser() |
|---|
| 125 | parser.add_option("-d", "--debug", |
|---|
| 126 | action="store_true", dest="debug", default=False, |
|---|
| 127 | help="print debug messages to stdout") |
|---|
| 128 | parser.add_option('-c', "--config", |
|---|
| 129 | dest='configfile', default=None, |
|---|
| 130 | help="config file to use") |
|---|
| 131 | parser.add_option('', '--dumpconfig', dest='dumpconfig', default=False, |
|---|
| 132 | help="dump the default config to stdout and quit") |
|---|
| 133 | |
|---|
| 134 | return parser.parse_args(args=args) |
|---|
| 135 | |
|---|
| 136 | |
|---|
| 137 | def handle_options(options, args): |
|---|
| 138 | log.debug('handling options... %s %s' % (options, args)) |
|---|
| 139 | if options.debug: |
|---|
| 140 | handler = logging.getLogger('').handlers[0] |
|---|
| 141 | handler.setLevel(logging.DEBUG) |
|---|
| 142 | |
|---|
| 143 | #if options.dumpconfig: |
|---|
| 144 | |
|---|
| 145 | def run_app(): |
|---|
| 146 | log.info('... and with (almost) god like speed ...') |
|---|
| 147 | try: |
|---|
| 148 | samuraix.app.run() |
|---|
| 149 | except Exception, e: |
|---|
| 150 | log.exception("exception in main loop!") |
|---|
| 151 | import traceback |
|---|
| 152 | log.warn(traceback.format_exc()) |
|---|
| 153 | finally: |
|---|
| 154 | xhelpers.close_display() |
|---|
| 155 | |
|---|
| 156 | |
|---|
| 157 | def run(app_func=None, config=None, args=None): |
|---|
| 158 | configure_logging() |
|---|
| 159 | |
|---|
| 160 | options, args = parse_options(args) |
|---|
| 161 | if options or args: |
|---|
| 162 | handle_options(options, args) |
|---|
| 163 | |
|---|
| 164 | if config is None: |
|---|
| 165 | config = load_user_config(options.configfile) |
|---|
| 166 | load_config(config=config) |
|---|
| 167 | |
|---|
| 168 | set_process_name('samurai-x') |
|---|
| 169 | |
|---|
| 170 | xhelpers.open_display() |
|---|
| 171 | xhelpers.check_for_other_wm() |
|---|
| 172 | xhelpers.setup_xerror() |
|---|
| 173 | |
|---|
| 174 | init_atoms() |
|---|
| 175 | xhelpers.get_numlock_mask() |
|---|
| 176 | init_cursors() |
|---|
| 177 | init_timer() |
|---|
| 178 | |
|---|
| 179 | if app_func is None: |
|---|
| 180 | from samuraix.appl import App |
|---|
| 181 | app_func = App |
|---|
| 182 | |
|---|
| 183 | log.info('creating app instance...') |
|---|
| 184 | samuraix.app = app_func() |
|---|
| 185 | samuraix.app.init() |
|---|
| 186 | run_app() |
|---|
| 187 | log.info('done') |
|---|
| 188 | |
|---|
| 189 | |
|---|
| 190 | if __name__ == '__main__': |
|---|
| 191 | run() |
|---|
| 192 | |
|---|
| 193 | |
|---|