Logo Search packages:      
Sourcecode: rosegarden version File versions  Download package

studiowidgets.cpp

// -*- c-basic-offset: 4 -*-

/*
    Rosegarden-4
    A sequencer and musical notation editor.

    This program is Copyright 2000-2006
        Guillaume Laurent   <glaurent@telegraph-road.org>,
        Chris Cannam        <cannam@all-day-breakfast.com>,
        Richard Bown        <bownie@bownie.com>

    The moral right of the authors to claim authorship of this work
    has been asserted.

    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.  See the file
    COPYING included with this distribution for more information.
*/

#include <cmath>

#include <kapp.h>
#include <klocale.h>
#include <kstddirs.h>
#include <kconfig.h>
#include <kcombobox.h>

#include <qlayout.h>
#include <qvbox.h>
#include <qtooltip.h>
#include <qpopupmenu.h>
#include <qcursor.h>

#include "Instrument.h"
#include "AudioLevel.h"
#include "studiowidgets.h"
#include "colours.h"
#include "constants.h"
#include "rosedebug.h"
#include "Studio.h"
#include "MappedStudio.h"
#include "studiocontrol.h"
#include "rosegardengui.h"
#include "audiopluginoscgui.h"

//----------------------------------------

RosegardenFader::PixmapCache RosegardenFader::m_pixmapCache;

RosegardenFader::RosegardenFader(Rosegarden::AudioLevel::FaderType type,
                         int w, int h, QWidget *parent) :
    QWidget(parent),
    m_integral(false),
    m_vertical(h > w),
    m_min(0),
    m_max(0),
    m_type(type),
    m_clickMousePos(-1),
    m_float(new RosegardenTextFloat(this)),
    m_floatTimer(new QTimer())
{
    setBackgroundMode(Qt::NoBackground);
    setFixedSize(w, h); // provisional
    calculateButtonPixmap();
//    if (m_vertical) {
//    setFixedSize(w, h + m_buttonPixmap->height() + 4);
//    } else {
//    setFixedSize(w + m_buttonPixmap->width() + 4, h);
//    }

    if (m_vertical) {
      m_sliderMin = buttonPixmap()->height()/2 + 2;
      m_sliderMax = height() - m_sliderMin;
    } else {
      m_sliderMin = buttonPixmap()->width()/2 + 2;
      m_sliderMax = width() - m_sliderMin;
    } 

    m_outlineColour = colorGroup().mid();

    calculateGroovePixmap();
    setFader(0.0);

    connect(m_floatTimer, SIGNAL(timeout()), this, SLOT(slotFloatTimeout()));
    m_float->hide();
}

RosegardenFader::RosegardenFader(int min, int max, int deflt,
                         int w, int h, QWidget *parent) :
    QWidget(parent),
    m_integral(true),
    m_vertical(h > w),
    m_min(min),
    m_max(max),
    m_clickMousePos(-1),
    m_float(new RosegardenTextFloat(this)),
    m_floatTimer(new QTimer())
{
    setBackgroundMode(Qt::NoBackground);
    setFixedSize(w, h); // provisional
    calculateButtonPixmap();
//    if (m_vertical) {
//    setFixedSize(w, h + m_buttonPixmap->height() + 4);
//    } else {
//    setFixedSize(w + m_buttonPixmap->width() + 4, h);
//    }

    if (m_vertical) {
      m_sliderMin = buttonPixmap()->height()/2 + 2;
      m_sliderMax = height() - m_sliderMin;
    } else {
      m_sliderMin = buttonPixmap()->width()/2 + 2;
      m_sliderMax = width() - m_sliderMin;
    } 

    m_outlineColour = colorGroup().mid();

    calculateGroovePixmap();
    setFader(deflt);

    connect(m_floatTimer, SIGNAL(timeout()), this, SLOT(slotFloatTimeout()));
    m_float->hide();
}

RosegardenFader::RosegardenFader(int min, int max, int deflt,
                         bool vertical, QWidget *parent) :
    QWidget(parent),
    m_integral(true),
    m_vertical(vertical),
    m_min(min),
    m_max(max),
    m_clickMousePos(-1),
    m_float(new RosegardenTextFloat(this)),
    m_floatTimer(new QTimer())
{
    setBackgroundMode(Qt::NoBackground);
    calculateButtonPixmap();

    if (m_vertical) {
      m_sliderMin = buttonPixmap()->height()/2 + 2;
      m_sliderMax = height() - m_sliderMin;
    } else {
      m_sliderMin = buttonPixmap()->width()/2 + 2;
      m_sliderMax = width() - m_sliderMin;
    } 

    m_outlineColour = colorGroup().mid();

    calculateGroovePixmap();
    setFader(deflt);

    connect(m_floatTimer, SIGNAL(timeout()), this, SLOT(slotFloatTimeout()));
    m_float->hide();
}

RosegardenFader::~RosegardenFader()
{
}

void
RosegardenFader::setOutlineColour(QColor c)
{
    m_outlineColour = c;
    calculateGroovePixmap();
}

QPixmap *
RosegardenFader::groovePixmap()
{
    PixmapCache::iterator i = m_pixmapCache.find(SizeRec(width(), height()));
    if (i != m_pixmapCache.end()) {
      ColourPixmapRec::iterator j = i->second.first.find(m_outlineColour.pixel());
      if (j != i->second.first.end()) {
          return j->second;
      }
    }
    return 0;
}

QPixmap *
RosegardenFader::buttonPixmap()
{
    PixmapCache::iterator i = m_pixmapCache.find(SizeRec(width(), height()));
    if (i != m_pixmapCache.end()) {
      return i->second.second;
    }
    else return 0;
}

float
RosegardenFader::getFaderLevel() const
{
    return m_value;
}

void
RosegardenFader::setFader(float value)
{
    m_value = value;
    emit faderChanged(value);
    paintEvent(0);
}

float
RosegardenFader::position_to_value(int position)
{
    float value;

    if (m_integral) {
      float sliderLength = float(m_sliderMax) - float(m_sliderMin);
      value = float(position)
          * float(m_max - m_min) / sliderLength - float(m_min);
        if (value > m_max) value = float(m_max);
        if (value < m_min) value = float(m_min);
    } else {
      value = Rosegarden::AudioLevel::fader_to_dB
          (position, m_sliderMax - m_sliderMin, m_type);
    }
/*
    RG_DEBUG << "RosegardenFader::position_to_value - position = " << position
             << ", new value = " << value << endl;

    if (m_min != m_max) // works for integral case
    {
        if (value > m_max) value = float(m_max);
        if (value < m_min) value = float(m_min);
    }

    RG_DEBUG << "RosegardenFader::position_to_value - limited value = " << value << endl;
*/
    return value;
}

int
RosegardenFader::value_to_position(float value)
{
    int position;

    if (m_integral) {
      float sliderLength = float(m_sliderMax) - float(m_sliderMin);
      position = 
          int(sliderLength * (value - float(m_min)) / float(m_max - m_min) + 0.1);
    } else {
      position = 
          Rosegarden::AudioLevel::dB_to_fader
          (value, m_sliderMax - m_sliderMin, m_type);
    }

    return position;
} 

void
RosegardenFader::paintEvent(QPaintEvent *)
{
    QPainter paint(this);
    int position = value_to_position(m_value);

    if (m_vertical) {

      int aboveButton = height() - position - m_sliderMin - buttonPixmap()->height()/2;
      int belowButton = position + m_sliderMin - buttonPixmap()->height()/2;

      if (aboveButton > 0) {
          paint.drawPixmap(0, 0,
                       *groovePixmap(),
                       0, 0,
                       groovePixmap()->width(), aboveButton);
      }

      if (belowButton > 0) {
          paint.drawPixmap(0, aboveButton + buttonPixmap()->height(),
                       *groovePixmap(),
                       0, aboveButton + buttonPixmap()->height(),
                       groovePixmap()->width(), belowButton);
      }

      int buttonMargin = (width() - buttonPixmap()->width()) / 2;

      paint.drawPixmap(buttonMargin, aboveButton, *buttonPixmap());

      paint.drawPixmap(0, aboveButton,
                   *groovePixmap(),
                   0, aboveButton,
                   buttonMargin, buttonPixmap()->height());

      paint.drawPixmap(buttonMargin + buttonPixmap()->width(), aboveButton,
                   *groovePixmap(),
                   buttonMargin + buttonPixmap()->width(), aboveButton,
                   width() - buttonMargin - buttonPixmap()->width(),
                   buttonPixmap()->height());

    } else {
//... update
      int leftOfButton =
          (m_sliderMax - m_sliderMin) - position - buttonPixmap()->width()/2;

      int rightOfButton =
          position - buttonPixmap()->width()/2;

      if (leftOfButton > 0) {
          paint.drawPixmap(0, 0,
                       *groovePixmap(),
                       0, 0,
                       leftOfButton, groovePixmap()->height());
      }

      if (rightOfButton > 0) {
          paint.drawPixmap(rightOfButton + buttonPixmap()->width(), 0,
                       *groovePixmap(),
                       groovePixmap()->width() - rightOfButton, 0,
                       rightOfButton, groovePixmap()->height());
      }

      paint.drawPixmap(leftOfButton, 0, *buttonPixmap());
    }

    paint.end();
}

void
RosegardenFader::mousePressEvent(QMouseEvent *e)
{
    m_clickMousePos = -1;

    if (e->button() == LeftButton) {
      
      if (e->type() == QEvent::MouseButtonDblClick) {
          setFader(0);
          return;
      }

      if (m_vertical) {
          int buttonPosition = value_to_position(m_value);
          int clickPosition = height() - e->y() - m_sliderMin;
          
          if (clickPosition < buttonPosition + buttonPixmap()->height()/2 &&
            clickPosition > buttonPosition - buttonPixmap()->height()/2) {
            m_clickMousePos = clickPosition;
            m_clickButtonPos = value_to_position(m_value);
            showFloatText();
          }
      }
    }
}

void
RosegardenFader::mouseReleaseEvent(QMouseEvent *e)
{
    mouseMoveEvent(e);
    m_clickMousePos = -1;
}

void
RosegardenFader::mouseMoveEvent(QMouseEvent *e)
{
    if (m_clickMousePos >= 0) {
      if (m_vertical) {
          int mousePosition = height() - e->y() - m_sliderMin;
          int delta = mousePosition - m_clickMousePos;
          int buttonPosition = m_clickButtonPos + delta;
          if (buttonPosition < 0) buttonPosition = 0;
          if (buttonPosition > m_sliderMax - m_sliderMin) {
            buttonPosition = m_sliderMax - m_sliderMin;
          }
          setFader(position_to_value(buttonPosition));
          showFloatText();
      }
    }
}

void
RosegardenFader::wheelEvent(QWheelEvent *e)
{
    int buttonPosition = value_to_position(m_value);
    if (e->state() & ShiftButton) {
      if (e->delta() > 0) buttonPosition += 10;
      else buttonPosition -= 10;
    } else {
      if (e->delta() > 0) buttonPosition += 1;
      else buttonPosition -= 1;
    }
    RG_DEBUG << "RosegardenFader::wheelEvent - button position = " << buttonPosition << endl;
    setFader(position_to_value(buttonPosition));
    RG_DEBUG << "RosegardenFader::wheelEvent - value = " << m_value << endl;

    showFloatText();
}

void
RosegardenFader::showFloatText()
{
    // draw on the float text

    QString text;

    if (m_integral) {
      text = QString("%1").arg(int(m_value));
    } else if (m_value == Rosegarden::AudioLevel::DB_FLOOR) {
      text = "Off";
    } else {
      float v = fabs(m_value);
      text = QString("%1%2.%3%4%5 dB")
          .arg(m_value < 0 ? '-' : '+')
          .arg(int(v))
          .arg(int(v * 10) % 10)
          .arg(int(v * 100) % 10)
          .arg(int(v * 1000) % 10);
    }

    m_float->setText(text);

    // Reposition - we need to sum the relative positions up to the
    // topLevel or dialog to please move().
    //
    QWidget *par = parentWidget();
    QPoint totalPos = this->pos();

    while (par->parentWidget() && !par->isTopLevel() && !par->isDialog())
    {
        totalPos += par->pos();
        par = par->parentWidget();
    }

    // Move just top/right
    //
    m_float->move(totalPos + QPoint(width() + 2, 0));

    // Show
    m_float->show();

    // one shot, 500ms
    m_floatTimer->start(500, true);
}

void
RosegardenFader::slotFloatTimeout()
{
    m_float->hide();
}

void
RosegardenFader::calculateGroovePixmap()
{
    QPixmap *& map = m_pixmapCache[SizeRec(width(), height())].first[m_outlineColour.pixel()];

    delete map;
    map = new QPixmap(width(), height());
    map->fill(colorGroup().background());
    QPainter paint(map);
    paint.setBrush(colorGroup().background());

    if (m_vertical) {

      paint.setPen(m_outlineColour);
      paint.drawRect(0, 0, width(), height());
 
      if (m_integral) {
          //...
      } else {
          for (int dB = -70; dB <= 10; ) {
            int position = value_to_position(float(dB));
            if (position >= 0 &&
                position < m_sliderMax - m_sliderMin) {
                if (dB == 0) paint.setPen(colorGroup().dark());
                else paint.setPen(colorGroup().midlight());
                paint.drawLine(1, (m_sliderMax - position),
                           width()-2, (m_sliderMax - position));
            }
            if (dB < -10) dB += 10;
            else dB += 2;
          }
      }
      
      paint.setPen(colorGroup().dark());
      paint.setBrush(colorGroup().mid());
      paint.drawRect(width()/2 - 3, height() - m_sliderMax,
                   6, m_sliderMax - m_sliderMin);
      paint.end();
    } else {
      //...
    }
}

void
RosegardenFader::calculateButtonPixmap()
{
    PixmapCache::iterator i = m_pixmapCache.find(SizeRec(width(), height()));
    if (i != m_pixmapCache.end() && i->second.second) return;
    
    QPixmap *& map = m_pixmapCache[SizeRec(width(), height())].second;

    if (m_vertical) {

      int buttonHeight = height()/7;
      buttonHeight /= 10;
      ++buttonHeight;
      buttonHeight *= 10;
      ++buttonHeight;
      int buttonWidth = width() * 2 / 3;
      buttonWidth /= 5;
      ++buttonWidth;
      buttonWidth *= 5;
      if (buttonWidth > width()-2) buttonWidth = width()-2;

      map = new QPixmap(buttonWidth, buttonHeight);
      map->fill(colorGroup().background());

      int x = 0;
      int y = 0;

      QPainter paint(map);

      paint.setPen(colorGroup().light());
      paint.drawLine(x + 1, y, x + buttonWidth - 2, y);
      paint.drawLine(x, y + 1, x, y + buttonHeight - 2);

      paint.setPen(colorGroup().midlight());
      paint.drawLine(x + 1, y + 1, x + buttonWidth - 2, y + 1);
      paint.drawLine(x + 1, y + 1, x + 1, y + buttonHeight - 2);

      paint.setPen(colorGroup().mid());
      paint.drawLine(x + 2, y + buttonHeight - 2, x + buttonWidth - 2,
                   y + buttonHeight - 2);
      paint.drawLine(x + buttonWidth - 2, y + 2, x + buttonWidth - 2,
                   y + buttonHeight - 2);

      paint.setPen(colorGroup().dark());
      paint.drawLine(x + 1, y + buttonHeight - 1, x + buttonWidth - 2,
                   y + buttonHeight - 1);
      paint.drawLine(x + buttonWidth - 1, y + 1, x + buttonWidth - 1,
                   y + buttonHeight - 2);

      paint.setPen(colorGroup().shadow());
      paint.drawLine(x + 1, y + buttonHeight/2, x + buttonWidth - 2,
                   y + buttonHeight/2);

      paint.setPen(colorGroup().mid());
      paint.drawLine(x + 1, y + buttonHeight/2 - 1, x + buttonWidth - 2,
                   y + buttonHeight/2 - 1);
      paint.drawPoint(x, y + buttonHeight/2);

      paint.setPen(colorGroup().light());
      paint.drawLine(x + 1, y + buttonHeight/2 + 1, x + buttonWidth - 2,
                   y + buttonHeight/2 + 1);

      paint.setPen(colorGroup().button());
      paint.setBrush(colorGroup().button());
      paint.drawRect(x + 2, y + 2, buttonWidth - 4, buttonHeight/2 - 4);
      paint.drawRect(x + 2, y + buttonHeight/2 + 2,
                   buttonWidth - 4, buttonHeight/2 - 4);

      paint.end();
    } else {
      //...
    }
}


    
//  ------------------  AudioVUMeter ---------------------
//
AudioVUMeter::AudioVUMeter(QWidget *parent,
                           VUMeter::VUMeterType type,
                           bool stereo,
                     bool hasRecord,
                           int width,
                           int height,
                           const char *name) :
    QWidget(parent, name),
    m_stereo(stereo)
{
    setBackgroundMode(Qt::NoBackground);
    setFixedSize(width, height);

    // This offset is intended to match that for the height of the
    // button pixmap in RosegardenFader (in studiowidgets.cpp, which
    // is probably where this class should be too)

    m_yoff = height / 7;
    m_yoff /= 10;
    ++m_yoff;
    m_yoff *= 10;
    ++m_yoff;

    // This one is _not_ intended to match that for the button width

    m_xoff = width / 4;
    if (m_xoff % 2 == 1) ++m_xoff;

    m_meter = new AudioVUMeterImpl(this, type, stereo, hasRecord,
                           width - m_xoff, height - m_yoff, name);

    m_meter->move(m_xoff/2, m_yoff/2);
}

void
AudioVUMeter::paintEvent(QPaintEvent *e)
{
    QPainter paint(this);
    paint.setPen(colorGroup().mid());
    paint.drawRect(0, 0, width(), height());

    paint.setPen(colorGroup().background());
    paint.setBrush(colorGroup().background());
    paint.drawRect(1, 1, width() - 2, m_yoff/2 - 1);
    paint.drawRect(1, 1, m_xoff/2 - 1, height() - 2);
    paint.drawRect(width() - m_xoff/2 - 1, 1, m_xoff/2, height() - 2);
    paint.drawRect(1, height() - m_yoff/2 - 1, width() - 2, m_yoff/2);
    paint.end();

    m_meter->paintEvent(e);
}

AudioVUMeter::AudioVUMeterImpl::AudioVUMeterImpl(QWidget *parent,
                                     VUMeterType type,
                                     bool stereo,
                                     bool hasRecord,
                                     int width,
                                     int height,
                                     const char *name) :
    VUMeter(parent, type, stereo, hasRecord, width, height, VUMeter::Vertical, name)
{
}


// ---------------- AudioRouteMenu ------------------
//

AudioRouteMenu::AudioRouteMenu(QWidget *par,
                         Direction direction,
                         Format format,
                         Rosegarden::Studio *studio,
                         Rosegarden::Instrument *instrument) :
    QObject(par),
    m_studio(studio),
    m_instrument(instrument),
    m_direction(direction),
    m_format(format)
{
    switch (format) {

    case Compact:
    {
      m_combo = 0;
      m_button = new WheelyButton(par);
      connect(m_button, SIGNAL(wheel(bool)), this, SLOT(slotWheel(bool)));
      connect(m_button, SIGNAL(clicked()), this, SLOT(slotShowMenu()));
      break;
    }

    case Regular:
    {
      m_button = 0;
      m_combo = new KComboBox(par);
      connect(m_combo, SIGNAL(activated(int)), this, SLOT(slotEntrySelected(int)));
      break;
    }

    }

    slotRepopulate();
}

QWidget *
AudioRouteMenu::getWidget()
{
    if (m_button) return m_button;
    else return m_combo;
}

void
AudioRouteMenu::slotRepopulate()
{
    switch (m_format) {

    case Compact:
      m_button->setText(getEntryText(getCurrentEntry()));
      break;

    case Regular:
      m_combo->clear();
      for (int i = 0; i < getNumEntries(); ++i) {
          m_combo->insertItem(getEntryText(i));
      }
      m_combo->setCurrentItem(getCurrentEntry());
      break;
    }
}

void
AudioRouteMenu::slotSetInstrument(Rosegarden::Studio *studio,
                          Rosegarden::Instrument *instrument)
{
    m_studio = studio;
    m_instrument = instrument;
    slotRepopulate();
}

void
AudioRouteMenu::slotWheel(bool up)
{
    int current = getCurrentEntry();
    if (up) { // actually moves down the list
      if (current > 0) slotEntrySelected(current - 1);
    } else {
      if (current < getNumEntries() - 1) slotEntrySelected(current + 1);
    }
}

class BlahPopupMenu : public QPopupMenu
{
    // just to make itemHeight public
public:
    BlahPopupMenu(QWidget *parent) : QPopupMenu(parent) { }
    using QPopupMenu::itemHeight;
};

void
AudioRouteMenu::slotShowMenu()
{
    if (getNumEntries() == 0) return;

    BlahPopupMenu *menu = new BlahPopupMenu((QWidget *)parent());

    for (int i = 0; i < getNumEntries(); ++i) {

      menu->insertItem(getEntryText(i), this, SLOT(slotEntrySelected(int)),
                   0, i);
      menu->setItemParameter(i, i);
    }

    int itemHeight = menu->itemHeight(0) + 2;
    QPoint pos = QCursor::pos();
    
    pos.rx() -= 10;
    pos.ry() -= (itemHeight / 2 + getCurrentEntry() * itemHeight);

    menu->popup(pos);
}

int
AudioRouteMenu::getNumEntries()
{
    if (!m_instrument) return 0;

    switch (m_direction) {

    case In:
    {
      int stereoIns =
          m_studio->getRecordIns().size() +
          m_studio->getBusses().size();

      if (m_instrument->getAudioChannels() > 1) {
          return stereoIns;
      } else {
          return stereoIns * 2;
      }

      break;
    }

    case Out:
      return m_studio->getBusses().size();
    }

    return 0;
}

int
AudioRouteMenu::getCurrentEntry()
{
    if (!m_instrument) return 0;

    switch (m_direction) {

    case In:
    {
      bool stereo = (m_instrument->getAudioChannels() > 1);

      bool isBuss;
      int channel;
      int input = m_instrument->getAudioInput(isBuss, channel);

      if (isBuss) {
          int recordIns = m_studio->getRecordIns().size();
          if (stereo) {
            return recordIns + input;
          } else {
            return recordIns * 2 + input * 2 + channel;
          }
      } else {
          if (stereo) {
            return input;
          } else {
            return input * 2 + channel;
          }
      }

      break;
    }

    case Out:
      return m_instrument->getAudioOutput();
    }

    return 0;
}    

QString
AudioRouteMenu::getEntryText(int entry)
{
    switch (m_direction) {

    case In:
    {
      bool stereo = (m_instrument->getAudioChannels() > 1);
      int recordIns = m_studio->getRecordIns().size();

      if (stereo) {
          if (entry < recordIns) {
            return i18n("In %1").arg(entry + 1);
          } else if (entry == recordIns) {
            return i18n("Master");
          } else {
            return i18n("Sub %1").arg(entry - recordIns);
          }
      } else {
          int channel = entry % 2;
          entry /= 2;
          if (entry < recordIns) {
            return (channel ? i18n("In %1 R") :
                            i18n("In %1 L")).arg(entry + 1);
          } else if (entry == recordIns) {
            return (channel ? i18n("Master R") :
                            i18n("Master L"));
          } else {
            return (channel ? i18n("Sub %1 R") :
                            i18n("Sub %1 L")).arg(entry - recordIns);
          }
      }
      break;
    }

    case Out:
      if (entry == 0) return i18n("Master");
      else return i18n("Sub %1").arg(entry);
    }

    return QString();
}

void
AudioRouteMenu::slotEntrySelected(int i)
{
    switch (m_direction) {

    case In:
    {
      bool stereo = (m_instrument->getAudioChannels() > 1);

      bool oldIsBuss;
      int oldChannel;
      int oldInput = m_instrument->getAudioInput(oldIsBuss, oldChannel);

      bool newIsBuss;
      int newChannel = 0;
      int newInput;

      int recordIns = m_studio->getRecordIns().size();

      if (stereo) {
          newIsBuss = (i >= recordIns);
          if (newIsBuss) {
            newInput = i - recordIns;
          } else {
            newInput = i;
          }
      } else {
          newIsBuss = (i >= recordIns * 2);
          newChannel = i % 2;
          if (newIsBuss) {
            newInput = i/2 - recordIns;
          } else {
            newInput = i/2;
          }
      }

      Rosegarden::MappedObjectId oldMappedId = 0, newMappedId = 0;

      if (oldIsBuss) {
          Rosegarden::Buss *buss = m_studio->getBussById(oldInput);
          if (buss) oldMappedId = buss->getMappedId();
      } else {
          Rosegarden::RecordIn *in = m_studio->getRecordIn(oldInput);
          if (in) oldMappedId = in->getMappedId();
      }

      if (newIsBuss) {
          Rosegarden::Buss *buss = m_studio->getBussById(newInput);
          if (!buss) return;
          newMappedId = buss->getMappedId();
      } else {
          Rosegarden::RecordIn *in = m_studio->getRecordIn(newInput);
          if (!in) return;
          newMappedId = in->getMappedId();
      }

      if (oldMappedId != 0) {
          Rosegarden::StudioControl::disconnectStudioObjects
            (oldMappedId, m_instrument->getMappedId());
      } else {
          Rosegarden::StudioControl::disconnectStudioObject
            (m_instrument->getMappedId());
      }

      Rosegarden::StudioControl::setStudioObjectProperty
          (m_instrument->getMappedId(),
           Rosegarden::MappedAudioFader::InputChannel, 
           Rosegarden::MappedObjectValue(newChannel));

      if (newMappedId != 0) {
          Rosegarden::StudioControl::connectStudioObjects
            (newMappedId, m_instrument->getMappedId());
      }
      
      if (newIsBuss) {
          m_instrument->setAudioInputToBuss(newInput, newChannel);
      } else {
          m_instrument->setAudioInputToRecord(newInput, newChannel);
      }
      
      break;
    }

    case Out:
    {
      Rosegarden::BussId bussId = m_instrument->getAudioOutput();
      Rosegarden::Buss *oldBuss = m_studio->getBussById(bussId);
      Rosegarden::Buss *newBuss = m_studio->getBussById(i);
      if (!newBuss) return;

      if (oldBuss) {
          Rosegarden::StudioControl::disconnectStudioObjects
            (m_instrument->getMappedId(), oldBuss->getMappedId());
      } else {
          Rosegarden::StudioControl::disconnectStudioObject
            (m_instrument->getMappedId());
      }

      Rosegarden::StudioControl::connectStudioObjects
          (m_instrument->getMappedId(), newBuss->getMappedId());

      m_instrument->setAudioOutput(i);
      break;
    }
    }
    
    slotRepopulate();
    emit changed();
}
    



// ---------------- AudioFaderBox ------------------
//


AudioFaderBox::AudioFaderBox(QWidget *parent,
                       QString id,
                       bool haveInOut,
                       const char *name):
    QFrame(parent, name),
    m_signalMapper(new QSignalMapper(this)),
    m_id(id),
    m_isStereo(false)
{
    // Plugin box
    //
    QPushButton *plugin;
    QVBox *pluginVbox = 0;
    
    pluginVbox = new QVBox(this);
    pluginVbox->setSpacing(2);
    
    for (int i = 0; i < 5; i++)
    {
      plugin = new QPushButton(pluginVbox);
      plugin->setText(i18n("<no plugin>"));
      
      QToolTip::add(plugin, i18n("Audio plugin button"));
      
      m_plugins.push_back(plugin);
      m_signalMapper->setMapping(plugin, i);
      connect(plugin, SIGNAL(clicked()),
            m_signalMapper, SLOT(map()));
    }

    m_synthButton = new QPushButton(this);
    m_synthButton->setText(i18n("<no synth>"));
    QToolTip::add(m_synthButton, i18n("Synth plugin button"));

    // VU meter and fader
    //
    QHBox *faderHbox = new QHBox(this);
    
    m_vuMeter = new AudioVUMeter(faderHbox, VUMeter::AudioPeakHoldShort,
                         true, true);
    
    m_recordFader = new RosegardenFader(Rosegarden::AudioLevel::ShortFader,
                              20, m_vuMeter->height(), faderHbox);

    m_recordFader->setOutlineColour(Rosegarden::GUIPalette::getColour(Rosegarden::GUIPalette::RecordFaderOutline));

    delete m_vuMeter; // only used the first one to establish height,
                  // actually want it after the record fader in
                  // hbox
    m_vuMeter = new AudioVUMeter(faderHbox, VUMeter::AudioPeakHoldShort,
                         true, true);

    m_fader = new RosegardenFader(Rosegarden::AudioLevel::ShortFader,
                          20, m_vuMeter->height(), faderHbox);

    m_fader->setOutlineColour(Rosegarden::GUIPalette::getColour(Rosegarden::GUIPalette::PlaybackFaderOutline));

    QString pixmapDir = KGlobal::dirs()->findResource("appdata", "pixmaps/");
    m_monoPixmap.load(QString("%1/misc/mono.xpm").arg(pixmapDir));
    m_stereoPixmap.load(QString("%1/misc/stereo.xpm").arg(pixmapDir));

    m_pan = new RosegardenRotary(this, -100.0, 100.0, 1.0, 5.0, 0.0, 22,
                         RosegardenRotary::NoTicks, false, true);

    // same as the knob colour on the MIDI pan
    m_pan->setKnobColour(Rosegarden::GUIPalette::getColour(Rosegarden::GUIPalette::RotaryPastelGreen));

    m_stereoButton = new QPushButton(this);
    m_stereoButton->setPixmap(m_monoPixmap); // default is mono
    m_stereoButton->setFixedSize(24, 24);
    
    connect(m_stereoButton, SIGNAL(clicked()),
          this, SLOT(slotChannelStateChanged()));

    m_synthGUIButton = new QPushButton(this);
    m_synthGUIButton->setText(i18n("Editor"));

    if (haveInOut) {
      m_audioInput  = new AudioRouteMenu(this,
                                 AudioRouteMenu::In,
                                 AudioRouteMenu::Regular);
      m_audioOutput = new AudioRouteMenu(this,
                                 AudioRouteMenu::Out,
                                 AudioRouteMenu::Regular);
    } else {
      m_pan->setKnobColour(Rosegarden::GUIPalette::getColour(Rosegarden::GUIPalette::RotaryPastelOrange));

      m_audioInput = 0;
      m_audioOutput = 0;
    }

    QToolTip::add(m_pan, i18n("Set the audio pan position in the stereo field"));
    QToolTip::add(m_synthGUIButton, i18n("Open synth plugin's native editor"));
    QToolTip::add(m_stereoButton, i18n("Mono or Stereo Instrument"));
    QToolTip::add(m_recordFader, i18n("Record level"));
    QToolTip::add(m_fader, i18n("Playback level"));
    QToolTip::add(m_vuMeter, i18n("Audio level"));

    QGridLayout *grid = new QGridLayout(this, 3, 6, 4, 4);
    
    grid->addMultiCellWidget(m_synthButton, 0, 0, 0, 2);

    if (haveInOut) {
      m_inputLabel = new QLabel(i18n("In:"), this);
      grid->addWidget(m_inputLabel, 0, 0, AlignRight);
      grid->addMultiCellWidget(m_audioInput->getWidget(), 0, 0, 1, 2);
      m_outputLabel = new QLabel(i18n("Out:"), this);
      grid->addWidget(m_outputLabel, 0, 3, AlignRight);
      grid->addMultiCellWidget(m_audioOutput->getWidget(), 0, 0, 4, 5);
    }

    grid->addMultiCellWidget(pluginVbox,   2, 2, 0, 2);
    grid->addMultiCellWidget(faderHbox,    1, 2, 3, 5);

    grid->addWidget(m_synthGUIButton,       1, 0);
    grid->addWidget(m_pan,                  1, 2);
    grid->addWidget(m_stereoButton,         1, 1);

    for (int i = 0; i < 5; ++i) {
      // Force width
      m_plugins[i]->setFixedWidth(m_plugins[i]->width());
    }
    m_synthButton->setFixedWidth(m_plugins[0]->width());
    
    m_synthButton->hide();
    m_synthGUIButton->hide();
}

void
AudioFaderBox::setIsSynth(bool isSynth)
{
    if (isSynth) {
      m_inputLabel->hide();
      m_synthButton->show();
      m_synthGUIButton->show();
      m_audioInput->getWidget()->hide();
      m_recordFader->hide();
    } else {
      m_synthButton->hide();
      m_synthGUIButton->hide();
      m_inputLabel->show();
      m_audioInput->getWidget()->show();
      m_recordFader->show();
    }
}

void
AudioFaderBox::slotSetInstrument(Rosegarden::Studio *studio,
                         Rosegarden::Instrument *instrument)
{
    if (m_audioInput) m_audioInput->slotSetInstrument(studio, instrument);
    if (m_audioOutput) m_audioOutput->slotSetInstrument(studio, instrument);
    if (instrument) setAudioChannels(instrument->getAudioChannels());
    if (instrument) {

      RG_DEBUG << "AudioFaderBox::slotSetInstrument(" << instrument->getId() << ")" << endl;

      setIsSynth(instrument->getType() == Rosegarden::Instrument::SoftSynth);
      if (instrument->getType() == Rosegarden::Instrument::SoftSynth) {
          bool gui = false;
          RG_DEBUG << "AudioFaderBox::slotSetInstrument(" << instrument->getId() << "): is soft synth" << endl;
#ifdef HAVE_LIBLO
          gui = RosegardenGUIApp::self()->getPluginGUIManager()->hasGUI
            (instrument->getId(), Rosegarden::Instrument::SYNTH_PLUGIN_POSITION);
          RG_DEBUG << "AudioFaderBox::slotSetInstrument(" << instrument->getId() << "): has gui = " << gui << endl;
#endif
          m_synthGUIButton->setEnabled(gui);
      }         
    }
}

bool
AudioFaderBox::owns(const QObject *object)
{
    return (object &&
          ((object->parent() == this) ||
           (object->parent() && (object->parent()->parent() == this))));
}

void
AudioFaderBox::setAudioChannels(int channels)
{
    m_isStereo = (channels > 1);

    switch (channels)
    {
        case 1:
          if (m_stereoButton) m_stereoButton->setPixmap(m_monoPixmap);
            m_isStereo = false;
            break;

        case 2:
            if (m_stereoButton) m_stereoButton->setPixmap(m_stereoPixmap);
            m_isStereo = true;
            break;
        default:
            RG_DEBUG << "AudioFaderBox::setAudioChannels - "
                     << "unsupported channel numbers (" << channels
                     << ")" << endl;
          return;
    }

    if (m_audioInput) m_audioInput->slotRepopulate();
    if (m_audioOutput) m_audioOutput->slotRepopulate();
}

void
AudioFaderBox::slotChannelStateChanged()
{
    if (m_isStereo)
    {
        setAudioChannels(1);
        emit audioChannelsChanged(1);
    }
    else
    {
        setAudioChannels(2);
        emit audioChannelsChanged(2);
    }
}


#include "studiowidgets.moc"

Generated by  Doxygen 1.6.0   Back to index