Changeset 1481

Show
Ignore:
Timestamp:
11/23/08 15:39:52 (12 years ago)
Author:
arnonym
Message:

Add two logging-handlers: One to log to the statusbar (INFO and higher) and one to log to a textwidget. Which is included as a dock-widget.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/libffado/support/mixer-qt4/ffado-mixer.in

    r1435 r1481  
    4444from ffado_panelmanager import PanelManager 
    4545 
     46from ffado_logginghandler import * 
     47 
    4648"""Just a small helper to ask the retry-question without a blocking messagebox""" 
    4749class StartDialog(QWidget): 
     
    5557        self.layout.addWidget(self.button, 1, 0, Qt.AlignCenter) 
    5658 
    57  
    5859class FFADOWindow(QMainWindow): 
    5960    def __init__(self, parent): 
    6061        QMainWindow.__init__(self, parent) 
     62 
     63        self.textlogger = QTextLogger(self) 
     64        dock = QDockWidget("Log Messages",self) 
     65        dock.setWidget(self.textlogger) 
     66        logging.getLogger('').addHandler(self.textlogger) 
     67        self.addDockWidget(Qt.BottomDockWidgetArea, dock) 
     68 
     69        self.statuslogger = QStatusLogger(self, self.statusBar(), 20) 
     70        logging.getLogger('').addHandler(self.statuslogger) 
    6171 
    6272        self.manager = PanelManager(self) 
     
    8696        helpmenu.addAction( aboutqtaction ) 
    8797 
    88         self.statusBar().showMessage( "Initializing...", 5000
     98        log.info( "Starting up"
    8999 
    90100        QTimer.singleShot( 1, self.connectToDBUS ) 
     
    94104            self.setupDeviceManager() 
    95105        except dbus.DBusException, ex: 
    96             log.error("") 
    97             log.error("") 
    98             log.error("===========================================================") 
    99             log.error("ERROR: Could not communicate with the FFADO DBus service...") 
    100             log.error("===========================================================") 
    101             log.error("") 
    102             log.error("") 
     106            log.error("Could not communicate with the FFADO DBus service...") 
    103107            if not hasattr(self,"retry"): 
    104108                self.retry = StartDialog(self) 
     
    143147    #set up logging 
    144148    import logging 
    145     logging.basicConfig(
     149    logging.basicConfig( datefmt="%H:%M:%S", format="%(asctime)s %(name)-16s %(levelname)-8s %(message)s"
    146150 
    147151    if DEBUG: 
  • trunk/libffado/support/mixer-qt4/ffado_logginghandler.py

    • Property svn:mergeinfo set
    r1435 r1481  
    11#!/usr/bin/python 
    22# 
    3 # Copyright (C) 2005-2008 by Pieter Palmers 
    4 #               2007-2008 by Arnold Krille 
     3# Copyright (C) 2008 by Arnold Krille 
    54# 
    65# This file is part of FFADO 
     
    2322# 
    2423 
    25 from ffadomixer_config import * #FFADO_VERSION, FFADO_DBUS_SERVER, FFADO_DBUS_BASEPATH 
    26  
    27 from PyQt4.QtGui import QFrame, QWidget, QTabWidget, QVBoxLayout, QMainWindow, QIcon, QAction, qApp, QStyleOptionTabWidgetFrame 
    28 from PyQt4.QtCore import QTimer 
    29  
    30 from ffado_panelmanagerstatusui import Ui_PanelManagerStatusUI 
    31  
    32 from ffado_dbus_util import * 
    33 from ffado_registration import * 
    34  
    35 from ffado_configuration import DeviceList 
    36  
    37 from mixer_phase88 import * 
    38 from mixer_phase24 import * 
    39 from mixer_saffire import SaffireMixer 
    40 from mixer_saffirepro import SaffireProMixer 
    41 from mixer_audiofire import AudioFireMixer 
    42 from mixer_bcoaudio5 import * 
    43 from mixer_edirolfa66 import * 
    44 from mixer_edirolfa101 import * 
    45 from mixer_mackie_onyxmixer import * 
    46 from mixer_quatafire import * 
    47 from mixer_motu import * 
    48 from mixer_dummy import * 
    49 from mixer_global import GlobalMixer 
    50  
    51 import time 
     24from PyQt4.QtGui import QTextEdit, QAbstractSlider, QColor 
     25from PyQt4.QtCore import QObject, SIGNAL, SLOT 
    5226 
    5327import logging 
    54 log = logging.getLogger('panelmanager') 
     28log = logging.getLogger('logginghandler') 
    5529 
    56 use_generic = False 
    57 try: 
    58     from mixer_generic import * 
    59     log.info("The generic mixer is found, seems to be a developer using ffadomixer...") 
    60 except ImportError: 
    61     pass 
    62 else: 
    63     use_generic = True 
     30class QStatusLogger( QObject, logging.Handler ): 
     31    def __init__( self, parent, statusbar, level=logging.NOTSET ): 
     32        QObject.__init__( self, parent ) 
     33        logging.Handler.__init__( self, level ) 
     34        self.setFormatter( logging.Formatter( "%(name)s: %(message)s" ) ) 
     35        self.connect( self, SIGNAL("log(QString,int)"), statusbar, SLOT("showMessage(QString,int)") ) 
    6436 
    65 # pseudo-guid 
    66 GUID_GENERIC_MIXER = 0 
     37    def emit( self, record ): 
     38        QObject.emit( self, SIGNAL("log(QString,int)"), "%s: %s" % (record.name, record.getMessage()), 5000 ) 
    6739 
     40class QTextLogger( QTextEdit, logging.Handler ): 
     41    def __init__( self, parent, level=logging.NOTSET ): 
     42        QTextEdit.__init__( self, parent ) 
     43        logging.Handler.__init__( self, level ) 
    6844 
    69 class HLine( QFrame ): 
    70     def __init__( self, parent ): 
    71         QFrame.__init__( self, parent ) 
    72         self.setFrameShape( QFrame.HLine ) 
    73         self.setLineWidth( 2 ) 
    74         self.setMinimumHeight( 10 ) 
     45        self.setReadOnly( True ) 
     46        self.setAcceptRichText( True ) 
    7547 
    76 class PanelManagerStatus(QWidget, Ui_PanelManagerStatusUI): 
    77     def __init__(self, parent): 
    78         QWidget.__init__(self,parent) 
    79         self.setupUi(self) 
     48    def emit( self, record ): 
     49        color = QColor( "#000000" ) 
     50        if record.levelno > 20: 
     51            color = QColor( "#ffff00" ) 
     52        if record.levelno > 30: 
     53            color = QColor( "#ff0000" ) 
     54        if record.levelno <= 10: 
     55            color = QColor( "#808080" ) 
     56        self.setTextColor( color ) 
     57        tmp = "%s %s: %s" % (record.asctime, record.name, record.getMessage()) 
     58        print tmp 
     59        self.append( tmp ) 
     60        self.verticalScrollBar().triggerAction( QAbstractSlider.SliderToMaximum ) 
    8061 
    81 class OwnTabWidget(QTabWidget): 
    82     def __init__(self,parent): 
    83         QTabWidget.__init__(self,parent) 
    84  
    85     def tabInserted(self,index): 
    86         self.checkTabBar() 
    87  
    88     def tabRemoved(self,index): 
    89         self.checkTabBar() 
    90  
    91     def checkTabBar(self): 
    92         if self.count()<2: 
    93             self.tabBar().hide() 
    94         else: 
    95             self.tabBar().show() 
    96  
    97 class PanelManager(QWidget): 
    98     def __init__(self, parent, devmgr=None): 
    99         QMainWindow.__init__(self, parent) 
    100         self.setObjectName("PanelManager") 
    101  
    102         # maps a device GUID to a QT panel 
    103         self.panels = {} 
    104  
    105         # a layout for ourselves 
    106         self.layout = QVBoxLayout(self) 
    107  
    108         # the tabs 
    109         self.tabs = OwnTabWidget(self) 
    110         self.tabs.hide() 
    111         self.layout.addWidget(self.tabs) 
    112  
    113         # a dialog that is shown during update 
    114         self.status = PanelManagerStatus(self) 
    115         self.layout.addWidget(self.status) 
    116         self.status.show() 
    117  
    118         self.devices = DeviceList( SYSTEM_CONFIG_FILE ) 
    119         self.devices.updateFromFile( USER_CONFIG_FILE ) 
    120  
    121         if devmgr is not None: 
    122             self.setManager(devmgr) 
    123  
    124     def setManager(self,devmgr): 
    125         self.devmgr = devmgr 
    126         self.devmgr.registerPreUpdateCallback(self.devlistPreUpdate) 
    127         self.devmgr.registerPostUpdateCallback(self.devlistPostUpdate) 
    128         self.devmgr.registerUpdateCallback(self.devlistUpdate) 
    129         self.devmgr.registerDestroyedCallback(self.devmgrDestroyed) 
    130         # create a timer to poll the panels 
    131         self.polltimer = QTimer() 
    132         self.connect( self.polltimer, SIGNAL('timeout()'), self.pollPanels ) 
    133         self.polltimer.start( POLL_SLEEP_TIME_MSEC ) 
    134  
    135         # create a timer to initialize the panel after the main form is shown 
    136         # since initialization can take a while 
    137         QTimer.singleShot( POLL_SLEEP_TIME_MSEC, self.updatePanels ) 
    138  
    139         # live check timer 
    140         self.alivetimer = QTimer() 
    141         QObject.connect( self.alivetimer, SIGNAL('timeout()'), self.commCheck ) 
    142         self.alivetimer.start( 2000 ) 
    143  
    144     def count(self): 
    145         return self.tabs.count() 
    146  
    147     def pollPanels(self): 
    148         #log.debug("PanelManager::pollPanels()") 
    149         # only when not modifying the tabs 
    150         if self.tabs.isEnabled(): 
    151             for guid in self.panels.keys(): 
    152                 w = self.panels[guid] 
    153                 for child in w.children(): 
    154                     #log.debug("poll child %s,%s" % (guid,child)) 
    155                     if 'polledUpdate' in dir(child): 
    156                         try: 
    157                             child.polledUpdate() 
    158                         except: 
    159                             log.error("error in polled update") 
    160                             raise 
    161  
    162     def devlistPreUpdate(self): 
    163         log.debug("devlistPreUpdate") 
    164         self.tabs.setEnabled(False) 
    165         self.tabs.hide() 
    166         self.status.lblMessage.setText("Bus reconfiguration in progress, please wait...") 
    167         self.status.show() 
    168         #self.statusBar().showMessage("bus reconfiguration in progress...", 5000) 
    169  
    170     def devlistPostUpdate(self): 
    171         log.debug("devlistPostUpdate") 
    172         # this can fail if multiple busresets happen in fast succession 
    173         ntries = 10 
    174         while ntries > 0: 
    175             try: 
    176                 self.updatePanels() 
    177                 return 
    178             except: 
    179                 log.debug("devlistPostUpdate failed (%d)" % ntries) 
    180                 for guid in self.panels.keys(): 
    181                     w = self.panels[guid] 
    182                     del self.panels[guid] # remove from the list 
    183                     idx = self.tabs.indexOf(w) 
    184                     self.tabs.removeTab(idx) 
    185                     del w # GC might also take care of that 
    186  
    187                 ntries = ntries - 1 
    188                 time.sleep(2) # sleep a few seconds 
    189  
    190         log.debug("devlistPostUpdate failed completely") 
    191         self.tabs.setEnabled(False) 
    192         self.tabs.hide() 
    193         self.status.lblMessage.setText("Error while reconfiguring. Please restart ffadomixer.") 
    194         self.status.show() 
    195  
    196  
    197     def devlistUpdate(self): 
    198         log.debug("devlistUpdate") 
    199  
    200     def devmgrDestroyed(self): 
    201         log.debug("devmgrDestroyed") 
    202         self.alivetimer.stop() 
    203         self.tabs.setEnabled(False) 
    204         self.tabs.hide() 
    205         self.status.lblMessage.setText("DBUS server was shut down, please restart it and restart ffadomixer...") 
    206         self.status.show() 
    207  
    208     def commCheck(self): 
    209         try: 
    210             nbDevices = self.devmgr.getNbDevices() 
    211         except: 
    212             log.debug("comms lost") 
    213             self.tabs.setEnabled(False) 
    214             self.tabs.hide() 
    215             self.status.lblMessage.setText("Failed to communicate with DBUS server. Please restart it and restart ffadomixer...") 
    216             self.status.show() 
    217             self.alivetimer.stop() 
    218  
    219     def updatePanels(self): 
    220         log.debug("PanelManager::updatePanels()") 
    221         nbDevices = self.devmgr.getNbDevices() 
    222         #self.statusBar().showMessage("Reconfiguring the mixer panels...") 
    223  
    224         # list of panels present 
    225         guids_with_tabs = self.panels.keys() 
    226  
    227         # build list of guids on the bus now 
    228         guids_present = [] 
    229         guid_indexes = {} 
    230         for idx in range(nbDevices): 
    231             path = self.devmgr.getDeviceName(idx) 
    232             cfgrom = ConfigRomInterface(FFADO_DBUS_SERVER, FFADO_DBUS_BASEPATH+'/DeviceManager/'+path) 
    233             guid = cfgrom.getGUID() 
    234             guids_present.append(guid) 
    235             guid_indexes[guid] = idx 
    236  
    237         # figure out what to remove 
    238         # the special panel (generic) 
    239         # that has (pseudo-)GUID 0 
    240         # is also automatically removed 
    241         to_remove = [] 
    242         for guid in guids_with_tabs: 
    243             if not guid in guids_present: 
    244                 to_remove.append(guid) 
    245                 log.debug("going to remove %s" % str(guid)) 
    246             else: 
    247                 log.debug("going to keep %s" % str(guid)) 
    248  
    249         # figure out what to add 
    250         to_add = [] 
    251         for guid in guids_present: 
    252             if not guid in guids_with_tabs: 
    253                 to_add.append(guid) 
    254                 log.debug("going to add %s" % str(guid)) 
    255  
    256         # update the widget 
    257         for guid in to_remove: 
    258             w = self.panels[guid] 
    259             del self.panels[guid] # remove from the list 
    260             idx = self.tabs.indexOf(w) 
    261             self.tabs.removeTab(idx) 
    262             del w # GC might also take care of that 
    263  
    264         for guid in to_add: 
    265             # retrieve the device manager index 
    266             idx = guid_indexes[guid] 
    267             path = self.devmgr.getDeviceName(idx) 
    268             log.debug("Adding device %d: %s" % (idx, path)) 
    269  
    270             cfgrom = ConfigRomInterface(FFADO_DBUS_SERVER, FFADO_DBUS_BASEPATH+'/DeviceManager/'+path) 
    271             vendorId = cfgrom.getVendorId() 
    272             modelId = cfgrom.getModelId() 
    273             unitVersion = cfgrom.getUnitVersion() 
    274             guid = cfgrom.getGUID() 
    275             vendorName = cfgrom.getVendorName() 
    276             modelName = cfgrom.getModelName() 
    277             log.debug(" Found (%s, %X, %X) %s %s" % (str(guid), vendorId, modelId, vendorName, modelName)) 
    278  
    279             # check whether this has already been registered at ffado.org 
    280             reg = ffado_registration(FFADO_VERSION, int(guid, 16), 
    281                                      vendorId, modelId, 
    282                                      vendorName, modelName) 
    283             reg.check_for_registration() 
    284  
    285             # The MOTU devices use unitVersion to differentiate models.  For the 
    286             # moment though we don't need to know precisely which model we're 
    287             # using. 
    288             if vendorId == 0x1f2: 
    289                 modelId = 0x00000000 
    290  
    291             dev = self.devices.getDeviceById( vendorId, modelId ) 
    292  
    293             w = QWidget( ) 
    294             l = QVBoxLayout( w ) 
    295  
    296             # create a control object 
    297             hw = ControlInterface(FFADO_DBUS_SERVER, FFADO_DBUS_BASEPATH+'/DeviceManager/'+path) 
    298             clockselect = ClockSelectInterface( FFADO_DBUS_SERVER, FFADO_DBUS_BASEPATH+"/DeviceManager/"+path ) 
    299             samplerateselect = SamplerateSelectInterface( FFADO_DBUS_SERVER, FFADO_DBUS_BASEPATH+"/DeviceManager/"+path ) 
    300             nickname = TextInterface( FFADO_DBUS_SERVER, FFADO_DBUS_BASEPATH+"/DeviceManager/"+path+"/Generic/Nickname" ) 
    301  
    302             # 
    303             # Generic elements for all mixers follow here: 
    304             # 
    305             globalmixer = GlobalMixer( w ) 
    306             globalmixer.configrom = cfgrom 
    307             globalmixer.clockselect = clockselect 
    308             globalmixer.samplerateselect = samplerateselect 
    309             globalmixer.nickname = nickname 
    310             globalmixer.hw = hw 
    311             globalmixer.initValues() 
    312             l.addWidget( globalmixer, 1 ) 
    313  
    314             # 
    315             # Line to separate 
    316             # 
    317             l.addWidget( HLine( w ) ) 
    318  
    319             # 
    320             # Specific (or dummy) mixer widgets get loaded in the following 
    321             # 
    322             if 'mixer' in dev and dev['mixer'] != None: 
    323                 mixerapp = dev['mixer'] 
    324                 exec( "mixerwidget = "+mixerapp+"( w )" ) 
    325             else: 
    326                 mixerwidget = DummyMixer( w ) 
    327                 mixerapp = modelName+" (Dummy)" 
    328  
    329             # 
    330             # The same for all mixers 
    331             # 
    332             l.addWidget( mixerwidget, 10 ) 
    333             mixerwidget.configrom = cfgrom 
    334             mixerwidget.clockselect = clockselect 
    335             mixerwidget.samplerateselect = samplerateselect 
    336             mixerwidget.nickname = nickname 
    337             mixerwidget.hw = hw 
    338             if 'buildMixer' in dir(mixerwidget): 
    339                 mixerwidget.buildMixer() 
    340             if 'initValues' in dir(mixerwidget): 
    341                 mixerwidget.initValues() 
    342             if 'getDisplayTitle' in dir(mixerwidget): 
    343                 title = mixerwidget.getDisplayTitle() 
    344             else: 
    345                 title = mixerapp 
    346  
    347             globalmixer.setName(title) 
    348             self.tabs.addTab( w, title ) 
    349             self.panels[guid] = w 
    350  
    351         # if there is no panel, add the no-device message 
    352         # else make sure it is not present 
    353         if self.count() == 0: 
    354             self.tabs.hide() 
    355             self.tabs.setEnabled(False) 
    356             self.status.lblMessage.setText("No supported device found.") 
    357             self.status.show() 
    358             #self.statusBar().showMessage("No supported device found.", 5000) 
    359         else: 
    360             self.tabs.show() 
    361             self.tabs.setEnabled(True) 
    362             self.status.hide() 
    363             #self.statusBar().showMessage("Configured the mixer for %i devices." % self.tabs.count()) 
    364             if use_generic: 
    365                 # 
    366                 # Show the generic (development) mixer if it is available 
    367                 # 
    368                 w = GenericMixer( devmgr.bus, FFADO_DBUS_SERVER, mw ) 
    369                 self.tabs.addTab( w, "Generic Mixer" ) 
    370                 self.panels[GUID_GENERIC_MIXER] = w 
    371  
    372     def busreset( self ): 
    373         QMessageBox.information( self, "Not supported", "Triggering bus resets from the mixer (via dbus) isn't yet supported." ) 
    374  
     62
    37563# vim: et 
     64#