// Copyright (c) 2000-2001 Brad Hughes // // Use, modification and distribution is allowed without limitation, // warranty, or liability of any kind. // #include #include #include #include #include #include "constants.h" #include "output.h" #include // static methods static QList *factories = 0; static QStringList files; static QTimer *timer = 0; static void checkFactories() { if ( ! factories ) { files.clear(); factories = new QList; QDir pluginsDir ( qApp->applicationDirPath() ); pluginsDir.cdUp(); pluginsDir.cd ( "./"LIB_DIR"/qmmp/Output" ); foreach ( QString fileName, pluginsDir.entryList ( QDir::Files ) ) { QPluginLoader loader ( pluginsDir.absoluteFilePath ( fileName ) ); QObject *plugin = loader.instance(); if ( loader.isLoaded() ) { qDebug ( "Output: plugin loaded - %s", qPrintable ( fileName ) ); } OutputFactory *factory = 0; if ( plugin ) factory = qobject_cast ( plugin ); if ( factory ) { Output::registerFactory ( factory ); files << pluginsDir.absoluteFilePath(fileName); } } } } void Output::registerFactory ( OutputFactory *fact ) { factories->append ( fact ); } Output *Output::create ( QObject *parent ) { Output *output = 0; checkFactories(); if (factories->isEmpty ()) { qDebug("Output: unable to find output plugins"); return output; } QSettings settings ( QDir::homePath() +"/.qmmp/qmmprc", QSettings::IniFormat ); QString pluginFileName = settings.value("Output/plugin_file","libalsa.so").toString(); int j = 0; for (int i = 0; i < factories->size(); ++i) { if (files.at(i).section('/',-1) == pluginFileName) j = i; } OutputFactory *fact = factories->at (j); if ( fact ) { output = fact->create (parent); } switch ((int) output->volumeControl()) { case Output::Standard: { break; } case Output::Custom: { timer = new QTimer(output); connect(timer, SIGNAL(timeout()), output, SLOT(checkVolume())); timer->start(125); break; } case Output::Disabled: { break; } } return output; } QList *Output::outputFactories() { checkFactories(); return factories; } QStringList Output::outputFiles() { checkFactories(); return files; } Output::Output ( QObject* parent, VolumeType vt) : QThread (parent), r (stackSize()) { qRegisterMetaType("OutputState"); m_vol = vt; } Output::~Output() { qDebug("Output::~Output()"); Visual *visual = 0; foreach(visual, m_vis_map.values ()) { visual->close(); } //m_vis_map.clear(); } void Output::error ( const QString &e ) { emit stateChanged ( OutputState ( e ) ); } void Output::addVisual ( Visual *v ) { if (visuals.indexOf (v) == -1) { visuals.append (v); v->setOutput(this); qDebug("Output: added external visualization"); } } void Output::removeVisual (Visual *v) { visuals.removeAll (v); if (m_vis_map.key(v)) { VisualFactory *factory = m_vis_map.key(v); m_vis_map.remove(factory); //Visual::setEnabled(factory, FALSE); } } void Output::addVisual(VisualFactory *factory, QWidget *parent) { if (m_vis_map.value(factory)) return; Visual::setEnabled(factory, TRUE); Visual* visual = factory->create(parent); visual->setWindowFlags(Qt::Window); if (visual) { visual->setOutput(this); qDebug("Output: added visual factory: %s", qPrintable(factory->properties().name)); m_vis_map.insert (factory, visual); visual->show(); } } void Output::removeVisual(VisualFactory *factory) { if (m_vis_map.value(factory)) { m_vis_map.value(factory)->close(); m_vis_map.remove (factory); } Visual::setEnabled(factory, FALSE); } void Output::dispatchVisual ( Buffer *buffer, unsigned long written, int chan, int prec ) { if ( ! buffer || !visuals.size()) return; Visual* visual = 0; foreach (visual , visuals) //external { visual->mutex()->lock (); visual->add ( buffer, written, chan, prec ); visual->mutex()->unlock(); } foreach (visual , m_vis_map.values ()) //internal { visual->mutex()->lock (); visual->add ( buffer, written, chan, prec ); visual->mutex()->unlock(); } } void Output::clearVisuals() { Visual *visual = 0; foreach (visual, visuals ) { visual->mutex()->lock (); visual->clear(); visual->mutex()->unlock(); } foreach(visual, m_vis_map.values ()) { visual->mutex()->lock (); visual->clear(); visual->mutex()->unlock(); } } void Output::dispatch(OutputState::Type st) { if (st == OutputState::Stopped) clearVisuals(); emit stateChanged ( OutputState(st) ); } void Output::dispatch(long s, unsigned long w, int b, int f, int p, int c) { emit stateChanged ( OutputState(s, w, b, f, p, c) ); } void Output::dispatch ( const OutputState &st ) { if (st.type() == OutputState::Stopped) clearVisuals(); emit stateChanged ( st ); } void Output::dispatchVolume(int L, int R) { emit stateChanged ( OutputState(L, R) ); }