fix #275313: rework mixer ui 2

Moving PartEditBase into separate file.  Creating new files for
building mixer.

Creating art assets/UI design for new components.

Styling the track control.

Adding track area.

Separating out score from update.

Creating instances of mixer UI.

Creating part per voice now.

Can click on tracks to select them now.

Can now switch bwtewwn tracks.

Setting patch channel now.

Setting enabled off when no track selected.

Improving slider ui.

Turning Channel into a class and adding listener to it.

Somewhat stabalized sharing track objects between interfaces.

Can now apply volume changes to both expanded and collapsed tracks.

Pan knob is now working.

Encapsulating the rest of the fields in Channel.

Mute and solo now working.

Reverb and chorus now working.

Drumkit checkbox now working.  Port and channel somewhat working.

Adding support for colors per track.

Part name change now working.

Separating out MixerTrackItem

Finishing moving MixerTrackItem to new file.

Cleaning up code.

Moving PartEditBase into separate file.  Creating new files for
building mixer.

Creating art assets/UI design for new components.

Styling the track control.

Adding track area.

Separating out score from update.

Creating instances of mixer UI.

Creating part per voice now.

Can click on tracks to select them now.

Can now switch bwtewwn tracks.

Setting patch channel now.

Setting enabled off when no track selected.

Improving slider ui.

Turning Channel into a class and adding listener to it.

Somewhat stabalized sharing track objects between interfaces.

Can now apply volume changes to both expanded and collapsed tracks.

Pan knob is now working.

Encapsulating the rest of the fields in Channel.

Mute and solo now working.

Reverb and chorus now working.

Drumkit checkbox now working.  Port and channel somewhat working.

Adding support for colors per track.

Part name change now working.

Separating out MixerTrackItem

Finishing moving MixerTrackItem to new file.

Cleaning up code.

Setting color in collapsed mode now affects all channels.

Using shared_ptr to track MixerTrackItem.  Part changes now affect
all instruments.

Creating new track UI object to handle parts.

Using shard_ptr to track MixerTrackItem objects.

setting port and channel data now.

Changing to horizontal layout.

Fixing knob display.  Chaning track control appearance.

Setting init slider window size.

Switchong back to vertical orientation.  Fixing a few UI bugs in
the slider.

Tracks now left aligned.

Moving details panel above mixer.  Now changing track selection when
user clicks on sliders.

Pan and volume controls now reflect track color.

Showing volume and pan values in tooltips.

Creating a new slider control for mixer.

Switching Channel's volume, pan, reverb and chorus and chaning them
to doubles with a decimal range.

No longer writing out vol, pan, chor, reverb when at default values.

Nolonger writing vol, pan, chorus, reverb as controler values in
output file.

Now testing against default values on write.

More export fixes.

Manually editing test files to reflect new channel parameters.

Manually editing more test files to reflect new channel parameters.

Manually editing more test files to reflect new channel parameters.

More test changes to make Travis happy.

More test changes to make Travis happy.

Importing MusicXML now matches new volume, pan ranges.

Changing range of pan.  Fixing a few bugs with calculating MIDI.
Altering test files for Travis.

fix #275313: rework-mixer-ui-2

Moving PartEditBase into separate file. Creating new files for
building mixer.

Creating art assets/UI design for new components.

Styling the track control.

Adding track area.

Separating out score from update.

Creating instances of mixer UI.

Creating part per voice now.

Can click on tracks to select them now.

Can now switch bwtewwn tracks.

Setting patch channel now.

Setting enabled off when no track selected.

Improving slider ui.

Turning Channel into a class and adding listener to it.

Somewhat stabalized sharing track objects between interfaces.

Can now apply volume changes to both expanded and collapsed tracks.

Pan knob is now working.

Encapsulating the rest of the fields in Channel.

Mute and solo now working.

Reverb and chorus now working.

Drumkit checkbox now working.  Port and channel somewhat working.

Adding support for colors per track.

Part name change now working.

Separating out MixerTrackItem

Finishing moving MixerTrackItem to new file.

Cleaning up code.

Moving PartEditBase into separate file.  Creating new files for
building mixer.

Creating art assets/UI design for new components.

Styling the track control.

Adding track area.

Separating out score from update.

Creating instances of mixer UI.

Creating part per voice now.

Can click on tracks to select them now.

Can now switch bwtewwn tracks.

Setting patch channel now.

Setting enabled off when no track selected.

Improving slider ui.

Turning Channel into a class and adding listener to it.

Somewhat stabalized sharing track objects between interfaces.

Can now apply volume changes to both expanded and collapsed tracks.

Pan knob is now working.

Encapsulating the rest of the fields in Channel.

Mute and solo now working.

Reverb and chorus now working.

Drumkit checkbox now working.  Port and channel somewhat working.

Adding support for colors per track.

Part name change now working.

Separating out MixerTrackItem

Finishing moving MixerTrackItem to new file.

Cleaning up code.

Setting color in collapsed mode now affects all channels.

Using shared_ptr to track MixerTrackItem.  Part changes now affect
all instruments.

Creating new track UI object to handle parts.

Using shard_ptr to track MixerTrackItem objects.

setting port and channel data now.

Changing to horizontal layout.

Fixing knob display.  Chaning track control appearance.

Setting init slider window size.

Switchong back to vertical orientation.  Fixing a few UI bugs in
the slider.

Tracks now left aligned.

Moving details panel above mixer.  Now changing track selection when
user clicks on sliders.

Pan and volume controls now reflect track color.

Showing volume and pan values in tooltips.

Creating a new slider control for mixer.

Switching Channel's volume, pan, reverb and chorus and chaning them
to doubles with a decimal range.

No longer writing out vol, pan, chor, reverb when at default values.

Nolonger writing vol, pan, chorus, reverb as controler values in
output file.

Now testing against default values on write.

More export fixes.

Manually editing test files to reflect new channel parameters.

Manually editing more test files to reflect new channel parameters.

Manually editing more test files to reflect new channel parameters.

More test changes to make Travis happy.

More test changes to make Travis happy.

Importing MusicXML now matches new volume, pan ranges.

Changing range of pan.  Fixing a few bugs with calculating MIDI.
Altering test files for Travis.

Restoring the volume, pan, chorus, reverb to original char data type
& range.  UI now shows different 'user friendly' ranges.

Overwriting tests with versions from master.

mtest/libmscore/compat114/clef_missing_first-ref.mscx
mtest/libmscore/compat114/hor_frame_and_mmrest-ref.mscx
mtest/musicxml/io/testInstrumentChangeMIDIportExport_ref.xml
mtest/musicxml/io/testUninitializedDivisions_ref.xml

Restoring test files to original state.

Restoring test files to original state.

Restoring old values for importing files.

Restoring part methods.

mtest/importmidi/simplify_8th_dotted_no_staccato.mscx
mtest/libmscore/compat114/clef_missing_first-ref.mscx
mtest/libmscore/compat114/hor_frame_and_mmrest-ref.mscx
mtest/musicxml/io/testInstrumentChangeMIDIportExport_ref.xml
mtest/musicxml/io/testUninitializedDivisions_ref.xml

Rearranging UI components for better feel.

Improving UI.  Fixed crash when changing part name.

Adding support for two lighting modes.  Showing part name over
channel expansion.

Adding master gain control to mixer.

Changing color of gain slider.

Adapting to latest source in main.

Changing master gain slider to use decibel calculation.

CSS now set on tracks whenever a Paint event received.

Restoring mixer slider values to refect MIDI ranges.  Fixing crash when drumkit checked.

Fixing crash when closing score.

Fixing alignment in mixer details.

Tweaking UI for better appearance.
This commit is contained in:
Mark McKay 2018-11-13 12:43:19 -05:00
parent cf24e6c1d7
commit fdeb795e34
74 changed files with 6710 additions and 1585 deletions

View file

@ -34,6 +34,7 @@ add_library (
midipanknob.cpp
colorlabel.cpp
slider.cpp
styledslider.cpp
volslider.cpp
mslider.cpp
pitchedit.cpp
@ -43,7 +44,8 @@ add_library (
denomspinbox.cpp
aslider.h colorlabel.h denomspinbox.h fastlog.h
knob.h midipanknob.h mslider.h panknob.h pitchedit.h pitchlabel.h
poslabel.h slider.h utils.h volknob.h volslider.h
poslabel.h slider.h styledslider.h
utils.h volknob.h volslider.h
)
if (NOT MSVC)
set_target_properties (
@ -80,6 +82,7 @@ add_library (
midipanknob.cpp
colorlabel.cpp
slider.cpp
styledslider.cpp
volslider.cpp
mslider.cpp
denomspinbox.cpp

View file

@ -36,6 +36,7 @@ AbstractSlider::AbstractSlider(QWidget* parent)
_lineStep = 0.1;
_pageStep = 0.2;
_center = false;
_enableMouseWheel = true;
_invert = false;
_scaleWidth = 4;
_log = false;
@ -55,6 +56,15 @@ void AbstractSlider::setEnabled(bool val)
update();
}
//---------------------------------------------------------
// setEnableMouseWheel
//---------------------------------------------------------
void AbstractSlider::setEnableMouseWheel(bool enabled)
{
_enableMouseWheel = enabled;
}
//---------------------------------------------------------
// setCenter
//! If the center flag is set, a notch is drawn to
@ -111,6 +121,9 @@ void AbstractSlider::setScaleValueColor(const QColor& c)
void AbstractSlider::wheelEvent(QWheelEvent* ev)
{
if (!_enableMouseWheel)
return;
int div = 50;
if (ev->modifiers() & Qt::ShiftModifier)
div = 15;
@ -182,6 +195,8 @@ void AbstractSlider::setValue(double val)
}
else
_value = val;
emit valueChanged(val, __id);
update();
}

View file

@ -64,6 +64,7 @@ class AbstractSlider : public QWidget {
double _dclickValue1;
double _dclickValue2;
bool _center;
bool _enableMouseWheel;
bool _invert;
int _scaleWidth; //! scale line width
QColor _scaleColor;
@ -90,6 +91,9 @@ class AbstractSlider : public QWidget {
virtual void setScaleColor(const QColor&);
virtual void setScaleValueColor(const QColor&);
bool enableMouseWheel() { return _enableMouseWheel; }
virtual void setEnableMouseWheel(bool enabled);
//! return the center flag
bool center() const { return _center; }

View file

@ -29,7 +29,7 @@ namespace Awl {
Knob::Knob(QWidget* parent)
: AbstractSlider(parent)
{
_scaleSize = 270;
_spanDegrees = 270;
_markSize = 6;
_border = 2;
points = 0;
@ -65,10 +65,10 @@ void Knob::setText(const QString& s)
//! in degrees
//---------------------------------------------------------
void Knob::setScaleSize(int val)
void Knob::setSpanDegrees(double val)
{
if (val != _scaleSize) {
_scaleSize = val;
if (val != _spanDegrees) {
_spanDegrees = val;
update();
}
}
@ -99,6 +99,16 @@ void Knob::setBorder(int val)
}
}
//---------------------------------------------------------
// setKnobIcon
//---------------------------------------------------------
void Knob::setKnobIcon(const QIcon& icon)
{
_knobIcon = icon;
update();
}
//---------------------------------------------------------
// mousePressEvent
//---------------------------------------------------------
@ -158,7 +168,7 @@ void Knob::paintEvent(QPaintEvent* /*ev*/)
p.setRenderHint(QPainter::Antialiasing, true);
int markSize2 = _markSize/2;
int restR = 360 - _scaleSize;
int emptyDegrees = 360 - _spanDegrees;
int w = width() - _scaleWidth - 2 * _border;
int h = height() - _scaleWidth/2 - 2 * _border;
@ -172,77 +182,57 @@ void Knob::paintEvent(QPaintEvent* /*ev*/)
}
else {
xoffset = 0;
// yoffset = (h - w) / 2; // center
yoffset = h - w; // top align
h = w;
}
int x = xoffset + _scaleWidth / 2 + _border;
int y = yoffset + _scaleWidth / 2 + _border + (_center ? _markSize+_scaleWidth/2 : 0);
QRectF ar(x, y, w, h);
QRectF dialArea(x, y, w, h);
QColor sc(isEnabled() ? _scaleColor : Qt::gray);
QColor svc(isEnabled() ? _scaleValueColor : Qt::gray);
QColor dialBgCol(isEnabled() ? _scaleColor : Qt::gray);
QColor dialCol(isEnabled() ? _scaleValueColor : Qt::lightGray);
//-----------------------------------------
// draw arc
//-----------------------------------------
double dvalue = maxValue() - minValue();
if (_center) {
int size = _scaleSize * 8;
if (_value >= 0) {
int offset = (restR-180) * 8;
int r1 = int (size * _value / maxValue());
int r2 = size - r1;
p.setPen(QPen(sc, _scaleWidth));
if (r2 > 1)
p.drawArc(ar, offset, r2);
if (size > 1)
p.drawArc(ar, 90*16, size);
if (r1 > 1) {
p.setPen(QPen(svc, _scaleWidth));
p.drawArc(ar, offset+r2, r1);
}
}
else {
// int offset = (restR+180) * 8;
int r1 = int(size * _value / minValue());
int r2 = size - r1;
double maxVal = maxValue();
double minVal = minValue();
double val = value();
p.setPen(QPen(sc, _scaleWidth));
if (size > 1)
p.drawArc(ar, (restR-180)*8, size);
if (r2 > 1)
p.drawArc(ar, 90 * 16 + r1, r2);
if (r1 > 1) {
p.setPen(QPen(svc, _scaleWidth));
p.drawArc(ar, 90*16, r1);
}
}
double span = maxVal - minVal;
p.setPen(QPen(dialBgCol, _scaleWidth));
p.drawArc(dialArea, (90 + (_spanDegrees / 2)) * 16, -_spanDegrees * 16);
if (_center) {
double frac = (val - minVal) / span - 0.5;
p.setPen(QPen(dialCol, _scaleWidth));
p.drawArc(dialArea, 90 * 16, -frac * _spanDegrees * 16);
}
else {
int offset = (180-restR) * 8;
int size = _scaleSize * 16;
int r1 = int(size * (_value - minValue()) / dvalue);
int r2 = size - r1;
if (r2 >= 1) {
p.setPen(QPen(sc, _scaleWidth));
p.drawArc(ar, -offset, r2);
}
if (r1 >= 1) {
p.setPen(QPen(svc, _scaleWidth));
p.drawArc(ar, r2-offset, r1);
}
double frac = (val - minVal) / span;
p.setPen(QPen(dialBgCol, _scaleWidth));
p.drawArc(dialArea, (90 + (_spanDegrees / 2)) * 16, frac * -_spanDegrees * 16);
}
//-----------------------------------------
// draw pointer
//-----------------------------------------
p.setPen(QPen(svc, _scaleWidth));
double r1 = double(_scaleSize) * (_value-minValue()) / dvalue + 90.0
+ double(restR/2);
//knob image
if (!_knobIcon.isNull()) {
QRect r((int)dialArea.x(), (int)dialArea.y(), (int)dialArea.width(), (int)dialArea.height());
_knobIcon.paint(&p, r);
}
//indicator line
p.setPen(QPen(dialCol, _scaleWidth));
double r1 = double(_spanDegrees) * (_value - _minValue) / span + 90.0
+ double(emptyDegrees / 2);
r1 = r1 / 180.0 * M_PI; // convert to radians
int rd = w/2;
int x1 = x + rd;
@ -251,17 +241,18 @@ void Knob::paintEvent(QPaintEvent* /*ev*/)
int y2 = y1 + lrint(sin(r1) * double(rd));
p.drawLine(x1, y1, x2, y2);
//-----------------------------------------
// draw center mark
//-----------------------------------------
p.setPen(QPen(svc, 0));
p.setBrush(svc);
p.setPen(QPen(dialCol, 0));
p.setBrush(dialCol);
if (_center) {
if (points)
delete points;
qreal x3 = ar.width() / 2 + ar.x();
qreal y3 = ar.y() - _markSize - _scaleWidth/2;
qreal x3 = dialArea.width() / 2 + dialArea.x();
qreal y3 = dialArea.y() - _markSize - _scaleWidth/2;
points = new QPainterPath(QPointF(x3 - markSize2, y3));
points->lineTo(x3 + markSize2, y3);
points->lineTo(x3, _markSize + y3);
@ -274,7 +265,7 @@ void Knob::paintEvent(QPaintEvent* /*ev*/)
//-----------------------------------------
if (!_text.isEmpty()) {
p.drawText(ar, Qt::AlignBottom | Qt::AlignHCenter, _text);
p.drawText(dialArea, Qt::AlignBottom | Qt::AlignHCenter, _text);
}
}
}

View file

@ -22,6 +22,7 @@
#include "aslider.h"
// #include <QtDesigner/QDesignerExportWidget>
#include <QIcon>
namespace Awl {
@ -36,14 +37,16 @@ namespace Awl {
class Q_DECL_EXPORT Knob : public AbstractSlider {
Q_OBJECT
Q_PROPERTY(int scaleSize READ scaleSize WRITE setScaleSize)
Q_PROPERTY(int spanDegrees READ spanDegrees WRITE setSpanDegrees)
Q_PROPERTY(int markSize READ markSize WRITE setMarkSize)
Q_PROPERTY(int border READ border WRITE setBorder)
Q_PROPERTY(QString text READ text WRITE setText)
int _scaleSize; //! scale size in degrees
double _spanDegrees; //! scale size in degrees
int _markSize;
int _border;
QIcon _knobIcon;
QPainterPath* points;
virtual void paintEvent(QPaintEvent*);
@ -68,10 +71,12 @@ class Q_DECL_EXPORT Knob : public AbstractSlider {
//! return text decoration
QString text() const { return _text; }
void setText(const QString& s);
QIcon knobIcon() const { return _knobIcon; }
void setKnobIcon(const QIcon& icon);
//! return scale size in degrees
int scaleSize() const { return _scaleSize; }
void setScaleSize(int val);
double spanDegrees() const { return _spanDegrees; }
void setSpanDegrees(double val);
int markSize() const { return _markSize; }
void setMarkSize(int val);
int border() const { return _border; }

View file

@ -38,10 +38,10 @@ MidiPanKnob::MidiPanKnob(QWidget* parent)
// valueChange
//---------------------------------------------------------
void MidiPanKnob::valueChange()
{
emit valueChanged(_value + 64.0f, __id);
update();
}
//void MidiPanKnob::valueChange()
// {
// emit valueChanged(_value, _id);
// update();
// }
}

View file

@ -36,14 +36,14 @@ namespace Awl {
class MidiPanKnob : public Knob {
Q_OBJECT
virtual void valueChange();
// virtual void valueChange();
public slots:
virtual void setValue(double v) { AbstractSlider::setValue(v - 64.0f); }
// virtual void setValue(double v) { AbstractSlider::setValue(v - 64.0f); }
public:
MidiPanKnob(QWidget* parent = 0);
virtual double value() const { return _value + 64.0f; }
// virtual double value() const { return _value + 64.0f; }
};
}

341
awl/styledslider.cpp Normal file
View file

@ -0,0 +1,341 @@
//=============================================================================
// Awl
// Audio Widget Library
// $Id:$
//
// Copyright (C) 2002-2006 by Werner Schweer and others
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.
//
// This program 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 this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#include "styledslider.h"
#include <QStyle>
#include <QStylePainter>
#include <QStyleOptionSlider>
#include <QMouseEvent>
#include <QDebug>
namespace Awl {
//---------------------------------------------------------
// StyledSlider
//---------------------------------------------------------
StyledSlider::StyledSlider(QWidget *parent) : QWidget(parent)
{
setFocusPolicy(Qt::StrongFocus);
}
//---------------------------------------------------------
// wheelEvent
//---------------------------------------------------------
void StyledSlider::wheelEvent(QWheelEvent* e)
{
QPoint ad = e->angleDelta();
setValue(_value + (_maxValue - _minValue) * ad.y() / 10000.0);
repaint();
}
//---------------------------------------------------------
// keyPressEvent
//---------------------------------------------------------
void StyledSlider::keyPressEvent(QKeyEvent* e)
{
switch (e->key())
{
case Qt::Key_Up:
setValue(_value + 1);
break;
case Qt::Key_Down:
setValue(_value - 1);
break;
}
}
//---------------------------------------------------------
// mousePressEvent
//---------------------------------------------------------
void StyledSlider::mousePressEvent(QMouseEvent* e)
{
draggingMouse = true;
mouseDownPos = e->pos();
lastMousePos = mouseDownPos;
emit(sliderPressed());
}
//---------------------------------------------------------
// mouseReleaseEvent
//---------------------------------------------------------
void StyledSlider::mouseReleaseEvent(QMouseEvent*)
{
draggingMouse = false;
}
//---------------------------------------------------------
// mouseMoveEvent
//---------------------------------------------------------
void StyledSlider::mouseMoveEvent(QMouseEvent* e)
{
if (draggingMouse) {
QPoint p = e->pos();
double dPixY = p.y() - lastMousePos.y();
double barLength = height() - (_margin * 2);
double dy = dPixY * (_maxValue - _minValue) / barLength;
double val = qBound(_minValue, _value - dy, _maxValue);
lastMousePos = p;
setValue(val);
repaint();
}
}
//---------------------------------------------------------
// paintEvent
//---------------------------------------------------------
void StyledSlider::paintEvent(QPaintEvent *ev)
{
QWidget::paintEvent(ev);
QPainter p(this);
//QRect geo = this->geometry();
int w = width();
int h = height();
double barLength = h - _margin * 2;
double x0 = (w - _barThickness) / 2;
double valueSpan = _maxValue - _minValue;
double span = (_value - _minValue) / (_maxValue - _minValue);
span = qMin(qMax(span, 0.0), 1.0);
double y1 = (1 - span) * barLength;
double midPtPix = w / 2.0;
//Ticks
p.setPen(QPen(_tickColor));
// for (qreal yVal = _minValue; yVal <= _maxValue + .00001; yVal += _numMinorTicks) {
// qreal yPix = (yVal - _minValue) / valueSpan;
// yPix = (1.0 - yPix) * barLength + _margin;
// QLineF line(midPtPix - _minorTickWidth, yPix, midPtPix + _minorTickWidth, yPix);
// p.drawLine(line);
// }
// for (qreal yVal = _minValue; yVal <= _maxValue + .00001; yVal += _numMajorTicks) {
// qreal yPix = (yVal - _minValue) / valueSpan;
// yPix = (1.0 - yPix) * barLength + _margin;
// QLineF line(midPtPix - _majorTickWidth, yPix, midPtPix + _majorTickWidth, yPix);
// p.drawLine(line);
// for (int i = 1; i < _numMinorTicks; ++i) {
// qreal yyPix = yPix + (i * _numMajorTicks) / _numMinorTicks;
// QLineF line(midPtPix - _minorTickWidth, yyPix, midPtPix + _minorTickWidth, yyPix);
// p.drawLine(line);
// }
// }
for (int i = 0; i <= _numMajorTicks; ++i) {
qreal yVal = i * barLength / _numMajorTicks + _margin;
QLineF line(midPtPix - _majorTickWidth, yVal, midPtPix + _majorTickWidth, yVal);
p.drawLine(line);
if (i < _numMajorTicks) {
qreal yValNext = (i + 1) * barLength / _numMajorTicks + _margin;
for (int j = 1; j < _numMinorTicks; ++j) {
qreal yyVal = yVal + j * (yValNext - yVal) / _numMinorTicks;
QLineF line(midPtPix - _minorTickWidth, yyVal, midPtPix + _minorTickWidth, yyVal);
p.drawLine(line);
}
}
}
//Marks
// p.setPen(QPen(_tickColor, 2));
// for (double mark: marks) {
// qreal yPix = (mark - _minValue) / valueSpan;
// yPix = (1.0 - yPix) * barLength + _margin;
// QLineF line(midPtPix - _majorTickWidth, yPix, midPtPix + _majorTickWidth, yPix);
// p.drawLine(line);
// }
//Bars
double yPix = _margin + y1;
QRectF bgRect(x0, _margin, _barThickness, barLength);
QRectF hiliteRect(x0, yPix, _barThickness, barLength - y1);
p.fillRect(bgRect, QBrush(_backgroundColor));
p.fillRect(hiliteRect, QBrush(_hilightColor));
//Slider head
if (!_sliderHeadIcon.isNull()) {
QRect r((int)midPtPix - 14, (int)yPix - 20, (int)28, (int)40);
_sliderHeadIcon.paint(&p, r);
}
}
//---------------------------------------------------------
// setValue
//---------------------------------------------------------
void StyledSlider::setValue(double v)
{
if (v == _value)
return;
_value = v;
repaint();
emit(valueChanged(v));
}
//---------------------------------------------------------
// setMinValue
//---------------------------------------------------------
void StyledSlider::setMinValue(double v)
{
if (v == _minValue)
return;
_minValue = v;
repaint();
emit(minValueChanged(v));
}
//---------------------------------------------------------
// setMaxValue
//---------------------------------------------------------
void StyledSlider::setMaxValue(double v)
{
if (v == _maxValue)
return;
_maxValue = v;
repaint();
emit(maxValueChanged(v));
}
//---------------------------------------------------------
// setBackgroundColor
//---------------------------------------------------------
void StyledSlider::setBackgroundColor(QColor v)
{
_backgroundColor = v;
repaint();
}
//---------------------------------------------------------
// setHilightColor
//---------------------------------------------------------
void StyledSlider::setHilightColor(QColor v)
{
_hilightColor = v;
repaint();
}
//---------------------------------------------------------
// setTickColor
//---------------------------------------------------------
void StyledSlider::setTickColor(QColor v)
{
_tickColor = v;
repaint();
}
//---------------------------------------------------------
// setBarThickness
//---------------------------------------------------------
void StyledSlider::setBarThickness(double v)
{
_barThickness = v;
repaint();
}
//---------------------------------------------------------
// setMargin
//---------------------------------------------------------
void StyledSlider::setMargin(double v)
{
_margin = v;
repaint();
}
//---------------------------------------------------------
// setMajorTickSpacing
//---------------------------------------------------------
void StyledSlider::setNumMajorTicks(int v)
{
_numMajorTicks = v;
repaint();
}
//---------------------------------------------------------
// setMinorTickSpacing
//---------------------------------------------------------
void StyledSlider::setNumMinorTicks(int v)
{
_numMinorTicks = v;
repaint();
}
//---------------------------------------------------------
// setMajorTickWidth
//---------------------------------------------------------
void StyledSlider::setMajorTickWidth(double v)
{
_majorTickWidth = v;
repaint();
}
//---------------------------------------------------------
// setMinorTickWidth
//---------------------------------------------------------
void StyledSlider::setMinorTickWidth(double v)
{
_minorTickWidth = v;
repaint();
}
//---------------------------------------------------------
// setSliderHeadIcon
//---------------------------------------------------------
void StyledSlider::setSliderHeadIcon(QIcon v)
{
_sliderHeadIcon = v;
repaint();
}
}

105
awl/styledslider.h Normal file
View file

@ -0,0 +1,105 @@
//=============================================================================
// Awl
// Audio Widget Library
// $Id:$
//
// Copyright (C) 2002-2006 by Werner Schweer and others
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.
//
// This program 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 this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#ifndef __STYLEDSLIDER_H__
#define __STYLEDSLIDER_H__
#include <QWidget>
#include <QIcon>
namespace Awl {
class StyledSlider : public QWidget
{
Q_OBJECT
QList<double> marks;
double _minValue;
double _maxValue = 100;
double _value;
double _barThickness = 4;
double _margin = 20;
int _numMajorTicks = 10;
int _numMinorTicks = 4;
double _majorTickWidth = 30;
double _minorTickWidth = 10;
QColor _backgroundColor = QColor(10, 10, 10);
QColor _hilightColor = QColor(0, 255, 0);
QColor _tickColor = QColor(150, 150, 150);
bool draggingMouse;
QPoint mouseDownPos;
QPoint lastMousePos;
QIcon _sliderHeadIcon;
public:
explicit StyledSlider(QWidget *parent = nullptr);
virtual QSize sizeHint() const { return QSize(50, 50); }
virtual void paintEvent(QPaintEvent *ev);
virtual void mousePressEvent(QMouseEvent*);
virtual void mouseReleaseEvent(QMouseEvent*);
virtual void mouseMoveEvent(QMouseEvent*);
virtual void wheelEvent(QWheelEvent*);
virtual void keyPressEvent(QKeyEvent*);
double maxValue() const { return _maxValue; }
double minValue() const { return _minValue; }
double value() const { return _value; }
double barThickness() const { return _barThickness; }
double margin() const { return _margin; }
double numMajorTicks() const { return _numMajorTicks; }
int numMinorTicks() const { return _numMinorTicks; }
double majorTickWidth() const { return _majorTickWidth; }
double minorTickWidth() const { return _minorTickWidth; }
QColor backgroundColor() const { return _backgroundColor; }
QColor hilightColor() const { return _hilightColor; }
QColor tickColor() const { return _tickColor; }
QIcon sliderHeadIcon() const { return _sliderHeadIcon; }
void addMark(double value) { marks.append(value); }
signals:
void valueChanged(double);
void minValueChanged(double);
void maxValueChanged(double);
void sliderPressed();
public slots:
void setValue(double v);
void setMinValue(double v);
void setMaxValue(double v);
void setBarThickness(double v);
void setMargin(double v);
void setNumMajorTicks(int v);
void setNumMinorTicks(int v);
void setMajorTickWidth(double v);
void setMinorTickWidth(double v);
void setBackgroundColor(QColor v);
void setHilightColor(QColor v);
void setTickColor(QColor v);
void setSliderHeadIcon(QIcon v);
};
}
#endif // __STYLEDSLIDER_H__

View file

@ -1964,7 +1964,7 @@ bool Score::processMidiInput()
ev.pitch += p->instrument(selection().tickStart())->transpose().chromatic;
}
MScore::seq->startNote(
p->instrument()->channel(0)->channel,
p->instrument()->channel(0)->channel(),
ev.pitch,
ev.velocity,
0.0);

View file

@ -4341,7 +4341,7 @@ void Score::undoAddElement(Element* element)
Part* part = nis->part();
Interval oldV = nis->part()->instrument(tickStart)->transpose();
// ws: instrument should not be changed here
if (is->instrument()->channel().empty() || is->instrument()->channel(0)->program == -1)
if (is->instrument()->channel().empty() || is->instrument()->channel(0)->program() == -1)
nis->setInstrument(*staff->part()->instrument(s1->tick()));
else if (nis != is)
nis->setInstrument(*is->instrument());

View file

@ -501,18 +501,18 @@ void InstrumentTemplate::read(XmlReader& e)
}
if (channel.empty()) {
Channel a;
a.chorus = 0;
a.reverb = 0;
a.name = "normal";
a.program = 0;
a.bank = 0;
a.volume = 100;
a.pan = 64; // actually 63.5 for center
a.setChorus(0);
a.setReverb(0);
a.setName("normal");
a.setProgram(0);
a.setBank(0);
a.setVolume(90);
a.setPan(0);
channel.append(a);
}
if (useDrumset) {
if (channel[0].bank == 0 && channel[0].synti.toLower() != "zerberus")
channel[0].bank = 128;
if (channel[0].bank() == 0 && channel[0].synti().toLower() != "zerberus")
channel[0].setBank(128);
channel[0].updateInitList();
}
if (trackName.isEmpty() && !longNames.isEmpty())
@ -790,7 +790,7 @@ ClefType defaultClef(int program)
for (InstrumentGroup* g : instrumentGroups) {
for (InstrumentTemplate* it : g->instrumentTemplates) {
if (it->channel[0].bank == 0 && it->channel[0].program == program){
if (it->channel[0].bank() == 0 && it->channel[0].program() == program){
return (it->clefTypes[0]._concertClef);
}
}

View file

@ -21,6 +21,7 @@
#include "part.h"
#include "score.h"
#include <QList>
namespace Ms {
Instrument InstrumentList::defaultInstrument;
@ -84,7 +85,7 @@ bool MidiArticulation::operator==(const MidiArticulation& i) const
Instrument::Instrument()
{
Channel* a = new Channel;
a->name = "normal";
a->setName(Channel::DEFAULT_NAME);
_channel.append(a);
_minPitchA = 0;
@ -271,8 +272,8 @@ void Instrument::read(XmlReader& e, Part* part)
e.unknown();
}
if (_useDrumset) {
if (_channel[0]->bank == 0 && _channel[0]->synti.toLower() != "zerberus")
_channel[0]->bank = 128;
if (_channel[0]->bank() == 0 && _channel[0]->synti().toLower() != "zerberus")
_channel[0]->setBank(128);
_channel[0]->updateInitList();
}
}
@ -398,6 +399,10 @@ NamedEventList* Instrument::midiAction(const QString& s, int channelIdx) const
return 0;
}
const char *Channel::DEFAULT_NAME = "normal";
//---------------------------------------------------------
// Channel
//---------------------------------------------------------
@ -406,18 +411,211 @@ Channel::Channel()
{
for(int i = 0; i < int(A::INIT_COUNT); ++i)
init.push_back(MidiCoreEvent());
synti = "Fluid"; // default synthesizer
channel = -1;
program = -1;
bank = 0;
volume = 100;
pan = 64; // actually 63.5 for center
chorus = 0;
reverb = 0;
_synti = "Fluid"; // default synthesizer
_channel = -1;
_program = -1;
_bank = 0;
_volume = 100;
_pan = 64; // actually 63.5 for center
_chorus = 0;
_reverb = 0;
_color = DEFAULT_COLOR;
mute = false;
solo = false;
soloMute = false;
_mute = false;
_solo = false;
_soloMute = false;
qDebug("construct Channel ");
}
Channel::~Channel()
{
QList<ChannelListener *> list(listeners);
for (ChannelListener * l: list) {
l->disconnectChannelListener();
}
}
//---------------------------------------------------------
// firePropertyChanged
//---------------------------------------------------------
void Channel::firePropertyChanged(Channel::Prop prop)
{
QList<ChannelListener *> list(listeners);
for (ChannelListener * l: list) {
l->propertyChanged(prop);
}
}
//---------------------------------------------------------
// setVolume
//---------------------------------------------------------
void Channel::setVolume(char value)
{
if (_volume != value) {
_volume = value;
firePropertyChanged(Prop::VOLUME);
}
}
//---------------------------------------------------------
// setPan
//---------------------------------------------------------
void Channel::setPan(char value)
{
if (_pan != value) {
_pan = value;
firePropertyChanged(Prop::PAN);
}
}
//---------------------------------------------------------
// setChorus
//---------------------------------------------------------
void Channel::setChorus(char value)
{
if (_chorus != value) {
_chorus = value;
firePropertyChanged(Prop::CHORUS);
}
}
//---------------------------------------------------------
// setReverb
//---------------------------------------------------------
void Channel::setReverb(char value)
{
if (_reverb != value) {
_reverb = value;
firePropertyChanged(Prop::REVERB);
}
}
//---------------------------------------------------------
// setName
//---------------------------------------------------------
void Channel::setName(const QString& value)
{
if (_name != value) {
_name = value;
firePropertyChanged(Prop::NAME);
}
}
//---------------------------------------------------------
// setDescr
//---------------------------------------------------------
void Channel::setDescr(const QString& value)
{
if (_descr != value) {
_descr = value;
firePropertyChanged(Prop::DESCR);
}
}
//---------------------------------------------------------
// setSynti
//---------------------------------------------------------
void Channel::setSynti(const QString& value)
{
if (_synti != value) {
_synti = value;
firePropertyChanged(Prop::SYNTI);
}
}
//---------------------------------------------------------
// setColor
//---------------------------------------------------------
void Channel::setColor(int value)
{
if (_color != value) {
_color = value;
firePropertyChanged(Prop::COLOR);
}
}
//---------------------------------------------------------
// setProgram
//---------------------------------------------------------
void Channel::setProgram(int value)
{
if (_program != value) {
_program = value;
firePropertyChanged(Prop::PROGRAM);
}
}
//---------------------------------------------------------
// setBank
//---------------------------------------------------------
void Channel::setBank(int value)
{
if (_bank != value) {
_bank = value;
firePropertyChanged(Prop::BANK);
}
}
//---------------------------------------------------------
// setChannel
//---------------------------------------------------------
void Channel::setChannel(int value)
{
if (_channel != value) {
_channel = value;
firePropertyChanged(Prop::CHANNEL);
}
}
//---------------------------------------------------------
// setSoloMute
//---------------------------------------------------------
void Channel::setSoloMute(bool value)
{
if (_soloMute != value) {
_soloMute = value;
firePropertyChanged(Prop::SOLOMUTE);
}
}
//---------------------------------------------------------
// setMute
//---------------------------------------------------------
void Channel::setMute(bool value)
{
if (_mute != value) {
_mute = value;
firePropertyChanged(Prop::MUTE);
}
}
//---------------------------------------------------------
// setSolo
//---------------------------------------------------------
void Channel::setSolo(bool value)
{
if (_solo != value) {
_solo = value;
firePropertyChanged(Prop::SOLO);
}
}
//---------------------------------------------------------
@ -426,12 +624,15 @@ Channel::Channel()
void Channel::write(XmlWriter& xml, Part* part) const
{
if (name.isEmpty() || name == "normal")
if (_name.isEmpty() || _name == DEFAULT_NAME)
xml.stag("Channel");
else
xml.stag(QString("Channel name=\"%1\"").arg(name));
if (!descr.isEmpty())
xml.tag("descr", descr);
xml.stag(QString("Channel name=\"%1\"").arg(_name));
if (!_descr.isEmpty())
xml.tag("descr", _descr);
if (_color != DEFAULT_COLOR)
xml.tag("color", _color);
updateInitList();
foreach(const MidiCoreEvent& e, init) {
if (e.type() == ME_INVALID)
@ -455,14 +656,14 @@ void Channel::write(XmlWriter& xml, Part* part) const
}
if (!MScore::testMode)
// xml.tag("synti", ::synti->name(synti));
xml.tag("synti", synti);
if (mute)
xml.tag("mute", mute);
if (solo)
xml.tag("solo", solo);
xml.tag("synti", _synti);
if (_mute)
xml.tag("mute", _mute);
if (_solo)
xml.tag("solo", _solo);
if (part && part->masterScore()->exportMidiMapping() && part->score() == part->masterScore()) {
xml.tag("midiPort", part->masterScore()->midiMapping(channel)->port);
xml.tag("midiChannel", part->masterScore()->midiMapping(channel)->channel);
xml.tag("midiPort", part->masterScore()->midiMapping(_channel)->port);
xml.tag("midiChannel", part->masterScore()->midiMapping(_channel)->channel);
}
for (const NamedEventList& a : midiActions)
a.write(xml, "MidiAction");
@ -478,15 +679,16 @@ void Channel::write(XmlWriter& xml, Part* part) const
void Channel::read(XmlReader& e, Part* part)
{
// synti = 0;
name = e.attribute("name");
if (name == "")
name = "normal";
_name = e.attribute("name");
if (_name == "")
_name = DEFAULT_NAME;
while (e.readNextStartElement()) {
const QStringRef& tag(e.name());
if (tag == "program") {
program = e.intAttribute("value", -1);
if (program == -1)
program = e.readInt();
_program = e.intAttribute("value", -1);
if (_program == -1)
_program = e.readInt();
else
e.readNext();
}
@ -495,22 +697,22 @@ void Channel::read(XmlReader& e, Part* part)
int ctrl = e.intAttribute("ctrl", 0);
switch (ctrl) {
case CTRL_HBANK:
bank = (value << 7) + (bank & 0x7f);
_bank = (value << 7) + (_bank & 0x7f);
break;
case CTRL_LBANK:
bank = (bank & ~0x7f) + (value & 0x7f);
_bank = (_bank & ~0x7f) + (value & 0x7f);
break;
case CTRL_VOLUME:
volume = value;
_volume = value;
break;
case CTRL_PANPOT:
pan = value;
_pan = value;
break;
case CTRL_CHORUS_SEND:
chorus = value;
_chorus = value;
break;
case CTRL_REVERB_SEND:
reverb = value;
_reverb = value;
break;
default:
{
@ -536,13 +738,15 @@ void Channel::read(XmlReader& e, Part* part)
midiActions.append(a);
}
else if (tag == "synti")
synti = e.readElementText();
_synti = e.readElementText();
else if (tag == "descr")
descr = e.readElementText();
_descr = e.readElementText();
else if (tag == "color")
_color = e.readInt();
else if (tag == "mute")
mute = e.readInt();
_mute = e.readInt();
else if (tag == "solo")
solo = e.readInt();
_solo = e.readInt();
else if (tag == "midiPort") {
int midiPort = e.readInt();
if (part) {
@ -552,19 +756,19 @@ void Channel::read(XmlReader& e, Part* part)
mm.part = part;
mm.articulation = this;
part->masterScore()->midiMapping()->append(mm);
channel = part->masterScore()->midiMapping()->size() - 1;
_channel = part->masterScore()->midiMapping()->size() - 1;
}
}
else if (tag == "midiChannel") {
int midiChannel = e.readInt();
if (part)
part->masterScore()->midiMapping(channel)->channel = midiChannel;
part->masterScore()->midiMapping(_channel)->channel = midiChannel;
}
else
e.unknown();
}
if (128 == bank && "zerberus" == synti.toLower())
bank = 0;
if (128 == _bank && "zerberus" == _synti.toLower())
_bank = 0;
updateInitList();
}
@ -575,30 +779,31 @@ void Channel::read(XmlReader& e, Part* part)
void Channel::updateInitList() const
{
MidiCoreEvent e;
if (program != -1) {
if (_program != -1) {
e.setType(ME_CONTROLLER);
e.setDataA(CTRL_PROGRAM);
e.setDataB(program);
e.setDataB(_program);
init[int(A::PROGRAM)] = e;
}
e.setData(ME_CONTROLLER, CTRL_HBANK, (bank >> 7) & 0x7f);
e.setData(ME_CONTROLLER, CTRL_HBANK, (_bank >> 7) & 0x7f);
init[int(A::HBANK)] = e;
e.setData(ME_CONTROLLER, CTRL_LBANK, bank & 0x7f);
e.setData(ME_CONTROLLER, CTRL_LBANK, _bank & 0x7f);
init[int(A::LBANK)] = e;
e.setData(ME_CONTROLLER, CTRL_VOLUME, volume);
e.setData(ME_CONTROLLER, CTRL_VOLUME, volume());
init[int(A::VOLUME)] = e;
e.setData(ME_CONTROLLER, CTRL_PANPOT, pan);
e.setData(ME_CONTROLLER, CTRL_PANPOT, pan());
init[int(A::PAN)] = e;
e.setData(ME_CONTROLLER, CTRL_CHORUS_SEND, chorus);
e.setData(ME_CONTROLLER, CTRL_CHORUS_SEND, chorus());
init[int(A::CHORUS)] = e;
e.setData(ME_CONTROLLER, CTRL_REVERB_SEND, reverb);
e.setData(ME_CONTROLLER, CTRL_REVERB_SEND, reverb());
init[int(A::REVERB)] = e;
}
//---------------------------------------------------------
@ -609,9 +814,9 @@ int Instrument::channelIdx(const QString& s) const
{
int idx = 0;
for (const Channel* a : _channel) {
if (a->name.isEmpty() && s == "normal")
if (a->name().isEmpty() && s == Channel::DEFAULT_NAME)
return idx;
if (s == a->name)
if (s == a->name())
return idx;
++idx;
}

View file

@ -18,6 +18,8 @@
#include "synthesizer/event.h"
#include "interval.h"
#include "clef.h"
#include <QtGlobal>
#include <QString>
namespace Ms {
@ -26,6 +28,7 @@ class XmlWriter;
class XmlReader;
class Drumset;
class StringData;
class ChannelListener;
//---------------------------------------------------------
// StaffName
@ -87,43 +90,113 @@ struct MidiArticulation {
bool operator==(const MidiArticulation& i) const;
};
//---------------------------------------------------------
// Channel
//---------------------------------------------------------
struct Channel {
class Channel {
// this are the indexes of controllers which are always present in
// Channel init EventList (maybe zero)
QString _name;
QString _descr;
static const int DEFAULT_COLOR = 0x3399ff;
int _color; //rgb
QString _synti;
char _volume;
char _pan;
char _chorus;
char _reverb;
int _program; // current values as shown in mixer
int _bank; // initialized from "init"
int _channel { 0 }; // mscore channel number, mapped to midi port/channel
bool _soloMute;
bool _mute;
bool _solo;
QList<ChannelListener *> listeners;
public:
static const char* DEFAULT_NAME;
enum class A : char {
HBANK, LBANK, PROGRAM, VOLUME, PAN, CHORUS, REVERB,
INIT_COUNT
};
QString name;
QString descr;
int channel { 0 }; // mscore channel number, mapped to midi port/channel
enum class Prop : char {
VOLUME, PAN, CHORUS, REVERB, NAME, DESCR, PROGRAM, BANK, COLOR,
SOLOMUTE, SOLO, MUTE, SYNTI, CHANNEL
};
private:
void firePropertyChanged(Channel::Prop prop);
public:
mutable std::vector<MidiCoreEvent> init;
QString synti;
int program; // current values as shown in mixer
int bank; // initialized from "init"
char volume;
char pan;
char chorus;
char reverb;
bool mute;
bool solo;
bool soloMute;
QString name() const { return _name; }
void setName(const QString& value);
QString descr() const { return _descr; }
void setDescr(const QString& value);
QString synti() const { return _synti; }
void setSynti(const QString& value);
int color() const { return _color; }
void setColor(int value);
char volume() const { return _volume; }
void setVolume(char value);
char pan() const { return _pan; }
void setPan(char value);
char chorus() const { return _chorus; }
void setChorus(char value);
char reverb() const { return _reverb; }
void setReverb(char value);
int program() const { return _program; }
void setProgram(int value);
int bank() const { return _bank; }
void setBank(int value);
int channel() const { return _channel; }
void setChannel(int value);
bool soloMute() const { return _soloMute; }
void setSoloMute(bool value);
bool mute() const { return _mute; }
void setMute(bool value);
bool solo() const { return _solo; }
void setSolo(bool value);
QList<NamedEventList> midiActions;
QList<MidiArticulation> articulation;
Channel();
~Channel();
void write(XmlWriter&, Part *part) const;
void read(XmlReader&, Part *part);
void updateInitList() const;
bool operator==(const Channel& c) { return (name == c.name) && (channel == c.channel); }
bool operator==(const Channel& c) { return (_name == c._name) && (_channel == c._channel); }
void addListener(ChannelListener *l) { listeners.append(l); }
void removeListener(ChannelListener *l) { listeners.removeOne(l); }
};
//---------------------------------------------------------
// ChannelListener
//---------------------------------------------------------
class ChannelListener {
public:
virtual void propertyChanged(Channel::Prop property) = 0;
virtual void disconnectChannelListener() = 0;
};
//---------------------------------------------------------

View file

@ -141,11 +141,11 @@ void MasterScore::reorderMidiMapping()
for (Channel* channel : instr->channel()) {
if (!(_midiMapping[sequenceNumber].part == part
&& _midiMapping[sequenceNumber].articulation == channel)) {
int shouldBe = channel->channel;
int shouldBe = channel->channel();
_midiMapping.swap(sequenceNumber, shouldBe);
_midiMapping[sequenceNumber].articulation->channel = sequenceNumber;
channel->channel = sequenceNumber;
_midiMapping[shouldBe].articulation->channel = shouldBe;
_midiMapping[sequenceNumber].articulation->setChannel(sequenceNumber);
channel->setChannel(sequenceNumber);
_midiMapping[shouldBe].articulation->setChannel(shouldBe);
}
sequenceNumber++;
}
@ -173,7 +173,8 @@ void MasterScore::removeDeletedMidiMapping()
const InstrumentList* il = p->instruments();
for (auto i = il->begin(); i != il->end() && !channelExists; ++i) {
const Instrument* instr = i->second;
channelExists = (_midiMapping[index].articulation->channel != -1 && instr->channel().contains(_midiMapping[index].articulation)
channelExists = (_midiMapping[index].articulation->channel() != -1
&& instr->channel().contains(_midiMapping[index].articulation)
&& !(_midiMapping[index].port == -1 && _midiMapping[index].channel == -1));
if (channelExists)
break;
@ -185,7 +186,9 @@ void MasterScore::removeDeletedMidiMapping()
// Let's do a left shift by 'removeOffset' items if necessary
if (index != 0 && removeOffset != 0) {
_midiMapping[index-removeOffset] = _midiMapping[index];
_midiMapping[index-removeOffset].articulation->channel -= removeOffset;
int chanVal = _midiMapping[index-removeOffset].articulation->channel();
_midiMapping[index-removeOffset].articulation->setChannel(chanVal - removeOffset);
}
}
// We have 'removeOffset' deleted instruments, let's remove their mappings
@ -221,26 +224,26 @@ int MasterScore::updateMidiMapping()
for (Channel* channel : instr->channel()) {
bool channelExists = false;
for (MidiMapping mapping: _midiMapping) {
if (channel == mapping.articulation && channel->channel != -1) {
if (channel == mapping.articulation && channel->channel() != -1) {
channelExists = true;
break;
}
}
// Channel could already exist, but have unassigned port or channel. Repair and continue
if (channelExists) {
if (_midiMapping[channel->channel].port == -1) {
int nm = getNextFreeMidiMapping(-1, _midiMapping[channel->channel].channel);
_midiMapping[channel->channel].port = nm / 16;
if (_midiMapping[channel->channel()].port == -1) {
int nm = getNextFreeMidiMapping(-1, _midiMapping[channel->channel()].channel);
_midiMapping[channel->channel()].port = nm / 16;
}
else if (_midiMapping[channel->channel].channel == -1) {
else if (_midiMapping[channel->channel()].channel == -1) {
if (drum) {
_midiMapping[channel->channel].port = getNextFreeDrumMidiMapping() / 16;
_midiMapping[channel->channel].channel = 9;
_midiMapping[channel->channel()].port = getNextFreeDrumMidiMapping() / 16;
_midiMapping[channel->channel()].channel = 9;
continue;
}
int nm = getNextFreeMidiMapping(_midiMapping[channel->channel].port);
_midiMapping[channel->channel].port = nm / 16;
_midiMapping[channel->channel].channel = nm % 16;
int nm = getNextFreeMidiMapping(_midiMapping[channel->channel()].port);
_midiMapping[channel->channel()].port = nm / 16;
_midiMapping[channel->channel()].channel = nm % 16;
}
continue;
}
@ -263,7 +266,7 @@ int MasterScore::updateMidiMapping()
mm.articulation = channel;
_midiMapping.append(mm);
channel->channel = _midiMapping.size()-1;
channel->setChannel(_midiMapping.size() - 1);
}
}
}

View file

@ -34,6 +34,7 @@ namespace Ms {
Part::Part(Score* s)
: ScoreElement(s)
{
_color = DEFAULT_COLOR;
_show = true;
_instruments.setInstrument(new Instrument, -1); // default instrument
}
@ -78,6 +79,8 @@ bool Part::readProperties(XmlReader& e)
}
else if (tag == "name")
instrument()->setLongName(e.readElementText());
else if (tag == "color")
_color = e.readInt();
else if (tag == "shortName")
instrument()->setShortName(e.readElementText());
else if (tag == "trackName")
@ -115,6 +118,8 @@ void Part::write(XmlWriter& xml) const
if (!_show)
xml.tag("show", _show);
xml.tag("trackName", _partName);
if (_color != DEFAULT_COLOR)
xml.tag("color", _color);
instrument()->write(xml, const_cast<Part*>(this)); // Safe, we do not write anything to it
xml.etag();
}
@ -191,8 +196,8 @@ void Part::removeStaff(Staff* staff)
void Part::setMidiProgram(int program, int bank)
{
Channel* c = instrument()->channel(0);
c->program = program;
c->bank = bank;
c->setProgram(program);
c->setBank(bank);
c->updateInitList();
// instrument()->setChannel(0, c);
}
@ -201,18 +206,18 @@ void Part::setMidiProgram(int program, int bank)
// volume
//---------------------------------------------------------
int Part::volume() const
double Part::volume() const
{
return instrument()->channel(0)->volume;
return instrument()->channel(0)->volume();
}
//---------------------------------------------------------
// setVolume
//---------------------------------------------------------
void Part::setVolume(int volume)
void Part::setVolume(double volume)
{
instrument()->channel(0)->volume = volume;
instrument()->channel(0)->setVolume(volume);
}
//---------------------------------------------------------
@ -221,7 +226,7 @@ void Part::setVolume(int volume)
bool Part::mute() const
{
return instrument()->channel(0)->mute;
return instrument()->channel(0)->mute();
}
//---------------------------------------------------------
@ -230,61 +235,61 @@ bool Part::mute() const
void Part::setMute(bool mute)
{
instrument()->channel(0)->mute = mute;
instrument()->channel(0)->setMute(mute);
}
//---------------------------------------------------------
// reverb
//---------------------------------------------------------
int Part::reverb() const
double Part::reverb() const
{
return instrument()->channel(0)->reverb;
return instrument()->channel(0)->reverb();
}
//---------------------------------------------------------
// setReverb
//---------------------------------------------------------
void Part::setReverb(int val)
void Part::setReverb(double val)
{
instrument()->channel(0)->reverb = val;
instrument()->channel(0)->setReverb(val);
}
//---------------------------------------------------------
// chorus
//---------------------------------------------------------
int Part::chorus() const
double Part::chorus() const
{
return instrument()->channel(0)->chorus;
return instrument()->channel(0)->chorus();
}
//---------------------------------------------------------
// setChorus
//---------------------------------------------------------
void Part::setChorus(int val)
void Part::setChorus(double val)
{
instrument()->channel(0)->chorus = val;
instrument()->channel(0)->setChorus(val);
}
//---------------------------------------------------------
// pan
//---------------------------------------------------------
int Part::pan() const
double Part::pan() const
{
return instrument()->channel(0)->pan;
return instrument()->channel(0)->pan();
}
//---------------------------------------------------------
// setPan
//---------------------------------------------------------
void Part::setPan(int pan)
void Part::setPan(double pan)
{
instrument()->channel(0)->pan = pan;
instrument()->channel(0)->setPan(pan);
}
//---------------------------------------------------------
@ -293,7 +298,7 @@ void Part::setPan(int pan)
int Part::midiProgram() const
{
return instrument()->channel(0)->program;
return instrument()->channel(0)->program();
}
//---------------------------------------------------------
@ -302,7 +307,7 @@ int Part::midiProgram() const
int Part::midiChannel() const
{
return masterScore()->midiChannel(instrument()->channel(0)->channel);
return masterScore()->midiChannel(instrument()->channel(0)->channel());
}
//---------------------------------------------------------
@ -311,7 +316,7 @@ int Part::midiChannel() const
int Part::midiPort() const
{
return masterScore()->midiPort(instrument()->channel(0)->channel);
return masterScore()->midiPort(instrument()->channel(0)->channel());
}
//---------------------------------------------------------
@ -327,7 +332,7 @@ int Part::midiPort() const
void Part::setMidiChannel(int ch, int port, int tick)
{
Channel* channel = instrument(tick)->channel(0);
if (channel->channel == -1) {
if (channel->channel() == -1) {
// Add new mapping
MidiMapping mm;
mm.part = this;
@ -338,21 +343,21 @@ void Part::setMidiChannel(int ch, int port, int tick)
mm.channel = ch;
if (port != -1)
mm.port = port;
channel->channel = masterScore()->midiMapping()->size();
channel->setChannel(masterScore()->midiMapping()->size());
masterScore()->midiMapping()->append(mm);
}
else {
// Update existing mapping
if (channel->channel >= masterScore()->midiMapping()->size()) {
if (channel->channel() >= masterScore()->midiMapping()->size()) {
qDebug()<<"Can't' set midi channel: midiMapping is empty!";
return;
}
if (ch != -1)
masterScore()->midiMapping(channel->channel)->channel = ch;
masterScore()->midiMapping(channel->channel())->channel = ch;
if (port != -1)
masterScore()->midiMapping(channel->channel)->port = port;
masterScore()->midiMapping(channel->channel)->part = this;
masterScore()->midiMapping(channel->channel())->port = port;
masterScore()->midiMapping(channel->channel())->part = this;
}
}

View file

@ -51,6 +51,9 @@ class Part final : public ScoreElement {
QString _id; ///< used for MusicXml import
bool _show; ///< show part in partitur if true
static const int DEFAULT_COLOR = 0x3399ff;
int _color; ///User specified color for helping to label parts
public:
Part(Score* = 0);
void initFromInstrTemplate(const InstrumentTemplate*);
@ -89,17 +92,17 @@ class Part final : public ScoreElement {
void setStaves(int);
int volume() const;
void setVolume(int volume);
double volume() const;
void setVolume(double volume);
bool mute() const;
void setMute(bool mute);
int reverb() const;
void setReverb(int);
int chorus() const;
void setChorus(int);
int pan() const;
void setPan(int pan);
double reverb() const;
void setReverb(double);
double chorus() const;
void setChorus(double);
double pan() const;
void setPan(double pan);
int midiProgram() const;
void setMidiProgram(int, int bank = 0);
@ -124,6 +127,8 @@ class Part final : public ScoreElement {
QString partName() const { return _partName; }
void setPartName(const QString& s) { _partName = s; }
int color() const { return _color; }
void setColor(int value) { _color = value; }
QVariant getProperty(Pid) const override;
bool setProperty(Pid, const QVariant&) override;

View file

@ -2478,18 +2478,18 @@ static void readInstrument(Instrument *i, Part* p, XmlReader& e)
}
if (i->channel().empty()) { // for backward compatibility
Channel* a = new Channel;
a->chorus = chorus;
a->reverb = reverb;
a->name = "normal";
a->program = program;
a->bank = bank;
a->volume = volume;
a->pan = pan;
a->setName(Channel::DEFAULT_NAME);
a->setProgram(program);
a->setBank(bank);
a->setVolume(volume);
a->setPan(pan);
a->setReverb(reverb);
a->setChorus(chorus);
i->appendChannel(a);
}
if (i->useDrumset()) {
if (i->channel()[0]->bank == 0)
i->channel()[0]->bank = 128;
if (i->channel()[0]->bank() == 0)
i->channel()[0]->setBank(128);
i->channel()[0]->updateInitList();
}
}
@ -2517,7 +2517,7 @@ static void readPart(Part* part, XmlReader& e)
if (i->stringData()->strings() == 0
&& i->channel().count() > 0
&& i->drumset() == nullptr) {
int program = i->channel(0)->program;
int program = i->channel(0)->program();
if (program >= 24 && program <= 30) // guitars
i->setStringData(StringData(19, 6, g_guitarStrings));
else if ( (program >= 32 && program <= 39) || program == 43) // bass / double-bass

View file

@ -974,10 +974,10 @@ static void readInstrument(Instrument *i, Part* p, XmlReader& e)
{
int program = -1;
int bank = 0;
int chorus = 30;
int reverb = 30;
int volume = 100;
int pan = 60;
int chorus = 30;
int reverb = 30;
bool customDrumset = false;
i->clearChannels(); // remove default channel
while (e.readNextStartElement()) {
@ -1001,18 +1001,18 @@ static void readInstrument(Instrument *i, Part* p, XmlReader& e)
}
if (i->channel().empty()) { // for backward compatibility
Channel* a = new Channel;
a->chorus = chorus;
a->reverb = reverb;
a->name = "normal";
a->program = program;
a->bank = bank;
a->volume = volume;
a->pan = pan;
a->setName(Channel::DEFAULT_NAME);
a->setProgram(program);
a->setBank(bank);
a->setVolume(volume);
a->setPan(pan);
a->setReverb(reverb);
a->setChorus(chorus);
i->appendChannel(a);
}
if (i->useDrumset()) {
if (i->channel()[0]->bank == 0)
i->channel()[0]->bank = 128;
if (i->channel()[0]->bank() == 0)
i->channel()[0]->setBank(128);
i->channel()[0]->updateInitList();
}
}

View file

@ -412,7 +412,7 @@ static void collectMeasureEvents(EventMap* events, Measure* m, Staff* staff, int
Staff* st1 = chord->staff();
int velocity = st1->velocities().velo(seg->tick());
Instrument* instr = chord->part()->instrument(tick);
int channel = instr->channel(chord->upNote()->subchannel())->channel;
int channel = instr->channel(chord->upNote()->subchannel())->channel();
for (Articulation* a : chord->articulations())
instr->updateVelocity(&velocity,channel, a->articulationName());
@ -445,7 +445,7 @@ static void collectMeasureEvents(EventMap* events, Measure* m, Staff* staff, int
Instrument* instr = e->part()->instrument(tick);
for (const ChannelActions& ca : *st1->channelActions()) {
int channel = instr->channel().at(ca.channel)->channel;
int channel = instr->channel().at(ca.channel)->channel();
for (const QString& ma : ca.midiActionNames) {
NamedEventList* nel = instr->midiAction(ma, ca.channel);
if (!nel)
@ -711,7 +711,7 @@ void Score::renderSpanners(EventMap* events, int staffIdx)
continue;
int idx = s->staff()->channel(s->tick(), 0);
int channel = s->part()->instrument(s->tick())->channel(idx)->channel;
int channel = s->part()->instrument(s->tick())->channel(idx)->channel();
if (s->isPedal() || s->isLetRing()) {
channelPedalEvents.insert({channel, std::vector<std::pair<int, bool>>()});

View file

@ -3480,12 +3480,12 @@ void Score::appendPart(const QString& name)
if (t->channel.empty()) {
Channel a;
a.chorus = 0;
a.reverb = 0;
a.name = "normal";
a.bank = 0;
a.volume = 100;
a.pan = 64; // actually 63.5 for center
a.setChorus(0);
a.setReverb(0);
a.setName(Channel::DEFAULT_NAME);
a.setBank(0);
a.setVolume(90);
a.setPan(0);
t->channel.append(a);
}
Part* part = new Part(this);
@ -3742,13 +3742,13 @@ void MasterScore::setSoloMute()
{
for (int i = 0; i < _midiMapping.size(); i++) {
Channel* b = _midiMapping[i].articulation;
if (b->solo) {
b->soloMute = false;
if (b->solo()) {
b->setSoloMute(false);
for (int j = 0; j < _midiMapping.size(); j++) {
Channel* a = _midiMapping[j].articulation;
bool sameMidiMapping = _midiMapping[i].port == _midiMapping[j].port && _midiMapping[i].channel == _midiMapping[j].channel;
a->soloMute = (i != j && !a->solo && !sameMidiMapping);
a->solo = (i == j || a->solo || sameMidiMapping);
a->setSoloMute((i != j && !a->solo() && !sameMidiMapping));
a->setSolo(i == j || a->solo() || sameMidiMapping);
}
}
}

View file

@ -82,7 +82,7 @@ class UndoCommand;
class UndoStack;
class Volta;
class XmlWriter;
struct Channel;
class Channel;
struct Interval;
struct TEvent;
struct LayoutContext;

View file

@ -1273,13 +1273,13 @@ void EditText::undoRedo()
void ChangePatch::flip(EditData*)
{
MidiPatch op;
op.prog = channel->program;
op.bank = channel->bank;
op.synti = channel->synti;
op.prog = channel->program();
op.bank = channel->bank();
op.synti = channel->synti();
channel->program = patch.prog;
channel->bank = patch.bank;
channel->synti = patch.synti;
channel->setProgram(patch.prog);
channel->setBank(patch.bank);
channel->setSynti(patch.synti);
patch = op;
@ -1290,10 +1290,10 @@ void ChangePatch::flip(EditData*)
NPlayEvent event;
event.setType(ME_CONTROLLER);
event.setChannel(channel->channel);
event.setChannel(channel->channel());
int hbank = (channel->bank >> 7) & 0x7f;
int lbank = channel->bank & 0x7f;
int hbank = (channel->bank() >> 7) & 0x7f;
int lbank = channel->bank() & 0x7f;
event.setController(CTRL_HBANK);
event.setValue(hbank);
@ -1304,7 +1304,7 @@ void ChangePatch::flip(EditData*)
MScore::seq->sendEvent(event);
event.setController(CTRL_PROGRAM);
event.setValue(channel->program);
event.setValue(channel->program());
score->setInstrumentsChanged(true);

View file

@ -64,7 +64,7 @@ class MeasureBase;
class Dynamic;
class Selection;
class Text;
struct Channel;
class Channel;
class Tuplet;
class KeySig;
class TimeSig;

View file

@ -39,7 +39,8 @@ endif (SCRIPT_INTERFACE)
QT5_WRAP_UI (ui_headers
insertmeasuresdialog.ui editinstrument.ui editstyle.ui instrdialog.ui instrwidget.ui
measuresdialog.ui pagesettings.ui mixer.ui playpanel.ui prefsdialog.ui measureproperties.ui
measuresdialog.ui pagesettings.ui mixer.ui mixertrackchannel.ui mixertrackpart.ui mixerdetails.ui parteditbase.ui
playpanel.ui prefsdialog.ui measureproperties.ui
textpalette.ui timedialog.ui symboldialog.ui shortcutcapturedialog.ui editdrumset.ui
editstaff.ui timesigproperties.ui
instrwizard.ui timesigwizard.ui newwizard.ui aboutbox.ui aboutmusicxmlbox.ui
@ -286,9 +287,10 @@ add_executable ( ${ExecutableName}
importmxmllogger.h importmxmlnoteduration.h importmxmlnotepitch.h importmxmlpass1.h
importmxmlpass2.h importptb.h importxmlfirstpass.h instrdialog.h instrwidget.h jackaudio.h
keycanvas.h keyedit.h layer.h licence.h logindialog.h loginmanager.h magbox.h masterpalette.h
measureproperties.h mediadialog.h metaedit.h miconengine.h mididriver.h mixer.h musedata.h
measureproperties.h mediadialog.h metaedit.h miconengine.h mididriver.h
mixer.h mixertrack.h mixertrackchannel.h mixertrackgroup.h mixertrackitem.h mixertrackpart.h mixerdetails.h musedata.h
musescore.h musicxml.h musicxmlfonthandler.h musicxmlsupport.h navigator.h newwizard.h noteGroups.h
omrpanel.h ove.h pa.h pagesettings.h palette.h palettebox.h paletteBoxButton.h partedit.h
omrpanel.h ove.h pa.h pagesettings.h palette.h palettebox.h paletteBoxButton.h partedit.h parteditbase.h
pathlistdialog.h piano.h pianolevels.h pianolevelschooser.h pianolevelsfilter.h
pianokeyboard.h pianoroll.h pianoruler.h pianotools.h pianoview.h
playpanel.h pluginCreator.h
@ -313,7 +315,9 @@ add_executable ( ${ExecutableName}
debugger/debugger.cpp menus.cpp
musescore.cpp navigator.cpp pagesettings.cpp palette.cpp
timeline.cpp
mixer.cpp playpanel.cpp selectionwindow.cpp preferences.cpp measureproperties.cpp
mixer.cpp mixertrackchannel.cpp mixertrackitem.cpp mixertrackpart.cpp mixerdetails.cpp
parteditbase.cpp playpanel.cpp selectionwindow.cpp
preferences.cpp measureproperties.cpp
seq.cpp textpalette.cpp
timedialog.cpp symboldialog.cpp shortcutcapturedialog.cpp
simplebutton.cpp musedata.cpp

View file

@ -57,13 +57,13 @@ ArticulationProperties::ArticulationProperties(Articulation* na, QWidget* parent
// const QList<Channel>& channel() const;
for (const Channel* a : instrument->channel()) {
if (a->name.isEmpty() || a->name == "normal") {
channelList->addItem(tr("normal"));
channelList->item(channelList->count() - 1)->setData(Qt::UserRole, "normal");
if (a->name().isEmpty() || a->name() == Channel::DEFAULT_NAME) {
channelList->addItem(tr(Channel::DEFAULT_NAME));
channelList->item(channelList->count() - 1)->setData(Qt::UserRole, Channel::DEFAULT_NAME);
}
else {
channelList->addItem(qApp->translate("InstrumentsXML", a->name.toUtf8().data()));
channelList->item(channelList->count() - 1)->setData(Qt::UserRole, a->name);
channelList->addItem(qApp->translate("InstrumentsXML", a->name().toUtf8().data()));
channelList->item(channelList->count() - 1)->setData(Qt::UserRole, a->name());
}
}
for (const NamedEventList& el : instrument->midiActions()) {

View file

@ -0,0 +1,105 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
sodipodi:docname="mixer-dial.svg"
inkscape:version="0.92.3 (2405546, 2018-03-11)"
id="svg4649"
version="1.1"
viewBox="0 0 32 32"
height="32"
width="32">
<sodipodi:namedview
viewbox-height="32"
inkscape:window-maximized="1"
inkscape:window-y="-8"
inkscape:window-x="-8"
inkscape:window-height="1017"
inkscape:window-width="1920"
inkscape:snap-grids="false"
units="px"
showgrid="false"
inkscape:current-layer="layer1"
inkscape:document-units="px"
inkscape:cy="11.996111"
inkscape:cx="-5.4001146"
inkscape:zoom="8"
inkscape:pageshadow="2"
inkscape:pageopacity="0.0"
borderopacity="1.0"
bordercolor="#666666"
pagecolor="#ffffff"
id="base">
<inkscape:grid
empspacing="4"
id="grid4651"
type="xygrid" />
</sodipodi:namedview>
<defs
id="defs4643">
<linearGradient
id="linearGradient823"
inkscape:collect="always">
<stop
id="stop819"
offset="0"
style="stop-color:#878787;stop-opacity:1" />
<stop
id="stop821"
offset="1"
style="stop-color:#353535;stop-opacity:1" />
</linearGradient>
<radialGradient
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(2.4995922,0,0,2.4919021,-2.5414783,-691.63044)"
r="4.6579642"
fy="288.55579"
fx="6.1641054"
cy="288.55579"
cx="6.1641054"
id="radialGradient825"
xlink:href="#linearGradient823"
inkscape:collect="always" />
</defs>
<metadata
id="metadata4646">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
transform="translate(0,-13.714286)"
id="layer1"
inkscape:groupmode="layer"
inkscape:label="Layer 1">
<path
id="grip"
d="M14.604574 15.679912C14.539094 15.687312 14.47361 15.697412 14.40824 15.705662C14.40824 15.705662 13.547465 17.012374 13.547465 17.012374C13.180411 17.569583 12.213426 17.82984 11.616955 17.530739C11.616955 17.530739 10.225988 16.8332 10.225988 16.8332C9.2523578 17.257831 8.3287385 17.788919 7.4720087 18.416817C7.4720087 18.416817 7.1172299 19.056837 7.3780687 19.973937C7.560697 20.616008 6.5958152 21.562053 5.9541101 21.378083C5.0414896 21.116427 4.4084342 21.472313 4.4084342 21.472313C3.7761742 22.324298 3.2400766 23.243598 2.8099202 24.21344C2.8099202 24.21344 3.5143202 25.616111 3.5143202 25.616111C3.813656 26.21219 3.5467542 27.178006 2.989161 27.544047C2.989161 27.544047 1.6817936 28.402307 1.6817936 28.402307C1.5693633 29.389694 1.5595262 30.386033 1.6524296 31.375446C1.8123764 31.872385 2.5340375 32.135367 2.9849914 32.432424C3.5422122 32.799489 3.8024672 33.766481 3.503357 34.362934C3.503357 34.362934 2.8058158 35.753908 2.8058158 35.753908C3.2304286 36.727548 3.761542 37.651172 4.3894457 38.507883C4.3894457 38.507883 5.94655 38.60187 5.94655 38.60187C6.6129298 38.64211 7.3100418 39.35952 7.3506833 40.025862C7.3506833 40.025862 7.4449603 41.571535 7.4449603 41.571535C8.2969362 42.203807 9.216226 42.739893 10.186063 43.170049C10.186063 43.170049 11.588759 42.465638 11.588759 42.465638C12.184844 42.166288 13.150705 42.433148 13.516698 42.990779C13.516698 42.990779 14.374937 44.29819 14.374937 44.29819C15.36232 44.410667 16.358668 44.420671 17.348088 44.32768C17.413568 44.32008 17.479046 44.31018 17.54442 44.30193C17.54442 44.30193 18.405191 42.995243 18.405191 42.995243C18.77225 42.438034 19.739231 42.177777 20.335703 42.476877C20.335703 42.476877 21.726671 43.174414 21.726671 43.174414C22.7003 42.74979 23.623923 42.218676 24.480652 41.59078C24.480652 41.59078 24.574592 40.03366 24.574592 40.03366C24.614782 39.367368 25.332233 38.670157 25.998552 38.629538C25.998552 38.629538 27.544227 38.535308 27.544227 38.535308C28.176491 37.683298 29.504554 36.514663 29.142742 35.79418C29.142742 35.79418 28.438341 34.391509 28.438341 34.391509C28.139005 33.795432 28.405891 32.829614 28.9635 32.463573C28.9635 32.463573 30.27087 31.605314 30.27087 31.605314C30.372822 30.475909 30.37062 29.414183 30.27437 28.435955C30.27437 28.435955 28.967679 27.575196 28.967679 27.575196C28.410454 27.208131 28.150203 26.241139 28.449313 25.644686C28.449313 25.644686 29.146853 24.253713 29.146853 24.253713C28.722241 23.280073 28.191128 22.356449 27.563222 21.499713C27.563222 21.499713 26.006119 21.405723 26.006119 21.405723C25.339741 21.365473 24.642627 20.648097 24.601985 19.981757C24.601985 19.981757 24.507715 18.436084 24.507715 18.436084C23.655741 17.803812 22.736449 17.267724 21.766611 16.837569C21.766611 16.837569 20.363913 17.541955 20.363913 17.541955C19.767827 17.841281 18.801973 17.574445 18.435978 17.016816C18.435978 17.016816 17.577739 15.709429 17.577739 15.709429C16.590367 15.596696 15.594007 15.586948 14.604588 15.679939C14.604588 15.679939 14.604595 15.679914 14.604595 15.679914"
style="stroke-linejoin:round;stroke-opacity:1;fill-opacity:1;stroke:#000000;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-width:1;fill:#444444" />
<ellipse
ry="10.607352"
rx="10.643174"
cy="29.927521"
cx="15.872563"
id="path5206-6"
style="stroke-opacity:1;fill-opacity:1;stroke:#b8b8b8;stroke-dasharray:none;stroke-miterlimit:4;stroke-width:2.82796569515;fill:url(#radialGradient825)" />
<path
id="pointer"
d="M13.330931 30.0038C13.330931 30.0038 13.330931 19.422202 13.330931 19.422202C13.330931 19.422202 15.976333 15.454099 15.976333 15.454099C15.976333 15.454099 18.621734 19.422202 18.621734 19.422202C18.621734 19.422202 18.621734 30.0038 18.621734 30.0038C18.621734 30.0038 13.330931 30.0038 13.330931 30.0038"
style="stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1;stroke:#000000;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-width:1;fill:#ffffff" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.4 KiB

View file

@ -0,0 +1,140 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="32"
height="32"
viewBox="0 0 8.4666665 8.4666669"
version="1.1"
id="svg28"
inkscape:version="0.92.3 (2405546, 2018-03-11)"
sodipodi:docname="mixer-mute-off.svg">
<defs
id="defs22">
<linearGradient
inkscape:collect="always"
id="linearGradient4599">
<stop
style="stop-color:#844747;stop-opacity:1"
offset="0"
id="stop4595" />
<stop
style="stop-color:#844747;stop-opacity:0"
offset="1"
id="stop4597" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4599"
id="linearGradient4605"
x1="4.1952744"
y1="290.3605"
x2="4.1910601"
y2="295.12302"
gradientUnits="userSpaceOnUse" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="8"
inkscape:cx="1.3172043"
inkscape:cy="22.960298"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:window-width="1920"
inkscape:window-height="1017"
inkscape:window-x="1912"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:snap-grids="false">
<inkscape:grid
type="xygrid"
id="grid30" />
</sodipodi:namedview>
<metadata
id="metadata25">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-288.53332)">
<circle
id="path32"
cx="4.2333331"
cy="292.76666"
r="3.7041667"
style="stroke-width:0.26458332;fill:#a9a9a9;fill-opacity:1;stroke:none;stroke-opacity:1" />
<path
style="fill:#6c6c6c;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-opacity:1"
d="m 7.2732044,292.43954 c 0.073048,-0.76338 -0.3126362,-1.59027 -0.9394394,-2.10939 -0.6268031,-0.51912 -1.483032,-0.83571 -2.1405976,-0.83571 -0.6575657,0 -1.4912279,0.33616 -2.0908597,0.8727 -0.5996318,0.53654 -0.9652333,1.41379 -0.9205384,2.07501 0.8740815,-1.16984 1.6469057,-2.6381 2.962032,-2.6381 1.3151265,0 2.3084979,1.54005 3.1294031,2.63549 z"
id="path4552-1-0"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cssscsc" />
<circle
style="fill:#781a1a;fill-opacity:1;stroke:#000000;stroke-width:0.26458332;stroke-opacity:1"
id="path4542"
cx="4.2333331"
cy="292.76666"
r="2.9104166" />
<ellipse
style="fill:url(#linearGradient4605);fill-opacity:1;stroke:none;stroke-width:0.19899577;stroke-opacity:1"
id="path4550"
cx="4.2675815"
cy="292.03067"
rx="2.3543382"
ry="1.8543748" />
<path
style="fill:#240a0a;fill-opacity:0.50970876;stroke:none;stroke-width:0.26458332;stroke-opacity:1"
d="m 6.9701172,293.31236 c -0.2397739,1.24612 -1.4193019,2.26147 -2.7344333,2.26147 -1.3151314,0 -2.5572334,-1.10392 -2.7367837,-2.21589 0.8244722,0.86392 1.4136325,1.36883 2.7287589,1.36883 1.3151263,0 2.2440139,-0.81507 2.7424581,-1.41441 z"
id="path4552"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cscsc" />
<path
style="fill:#6c6c6c;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-opacity:1"
d="m 7.5311815,294.19907 c -0.2397738,1.24612 -2.0642238,2.27801 -3.3793551,2.27801 -1.3151316,0 -3.003718,-1.1866 -3.18326827,-2.29857 0.53767807,0.74532 0.97234997,1.1421 1.44496747,1.4342 0.4726175,0.2921 1.0698754,0.50974 1.7274386,0.50974 0.6575632,0 1.4687479,-0.23019 1.9382783,-0.54888 0.4693144,-0.31854 0.7836309,-0.54991 1.451939,-1.3745 z"
id="path4552-1"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cscsssc" />
<circle
id="path32-6"
cx="4.2333331"
cy="292.76666"
r="3.7041667"
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.26458332;stroke-opacity:1" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:3.89016056px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.097254"
x="2.3482678"
y="294.27344"
id="text4641"><tspan
sodipodi:role="line"
id="tspan4639"
x="2.3482678"
y="294.27344"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.89016056px;font-family:Academico;-inkscape-font-specification:'Academico, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.097254">M</tspan></text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.5 KiB

View file

@ -0,0 +1,140 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="32"
height="32"
viewBox="0 0 8.4666665 8.4666669"
version="1.1"
id="svg28"
inkscape:version="0.92.3 (2405546, 2018-03-11)"
sodipodi:docname="mixer-mute-on.svg">
<defs
id="defs22">
<linearGradient
inkscape:collect="always"
id="linearGradient4599">
<stop
style="stop-color:#f1abab;stop-opacity:1"
offset="0"
id="stop4595" />
<stop
style="stop-color:#f1abab;stop-opacity:0"
offset="1"
id="stop4597" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4599"
id="linearGradient4605"
x1="4.1952744"
y1="290.3605"
x2="4.1910601"
y2="295.12302"
gradientUnits="userSpaceOnUse" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="8"
inkscape:cx="7.6303127"
inkscape:cy="13.350232"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:window-width="1920"
inkscape:window-height="1017"
inkscape:window-x="1912"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:snap-grids="false">
<inkscape:grid
type="xygrid"
id="grid30" />
</sodipodi:namedview>
<metadata
id="metadata25">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-288.53332)">
<circle
id="path32"
cx="4.2333331"
cy="292.76666"
r="3.7041667"
style="stroke-width:0.26458332;fill:#a9a9a9;fill-opacity:1;stroke:none;stroke-opacity:1" />
<path
style="fill:#6c6c6c;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-opacity:1"
d="m 7.2732044,292.43954 c 0.073048,-0.76338 -0.3126362,-1.59027 -0.9394394,-2.10939 -0.6268031,-0.51912 -1.483032,-0.83571 -2.1405976,-0.83571 -0.6575657,0 -1.4912279,0.33616 -2.0908597,0.8727 -0.5996318,0.53654 -0.9652333,1.41379 -0.9205384,2.07501 0.8740815,-1.16984 1.6469057,-2.6381 2.962032,-2.6381 1.3151265,0 2.3084979,1.54005 3.1294031,2.63549 z"
id="path4552-1-0"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cssscsc" />
<circle
style="fill:#ef2c2c;fill-opacity:1;stroke:#000000;stroke-width:0.26458332;stroke-opacity:1"
id="path4542"
cx="4.2333331"
cy="292.76666"
r="2.9104166" />
<ellipse
style="fill:url(#linearGradient4605);fill-opacity:1;stroke:none;stroke-width:0.19899577;stroke-opacity:1"
id="path4550"
cx="4.2675815"
cy="292.03067"
rx="2.3543382"
ry="1.8543748" />
<path
style="fill:#821b1b;fill-opacity:0.50970876;stroke:none;stroke-width:0.26458332;stroke-opacity:1"
d="m 6.9701172,293.31236 c -0.2397739,1.24612 -1.4193019,2.26147 -2.7344333,2.26147 -1.3151314,0 -2.5572334,-1.10392 -2.7367837,-2.21589 0.8244722,0.86392 1.4136325,1.36883 2.7287589,1.36883 1.3151263,0 2.2440139,-0.81507 2.7424581,-1.41441 z"
id="path4552"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cscsc" />
<path
style="fill:#6c6c6c;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-opacity:1"
d="m 7.5311815,294.19907 c -0.2397738,1.24612 -2.0642238,2.27801 -3.3793551,2.27801 -1.3151316,0 -3.003718,-1.1866 -3.18326827,-2.29857 0.53767807,0.74532 0.97234997,1.1421 1.44496747,1.4342 0.4726175,0.2921 1.0698754,0.50974 1.7274386,0.50974 0.6575632,0 1.4687479,-0.23019 1.9382783,-0.54888 0.4693144,-0.31854 0.7836309,-0.54991 1.451939,-1.3745 z"
id="path4552-1"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cscsssc" />
<circle
id="path32-6"
cx="4.2333331"
cy="292.76666"
r="3.7041667"
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.26458332;stroke-opacity:1" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:3.89016056px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.097254"
x="2.3482678"
y="294.27344"
id="text4641"><tspan
sodipodi:role="line"
id="tspan4639"
x="2.3482678"
y="294.27344"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.89016056px;font-family:Academico;-inkscape-font-specification:'Academico, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.097254">M</tspan></text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.5 KiB

View file

@ -0,0 +1,128 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="30"
height="45"
viewBox="0 0 7.9374997 11.90625"
version="1.1"
id="svg8"
inkscape:version="0.92.3 (2405546, 2018-03-11)"
sodipodi:docname="mixer-slider-handle.svg"
inkscape:export-filename="D:\dev\github.com\MuseScoreMinGW\mscore\data\icons\mixer-slider-handle.png"
inkscape:export-xdpi="48"
inkscape:export-ydpi="48">
<defs
id="defs2">
<linearGradient
id="linearGradient844"
inkscape:collect="always">
<stop
id="stop840"
offset="0"
style="stop-color:#898989;stop-opacity:1" />
<stop
id="stop842"
offset="1"
style="stop-color:#e4e4e4;stop-opacity:1" />
</linearGradient>
<linearGradient
inkscape:collect="always"
id="linearGradient824">
<stop
style="stop-color:#898989;stop-opacity:1"
offset="0"
id="stop820" />
<stop
style="stop-color:#e4e4e4;stop-opacity:1"
offset="1"
id="stop822" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient824"
id="linearGradient826"
x1="-3.9103179"
y1="297.24557"
x2="-3.8304768"
y2="285.38882"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.8683302,0,0,0.96503255,7.3827223,9.9179025)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient844"
id="linearGradient838"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.86322913,0,0,0.81935486,7.5301966,52.317886)"
x1="-3.8119318"
y1="285.99686"
x2="-3.7885454"
y2="296.82458" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="5.6568542"
inkscape:cx="15.534403"
inkscape:cy="21.715691"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:window-width="986"
inkscape:window-height="821"
inkscape:window-x="135"
inkscape:window-y="160"
inkscape:window-maximized="0" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-285.09375)">
<rect
style="fill:url(#linearGradient826);fill-opacity:1;stroke:#0e0e0e;stroke-width:0.1373108;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect818"
width="5.157938"
height="11.397007"
x="1.453124"
y="285.36124"
ry="2.866178" />
<rect
style="opacity:1;fill:url(#linearGradient838);fill-opacity:1;stroke:none;stroke-width:0.12615089;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect828"
width="4.6027613"
height="8.9100981"
x="1.7161824"
y="286.60291"
ry="2.184411" />
<path
style="fill:none;stroke:#000000;stroke-width:0.24780074px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 1.8804469,291.0695 4.3266789,0.047"
id="path846"
inkscape:connector-curvature="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 4 KiB

View file

@ -0,0 +1,130 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="45"
height="25"
viewBox="0 0 11.90625 6.6145833"
version="1.1"
id="svg8"
inkscape:version="0.92.3 (2405546, 2018-03-11)"
sodipodi:docname="mixer-slider-handle.svg"
inkscape:export-filename="D:\dev\github.com\MuseScoreMinGW\mscore\data\icons\mixer-slider-handle.png"
inkscape:export-xdpi="48"
inkscape:export-ydpi="48">
<defs
id="defs2">
<linearGradient
id="linearGradient844"
inkscape:collect="always">
<stop
id="stop840"
offset="0"
style="stop-color:#898989;stop-opacity:1" />
<stop
id="stop842"
offset="1"
style="stop-color:#e4e4e4;stop-opacity:1" />
</linearGradient>
<linearGradient
inkscape:collect="always"
id="linearGradient824">
<stop
style="stop-color:#898989;stop-opacity:1"
offset="0"
id="stop820" />
<stop
style="stop-color:#e4e4e4;stop-opacity:1"
offset="1"
id="stop822" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient824"
id="linearGradient826"
x1="-3.9103179"
y1="297.24557"
x2="-3.8304768"
y2="285.38882"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.8683302,0,0,0.96503255,297.2167,-287.09159)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient844"
id="linearGradient838"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.86322913,0,0,0.81935486,297.37692,-244.67529)"
x1="-3.8119318"
y1="285.99686"
x2="-3.7885454"
y2="296.82458" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="5.6568542"
inkscape:cx="-12.566834"
inkscape:cy="21.715691"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:window-width="1409"
inkscape:window-height="928"
inkscape:window-x="464"
inkscape:window-y="56"
inkscape:window-maximized="0" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-290.38542)">
<rect
style="fill:url(#linearGradient826);fill-opacity:1;stroke:#0e0e0e;stroke-width:0.1373108;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect818"
width="5.157938"
height="11.397007"
x="291.28711"
y="-11.648255"
ry="2.866178"
transform="rotate(90)" />
<rect
style="opacity:1;fill:url(#linearGradient838);fill-opacity:1;stroke:none;stroke-width:0.12615089;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect828"
width="4.6027613"
height="8.9100981"
x="291.5629"
y="-10.390271"
ry="2.184411"
transform="rotate(90)" />
<path
style="fill:none;stroke:#000000;stroke-width:0.24780074px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 5.9849453,291.73599 -0.047,4.32668"
id="path846"
inkscape:connector-curvature="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 4 KiB

View file

@ -0,0 +1,140 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="32"
height="32"
viewBox="0 0 8.4666665 8.4666669"
version="1.1"
id="svg28"
inkscape:version="0.92.3 (2405546, 2018-03-11)"
sodipodi:docname="mixer-solo-off.svg">
<defs
id="defs22">
<linearGradient
inkscape:collect="always"
id="linearGradient4599">
<stop
style="stop-color:#618569;stop-opacity:1"
offset="0"
id="stop4595" />
<stop
style="stop-color:#566d5b;stop-opacity:0"
offset="1"
id="stop4597" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4599"
id="linearGradient4605"
x1="4.1952744"
y1="290.3605"
x2="4.1910601"
y2="295.12302"
gradientUnits="userSpaceOnUse" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="22.627417"
inkscape:cx="8.7353719"
inkscape:cy="20.532464"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:window-width="1920"
inkscape:window-height="1017"
inkscape:window-x="1912"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:snap-grids="false">
<inkscape:grid
type="xygrid"
id="grid30" />
</sodipodi:namedview>
<metadata
id="metadata25">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-288.53332)">
<circle
id="path32"
cx="4.2333331"
cy="292.76666"
r="3.7041667"
style="stroke-width:0.26458332;fill:#a9a9a9;fill-opacity:1;stroke:none;stroke-opacity:1" />
<path
style="fill:#6c6c6c;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-opacity:1"
d="m 7.2732044,292.43954 c 0.073048,-0.76338 -0.3126362,-1.59027 -0.9394394,-2.10939 -0.6268031,-0.51912 -1.483032,-0.83571 -2.1405976,-0.83571 -0.6575657,0 -1.4912279,0.33616 -2.0908597,0.8727 -0.5996318,0.53654 -0.9652333,1.41379 -0.9205384,2.07501 0.8740815,-1.16984 1.6469057,-2.6381 2.962032,-2.6381 1.3151265,0 2.3084979,1.54005 3.1294031,2.63549 z"
id="path4552-1-0"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cssscsc" />
<circle
style="fill:#146b24;fill-opacity:1;stroke:#000000;stroke-width:0.26458332;stroke-opacity:1"
id="path4542"
cx="4.2333331"
cy="292.76666"
r="2.9104166" />
<ellipse
style="fill:url(#linearGradient4605);fill-opacity:1;stroke:none;stroke-width:0.19899577;stroke-opacity:1"
id="path4550"
cx="4.2675815"
cy="292.03067"
rx="2.3543382"
ry="1.8543748" />
<path
style="fill:#0c2b12;fill-opacity:0.50970876;stroke:none;stroke-width:0.26458332;stroke-opacity:1"
d="m 6.9701172,293.31236 c -0.2397739,1.24612 -1.4193019,2.26147 -2.7344333,2.26147 -1.3151314,0 -2.5572334,-1.10392 -2.7367837,-2.21589 0.8244722,0.86392 1.4136325,1.36883 2.7287589,1.36883 1.3151263,0 2.2440139,-0.81507 2.7424581,-1.41441 z"
id="path4552"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cscsc" />
<path
style="fill:#6c6c6c;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-opacity:1"
d="m 7.5311815,294.19907 c -0.2397738,1.24612 -2.0642238,2.27801 -3.3793551,2.27801 -1.3151316,0 -3.003718,-1.1866 -3.18326827,-2.29857 0.53767807,0.74532 0.97234997,1.1421 1.44496747,1.4342 0.4726175,0.2921 1.0698754,0.50974 1.7274386,0.50974 0.6575632,0 1.4687479,-0.23019 1.9382783,-0.54888 0.4693144,-0.31854 0.7836309,-0.54991 1.451939,-1.3745 z"
id="path4552-1"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cscsssc" />
<circle
id="path32-6"
cx="4.2333331"
cy="292.76666"
r="3.7041667"
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.26458332;stroke-opacity:1" />
<g
aria-label="S"
style="font-style:normal;font-weight:normal;font-size:3.73521566px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.09338038"
id="text4613"
transform="translate(-0.06614583,0.08268229)">
<path
d="m 3.6539353,293.90217 c 0.041087,0.0261 0.1792903,0.11953 0.2614651,0.16062 0.1456734,0.0635 0.2988172,0.0896 0.4556963,0.0896 0.537871,0 0.8852461,-0.35111 0.8852461,-0.88151 0,-0.99356 -1.6659062,-0.51172 -1.6659062,-1.28865 0,-0.29881 0.2726707,-0.49678 0.5565471,-0.49678 0.4818429,0 0.7208967,0.45196 0.8329531,0.86283 H 5.0994637 V 291.3697 H 4.9687312 l -0.1830256,0.22411 C 4.60268,291.43693 4.393508,291.34355 4.150719,291.34355 c -0.4631668,0 -0.8068066,0.35111 -0.8068066,0.81428 0,0.34737 0.2129073,0.58643 0.5453415,0.67981 l 0.78066,0.22411 c 0.1867608,0.0486 0.3249638,0.22038 0.3249638,0.41087 0,0.33617 -0.2913468,0.53414 -0.6051049,0.53414 -0.5602824,0 -0.795601,-0.39967 -0.9487448,-0.90766 H 3.3177659 v 1.02719 h 0.1307325 z"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.73521566px;font-family:Academico;-inkscape-font-specification:'Academico, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.09338038"
id="path4615"
inkscape:connector-curvature="0" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.3 KiB

View file

@ -0,0 +1,140 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="32"
height="32"
viewBox="0 0 8.4666665 8.4666669"
version="1.1"
id="svg28"
inkscape:version="0.92.3 (2405546, 2018-03-11)"
sodipodi:docname="mixer-solo-on.svg">
<defs
id="defs22">
<linearGradient
inkscape:collect="always"
id="linearGradient4599">
<stop
style="stop-color:#c4f5cf;stop-opacity:1"
offset="0"
id="stop4595" />
<stop
style="stop-color:#c4f5cf;stop-opacity:0"
offset="1"
id="stop4597" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4599"
id="linearGradient4605"
x1="4.1952744"
y1="290.3605"
x2="4.1910601"
y2="295.12302"
gradientUnits="userSpaceOnUse" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="2.8284271"
inkscape:cx="-93.032621"
inkscape:cy="45.202522"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:window-width="1920"
inkscape:window-height="1017"
inkscape:window-x="1912"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:snap-grids="false">
<inkscape:grid
type="xygrid"
id="grid30" />
</sodipodi:namedview>
<metadata
id="metadata25">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-288.53332)">
<circle
id="path32"
cx="4.2333331"
cy="292.76666"
r="3.7041667"
style="stroke-width:0.26458332;fill:#a9a9a9;fill-opacity:1;stroke:none;stroke-opacity:1" />
<path
style="fill:#6c6c6c;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-opacity:1"
d="m 7.2732044,292.43954 c 0.073048,-0.76338 -0.3126362,-1.59027 -0.9394394,-2.10939 -0.6268031,-0.51912 -1.483032,-0.83571 -2.1405976,-0.83571 -0.6575657,0 -1.4912279,0.33616 -2.0908597,0.8727 -0.5996318,0.53654 -0.9652333,1.41379 -0.9205384,2.07501 0.8740815,-1.16984 1.6469057,-2.6381 2.962032,-2.6381 1.3151265,0 2.3084979,1.54005 3.1294031,2.63549 z"
id="path4552-1-0"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cssscsc" />
<circle
style="fill:#2cef51;fill-opacity:1;stroke:#000000;stroke-width:0.26458332;stroke-opacity:1"
id="path4542"
cx="4.2333331"
cy="292.76666"
r="2.9104166" />
<ellipse
style="fill:url(#linearGradient4605);fill-opacity:1;stroke:none;stroke-width:0.19899577;stroke-opacity:1"
id="path4550"
cx="4.2675815"
cy="292.03067"
rx="2.3543382"
ry="1.8543748" />
<path
style="fill:#1b822f;fill-opacity:0.50970876;stroke:none;stroke-width:0.26458332;stroke-opacity:1"
d="m 6.9701172,293.31236 c -0.2397739,1.24612 -1.4193019,2.26147 -2.7344333,2.26147 -1.3151314,0 -2.5572334,-1.10392 -2.7367837,-2.21589 0.8244722,0.86392 1.4136325,1.36883 2.7287589,1.36883 1.3151263,0 2.2440139,-0.81507 2.7424581,-1.41441 z"
id="path4552"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cscsc" />
<path
style="fill:#6c6c6c;fill-opacity:1;stroke:none;stroke-width:0.26458332;stroke-opacity:1"
d="m 7.5311815,294.19907 c -0.2397738,1.24612 -2.0642238,2.27801 -3.3793551,2.27801 -1.3151316,0 -3.003718,-1.1866 -3.18326827,-2.29857 0.53767807,0.74532 0.97234997,1.1421 1.44496747,1.4342 0.4726175,0.2921 1.0698754,0.50974 1.7274386,0.50974 0.6575632,0 1.4687479,-0.23019 1.9382783,-0.54888 0.4693144,-0.31854 0.7836309,-0.54991 1.451939,-1.3745 z"
id="path4552-1"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cscsssc" />
<circle
id="path32-6"
cx="4.2333331"
cy="292.76666"
r="3.7041667"
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.26458332;stroke-opacity:1" />
<g
aria-label="S"
style="font-style:normal;font-weight:normal;font-size:3.73521566px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.09338038"
id="text4613"
transform="translate(-0.06614583,0.08268229)">
<path
d="m 3.6539353,293.90217 c 0.041087,0.0261 0.1792903,0.11953 0.2614651,0.16062 0.1456734,0.0635 0.2988172,0.0896 0.4556963,0.0896 0.537871,0 0.8852461,-0.35111 0.8852461,-0.88151 0,-0.99356 -1.6659062,-0.51172 -1.6659062,-1.28865 0,-0.29881 0.2726707,-0.49678 0.5565471,-0.49678 0.4818429,0 0.7208967,0.45196 0.8329531,0.86283 H 5.0994637 V 291.3697 H 4.9687312 l -0.1830256,0.22411 C 4.60268,291.43693 4.393508,291.34355 4.150719,291.34355 c -0.4631668,0 -0.8068066,0.35111 -0.8068066,0.81428 0,0.34737 0.2129073,0.58643 0.5453415,0.67981 l 0.78066,0.22411 c 0.1867608,0.0486 0.3249638,0.22038 0.3249638,0.41087 0,0.33617 -0.2913468,0.53414 -0.6051049,0.53414 -0.5602824,0 -0.795601,-0.39967 -0.9487448,-0.90766 H 3.3177659 v 1.02719 h 0.1307325 z"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:3.73521566px;font-family:Academico;-inkscape-font-specification:'Academico, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;stroke-width:0.09338038"
id="path4615"
inkscape:connector-curvature="0" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.3 KiB

View file

@ -367,7 +367,7 @@ void DrumrollEditor::velocityChanged(int val)
void DrumrollEditor::keyPressed(int p)
{
seq->startNote(staff->part()->instrument()->channel(0)->channel, p, 80, 0, 0.0);
seq->startNote(staff->part()->instrument()->channel(0)->channel(), p, 80, 0, 0.0);
}
//---------------------------------------------------------

View file

@ -203,7 +203,7 @@ void DrumTools::drumNoteSelected(int val)
Note* note = ch->downNote();
int ticks = MScore::defaultPlayDuration;
int pitch = note->pitch();
seq->startNote(staff->part()->instrument()->channel(0)->channel, pitch, 80, ticks, 0.0);
seq->startNote(staff->part()->instrument()->channel(0)->channel(), pitch, 80, ticks, 0.0);
int track = (_score->inputState().track() / VOICES) * VOICES + element->track();
_score->inputState().setTrack(track);

View file

@ -100,8 +100,8 @@ bool MuseScore::saveAudio(Score* score, QIODevice *device, std::function<bool(fl
for (MidiCoreEvent e : a->init) {
if (e.type() == ME_INVALID)
continue;
e.setChannel(a->channel);
int syntiIdx = synth->index(score->masterScore()->midiMapping(a->channel)->articulation->synti);
e.setChannel(a->channel());
int syntiIdx = synth->index(score->masterScore()->midiMapping(a->channel())->articulation->synti());
synth->play(e, syntiIdx);
}
}
@ -137,8 +137,8 @@ bool MuseScore::saveAudio(Score* score, QIODevice *device, std::function<bool(fl
if (e.isChannelEvent()) {
int channelIdx = e.channel();
Channel* c = score->masterScore()->midiMapping(channelIdx)->articulation;
if (!c->mute) {
synth->play(e, synth->index(c->synti));
if (!c->mute()) {
synth->play(e, synth->index(c->synti()));
}
}
}

View file

@ -250,8 +250,8 @@ bool ExportMidi::write(const QString& name, bool midiExpandRepeats, bool exportR
// "normal", "pizzicato", "tremolo" for Strings,
// "normal", "mute" for Trumpet
foreach(const Channel* ch, j->second->channel()) {
char port = part->masterScore()->midiPort(ch->channel);
char channel = part->masterScore()->midiChannel(ch->channel);
char port = part->masterScore()->midiPort(ch->channel());
char channel = part->masterScore()->midiChannel(ch->channel());
if (staff->isTop()) {
track.insert(0, MidiEvent(ME_CONTROLLER, channel, CTRL_RESET_ALL_CTRL, 0));
@ -274,12 +274,12 @@ bool ExportMidi::write(const QString& name, bool midiExpandRepeats, bool exportR
track.insert(0, MidiEvent(ME_CONTROLLER, channel, CTRL_HRPN, 127));
}
if (ch->program != -1)
track.insert(0, MidiEvent(ME_CONTROLLER, channel, CTRL_PROGRAM, ch->program));
track.insert(0, MidiEvent(ME_CONTROLLER, channel, CTRL_VOLUME, ch->volume));
track.insert(0, MidiEvent(ME_CONTROLLER, channel, CTRL_PANPOT, ch->pan));
track.insert(0, MidiEvent(ME_CONTROLLER, channel, CTRL_REVERB_SEND, ch->reverb));
track.insert(0, MidiEvent(ME_CONTROLLER, channel, CTRL_CHORUS_SEND, ch->chorus));
if (ch->program() != -1)
track.insert(0, MidiEvent(ME_CONTROLLER, channel, CTRL_PROGRAM, ch->program()));
track.insert(0, MidiEvent(ME_CONTROLLER, channel, CTRL_VOLUME, ch->volume()));
track.insert(0, MidiEvent(ME_CONTROLLER, channel, CTRL_PANPOT, ch->pan()));
track.insert(0, MidiEvent(ME_CONTROLLER, channel, CTRL_REVERB_SEND, ch->reverb()));
track.insert(0, MidiEvent(ME_CONTROLLER, channel, CTRL_CHORUS_SEND, ch->chorus()));
}
// Export port to MIDI META event

View file

@ -4535,16 +4535,16 @@ static void midiInstrument(XmlWriter& xml, const int partNr, const int instrNr,
const Instrument* instr, const Score* score, const int unpitched = 0)
{
xml.stag(QString("midi-instrument %1").arg(instrId(partNr, instrNr)));
int midiChannel = score->masterScore()->midiChannel(instr->channel(0)->channel);
int midiChannel = score->masterScore()->midiChannel(instr->channel(0)->channel());
if (midiChannel >= 0 && midiChannel < 16)
xml.tag("midi-channel", midiChannel + 1);
int midiProgram = instr->channel(0)->program;
int midiProgram = instr->channel(0)->program();
if (midiProgram >= 0 && midiProgram < 128)
xml.tag("midi-program", midiProgram + 1);
if (unpitched > 0)
xml.tag("midi-unpitched", unpitched);
xml.tag("volume", (instr->channel(0)->volume / 127.0) * 100); //percent
xml.tag("pan", int(((instr->channel(0)->pan - 63.5) / 63.5) * 90)); //-90 hard left, +90 hard right
xml.tag("volume", (instr->channel(0)->volume() / 127.0) * 100); //percent
xml.tag("pan", int(((instr->channel(0)->pan() - 63.5) / 63.5) * 90)); //-90 hard left, +90 hard right xml.etag();
xml.etag();
}
@ -4960,7 +4960,7 @@ static void partList(XmlWriter& xml, Score* score, const QList<Part*>& il, MxmlI
int instNr = ii.key();
int midiPort = part->midiPort() + 1;
if (ii.value()->channel().size() > 0)
midiPort = score->masterScore()->midiMapping(ii.value()->channel(0)->channel)->port + 1;
midiPort = score->masterScore()->midiMapping(ii.value()->channel(0)->channel())->port + 1;
if (midiPort >= 1 && midiPort <= 16)
xml.tag(QString("midi-device %1 port=\"%2\"").arg(instrId(idx+1, instNr + 1)).arg(midiPort), "");
else

View file

@ -759,17 +759,17 @@ bool GuitarPro4::read(QFile* fp)
Channel* ch = instr->channel(0);
if (midiChannel == GP_DEFAULT_PERCUSSION_CHANNEL) {
ch->program = 0;
ch->bank = 128;
ch->setProgram(0);
ch->setBank(128);
}
else {
ch->program = patch;
ch->bank = 0;
ch->setProgram(patch);
ch->setBank(0);
}
ch->volume = channelDefaults[midiChannel].volume;
ch->pan = channelDefaults[midiChannel].pan;
ch->chorus = channelDefaults[midiChannel].chorus;
ch->reverb = channelDefaults[midiChannel].reverb;
ch->setVolume(channelDefaults[midiChannel].volume);
ch->setPan(channelDefaults[midiChannel].pan);
ch->setChorus(channelDefaults[midiChannel].chorus);
ch->setReverb(channelDefaults[midiChannel].reverb);
staff->part()->setMidiChannel(midiChannel, midiPort);
// missing: phase, tremolo
ch->updateInitList();

View file

@ -573,17 +573,17 @@ bool GuitarPro5::readTracks()
Channel* ch = instr->channel(0);
if (midiChannel == GP_DEFAULT_PERCUSSION_CHANNEL) {
ch->program = 0;
ch->bank = 128;
ch->setProgram(0);
ch->setBank(128);
}
else {
ch->program = patch;
ch->bank = 0;
ch->setProgram(patch);
ch->setBank(0);
}
ch->volume = channelDefaults[midiChannel].volume;
ch->pan = channelDefaults[midiChannel].pan;
ch->chorus = channelDefaults[midiChannel].chorus;
ch->reverb = channelDefaults[midiChannel].reverb;
ch->setVolume(channelDefaults[midiChannel].volume);
ch->setPan(channelDefaults[midiChannel].pan);
ch->setChorus(channelDefaults[midiChannel].chorus);
ch->setReverb(channelDefaults[midiChannel].reverb);
staff->part()->setMidiChannel(midiChannel, midiPort);
//qDebug("default2: %d", channelDefaults[i].reverb);

View file

@ -486,7 +486,7 @@ void GuitarPro6::readTracks(QDomNode* track)
auto prog = currentNode.firstChildElement("Program");
if (!prog.isNull()) {
auto p = prog.text().toInt();
part->instrument(0)->channel(0)->program = p;
part->instrument(0)->channel(0)->setProgram(p);
}
int midiChannel = currentNode.firstChildElement("PrimaryChannel").text().toInt();
//if (!prog.isNull() && midiChannel != GP_DEFAULT_PERCUSSION_CHANNEL)

View file

@ -1597,17 +1597,17 @@ bool GuitarPro2::read(QFile* fp)
Channel* ch = instr->channel(0);
if (midiChannel == int(StaffTypes::PERC_DEFAULT)) {
ch->program = 0;
ch->bank = 128;
ch->setProgram(0);
ch->setBank(128);
}
else {
ch->program = patch;
ch->bank = 0;
ch->setProgram(patch);
ch->setBank(0);
}
ch->volume = channelDefaults[midiChannel].volume;
ch->pan = channelDefaults[midiChannel].pan;
ch->chorus = channelDefaults[midiChannel].chorus;
ch->reverb = channelDefaults[midiChannel].reverb;
ch->setVolume(channelDefaults[midiChannel].volume);
ch->setPan(channelDefaults[midiChannel].pan);
ch->setChorus(channelDefaults[midiChannel].chorus);
ch->setReverb(channelDefaults[midiChannel].reverb);
// missing: phase, tremolo
ch->updateInitList();
}
@ -2287,17 +2287,17 @@ bool GuitarPro3::read(QFile* fp)
Channel* ch = instr->channel(0);
if (midiChannel == GP_DEFAULT_PERCUSSION_CHANNEL) {
ch->program = 0;
ch->bank = 128;
ch->setProgram(0);
ch->setBank(128);
}
else {
ch->program = patch;
ch->bank = 0;
ch->setProgram(patch);
ch->setBank(0);
}
ch->volume = channelDefaults[midiChannel].volume;
ch->pan = channelDefaults[midiChannel].pan;
ch->chorus = channelDefaults[midiChannel].chorus;
ch->reverb = channelDefaults[midiChannel].reverb;
ch->setVolume(channelDefaults[midiChannel].volume);
ch->setPan(channelDefaults[midiChannel].pan);
ch->setChorus(channelDefaults[midiChannel].chorus);
ch->setReverb(channelDefaults[midiChannel].reverb);
// missing: phase, tremolo
ch->updateInitList();
}

View file

@ -171,9 +171,9 @@ const InstrumentTemplate* findClosestInstrument(const MTrack &track)
if (track.mtrack->drumTrack() != isDrumTemplate)
continue;
for (const auto &channel: templ->channel) {
if (channel.program < track.program
&& channel.program > maxLessProgram) {
maxLessProgram = channel.program;
if (channel.program() < track.program
&& channel.program() > maxLessProgram) {
maxLessProgram = channel.program();
closestTemplate = templ;
break;
}
@ -205,7 +205,7 @@ std::vector<const InstrumentTemplate *> findInstrumentsForProgram(const MTrack &
findNotEmptyDrumPitches(drumPitches, templ);
for (const auto &channel: templ->channel) {
if (channel.program == program) {
if (channel.program() == program) {
if (isDrumTemplate && templ->drumset) {
if (hasNotDefinedDrumPitch(trackPitches, drumPitches))
break;
@ -438,7 +438,7 @@ void createInstruments(Score *score, QList<MTrack> &tracks)
if (track.volumes.size() == 1) {
for (auto &i: track.volumes) {
if (i.first == ReducedFraction(0, 1)) {
part->instrument()->channel(0)->volume = i.second;
part->instrument()->channel(0)->setVolume(i.second);
}
}
}

View file

@ -435,12 +435,12 @@ static Instrument createInstrument(const MusicXMLDrumInstrument& mxmlInstr)
// set articulations to default (global articulations)
instr.setArticulation(articulation);
// set default program
instr.channel(0)->program = mxmlInstr.midiProgram >= 0 ? mxmlInstr.midiProgram : 0;
instr.channel(0)->setProgram(mxmlInstr.midiProgram >= 0 ? mxmlInstr.midiProgram : 0);
}
// add / overrule with values read from MusicXML
instr.channel(0)->pan = mxmlInstr.midiPan;
instr.channel(0)->volume = mxmlInstr.midiVolume;
instr.channel(0)->setPan(mxmlInstr.midiPan);
instr.channel(0)->setVolume(mxmlInstr.midiVolume);
instr.setTrackName(mxmlInstr.name);
return instr;
@ -497,7 +497,7 @@ static void setStaffTypePercussion(Part* part, Drumset* drumset)
part->staff(j)->setStaffType(0, *StaffType::preset(StaffTypes::PERC_DEFAULT));
// set drumset for instrument
part->instrument()->setDrumset(drumset);
part->instrument()->channel(0)->bank = 128;
part->instrument()->channel(0)->setBank(128);
part->instrument()->channel(0)->updateInitList();
}

View file

@ -621,7 +621,7 @@ void OveToMScore::convertTrackHeader(OVE::Track* track, Part* part){
}
}
part->instrument()->channel(0)->bank = 128;
part->instrument()->channel(0)->setBank(128);
part->setMidiProgram(0);
part->instrument()->setDrumset(smDrumset);
part->instrument()->setDrumset(drumset);

View file

@ -18,6 +18,8 @@
//=============================================================================
#include "musescore.h"
#include "parteditbase.h"
#include "libmscore/score.h"
#include "libmscore/part.h"
#include "mixer.h"
@ -26,8 +28,14 @@
#include "synthcontrol.h"
#include "synthesizer/msynthesizer.h"
#include "preferences.h"
#include <QtGlobal>
#include <qmessagebox.h>
#include <accessibletoolbutton.h>
#include "mixerdetails.h"
#include "mixertrack.h"
#include "mixertrackchannel.h"
#include "mixertrackpart.h"
#include "mixertrackitem.h"
namespace Ms {
@ -41,171 +49,118 @@ namespace Ms {
__x->setChecked(__y); \
__x->blockSignals(false);
//---------------------------------------------------------
// PartEdit
//---------------------------------------------------------
PartEdit::PartEdit(QWidget* parent)
: QWidget(parent, Qt::Dialog)
{
setupUi(this);
connect(patch, SIGNAL(activated(int)), SLOT(patchChanged(int)));
connect(volume, SIGNAL(valueChanged(double,int)), SLOT(volChanged(double)));
connect(pan, SIGNAL(valueChanged(double,int)), SLOT(panChanged(double)));
connect(chorus, SIGNAL(valueChanged(double,int)), SLOT(chorusChanged(double)));
connect(reverb, SIGNAL(valueChanged(double,int)), SLOT(reverbChanged(double)));
connect(mute, SIGNAL(toggled(bool)), SLOT(muteChanged(bool)));
connect(solo, SIGNAL(toggled(bool)), SLOT(soloToggled(bool)));
connect(drumset, SIGNAL(toggled(bool)), SLOT(drumsetToggled(bool)));
connect(portSpinBox, SIGNAL(valueChanged(int)), SLOT(midiChannelChanged(int)));
connect(channelSpinBox, SIGNAL(valueChanged(int)), SLOT(midiChannelChanged(int)));
connect(expand, SIGNAL(toggled(bool)), SLOT(expandToggled(bool)));
double volumeToUserRange(char v) { return v * 100.0 / 128.0; }
double panToUserRange(char v) { return (v / 128.0) * 360.0; }
double chorusToUserRange(char v) { return v * 100.0 / 128.0; }
double reverbToUserRange(char v) { return v * 100.0 / 128.0; }
expandToggled(false);
}
const float minDecibels = -3;
//---------------------------------------------------------
// expandToggled
//---------------------------------------------------------
void PartEdit::expandToggled(bool val)
{
details->setVisible(val);
}
//---------------------------------------------------------
// setPart
//---------------------------------------------------------
void PartEdit::setPart(Part* p, Channel* a)
{
Channel dummy;
channel = a;
part = p;
QString s = part->partName();
if (!a->name.isEmpty()) {
if (a->name != "normal") {
s += "-";
s += qApp->translate("InstrumentsXML", a->name.toUtf8().data());
}
}
partName->setText(s);
_setValue(volume, a->volume);
volume->setDclickValue1(dummy.volume);
volume->setDclickValue2(dummy.volume);
_setValue(reverb, a->reverb);
reverb->setDclickValue1(dummy.reverb);
reverb->setDclickValue2(dummy.reverb);
_setValue(chorus, a->chorus);
chorus->setDclickValue1(dummy.chorus);
chorus->setDclickValue2(dummy.chorus);
_setValue(pan, a->pan);
pan->setDclickValue1(0);
pan->setDclickValue2(0);
for (int i = 0; i < patch->count(); ++i) {
MidiPatch* mp = (MidiPatch*)patch->itemData(i, Qt::UserRole).value<void*>();
if (a->synti == mp->synti && a->program == mp->prog && a->bank == mp->bank) {
patch->setCurrentIndex(i);
break;
}
}
_setChecked(drumset, p->instrument()->useDrumset());
_setValue(portSpinBox, part->masterScore()->midiMapping(a->channel)->port + 1);
_setValue(channelSpinBox, part->masterScore()->midiMapping(a->channel)->channel + 1);
QHBoxLayout* hb = voiceButtonBox;
int idx = 0;
for (Staff* staff : *part->staves()) {
for (int voice = 0; voice < VOICES; ++voice) {
if (!voiceButtons.value(idx)) {
QToolButton* tb = new QToolButton;
tb->setText(QString("%1").arg(voice+1));
tb->setCheckable(true);
tb->setChecked(staff->playbackVoice(voice));
tb->setFocusPolicy(Qt::ClickFocus);
tb->setToolButtonStyle(Qt::ToolButtonTextOnly);
QPalette pal(tb->palette());
pal.setColor(QPalette::Base, MScore::selectColor[voice]);
tb->setPalette(pal);
hb->addWidget(tb);
voiceButtons.append(tb);
connect(tb, SIGNAL(clicked()), SLOT(playbackVoiceChanged()));
}
++idx;
}
hb->addStretch(5);
}
while (voiceButtons.value(idx)) {
QToolButton* tb = voiceButtons.value(idx);
if (!tb)
break;
voiceButtons.takeAt(idx);
delete tb;
}
}
//---------------------------------------------------------
// playbackVoiceChanged
//---------------------------------------------------------
void PartEdit::playbackVoiceChanged()
{
int idx = 0;
Score* score = part->score();
score->startCmd();
for (Staff* staff : *part->staves()) {
for (int voice = 0; voice < VOICES; ++voice) {
QToolButton* tb = voiceButtons[idx];
bool val = tb->isChecked();
if (val != staff->playbackVoice(voice)) {
switch (voice) {
case 0:
printf("undo\n");
staff->undoChangeProperty(Pid::PLAYBACK_VOICE1, val);
break;
case 1:
staff->undoChangeProperty(Pid::PLAYBACK_VOICE2, val);
break;
case 2:
staff->undoChangeProperty(Pid::PLAYBACK_VOICE3, val);
break;
case 3:
staff->undoChangeProperty(Pid::PLAYBACK_VOICE4, val);
break;
}
}
++idx;
}
}
score->endCmd();
}
//0 to 100
char userRangeToVolume(double v) { return (char)qBound(0, (int)(v / 100.0 * 128.0), 127); }
//-180 to 180
char userRangeToPan(double v) { return (char)qBound(0, (int)((v / 360.0) * 128.0), 127); }
//0 to 100
char userRangeToChorus(double v) { return (char)qBound(0, (int)(v / 100.0 * 128.0), 127); }
//0 to 100
char userRangeToReverb(double v) { return (char)qBound(0, (int)(v / 100.0 * 128.0), 127); }
//---------------------------------------------------------
// Mixer
//---------------------------------------------------------
Mixer::Mixer(QWidget* parent)
: QScrollArea(parent)
: QWidget(parent, Qt::Dialog),
showExpanded(false),
trackHolder(0)
{
setupUi(this);
setObjectName("Mixer");
setWidgetResizable(true);
setWindowFlags(Qt::Tool);
setWindowFlags(this->windowFlags() & ~Qt::WindowContextHelpButtonHint);
QWidget* area = new QWidget(this);
vb = new QVBoxLayout;
vb->setMargin(0);
vb->setSpacing(0);
area->setLayout(vb);
setWidget(area);
trackAreaLayout = new QHBoxLayout;
trackAreaLayout->setMargin(0);
trackAreaLayout->setSpacing(0);
trackArea->setLayout(trackAreaLayout);
mixerDetails = new MixerDetails(this);
QGridLayout* detailsLayout = new QGridLayout(this);
detailsLayout->addWidget(mixerDetails);
detailsLayout->setContentsMargins(0, 0, 0, 0);
detailsArea->setLayout(detailsLayout);
//Range in decibels
masterSlider->setMaxValue(0);
masterSlider->setMinValue(minDecibels);
masterSlider->setNumMinorTicks(4);
masterSlider->setNumMajorTicks(3);
masterSlider->setHilightColor(QColor(51, 153, 255));
float decibels = qBound(minDecibels, log10(synti->gain()), 0.0f);
masterSlider->setValue(decibels);
masterSlider->setToolTip(QString("Decibels: %1").arg(decibels));
masterSpin->setMaximum(0);
masterSpin->setMinimum(minDecibels);
masterSpin->setSingleStep(.1);
masterSpin->setValue(decibels);
QIcon iconSliderHead;
iconSliderHead.addFile(QStringLiteral(":/data/icons/mixer-slider-handle-vertical.svg"), QSize(), QIcon::Normal, QIcon::Off);
masterSlider->setSliderHeadIcon(iconSliderHead);
connect(masterSlider, SIGNAL(valueChanged(double)), SLOT(masterVolumeChanged(double)));
connect(masterSpin, SIGNAL(valueChanged(double)), SLOT(masterVolumeChanged(double)));
connect(synti, SIGNAL(gainChanged(float)), SLOT(synthGainChanged(float)));
enablePlay = new EnablePlayForWidget(this);
readSettings();
retranslate(true);
}
//---------------------------------------------------------
// synthGainChanged
//---------------------------------------------------------
void Mixer::synthGainChanged(float val)
{
float decibels = qBound(minDecibels, log10f(synti->gain()), 0.0f);
masterSlider->blockSignals(true);
masterSlider->setValue(decibels);
masterSlider->setToolTip(QString("Decibels: %1").arg(decibels));
masterSlider->blockSignals(false);
masterSpin->blockSignals(true);
masterSpin->setValue(decibels);
masterSpin->blockSignals(false);
}
//---------------------------------------------------------
// masterVolumeChanged
//---------------------------------------------------------
void Mixer::masterVolumeChanged(double decibels)
{
float gain = qBound(0.0f, powf(10, (float)decibels), 1.0f);
synti->setGain(gain);
masterSlider->blockSignals(true);
masterSlider->setValue(decibels);
masterSlider->setToolTip(QString("Decibels: %1").arg(decibels));
masterSlider->blockSignals(false);
masterSpin->blockSignals(true);
masterSpin->setValue(decibels);
masterSpin->blockSignals(false);
}
//---------------------------------------------------------
// retranslate
//---------------------------------------------------------
@ -214,8 +169,8 @@ void Mixer::retranslate(bool firstTime)
{
setWindowTitle(tr("Mixer"));
if (!firstTime) {
for (int i = 0; i < vb->count(); i++) {
PartEdit* p = partEdit(i);
for (int i = 0; i < trackAreaLayout->count(); i++) {
PartEdit* p = getPartAtIndex(i);
if (p) p->retranslateUi(p);
}
}
@ -238,7 +193,7 @@ void Mixer::closeEvent(QCloseEvent* ev)
void Mixer::showEvent(QShowEvent* e)
{
enablePlay->showEvent(e);
QScrollArea::showEvent(e);
QWidget::showEvent(e);
activateWindow();
setFocus();
}
@ -251,9 +206,13 @@ bool Mixer::eventFilter(QObject* obj, QEvent* e)
{
if (enablePlay->eventFilter(obj, e))
return true;
return QScrollArea::eventFilter(obj, e);
return QWidget::eventFilter(obj, e);
}
//---------------------------------------------------------
// keyPressEvent
//---------------------------------------------------------
void Mixer::keyPressEvent(QKeyEvent* ev) {
if (ev->key() == Qt::Key_Escape && ev->modifiers() == Qt::NoModifier) {
close();
@ -268,332 +227,174 @@ void Mixer::keyPressEvent(QKeyEvent* ev) {
void Mixer::changeEvent(QEvent *event)
{
QScrollArea::changeEvent(event);
QWidget::changeEvent(event);
if (event->type() == QEvent::LanguageChange)
retranslate();
}
//---------------------------------------------------------
// updateAll
//---------------------------------------------------------
void Mixer::updateAll(MasterScore* score)
{
cs = score;
int n = -vb->count();
if (n < 0) {
QLayoutItem* wi = vb->itemAt(vb->count()-1);
vb->removeItem(wi);
delete wi;
n += 1;
}
if (cs) {
QList<MidiMapping>* mm = cs->midiMapping();
n += mm->size();
}
while (n < 0) {
QLayoutItem* wi = vb->itemAt(0);
vb->removeItem(wi);
delete wi->widget();
delete wi;
++n;
}
while (n > 0) {
PartEdit* pe = new PartEdit;
connect(pe, SIGNAL(soloChanged(bool)), SLOT(updateSolo(bool)));
vb->addWidget(pe);
--n;
}
vb->addStretch(5);
patchListChanged();
}
//---------------------------------------------------------
// partEdit
//---------------------------------------------------------
PartEdit* Mixer::partEdit(int index)
PartEdit* Mixer::getPartAtIndex(int)
{
if (index < vb->count()) {
QWidgetItem* wi = (QWidgetItem*)(vb->itemAt(index));
return (PartEdit*) wi->widget();
}
return 0;
}
//---------------------------------------------------------
// patchListChanged
// setScore
//---------------------------------------------------------
void Mixer::patchListChanged()
void Mixer::setScore(MasterScore* score)
{
if (!cs)
if (_score != score) {
_score = score;
mixerDetails->setTrack(0);
}
updateTracks();
}
//---------------------------------------------------------
// updateTracks
//---------------------------------------------------------
void Mixer::updateTracks()
{
MixerTrackItem* oldSel = mixerDetails->track().get();
Part* selPart = oldSel ? oldSel->part() : 0;
Channel* selChan = oldSel ? oldSel->chan() : 0;
if (_score && !selPart) {
//If nothing selected, select first available track
if (!_score->parts().isEmpty())
{
selPart = _score->parts()[0];
selChan = selPart->instrument(0)->channel(0);
}
}
if (trackHolder) {
trackAreaLayout->removeWidget(trackHolder);
trackHolder->deleteLater();
trackHolder = 0;
}
trackList.clear();
mixerDetails->setTrack(0);
if (!_score)
return;
int idx = 0;
QList<MidiMapping>* mm = cs->midiMapping();
const QList<MidiPatch*> pl = synti->getPatchInfo();
for (const MidiMapping& m : *mm) {
QLayoutItem* wi = (QWidgetItem*)(vb->itemAt(idx));
if (!wi->widget())
continue;
PartEdit* pe = (PartEdit*)(wi->widget());
bool drum = m.part->instrument()->useDrumset();
pe->patch->clear();
for (const MidiPatch* p : pl) {
if (p->drum == drum || p->synti != "Fluid")
pe->patch->addItem(p->name, QVariant::fromValue<void*>((void*)p));
trackHolder = new QWidget();
QHBoxLayout* holderLayout = new QHBoxLayout();
holderLayout->setContentsMargins(0, 0, 0, 0);
holderLayout->setSpacing(0);
trackHolder->setLayout(holderLayout);
trackAreaLayout->addWidget(trackHolder);
for (Part* part : _score->parts()) {
//Add per part tracks
bool expanded = expandedParts.contains(part);
const InstrumentList* il = part->instruments();
Instrument* proxyInstr = nullptr;
Channel* proxyChan = nullptr;
if (!il->empty()) {
il->begin();
proxyInstr = il->begin()->second;
proxyChan = proxyInstr->channel(0);
}
MixerTrackItemPtr mti = std::make_shared<MixerTrackItem>(
MixerTrackItem::TrackType::PART, part, proxyInstr, proxyChan);
MixerTrackPart* track = new MixerTrackPart(this, mti, expanded);
track->setGroup(this);
trackList.append(track);
holderLayout->addWidget(track);
if (selPart == part &&
(selChan == 0 || !expanded)) {
track->setSelected(true);
mixerDetails->setTrack(mti);
}
if (expanded) {
//Add per channel tracks
const InstrumentList* il = part->instruments();
for (auto it = il->begin(); it != il->end(); ++it) {
Instrument* instr = it->second;
for (int i = 0; i < instr->channel().size(); ++i) {
Channel *chan = instr->channel()[i];
MixerTrackItemPtr mti = std::make_shared<MixerTrackItem>(
MixerTrackItem::TrackType::CHANNEL, part, instr, chan);
// MixerTrackItemPtr mti = new MixerTrackItem(
// MixerTrackItem::TrackType::CHANNEL, part, instr, chan);
MixerTrackChannel* track = new MixerTrackChannel(this, mti);
track->setGroup(this);
trackList.append(track);
holderLayout->addWidget(track);
if (selPart == part &&
selChan == chan) {
track->setSelected(true);
mixerDetails->setTrack(mti);
}
}
}
}
pe->setPart(m.part, m.articulation);
idx++;
}
// Update solo & mute only after creating all controls (we need to sync all controls)
idx = 0;
for (const MidiMapping& m : *mm) {
QLayoutItem* wi = (QWidgetItem*)(vb->itemAt(idx));
if (!wi->widget())
continue;
PartEdit* pe = (PartEdit*)(wi->widget());
pe->mute->setChecked(m.articulation->mute);
pe->solo->setChecked(m.articulation->solo);
idx++;
}
holderLayout->addSpacerItem(new QSpacerItem(1, 1, QSizePolicy::Expanding, QSizePolicy::Fixed));
update();
}
//---------------------------------------------------------
// midiPrefsChanged
//---------------------------------------------------------
void Mixer::midiPrefsChanged(bool showMidiControls)
void Mixer::midiPrefsChanged(bool)
{
if (!cs)
return;
for (int i = 0; i < vb->count(); i++ ){
QWidgetItem* wi = (QWidgetItem*)(vb->itemAt(i));
PartEdit* pe = (PartEdit*)(wi->widget());
pe->channelLabel ->setVisible(showMidiControls);
pe->portLabel ->setVisible(showMidiControls);
pe->channelSpinBox->setVisible(showMidiControls);
pe->portSpinBox ->setVisible(showMidiControls);
if (!showMidiControls)
pe->hboxLayout->setSpacing(20);
else
pe->hboxLayout->setSpacing(5);
}
updateTracks();
}
//---------------------------------------------------------
// showMixer
// notifyTrackSelected
//---------------------------------------------------------
void MuseScore::showMixer(bool val)
void Mixer::expandToggled(Part* part, bool expanded)
{
if (!cs)
return;
if (expanded)
expandedParts.insert(part);
else
expandedParts.remove(part);
QAction* a = getAction("toggle-mixer");
if (mixer == 0) {
mixer = new Mixer(this);
mscore->stackUnder(mixer);
if (synthControl)
connect(synthControl, SIGNAL(soundFontChanged()), mixer, SLOT(patchListChanged()));
connect(synti, SIGNAL(soundFontChanged()), mixer, SLOT(patchListChanged()));
connect(mixer, SIGNAL(closed(bool)), a, SLOT(setChecked(bool)));
}
mixer->updateAll(cs->masterScore());
mixer->setVisible(val);
updateTracks();
}
//---------------------------------------------------------
// patchChanged
// notifyTrackSelected
//---------------------------------------------------------
void PartEdit::patchChanged(int n, bool syncControls)
void Mixer::notifyTrackSelected(MixerTrack* track)
{
if (part == 0)
return;
const MidiPatch* p = (MidiPatch*)patch->itemData(n, Qt::UserRole).value<void*>();
if (p == 0) {
qDebug("PartEdit::patchChanged: no patch");
return;
}
Score* score = part->score();
if (score) {
score->startCmd();
score->undo(new ChangePatch(score, channel, p));
score->setLayoutAll();
score->endCmd();
}
channel->updateInitList();
sync(syncControls);
}
//---------------------------------------------------------
// volChanged
//---------------------------------------------------------
void PartEdit::volChanged(double val, bool syncControls)
{
int iv = lrint(val);
seq->setController(channel->channel, CTRL_VOLUME, iv);
channel->volume = iv;
channel->updateInitList();
sync(syncControls);
}
//---------------------------------------------------------
// panChanged
//---------------------------------------------------------
void PartEdit::panChanged(double val, bool syncControls)
{
int iv = lrint(val);
seq->setController(channel->channel, CTRL_PANPOT, iv);
channel->pan = iv;
channel->updateInitList();
sync(syncControls);
}
//---------------------------------------------------------
// reverbChanged
//---------------------------------------------------------
void PartEdit::reverbChanged(double val, bool syncControls)
{
int iv = lrint(val);
seq->setController(channel->channel, CTRL_REVERB_SEND, iv);
channel->reverb = iv;
channel->updateInitList();
sync(syncControls);
}
//---------------------------------------------------------
// chorusChanged
//---------------------------------------------------------
void PartEdit::chorusChanged(double val, bool syncControls)
{
int iv = lrint(val);
seq->setController(channel->channel, CTRL_CHORUS_SEND, iv);
channel->chorus = iv;
channel->updateInitList();
sync(syncControls);
}
//---------------------------------------------------------
// muteChanged
//---------------------------------------------------------
void PartEdit::muteChanged(bool val, bool syncControls)
{
if (val)
seq->stopNotes(channel->channel);
channel->mute = val;
sync(syncControls);
}
//---------------------------------------------------------
// soloToggled
//---------------------------------------------------------
void PartEdit::soloToggled(bool val, bool syncControls)
{
channel->solo = val;
channel->soloMute = !val;
if (val) {
mute->setChecked(false);
for (Part* p : part->score()->parts()) {
const InstrumentList* il = p->instruments();
for (auto i = il->begin(); i != il->end(); ++i) {
const Instrument* instr = i->second;
for (Channel* a : instr->channel()) {
a->soloMute = (channel != a && !a->solo);
a->solo = (channel == a || a->solo);
if (a->soloMute)
seq->stopNotes(a->channel);
}
}
}
emit soloChanged(true);
}
else { //do nothing except if it's the last solo to be switched off
bool found = false;
for (Part* p : part->score()->parts()) {
const InstrumentList* il = p->instruments();
for (auto i = il->begin(); i != il->end(); ++i) {
const Instrument* instr = i->second;
for (Channel* a : instr->channel()) {
if (a->solo){
found = true;
break;
}
}
}
}
if (!found){
foreach(Part* p, part->score()->parts()) {
const InstrumentList* il = p->instruments();
for (auto i = il->begin(); i != il->end(); ++i) {
const Instrument* instr = i->second;
for (Channel* a : instr->channel()) {
a->soloMute = false;
a->solo = false;
}
}
}
emit soloChanged(false);
for (MixerTrack *mt: trackList) {
if (!(mt->mti()->part() == track->mti()->part() &&
mt->mti()->chan() == track->mti()->chan())) {
mt->setSelected(false);
}
}
sync(syncControls);
mixerDetails->setTrack(track->mti());
// selPart = track->mti()->part();
// selChan = track->mti()->chan();
}
//---------------------------------------------------------
// drumsetToggled
//---------------------------------------------------------
void PartEdit::drumsetToggled(bool val, bool syncControls)
{
if (part == 0)
return;
Score* score = part->score();
score->startCmd();
part->undoChangeProperty(Pid::USE_DRUMSET, val);
patch->clear();
const QList<MidiPatch*> pl = synti->getPatchInfo();
for (const MidiPatch* p : pl) {
if (p->drum == val)
patch->addItem(p->name, QVariant::fromValue<void*>((void*)p));
}
// switch to first instrument
const MidiPatch* p = (MidiPatch*)patch->itemData(0, Qt::UserRole).value<void*>();
if (p == 0) {
qDebug("PartEdit::patchChanged: no patch");
return;
}
score->undo(new ChangePatch(score, channel, p));
score->setLayoutAll();
score->endCmd();
sync(syncControls);
}
//---------------------------------------------------------
// updateSolo
//---------------------------------------------------------
void Mixer::updateSolo(bool val)
{
for (int i = 0; i < vb->count(); i++ ){
QWidgetItem* wi = (QWidgetItem*)(vb->itemAt(i));
PartEdit* pe = (PartEdit*)(wi->widget());
if (pe)
pe->mute->setEnabled(!val);
}
}
//---------------------------------------------------------
// writeSettings
@ -614,192 +415,27 @@ void Mixer::readSettings()
MuseScore::restoreGeometry(this);
}
//---------------------------------------------------------
// sync
// synchronizes controls with same MIDI port and channel
// showMixer
//---------------------------------------------------------
void PartEdit::sync(bool syncControls)
void MuseScore::showMixer(bool val)
{
if (!syncControls)
if (!cs)
return;
int count = this->parentWidget()->layout()->count();
for(int i = 0; i < count; i++) {
QWidgetItem* wi = (QWidgetItem*)(this->parentWidget()->layout()->itemAt(i));
PartEdit* pe = (PartEdit*)(wi->widget());
if (pe != 0 && pe != this
&& this->channelSpinBox->value() == pe->channelSpinBox->value()
&& this->portSpinBox->value() == pe->portSpinBox->value()) {
if (volume->value() != pe->volume->value()) {
_setValue(pe->volume, this->volume->value());
emit pe->volChanged(this->volume->value(), false);
}
if (pan->value() != pe->pan->value()) {
_setValue(pe->pan, this->pan->value());
emit pe->panChanged(this->pan->value(), false);
}
if (reverb->value() != pe->reverb->value()) {
_setValue(pe->reverb, this->reverb->value());
emit pe->reverbChanged(this->reverb->value(), false);
}
if (chorus->value() != pe->chorus->value()) {
_setValue(pe->chorus, this->chorus->value());
emit pe->chorusChanged(this->chorus->value(), false);
}
if (mute->isChecked() != pe->mute->isChecked()) {
_setChecked(pe->mute, channel->mute);
emit pe->muteChanged(channel->mute, false);
}
if (solo->isChecked() != pe->solo->isChecked()) {
_setChecked(pe->solo, channel->solo);
emit pe->soloToggled(channel->solo, false);
}
if (drumset->isChecked() != pe->drumset->isChecked()) {
_setChecked(pe->drumset, drumset->isChecked());
emit pe->drumsetToggled(drumset->isChecked(), false);
}
if (patch->currentIndex() != pe->patch->currentIndex()) {
pe->patch->blockSignals(true);
pe->patch->setCurrentIndex(this->patch->currentIndex());
pe->patch->blockSignals(false);
}
}
QAction* a = getAction("toggle-mixer");
if (mixer == 0) {
mixer = new Mixer(this);
mscore->stackUnder(mixer);
if (synthControl)
connect(synthControl, SIGNAL(soundFontChanged()), mixer, SLOT(patchListChanged()));
connect(synti, SIGNAL(soundFontChanged()), mixer, SLOT(patchListChanged()));
connect(mixer, SIGNAL(closed(bool)), a, SLOT(setChecked(bool)));
}
mixer->setScore(cs->masterScore());
mixer->setVisible(val);
}
//---------------------------------------------------------
// midiChannelChanged
// handles MIDI port & channel change
//---------------------------------------------------------
void PartEdit::midiChannelChanged(int)
{
if (part == 0)
return;
seq->stopNotes(channel->channel);
int p = portSpinBox->value() - 1;
int c = channelSpinBox->value() - 1;
// 1 is for going up, -1 for going down
int direction = copysign(1, c - part->masterScore()->midiMapping(channel->channel)->channel);
// Channel 9 is special for drums
if (part->instrument()->useDrumset() && c != 9) {
_setValue(channelSpinBox, 10);
return;
}
else if (!part->instrument()->useDrumset() && c == 9) {
c = 9 + direction;
}
if (c == 16) {
c = 0;
p++;
}
int newChannel = p*16+c;
// If there is an instrument with the same MIDI port and channel, sync this instrument to a found one
bool needSync = true;
int elementsInMixer = parentWidget()->layout()->count();
for (int i = 0; i < elementsInMixer; i++) {
QWidgetItem* wi = (QWidgetItem*)(this->parentWidget()->layout()->itemAt(i));
PartEdit* pe = (PartEdit*)(wi->widget());
if (pe != 0 && pe != this
&& pe->channelSpinBox->value() == this->channelSpinBox->value()
&& pe->portSpinBox->value() == this->portSpinBox->value()) {
// Show datails if parameters are different
QString detailedText;
if (patch->currentIndex() != pe->patch->currentIndex())
detailedText += QString(tr("Sound: '%1'' vs '%2'\n")).arg(patch->itemText(patch->currentIndex()), pe->patch->itemText(pe->patch->currentIndex()));
if (this->volume->value() != pe->volume->value())
detailedText += QString(tr("Volume: %1 vs %2\n")).arg(QString::number(volume->value()), QString::number(pe->volume->value()));
if (this->pan->value() != pe->pan->value())
detailedText += QString(tr("Pan: %1 vs %2\n")).arg(QString::number(pan->value()), QString::number(pe->pan->value()));
if (this->reverb->value() != pe->reverb->value())
detailedText += QString(tr("Reverb: %1 vs %2\n")).arg(QString::number(reverb->value()), QString::number(pe->reverb->value()));
if (this->chorus->value() != pe->chorus->value())
detailedText += QString(tr("Chorus: %1 vs %2\n")).arg(QString::number(chorus->value()), QString::number(pe->chorus->value()));
if (this->solo->isChecked() != pe->solo->isChecked())
detailedText += QString(tr("Solo: %1 vs %2\n")).arg(solo->isChecked()?"Yes":"No", pe->solo->isChecked()?"Yes":"No");
if (this->mute->isChecked() != pe->mute->isChecked())
detailedText += QString(tr("Mute: %1 vs %2\n")).arg(mute->isChecked()?"Yes":"No", pe->mute->isChecked()?"Yes":"No");
if (!detailedText.isEmpty())
detailedText = QString(tr("Instrument '%1' Instrument '%2'\n")).arg(this->partName->text(), pe->partName->text())+ detailedText;
QMessageBox msgBox;
msgBox.setIcon(QMessageBox::Warning);
QString text = QString(tr("There is already an instrument '%1' with MIDI port = %2 and channel = %3.")).arg(pe->partName->text(), QString::number(pe->portSpinBox->value()), QString::number(pe->channelSpinBox->value()));
msgBox.setText(text);
msgBox.setInformativeText(tr("Do you want to synchronize current instrument with an existing one?"));
msgBox.setDetailedText(detailedText);
msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
QPushButton *assignFreeChannel = msgBox.addButton(tr("Assign next free MIDI channel"), QMessageBox::HelpRole);
msgBox.setDefaultButton(QMessageBox::Ok);
if (msgBox.exec() == QMessageBox::Cancel) {
_setValue(channelSpinBox, part->masterScore()->midiMapping(channel->channel)->channel + 1);
_setValue(portSpinBox, part->masterScore()->midiMapping(channel->channel)->port + 1);
needSync = false;
break;
}
if (msgBox.clickedButton() == assignFreeChannel) {
newChannel = part->masterScore()->getNextFreeMidiMapping();
break;
}
// Sync
_setValue(channelSpinBox, newChannel % 16 + 1);
_setValue(portSpinBox, newChannel / 16 + 1);
part->masterScore()->midiMapping(channel->channel)->channel = newChannel % 16;
part->masterScore()->midiMapping(channel->channel)->port = newChannel / 16;
channel->volume = lrint(pe->volume->value());
channel->pan = lrint(pe->pan->value());
channel->reverb = lrint(pe->reverb->value());
channel->chorus = lrint(pe->chorus->value());
channel->mute = pe->mute->isChecked();
channel->solo = pe->solo->isChecked();
MidiPatch* newPatch = (MidiPatch*)pe->patch->itemData(pe->patch->currentIndex(), Qt::UserRole).value<void*>();
if (newPatch == 0)
return;
patch->setCurrentIndex(pe->patch->currentIndex());
channel->program = newPatch->prog;
channel->bank = newPatch->bank;
channel->synti = newPatch->synti;
part->masterScore()->setSoloMute();
part->score()->setInstrumentsChanged(true);
part->score()->setLayoutAll();
break;
}
}
channel->updateInitList();
if (needSync) {
_setValue(channelSpinBox, newChannel % 16 + 1);
_setValue(portSpinBox, newChannel / 16 + 1);
part->masterScore()->midiMapping(channel->channel)->channel = newChannel % 16;
part->masterScore()->midiMapping(channel->channel)->port = newChannel / 16;
part->score()->setInstrumentsChanged(true);
part->score()->setLayoutAll();
seq->initInstruments();
}
else {
// Initializing an instrument with new channel
foreach(const MidiCoreEvent& e, channel->init) {
if (e.type() == ME_INVALID)
continue;
NPlayEvent event(e.type(), channel->channel, e.dataA(), e.dataB());
seq->sendEvent(event);
}
}
// Update MIDI Out ports
int maxPort = max(p, part->score()->masterScore()->midiPortCount());
part->score()->masterScore()->setMidiPortCount(maxPort);
if (seq->driver() && (preferences.getBool(PREF_IO_JACK_USEJACKMIDI) || preferences.getBool(PREF_IO_ALSA_USEALSAAUDIO)))
seq->driver()->updateOutPortCount(maxPort + 1);
}
}

View file

@ -20,89 +20,87 @@
#ifndef __ILEDIT_H__
#define __ILEDIT_H__
#include "ui_parteditbase.h"
#include "ui_mixer.h"
#include "libmscore/instrument.h"
#include "enableplayforwidget.h"
#include "mixertrackgroup.h"
#include <QWidget>
#include <QScrollArea>
#include <QList>
namespace Ms {
class Score;
struct Channel;
class Channel;
class Part;
class PartEdit;
class MixerDetails;
class MixerTrack;
class MidiMapping;
//---------------------------------------------------------
// PartEdit
//---------------------------------------------------------
double volumeToUserRange(char v);
double panToUserRange(char v);
double chorusToUserRange(char v);
double reverbToUserRange(char v);
class PartEdit : public QWidget, public Ui::PartEditBase {
Q_OBJECT
//0 to 100
char userRangeToVolume(double v);
//-180 to 180
char userRangeToPan(double v);
//0 to 100
char userRangeToChorus(double v);
//0 to 100
char userRangeToReverb(double v);
Channel* channel;
Part* part;
QList<QToolButton*> voiceButtons;
private slots:
void patchChanged(int, bool syncControls = true);
void volChanged(double, bool syncControls = true);
void panChanged(double, bool syncControls = true);
void reverbChanged(double, bool syncControls = true);
void chorusChanged(double, bool syncControls = true);
void muteChanged(bool, bool syncControls = true);
void soloToggled(bool, bool syncControls = true);
void drumsetToggled(bool, bool syncControls = true);
void midiChannelChanged(int);
void sync(bool syncControls);
void expandToggled(bool);
void playbackVoiceChanged();
public slots:
signals:
void soloChanged(bool);
public:
PartEdit(QWidget* parent = 0);
void setPart(Part*, Channel*);
};
//---------------------------------------------------------
// Mixer
//---------------------------------------------------------
class Mixer : public QScrollArea
class Mixer : public QWidget, public Ui::Mixer, public MixerTrackGroup
{
Q_OBJECT
MasterScore* cs;
MasterScore* _score;
QScrollArea* sa;
QVBoxLayout* vb;
QHBoxLayout* trackAreaLayout;
EnablePlayForWidget* enablePlay;
virtual void closeEvent(QCloseEvent*);
MixerDetails* mixerDetails;
bool showExpanded;
QSet<Part*> expandedParts;
QWidget* trackHolder;
QList<MixerTrack*> trackList;
virtual void closeEvent(QCloseEvent*) override;
virtual void showEvent(QShowEvent*) override;
virtual bool eventFilter(QObject*, QEvent*) override;
virtual void keyPressEvent(QKeyEvent*) override;
void readSettings();
private slots:
void updateSolo(bool);
void updateTracks();
public slots:
void patchListChanged();
void midiPrefsChanged(bool showMidiControls);
void masterVolumeChanged(double val);
void synthGainChanged(float val);
signals:
void closed(bool);
protected:
virtual void changeEvent(QEvent *event);
virtual void changeEvent(QEvent *event) override;
void retranslate(bool firstTime = false);
public:
Mixer(QWidget* parent);
void updateAll(MasterScore*);
PartEdit* partEdit(int index);
void setScore(MasterScore*);
PartEdit* getPartAtIndex(int index);
void writeSettings();
void expandToggled(Part* part, bool expanded) override;
void notifyTrackSelected(MixerTrack* track) override;
};

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>PartEditBase</class>
<widget class="QWidget" name="PartEditBase">
<class>Mixer</class>
<widget class="QWidget" name="Mixer">
<property name="enabled">
<bool>true</bool>
</property>
@ -9,8 +9,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>730</width>
<height>475</height>
<width>648</width>
<height>620</height>
</rect>
</property>
<property name="sizePolicy">
@ -19,604 +19,131 @@
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>620</height>
</size>
</property>
<property name="focusPolicy">
<enum>Qt::ClickFocus</enum>
</property>
<property name="windowTitle">
<string/>
</property>
<layout class="QVBoxLayout">
<property name="spacing">
<number>3</number>
</property>
<property name="leftMargin">
<number>1</number>
</property>
<property name="topMargin">
<number>1</number>
</property>
<property name="rightMargin">
<number>1</number>
</property>
<property name="bottomMargin">
<number>1</number>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QGroupBox" name="groupBox">
<widget class="QWidget" name="detailsArea" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string/>
</property>
<property name="flat">
<bool>true</bool>
</property>
<layout class="QGridLayout">
<property name="leftMargin">
<number>1</number>
</property>
<property name="topMargin">
<number>1</number>
</property>
<property name="rightMargin">
<number>1</number>
</property>
<property name="bottomMargin">
<number>1</number>
</property>
<property name="spacing">
<number>0</number>
</property>
<item row="0" column="0">
<widget class="QLineEdit" name="partName">
<property name="toolTip">
<string>Part name</string>
</property>
<property name="accessibleName">
<string>Part Name</string>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="1" rowspan="4">
<layout class="QGridLayout">
<property name="sizeConstraint">
<enum>QLayout::SetFixedSize</enum>
</property>
<property name="spacing">
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QWidget" name="widgetMaster" native="true">
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="leftMargin">
<number>0</number>
</property>
<item row="0" column="0">
<widget class="Awl::Knob" name="volume" native="true">
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>9</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="Awl::StyledSlider" name="masterSlider" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Ignored">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>50</width>
<height>16777215</height>
</size>
</property>
<property name="focusPolicy">
<enum>Qt::TabFocus</enum>
</property>
<property name="toolTip">
<string>Volume</string>
</property>
<property name="accessibleName">
<string>Volume</string>
</property>
<property name="accessibleDescription">
<string>Use arrows to modify</string>
</property>
<property name="invertedAppearance" stdset="0">
<bool>false</bool>
</property>
<property name="scaleWidth" stdset="0">
<number>5</number>
</property>
<property name="scaleValueColor" stdset="0">
<color>
<red>238</red>
<green>80</green>
<blue>54</blue>
</color>
</property>
<property name="maxValue" stdset="0">
<double>127.000000000000000</double>
</property>
<property name="lineStep" stdset="0">
<double>1.000000000000000</double>
</property>
<property name="pageStep" stdset="0">
<double>10.000000000000000</double>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="Awl::MidiPanKnob" name="pan" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Ignored">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>50</width>
<height>16777215</height>
</size>
</property>
<property name="focusPolicy">
<enum>Qt::TabFocus</enum>
</property>
<property name="toolTip">
<string>Panorama position</string>
</property>
<property name="accessibleName">
<string>Panorama position</string>
</property>
<property name="accessibleDescription">
<string>Use arrows to modify</string>
</property>
<property name="scaleWidth" stdset="0">
<number>5</number>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="Awl::Knob" name="reverb" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Ignored">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>50</width>
<height>16777215</height>
</size>
</property>
<property name="focusPolicy">
<enum>Qt::TabFocus</enum>
</property>
<property name="toolTip">
<string>Reverb</string>
</property>
<property name="accessibleName">
<string>Reverb</string>
</property>
<property name="accessibleDescription">
<string>Use arrows to modify</string>
</property>
<property name="scaleWidth" stdset="0">
<number>5</number>
</property>
<property name="maxValue" stdset="0">
<double>127.000000000000000</double>
</property>
<property name="lineStep" stdset="0">
<double>1.000000000000000</double>
</property>
<property name="pageStep" stdset="0">
<double>10.000000000000000</double>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="Awl::Knob" name="chorus" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Ignored">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>50</width>
<height>16777215</height>
</size>
</property>
<property name="focusPolicy">
<enum>Qt::TabFocus</enum>
</property>
<property name="toolTip">
<string>Chorus</string>
</property>
<property name="accessibleName">
<string>Chorus</string>
</property>
<property name="accessibleDescription">
<string>Use arrows to modify</string>
</property>
<property name="scaleWidth" stdset="0">
<number>5</number>
</property>
<property name="maxValue" stdset="0">
<double>127.000000000000000</double>
</property>
<property name="lineStep" stdset="0">
<double>1.000000000000000</double>
</property>
<property name="pageStep" stdset="0">
<double>10.000000000000000</double>
</property>
</widget>
</item>
<item row="1" column="0">
<item>
<widget class="QLabel" name="label">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>50</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Vol</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
<string>Master Gain</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="label_3">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>50</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Pan</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QLabel" name="label_4">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>50</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Rev</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QLabel" name="label_5">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>50</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Cho</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
<item>
<widget class="QDoubleSpinBox" name="masterSpin"/>
</item>
</layout>
</item>
<item row="2" column="0">
<layout class="QHBoxLayout" name="midiportchannel">
<property name="spacing">
<number>5</number>
</widget>
</item>
<item>
<widget class="QScrollArea" name="tracks_scrollArea">
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>554</width>
<height>582</height>
</rect>
</property>
</layout>
</item>
<item row="1" column="0">
<layout class="QHBoxLayout">
<item>
<widget class="QToolButton" name="expand">
<property name="statusTip">
<string>show details</string>
</property>
<property name="text">
<string>+</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="mute">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>40</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>mute</string>
</property>
<property name="accessibleName">
<string>Mute</string>
</property>
<property name="text">
<string>M</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="solo">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>40</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>solo</string>
</property>
<property name="accessibleName">
<string>Solo</string>
</property>
<property name="text">
<string>S</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="patch">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>MIDI sound</string>
</property>
<property name="accessibleName">
<string>Sound</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="drumset">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Drumset</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="4" column="0" colspan="2">
<widget class="QWidget" name="details" native="true">
<property name="minimumSize">
<size>
<width>0</width>
<height>42</height>
</size>
</property>
<layout class="QGridLayout" name="gridLayout2">
<item row="0" column="1">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Midi: </string>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QWidget" name="trackArea" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLabel" name="portLabel">
<property name="text">
<string>Port:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Voice Playback:</string>
</property>
</widget>
</item>
<item row="0" column="4">
<widget class="QLabel" name="channelLabel">
<property name="text">
<string>Channel:</string>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QSpinBox" name="portSpinBox">
<property name="minimum">
<number>1</number>
</property>
</widget>
</item>
<item row="0" column="5">
<widget class="QSpinBox" name="channelSpinBox">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>17</number>
</property>
</widget>
</item>
<item row="1" column="2" colspan="4">
<layout class="QHBoxLayout" name="voiceButtonBox"/>
</item>
<item row="0" column="6">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>134</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="0">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>Awl::Knob</class>
<class>Awl::StyledSlider</class>
<extends>QWidget</extends>
<header>awl/knob.h</header>
</customwidget>
<customwidget>
<class>Awl::MidiPanKnob</class>
<extends>Awl::Knob</extends>
<header>awl/midipanknob.h</header>
<header>awl/styledslider.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>partName</tabstop>
<tabstop>patch</tabstop>
<tabstop>volume</tabstop>
<tabstop>pan</tabstop>
<tabstop>reverb</tabstop>
<tabstop>chorus</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>

519
mscore/mixerdetails.cpp Normal file
View file

@ -0,0 +1,519 @@
//=============================================================================
// MuseScore
// Linux Music Score Editor
// $Id: mixer.h 4388 2011-06-18 13:17:58Z wschweer $
//
// Copyright (C) 2002-2016 Werner Schweer and others
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.
//
// This program 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 this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#include "mixerdetails.h"
#include "musescore.h"
#include "libmscore/score.h"
#include "libmscore/part.h"
#include "mixer.h"
#include "mixertrack.h"
#include "mixertrackitem.h"
#include "seq.h"
#include "libmscore/undo.h"
#include "synthcontrol.h"
#include "synthesizer/msynthesizer.h"
#include "preferences.h"
namespace Ms {
//---------------------------------------------------------
// MixerDetails
//---------------------------------------------------------
MixerDetails::MixerDetails(QWidget *parent) :
QWidget(parent), _mti(0)
{
setupUi(this);
connect(partNameLineEdit, SIGNAL(editingFinished()), SLOT(partNameChanged()));
connect(trackColorLabel, SIGNAL(colorChanged(QColor)), SLOT(trackColorChanged(QColor)));
connect(patchCombo, SIGNAL(activated(int)), SLOT(patchChanged(int)));
connect(volumeSlider, &QSlider::valueChanged, this, &MixerDetails::volumeChanged);
connect(volumeSpinBox, SIGNAL(valueChanged(double)), SLOT(volumeChanged(double)));
connect(panSlider, &QSlider::valueChanged, this, &MixerDetails::panChanged);
connect(panSpinBox, SIGNAL(valueChanged(double)), SLOT(panChanged(double)));
connect(chorusSlider, &QSlider::valueChanged, this, &MixerDetails::chorusChanged);
connect(chorusSpinBox, SIGNAL(valueChanged(double)), SLOT(chorusChanged(double)));
connect(reverbSlider, &QSlider::valueChanged, this, &MixerDetails::reverbChanged);
connect(reverbSpinBox, SIGNAL(valueChanged(double)), SLOT(reverbChanged(double)));
connect(portSpinBox, SIGNAL(valueChanged(int)), SLOT(midiChannelChanged(int)));
connect(channelSpinBox, SIGNAL(valueChanged(int)), SLOT(midiChannelChanged(int)));
connect(drumkitCheck, SIGNAL(toggled(bool)), SLOT(drumkitToggled(bool)));
updateFromTrack();
}
//---------------------------------------------------------
// ~MixerDetails
//---------------------------------------------------------
MixerDetails::~MixerDetails()
{
if (_mti) {
//Remove old attachment
_mti->midiMap()->articulation->removeListener(this);
}
}
//---------------------------------------------------------
// setTrack
//---------------------------------------------------------
void MixerDetails::setTrack(MixerTrackItemPtr track)
{
if (_mti) {
//Remove old attachment
Channel* chan = _mti->focusedChan();
chan->removeListener(this);
}
_mti = track;
if (_mti) {
//Listen to new track
Channel* chan = _mti->focusedChan();
chan->addListener(this);
}
updateFromTrack();
}
//---------------------------------------------------------
// updateFromTrack
//---------------------------------------------------------
void MixerDetails::updateFromTrack()
{
if (!_mti) {
drumkitCheck->setChecked(false);
patchCombo->clear();
partNameLineEdit->setText("");
channelLabel->setText("");
volumeSlider->setValue(0);
volumeSpinBox->setValue(0);
panSlider->setValue(0);
panSpinBox->setValue(0);
reverbSlider->setValue(0);
reverbSpinBox->setValue(0);
chorusSlider->setValue(0);
chorusSpinBox->setValue(0);
portSpinBox->setValue(0);
channelSpinBox->setValue(0);
trackColorLabel->setColor(QColor());
drumkitCheck->setEnabled(false);
patchCombo->setEnabled(false);
partNameLineEdit->setEnabled(false);
volumeSlider->setEnabled(false);
volumeSpinBox->setEnabled(false);
panSlider->setEnabled(false);
panSpinBox->setEnabled(false);
reverbSlider->setEnabled(false);
reverbSpinBox->setEnabled(false);
chorusSlider->setEnabled(false);
chorusSpinBox->setEnabled(false);
portSpinBox->setEnabled(false);
channelSpinBox->setEnabled(false);
trackColorLabel->setEnabled(false);
labelName->setEnabled(false);
labelChannel->setEnabled(false);
labelChannel_2->setEnabled(false);
labelChorus->setEnabled(false);
labelPan->setEnabled(false);
labelPatch->setEnabled(false);
labelPort->setEnabled(false);
labelReverb->setEnabled(false);
labelVolume->setEnabled(false);
return;
}
drumkitCheck->setEnabled(true);
patchCombo->setEnabled(true);
partNameLineEdit->setEnabled(true);
volumeSlider->setEnabled(true);
volumeSpinBox->setEnabled(true);
panSlider->setEnabled(true);
panSpinBox->setEnabled(true);
reverbSlider->setEnabled(true);
reverbSpinBox->setEnabled(true);
chorusSlider->setEnabled(true);
chorusSpinBox->setEnabled(true);
portSpinBox->setEnabled(true);
channelSpinBox->setEnabled(true);
trackColorLabel->setEnabled(true);
labelName->setEnabled(true);
labelChannel->setEnabled(true);
labelChannel_2->setEnabled(true);
labelChorus->setEnabled(true);
labelPan->setEnabled(true);
labelPatch->setEnabled(true);
labelPort->setEnabled(true);
labelReverb->setEnabled(true);
labelVolume->setEnabled(true);
MidiMapping* midiMap = _mti->midiMap();
Part* part = _mti->part();
Channel* chan = _mti->focusedChan();
//Check if drumkit
bool drum = midiMap->part->instrument()->useDrumset();
drumkitCheck->blockSignals(true);
drumkitCheck->setChecked(drum);
drumkitCheck->blockSignals(false);
//Populate patch combo
patchCombo->blockSignals(true);
patchCombo->clear();
const QList<MidiPatch*> pl = synti->getPatchInfo();
int patchIndex = 0;
for (const MidiPatch* p : pl) {
if (p->drum == drum || p->synti != "Fluid") {
patchCombo->addItem(p->name, QVariant::fromValue<void*>((void*)p));
if (p->bank == chan->bank() && p->prog == chan->program())
patchIndex = patchCombo->count() - 1;
}
}
patchCombo->setCurrentIndex(patchIndex);
patchCombo->blockSignals(false);
QString partName = part->partName();
if (!chan->name().isEmpty())
channelLabel->setText(qApp->translate("InstrumentsXML", chan->name().toUtf8().data()));
else
channelLabel->setText("");
partNameLineEdit->setText(partName);
partNameLineEdit->setToolTip(partName);
trackColorLabel->blockSignals(true);
volumeSlider->blockSignals(true);
volumeSpinBox->blockSignals(true);
panSlider->blockSignals(true);
panSpinBox->blockSignals(true);
reverbSlider->blockSignals(true);
reverbSpinBox->blockSignals(true);
chorusSlider->blockSignals(true);
chorusSpinBox->blockSignals(true);
trackColorLabel->setColor(QColor(_mti->color() | 0xff000000));
volumeSlider->setValue((int)chan->volume());
volumeSpinBox->setValue(chan->volume());
panSlider->setValue((int)chan->pan());
panSpinBox->setValue(chan->pan());
reverbSlider->setValue((int)chan->reverb());
reverbSpinBox->setValue(chan->reverb());
chorusSlider->setValue((int)chan->chorus());
chorusSpinBox->setValue(chan->chorus());
portSpinBox->setValue(part->masterScore()->midiMapping(chan->channel())->port + 1);
channelSpinBox->setValue(part->masterScore()->midiMapping(chan->channel())->channel + 1);
trackColorLabel->blockSignals(false);
volumeSlider->blockSignals(false);
volumeSpinBox->blockSignals(false);
panSlider->blockSignals(false);
panSpinBox->blockSignals(false);
reverbSlider->blockSignals(false);
reverbSpinBox->blockSignals(false);
chorusSlider->blockSignals(false);
chorusSpinBox->blockSignals(false);
}
//---------------------------------------------------------
// partNameChanged
//---------------------------------------------------------
void MixerDetails::partNameChanged()
{
if (!_mti)
return;
QString text = partNameLineEdit->text();
Part* part = _mti->part();
if (part->partName() == text) {
return;
}
Score* score = part->score();
if (score) {
score->startCmd();
score->undo(new ChangePart(part, part->instrument(), text));
score->endCmd();
}
}
//---------------------------------------------------------
// trackColorChanged
//---------------------------------------------------------
void MixerDetails::trackColorChanged(QColor col)
{
Part* part = _mti->midiMap()->part;
Channel* channel = _mti->midiMap()->articulation;
if (trackColorLabel->color() != col) {
trackColorLabel->blockSignals(true);
trackColorLabel->setColor(col);
trackColorLabel->blockSignals(false);
}
_mti->setColor(col.rgb());
}
//---------------------------------------------------------
// disconnectChannelListener
//---------------------------------------------------------
void MixerDetails::disconnectChannelListener()
{
//Channel has been destroyed. Don't remove listener when invoking destructor.
_mti = nullptr;
}
//---------------------------------------------------------
// propertyChanged
//---------------------------------------------------------
void MixerDetails::propertyChanged(Channel::Prop property)
{
if (!_mti)
return;
MidiMapping* _midiMap = _mti->midiMap();
Channel* chan = _midiMap->articulation;
switch (property) {
case Channel::Prop::VOLUME: {
volumeSlider->blockSignals(true);
volumeSpinBox->blockSignals(true);
volumeSlider->setValue((int)chan->volume());
volumeSpinBox->setValue(chan->volume());
volumeSlider->blockSignals(false);
volumeSpinBox->blockSignals(false);
break;
}
case Channel::Prop::PAN: {
panSlider->blockSignals(true);
panSpinBox->blockSignals(true);
panSlider->setValue((int)chan->pan());
panSpinBox->setValue(chan->pan());
panSlider->blockSignals(false);
panSpinBox->blockSignals(false);
break;
}
case Channel::Prop::CHORUS: {
chorusSlider->blockSignals(true);
chorusSpinBox->blockSignals(true);
chorusSlider->setValue((int)chan->chorus());
chorusSpinBox->setValue(chan->chorus());
chorusSlider->blockSignals(false);
chorusSpinBox->blockSignals(false);
break;
}
case Channel::Prop::REVERB: {
reverbSlider->blockSignals(true);
reverbSpinBox->blockSignals(true);
reverbSlider->setValue((int)chan->reverb());
reverbSpinBox->setValue(chan->reverb());
reverbSlider->blockSignals(false);
reverbSpinBox->blockSignals(false);
break;
}
case Channel::Prop::COLOR: {
trackColorChanged(chan->color());
break;
}
}
}
//---------------------------------------------------------
// volumeChanged
//---------------------------------------------------------
void MixerDetails::volumeChanged(double value)
{
if (!_mti)
return;
_mti->setVolume(value);
}
//---------------------------------------------------------
// panChanged
//---------------------------------------------------------
void MixerDetails::panChanged(double value)
{
if (!_mti)
return;
_mti->setPan(value);
}
//---------------------------------------------------------
// reverbChanged
//---------------------------------------------------------
void MixerDetails::reverbChanged(double v)
{
if (!_mti)
return;
_mti->setReverb(v);
}
//---------------------------------------------------------
// chorusChanged
//---------------------------------------------------------
void MixerDetails::chorusChanged(double v)
{
if (!_mti)
return;
_mti->setChorus(v);
}
//---------------------------------------------------------
// patchChanged
//---------------------------------------------------------
void MixerDetails::patchChanged(int n)
{
if (!_mti)
return;
const MidiPatch* p = (MidiPatch*)patchCombo->itemData(n, Qt::UserRole).value<void*>();
if (p == 0) {
qDebug("PartEdit::patchChanged: no patch");
return;
}
Part* part = _mti->midiMap()->part;
Channel* channel = _mti->midiMap()->articulation;
Score* score = part->score();
if (score) {
score->startCmd();
score->undo(new ChangePatch(score, channel, p));
score->setLayoutAll();
score->endCmd();
}
channel->updateInitList();
}
//---------------------------------------------------------
// drumkitToggled
//---------------------------------------------------------
void MixerDetails::drumkitToggled(bool val)
{
if (_mti == 0)
return;
MidiMapping* midiMap = _mti->midiMap();
Part* part = _mti->part();
Channel* channel = _mti->focusedChan();
Instrument *instr;
if (_mti->trackType() == MixerTrackItem::TrackType::CHANNEL)
instr = _mti->instrument();
else
instr = part->instrument(0);
if (instr->useDrumset() == val)
return;
const MidiPatch* newPatch = 0;
const QList<MidiPatch*> pl = synti->getPatchInfo();
for (const MidiPatch* p : pl) {
if (p->drum == val) {
newPatch = p;
break;
}
}
Score* score = part->score();
if (newPatch) {
score->startCmd();
part->undoChangeProperty(Pid::USE_DRUMSET, val);
score->undo(new ChangePatch(score, channel, newPatch));
score->setLayoutAll();
score->endCmd();
}
channel->updateInitList();
}
//---------------------------------------------------------
// midiChannelChanged
// handles MIDI port & channel change
//---------------------------------------------------------
void MixerDetails::midiChannelChanged(int)
{
if (_mti == 0)
return;
Part* part = _mti->part();
Channel* channel = _mti->focusedChan();
seq->stopNotes(channel->channel());
int p = portSpinBox->value() - 1;
int c = channelSpinBox->value() - 1;
MidiMapping* midiMap = _mti->midiMap();
midiMap->port = p;
midiMap->channel = c;
// channel->updateInitList();
part->score()->setInstrumentsChanged(true);
part->score()->setLayoutAll();
seq->initInstruments();
// Update MIDI Out ports
int maxPort = max(p, part->score()->masterScore()->midiPortCount());
part->score()->masterScore()->setMidiPortCount(maxPort);
if (seq->driver() && (preferences.getBool(PREF_IO_JACK_USEJACKMIDI) || preferences.getBool(PREF_IO_ALSA_USEALSAAUDIO)))
seq->driver()->updateOutPortCount(maxPort + 1);
}
}

69
mscore/mixerdetails.h Normal file
View file

@ -0,0 +1,69 @@
//=============================================================================
// MuseScore
// Linux Music Score Editor
// $Id: mixer.h 4388 2011-06-18 13:17:58Z wschweer $
//
// Copyright (C) 2002-2016 Werner Schweer and others
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.
//
// This program 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 this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#ifndef __MIXERDETAILS_H__
#define __MIXERDETAILS_H__
#include "ui_mixerdetails.h"
#include "libmscore/instrument.h"
#include "mixertrackitem.h"
namespace Ms {
class MixerTrackItem;
//---------------------------------------------------------
// MixerDetails
//---------------------------------------------------------
class MixerDetails : public QWidget, public Ui::MixerDetails, public ChannelListener
{
Q_OBJECT
MixerTrackItemPtr _mti;
void updateFromTrack();
public slots:
void partNameChanged();
void trackColorChanged(QColor);
void patchChanged(int);
void volumeChanged(double);
void panChanged(double);
void chorusChanged(double);
void reverbChanged(double);
void drumkitToggled(bool);
void midiChannelChanged(int);
public:
explicit MixerDetails(QWidget *parent);
~MixerDetails() override;
MixerTrackItemPtr track() { return _mti; }
void setTrack(MixerTrackItemPtr track);
void propertyChanged(Channel::Prop property) override;
void disconnectChannelListener() override;
};
}
#endif // __MIXERDETAILS_H__

430
mscore/mixerdetails.ui Normal file
View file

@ -0,0 +1,430 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MixerDetails</class>
<widget class="QWidget" name="MixerDetails">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>909</width>
<height>183</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<layout class="QGridLayout" name="gridLayout_4">
<property name="horizontalSpacing">
<number>11</number>
</property>
<property name="verticalSpacing">
<number>0</number>
</property>
<item row="0" column="3">
<layout class="QGridLayout" name="gridLayout" rowstretch="0,0,0">
<property name="spacing">
<number>11</number>
</property>
<item row="2" column="0">
<spacer name="verticalSpacer_3">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="0">
<widget class="QGroupBox" name="groupBox">
<property name="toolTip">
<string>MIDI Out controllers</string>
</property>
<property name="title">
<string>MIDI</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QGridLayout" name="gridLayout_5">
<item row="2" column="0">
<widget class="QLabel" name="labelChorus">
<property name="text">
<string>Chorus:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSlider" name="reverbSlider">
<property name="minimumSize">
<size>
<width>200</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>MIDI OUT reverb</string>
</property>
<property name="maximum">
<number>127</number>
</property>
<property name="pageStep">
<number>16</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="tickPosition">
<enum>QSlider::TicksBelow</enum>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QSlider" name="chorusSlider">
<property name="minimumSize">
<size>
<width>200</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>MIDI OUT chorus</string>
</property>
<property name="maximum">
<number>127</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="tickPosition">
<enum>QSlider::TicksBelow</enum>
</property>
<property name="tickInterval">
<number>16</number>
</property>
</widget>
</item>
<item row="0" column="0" colspan="3">
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="2">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="0">
<widget class="QLabel" name="labelPort">
<property name="text">
<string>Port:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QSpinBox" name="portSpinBox">
<property name="toolTip">
<string>MIDI Port Number</string>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>16</number>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QLabel" name="labelChannel_2">
<property name="text">
<string>Channel:</string>
</property>
</widget>
</item>
<item row="0" column="4">
<widget class="QSpinBox" name="channelSpinBox">
<property name="toolTip">
<string>MIDI Channel Number</string>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>16</number>
</property>
</widget>
</item>
<item row="0" column="5">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QLabel" name="labelReverb">
<property name="text">
<string>Reverb:</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QDoubleSpinBox" name="reverbSpinBox">
<property name="toolTip">
<string>MIDI OUT reverb</string>
</property>
<property name="decimals">
<number>0</number>
</property>
<property name="maximum">
<double>127.000000000000000</double>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QDoubleSpinBox" name="chorusSpinBox">
<property name="toolTip">
<string>MIDI OUT reverb</string>
</property>
<property name="decimals">
<number>0</number>
</property>
<property name="maximum">
<double>127.000000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
</layout>
</item>
<item row="0" column="2">
<layout class="QGridLayout" name="gridLayout_2">
<property name="spacing">
<number>11</number>
</property>
<item row="5" column="2">
<widget class="QDoubleSpinBox" name="panSpinBox">
<property name="toolTip">
<string>Pan</string>
</property>
<property name="decimals">
<number>0</number>
</property>
<property name="minimum">
<double>0.000000000000000</double>
</property>
<property name="maximum">
<double>127.000000000000000</double>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QSlider" name="panSlider">
<property name="minimumSize">
<size>
<width>200</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Pan</string>
</property>
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>127</number>
</property>
<property name="pageStep">
<number>16</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="tickPosition">
<enum>QSlider::TicksBelow</enum>
</property>
<property name="tickInterval">
<number>16</number>
</property>
</widget>
</item>
<item row="4" column="2">
<widget class="QDoubleSpinBox" name="volumeSpinBox">
<property name="toolTip">
<string>Volume</string>
</property>
<property name="decimals">
<number>0</number>
</property>
<property name="maximum">
<double>127.000000000000000</double>
</property>
</widget>
</item>
<item row="2" column="1" colspan="2">
<widget class="QComboBox" name="patchCombo">
<property name="minimumSize">
<size>
<width>200</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Patch Voice</string>
</property>
</widget>
</item>
<item row="3" column="0" colspan="3">
<widget class="QCheckBox" name="drumkitCheck">
<property name="text">
<string>Drumkit</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="labelPatch">
<property name="text">
<string>Patch:</string>
</property>
</widget>
</item>
<item row="1" column="1" colspan="2">
<widget class="QLabel" name="channelLabel">
<property name="toolTip">
<string>Channel Name</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="labelChannel">
<property name="text">
<string>Channel:</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="labelName">
<property name="text">
<string>Name:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="partNameLineEdit">
<property name="toolTip">
<string>Part Name</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="Awl::ColorLabel" name="trackColorLabel" native="true">
<property name="minimumSize">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
<property name="toolTip">
<string>Track Color</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QSlider" name="volumeSlider">
<property name="minimumSize">
<size>
<width>200</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Volume</string>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="maximum">
<number>128</number>
</property>
<property name="pageStep">
<number>16</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="tickPosition">
<enum>QSlider::TicksBelow</enum>
</property>
<property name="tickInterval">
<number>16</number>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="labelVolume">
<property name="text">
<string>Volume:</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="labelPan">
<property name="text">
<string>Pan:</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>Awl::ColorLabel</class>
<extends>QWidget</extends>
<header>awl/colorlabel.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

43
mscore/mixertrack.h Normal file
View file

@ -0,0 +1,43 @@
//=============================================================================
// MuseScore
// Linux Music Score Editor
// $Id: mixer.h 4388 2011-06-18 13:17:58Z wschweer $
//
// Copyright (C) 2002-2016 Werner Schweer and others
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.
//
// This program 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 this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#ifndef __MIXERTRACK_H__
#define __MIXERTRACK_H__
#include "mixertrackitem.h"
#include <QWidget>
class MixerTrackGroup;
namespace Ms {
class MixerTrack {
public:
virtual ~MixerTrack() {}
virtual QWidget* getWidget() = 0;
virtual MixerTrackGroup* group() = 0;
virtual MixerTrackItemPtr mti() = 0;
virtual bool selected() = 0;
virtual void setSelected(bool) = 0;
};
}
#endif // MIXERTRACK_H

View file

@ -0,0 +1,363 @@
//=============================================================================
// MuseScore
// Linux Music Score Editor
// $Id: mixer.h 4388 2011-06-18 13:17:58Z wschweer $
//
// Copyright (C) 2002-2016 Werner Schweer and others
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.
//
// This program 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 this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#include "mixertrackchannel.h"
#include "musescore.h"
#include "libmscore/score.h"
#include "libmscore/part.h"
#include "mixer.h"
#include "mixertrackitem.h"
#include "seq.h"
#include "libmscore/undo.h"
#include "synthcontrol.h"
#include "synthesizer/msynthesizer.h"
#include "preferences.h"
namespace Ms {
const QString MixerTrackChannel::unselStyleLight = "#controlWidget {"
" background: #aaa;"
" border-left: 2px solid #ddd;"
" border-top: 2px solid #ddd;"
" border-right: 2px solid #777;"
" border-bottom: 2px solid #777;"
"}";
const QString MixerTrackChannel::selStyleLight = "#controlWidget {"
" background: #ccc;"
" border-left: 2px solid #eee;"
" border-top: 2px solid #eee;"
" border-right: 2px solid #777;"
" border-bottom: 2px solid #777;"
"}";
const QString MixerTrackChannel::unselStyleDark = "#controlWidget {"
" background: #444;"
" border-left: 2px solid #888;"
" border-top: 2px solid #888;"
" border-right: 2px solid #000;"
" border-bottom: 2px solid #000;"
"}"
".expandBn {"
" background-color: #aaa;"
"}";
const QString MixerTrackChannel::selStyleDark = "#controlWidget {"
" background: #666;"
" border-left: 2px solid #888;"
" border-top: 2px solid #888;"
" border-right: 2px solid #000;"
" border-bottom: 2px solid #000;"
"}"
".expandBn {"
" background-color: #aaa;"
"}";
//---------------------------------------------------------
// MixerTrack
//---------------------------------------------------------
MixerTrackChannel::MixerTrackChannel(QWidget *parent, MixerTrackItemPtr mti) :
QWidget(parent), _mti(mti), _selected(false), _group(0)
{
setupUi(this);
connect(soloBn, SIGNAL(toggled(bool)), SLOT(updateSolo(bool)));
connect(muteBn, SIGNAL(toggled(bool)), SLOT(updateMute(bool)));
updateNameLabel();
//set up rest
Channel* chan = mti->chan();
soloBn->setChecked(chan->solo());
muteBn->setChecked(chan->mute());
chan->addListener(this);
volumeSlider->setValue(chan->volume());
volumeSlider->setToolTip("Volume: " + QString::number(chan->volume()));
volumeSlider->setMaxValue(127);
volumeSlider->setNumMajorTicks(10);
volumeSlider->setNumMinorTicks(5);
QIcon iconSliderHead;
iconSliderHead.addFile(QStringLiteral(":/data/icons/mixer-slider-handle-vertical.svg"), QSize(), QIcon::Normal, QIcon::Off);
volumeSlider->setSliderHeadIcon(iconSliderHead);
panSlider->setValue(chan->pan());
panSlider->setToolTip("Pan: " + QString::number(chan->pan()));
panSlider->setMaxValue(127);
panSlider->setMinValue(0);
connect(volumeSlider, SIGNAL(valueChanged(double)), SLOT(volumeChanged(double)));
connect(panSlider, SIGNAL(valueChanged(double, int)), SLOT(panChanged(double)));
connect(volumeSlider, SIGNAL(sliderPressed()), SLOT(controlSelected()));
connect(panSlider, SIGNAL(sliderPressed(int)), SLOT(controlSelected()));
applyStyle();
}
//---------------------------------------------------------
// ~MixerTrack
//---------------------------------------------------------
MixerTrackChannel::~MixerTrackChannel()
{
if (_mti) {
Channel* chan = _mti->chan();
chan->removeListener(this);
}
}
//---------------------------------------------------------
// expandToggled
//---------------------------------------------------------
void MixerTrackChannel::applyStyle()
{
QString style;
switch (preferences.globalStyle()){
case MuseScoreStyleType::DARK_FUSION:
style = _selected ? selStyleDark : unselStyleDark;
break;
case MuseScoreStyleType::LIGHT_FUSION:
style = _selected ? selStyleLight : unselStyleLight;
break;
}
setStyleSheet(style);
}
//---------------------------------------------------------
// updateNameLabel
//---------------------------------------------------------
void MixerTrackChannel::updateNameLabel()
{
Part* part = _mti->part();
Instrument* instr = _mti->instrument();
Channel* chan = _mti->chan();
//instr->trackName();
QString shortName = instr->shortNames().first().name();
QString text = QString("%1-%2")
.arg(shortName, chan->name());
trackLabel->setText(text);
MidiPatch* mp = synti->getPatchInfo(chan->synti(), chan->bank(), chan->program());
QString tooltip = QString("Part Name: %1\n"
"Instrument: %2\n"
"Channel: %3\n"
"Bank: %4\n"
"Program: %5\n"
"Patch: %6")
.arg(part->partName(),
instr->trackName(),
chan->name(),
QString::number(chan->bank()),
QString::number(chan->program()),
mp ? mp->name : "~no patch~");
trackLabel->setToolTip(tooltip);
QColor bgCol((QRgb)chan->color());
QString trackColorName = bgCol.name();
int val = bgCol.value();
QString trackStyle = QString(".QLabel {"
"border: 2px solid black;"
"background: %1;"
"color: %2;"
"padding: 6px 0px;"
"}").arg(trackColorName, val > 128 ? "black" : "white");
trackLabel->setStyleSheet(trackStyle);
QColor bgPartCol((QRgb)part->color());
QString partColorName = bgPartCol.name();
val = bgPartCol.value();
//Part header
partLabel->setText(part->partName());
QString partStyle = QString(".QLabel {"
"border: 2px solid black;"
"background: %1;"
"color: %2;"
"padding: 6px 0px;"
"}").arg(partColorName, val > 128 ? "black" : "white");
partLabel->setStyleSheet(partStyle);
partLabel->setToolTip(QString("This channel is a child of part %1").arg(part->partName()));
//Update component colors
qreal h, s, v;
bgCol.getHsvF(&h, &s, &v);
QColor brightCol = QColor::fromHsvF(h, s, 1);
panSlider->setScaleValueColor(brightCol);
volumeSlider->setHilightColor(brightCol);
}
//---------------------------------------------------------
// paintEvent
//---------------------------------------------------------
void MixerTrackChannel::paintEvent(QPaintEvent* evt)
{
applyStyle();
}
//---------------------------------------------------------
// disconnectChannelListener
//---------------------------------------------------------
void MixerTrackChannel::disconnectChannelListener()
{
//Channel has been destroyed. Don't remove listener when invoking destructor.
_mti = nullptr;
}
//---------------------------------------------------------
// propertyChanged
//---------------------------------------------------------
void MixerTrackChannel::propertyChanged(Channel::Prop property)
{
Channel* chan = _mti->chan();
switch (property) {
case Channel::Prop::VOLUME: {
volumeSlider->blockSignals(true);
volumeSlider->setValue(chan->volume());
volumeSlider->setToolTip("Volume: " + QString::number(chan->volume()));
volumeSlider->blockSignals(false);
break;
}
case Channel::Prop::PAN: {
panSlider->blockSignals(true);
panSlider->setValue(chan->pan());
panSlider->setToolTip("Pan: " + QString::number(chan->pan()));
panSlider->blockSignals(false);
break;
}
case Channel::Prop::MUTE: {
muteBn->blockSignals(true);
muteBn->setChecked(chan->mute());
muteBn->blockSignals(false);
break;
}
case Channel::Prop::SOLO: {
soloBn->blockSignals(true);
soloBn->setChecked(chan->solo());
soloBn->blockSignals(false);
break;
}
case Channel::Prop::COLOR: {
updateNameLabel();
break;
}
default:
break;
}
}
//---------------------------------------------------------
// volumeChanged
//---------------------------------------------------------
void MixerTrackChannel::volumeChanged(double value)
{
_mti->setVolume(value);
volumeSlider->setToolTip("Volume: " + QString::number(value));
}
//---------------------------------------------------------
// panChanged
//---------------------------------------------------------
void MixerTrackChannel::panChanged(double value)
{
_mti->setPan(value);
panSlider->setToolTip("Pan: " + QString::number(value));
}
//---------------------------------------------------------
// updateSolo
//---------------------------------------------------------
void MixerTrackChannel::updateSolo(bool val)
{
_mti->setSolo(val);
}
//---------------------------------------------------------
// udpateMute
//---------------------------------------------------------
void MixerTrackChannel::updateMute(bool val)
{
_mti->setMute(val);
}
//---------------------------------------------------------
// controlSelected
//---------------------------------------------------------
void MixerTrackChannel::controlSelected()
{
setSelected(true);
}
//---------------------------------------------------------
// mouseReleaseEvent
//---------------------------------------------------------
void MixerTrackChannel::mouseReleaseEvent(QMouseEvent * event)
{
setSelected(true);
}
//---------------------------------------------------------
// setSelected
//---------------------------------------------------------
void MixerTrackChannel::setSelected(bool sel)
{
if (_selected == sel)
return;
_selected = sel;
applyStyle();
emit(selectedChanged(sel));
if (_selected && _group)
_group->notifyTrackSelected(this);
}
}

View file

@ -0,0 +1,86 @@
//=============================================================================
// MuseScore
// Linux Music Score Editor
// $Id: mixer.h 4388 2011-06-18 13:17:58Z wschweer $
//
// Copyright (C) 2002-2016 Werner Schweer and others
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.
//
// This program 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 this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#ifndef __MIXERTRACKCHANNEL_H__
#define __MIXERTRACKCHANNEL_H__
#include "ui_mixertrackchannel.h"
#include "mixertrackgroup.h"
#include "mixertrack.h"
#include "mixertrackitem.h"
#include "libmscore/instrument.h"
namespace Ms {
class MidiMapping;
class MixerTrackItem;
//---------------------------------------------------------
// MixerTrack
//---------------------------------------------------------
class MixerTrackChannel : public QWidget, public Ui::MixerTrackChannel, public ChannelListener, public MixerTrack
{
Q_OBJECT
MixerTrackItemPtr _mti;
bool _selected;
static const QString unselStyleLight;
static const QString selStyleLight;
static const QString unselStyleDark;
static const QString selStyleDark;
static const QString sliderStyle;
MixerTrackGroup* _group;
void updateNameLabel();
signals:
void selectedChanged(bool);
public slots:
void updateSolo(bool);
void updateMute(bool);
void setSelected(bool) override;
void volumeChanged(double);
void panChanged(double);
void controlSelected();
void applyStyle();
protected:
void mouseReleaseEvent(QMouseEvent * event) override;
void propertyChanged(Channel::Prop property) override;
void disconnectChannelListener() override;
public:
explicit MixerTrackChannel(QWidget *parent, MixerTrackItemPtr trackItem);
~MixerTrackChannel() override;
bool selected() override { return _selected; }
QWidget* getWidget() override { return this; }
MixerTrackGroup* group() override { return _group; }
MixerTrackItemPtr mti() override { return _mti; }
void setGroup(MixerTrackGroup* group) { _group = group; }
void paintEvent(QPaintEvent* evt) override;
};
}
#endif // __MIXERTRACKCHANNEL_H__

309
mscore/mixertrackchannel.ui Normal file
View file

@ -0,0 +1,309 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MixerTrackChannel</class>
<widget class="QWidget" name="MixerTrackChannel">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>80</width>
<height>385</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>80</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>80</width>
<height>16777215</height>
</size>
</property>
<property name="windowTitle">
<string>MixerTrackChannel</string>
</property>
<property name="styleSheet">
<string notr="true">#controlWidget {
background: #444;
border-left: 2px solid #888;
border-top: 2px solid #888;
border-right: 2px solid #111;
border-bottom: 2px solid #111;
}
</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QWidget" name="controlWidget" native="true">
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>2</number>
</property>
<property name="topMargin">
<number>2</number>
</property>
<property name="rightMargin">
<number>2</number>
</property>
<property name="bottomMargin">
<number>2</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="partLabel">
<property name="minimumSize">
<size>
<width>0</width>
<height>28</height>
</size>
</property>
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="2" column="0">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="soloBn">
<property name="toolTip">
<string>Solo</string>
</property>
<property name="styleSheet">
<string notr="true">.QPushButton {
border: none;
background-color: none;
}
</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="musescore.qrc">
<normaloff>:/data/icons/mixer-solo-off.svg</normaloff>
<normalon>:/data/icons/mixer-solo-on.svg</normalon>:/data/icons/mixer-solo-off.svg</iconset>
</property>
<property name="iconSize">
<size>
<width>32</width>
<height>32</height>
</size>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item row="2" column="2">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="3" column="1">
<widget class="Awl::Knob" name="panSlider" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>40</width>
<height>40</height>
</size>
</property>
<property name="toolTip">
<string>Pan</string>
</property>
<property name="maxValue" stdset="0">
<double>127.000000000000000</double>
</property>
<property name="scaleValueColor" stdset="0">
<color>
<red>51</red>
<green>170</green>
<blue>255</blue>
</color>
</property>
<property name="scaleColor" stdset="0">
<color>
<red>17</red>
<green>17</green>
<blue>17</blue>
</color>
</property>
<property name="knobIcon" stdset="0">
<iconset resource="musescore.qrc">
<normaloff>:/data/icons/mixer-dial.svg</normaloff>:/data/icons/mixer-dial.svg</iconset>
</property>
<property name="minValue" stdset="0">
<double>0.000000000000000</double>
</property>
<property name="value" stdset="0">
<double>63.500000000000000</double>
</property>
<property name="center" stdset="0">
<bool>true</bool>
</property>
<property name="lineStep" stdset="0">
<double>1.000000000000000</double>
</property>
<property name="pageStep" stdset="0">
<double>10.000000000000000</double>
</property>
<property name="enableMouseWheel" stdset="0">
<bool>false</bool>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QPushButton" name="muteBn">
<property name="toolTip">
<string>Mute</string>
</property>
<property name="styleSheet">
<string notr="true">.QPushButton {
border: none;
background-color: none;
}
</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="musescore.qrc">
<normaloff>:/data/icons/mixer-mute-off.svg</normaloff>
<normalon>:/data/icons/mixer-mute-on.svg</normalon>:/data/icons/mixer-mute-off.svg</iconset>
</property>
<property name="iconSize">
<size>
<width>32</width>
<height>32</height>
</size>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="Awl::StyledSlider" name="volumeSlider" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>200</height>
</size>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="trackLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Channel Name</string>
</property>
<property name="styleSheet">
<string notr="true">.QLabel {
border: 2px solid black;
background: red;
color: white;
padding: 6px 0px;
line-height:2px;
}
</string>
</property>
<property name="text">
<string>Part Name</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>Awl::StyledSlider</class>
<extends>QWidget</extends>
<header>awl/styledslider.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>Awl::Knob</class>
<extends>QWidget</extends>
<header>awl/knob.h</header>
</customwidget>
</customwidgets>
<resources>
<include location="musescore.qrc"/>
</resources>
<connections/>
</ui>

43
mscore/mixertrackgroup.h Normal file
View file

@ -0,0 +1,43 @@
//=============================================================================
// MuseScore
// Linux Music Score Editor
// $Id: mixer.h 4388 2011-06-18 13:17:58Z wschweer $
//
// Copyright (C) 2002-2016 Werner Schweer and others
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.
//
// This program 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 this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#ifndef __MIXERTRACKGROUP_H__
#define __MIXERTRACKGROUP_H__
namespace Ms {
class Part;
class MixerTrack;
//---------------------------------------------------------
// MixerTrackGroup
//---------------------------------------------------------
class MixerTrackGroup
{
public:
virtual ~MixerTrackGroup() {}
virtual void expandToggled(Part* part, bool expanded) = 0;
virtual void notifyTrackSelected(MixerTrack* track) = 0;
};
}
#endif // MIXERTRACKGROUP_H

285
mscore/mixertrackitem.cpp Normal file
View file

@ -0,0 +1,285 @@
//=============================================================================
// MuseScore
// Linux Music Score Editor
// $Id: mixer.h 4388 2011-06-18 13:17:58Z wschweer $
//
// Copyright (C) 2002-2016 Werner Schweer and others
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.
//
// This program 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 this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#include "mixertrackitem.h"
#include "libmscore/score.h"
#include "libmscore/part.h"
#include "seq.h"
namespace Ms {
//---------------------------------------------------------
// MixerTrackItem
//---------------------------------------------------------
MixerTrackItem::MixerTrackItem(TrackType tt, Part* part, Instrument* instr, Channel *chan)
:_trackType(tt), _part(part), _instr(instr), _chan(chan)
{
}
//---------------------------------------------------------
// midiMap
//---------------------------------------------------------
MidiMapping *MixerTrackItem::midiMap()
{
return _part->masterScore()->midiMapping(focusedChan()->channel());
}
//---------------------------------------------------------
// partChan
//---------------------------------------------------------
Channel *MixerTrackItem::focusedChan()
{
return _chan;
}
//---------------------------------------------------------
// color
//---------------------------------------------------------
int MixerTrackItem::color()
{
return _trackType ==TrackType::PART ? _part->color()
: _chan->color();
}
//---------------------------------------------------------
// setVolume
//---------------------------------------------------------
void MixerTrackItem::setVolume(char value)
{
// char v = (char)qBound(0, (int)(value * 128.0 / 100.0), 127);
if (_trackType == TrackType::PART) {
const InstrumentList* il = _part->instruments();
for (auto it = il->begin(); it != il->end(); ++it) {
Instrument* instr = it->second;
for (Channel *chan: instr->channel()) {
if (chan->volume() != value) {
chan->setVolume(value);
seq->setController(chan->channel(), CTRL_VOLUME, chan->volume());
chan->updateInitList();
}
}
}
}
else {
if (_chan->volume() != value) {
_chan->setVolume(value);
seq->setController(_chan->channel(), CTRL_VOLUME, _chan->volume());
_chan->updateInitList();
}
}
}
//---------------------------------------------------------
// setPan
//---------------------------------------------------------
void MixerTrackItem::setPan(char value)
{
// char v = (char)qBound(0, (int)((value + 180.0) / 360.0 * 128.0), 127);
if (_trackType == TrackType::PART) {
const InstrumentList* il = _part->instruments();
for (auto it = il->begin(); it != il->end(); ++it) {
Instrument* instr = it->second;
for (Channel *chan: instr->channel()) {
if (chan->pan() != value) {
chan->setPan(value);
seq->setController(chan->channel(), CTRL_PANPOT, chan->pan());
chan->updateInitList();
}
}
}
}
else {
if (_chan->pan() != value) {
_chan->setPan(value);
seq->setController(_chan->channel(), CTRL_PANPOT, _chan->pan());
_chan->updateInitList();
}
}
}
//---------------------------------------------------------
// setChorus
//---------------------------------------------------------
void MixerTrackItem::setChorus(char value)
{
// char v = (char)qBound(0, (int)(value * 128.0 / 100.0), 127);
if (_trackType == TrackType::PART) {
const InstrumentList* il = _part->instruments();
for (auto it = il->begin(); it != il->end(); ++it) {
Instrument* instr = it->second;
for (Channel *chan: instr->channel()) {
if (chan->chorus() != value) {
chan->setChorus(value);
seq->setController(chan->channel(), CTRL_CHORUS_SEND, chan->chorus());
chan->updateInitList();
}
}
}
}
else {
if (_chan->chorus() != value) {
_chan->setChorus(value);
seq->setController(_chan->channel(), CTRL_CHORUS_SEND, _chan->chorus());
_chan->updateInitList();
}
}
}
//---------------------------------------------------------
// setReverb
//---------------------------------------------------------
void MixerTrackItem::setReverb(char value)
{
// char v = (char)qBound(0, (int)(value * 128.0 / 100.0), 127);
if (_trackType == TrackType::PART) {
const InstrumentList* il = _part->instruments();
for (auto it = il->begin(); it != il->end(); ++it) {
Instrument* instr = it->second;
for (Channel *chan: instr->channel()) {
if (chan->reverb() != value) {
chan->setReverb(value);
seq->setController(chan->channel(), CTRL_REVERB_SEND, chan->reverb());
chan->updateInitList();
}
}
}
}
else {
if (_chan->reverb() != value) {
_chan->setReverb(value);
seq->setController(_chan->channel(), CTRL_REVERB_SEND, _chan->reverb());
_chan->updateInitList();
}
}
}
//---------------------------------------------------------
// setColor
//---------------------------------------------------------
void MixerTrackItem::setColor(int valueRgb)
{
if (_trackType == TrackType::PART) {
_part->setColor(valueRgb);
const InstrumentList* il = _part->instruments();
for (auto it = il->begin(); it != il->end(); ++it) {
Instrument* instr = it->second;
for (Channel *chan: instr->channel()) {
chan->setColor(valueRgb);
}
}
}
else {
_chan->setColor(valueRgb);
}
}
//---------------------------------------------------------
// setMute
//---------------------------------------------------------
void MixerTrackItem::setMute(bool value)
{
if (_trackType == TrackType::PART) {
const InstrumentList* il = _part->instruments();
for (auto it = il->begin(); it != il->end(); ++it) {
Instrument* instr = it->second;
for (Channel *chan: instr->channel()) {
if (value)
seq->stopNotes(chan->channel());
chan->setMute(value);
}
}
}
else {
if (value)
seq->stopNotes(_chan->channel());
_chan->setMute(value);
}
}
//---------------------------------------------------------
// setSolo
//---------------------------------------------------------
void MixerTrackItem::setSolo(bool value)
{
if (_trackType == TrackType::PART) {
const InstrumentList* il = _part->instruments();
for (auto it = il->begin(); it != il->end(); ++it) {
Instrument* instr = it->second;
for (Channel *chan: instr->channel()) {
chan->setSolo(value);
}
}
}
else {
_chan->setSolo(value);
}
//Go through all channels so that all not being soloed are mute
int numSolo = 0;
for (Part* p : _part->score()->parts()) {
const InstrumentList* il = p->instruments();
for (auto i = il->begin(); i != il->end(); ++i) {
const Instrument* instr = i->second;
for (Channel* a : instr->channel()) {
if (a->solo()) {
numSolo++;
}
}
}
}
for (Part* p : _part->score()->parts()) {
const InstrumentList* il = p->instruments();
for (auto i = il->begin(); i != il->end(); ++i) {
const Instrument* instr = i->second;
for (Channel* a : instr->channel()) {
if (numSolo == 0) {
a->setSoloMute(false);
}
else {
a->setSoloMute(!a->solo());
if (a->soloMute()) {
seq->stopNotes(a->channel());
}
}
}
}
}
}
}

79
mscore/mixertrackitem.h Normal file
View file

@ -0,0 +1,79 @@
//=============================================================================
// MuseScore
// Linux Music Score Editor
// $Id: mixer.h 4388 2011-06-18 13:17:58Z wschweer $
//
// Copyright (C) 2002-2016 Werner Schweer and others
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.
//
// This program 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 this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#ifndef __MIXERTRACKITEM_H__
#define __MIXERTRACKITEM_H__
#include "libmscore/instrument.h"
#include <memory>
namespace Ms {
class Part;
class Instrument;
class Channel;
class MidiMapping;
class MixerTrackItem;
typedef std::shared_ptr<MixerTrackItem> MixerTrackItemPtr;
//typedef MixerTrackItem* MixerTrackItemPtr;
//---------------------------------------------------------
// MixerTrackItem
//---------------------------------------------------------
class MixerTrackItem
{
public:
enum class TrackType { PART, CHANNEL };
private:
TrackType _trackType;
Part* _part;
Instrument* _instr;
Channel* _chan;
// int _instrIdx;
// int _chanIdx; //If -1, this track handles all channels attached to this part
public:
MixerTrackItem(TrackType tt, Part* part, Instrument* _instr, Channel* _chan);
TrackType trackType() { return _trackType; }
Part* part() { return _part; }
Instrument* instrument() { return _instr; }
Channel* chan() { return _chan; }
Channel* focusedChan();
// int chanIdx() { return _chanIdx; }
MidiMapping *midiMap();
int color();
void setColor(int valueRgb);
void setVolume(char value);
void setPan(char value);
void setChorus(char value);
void setReverb(char value);
void setMute(bool value);
void setSolo(bool value);
};
}
#endif // __MIXERTRACKITEM_H__

355
mscore/mixertrackpart.cpp Normal file
View file

@ -0,0 +1,355 @@
//=============================================================================
// MuseScore
// Linux Music Score Editor
// $Id: mixer.h 4388 2011-06-18 13:17:58Z wschweer $
//
// Copyright (C) 2002-2016 Werner Schweer and others
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.
//
// This program 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 this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#include "mixertrackpart.h"
#include "musescore.h"
#include "libmscore/score.h"
#include "libmscore/part.h"
#include "mixer.h"
#include "mixertrackitem.h"
#include "seq.h"
#include "libmscore/undo.h"
#include "synthcontrol.h"
#include "synthesizer/msynthesizer.h"
#include "preferences.h"
namespace Ms {
const QString MixerTrackPart::unselStyleLight = "#controlWidget {"
" background: #aaa;"
" border-left: 2px solid #ddd;"
" border-top: 2px solid #ddd;"
" border-right: 2px solid #777;"
" border-bottom: 2px solid #777;"
"}";
const QString MixerTrackPart::selStyleLight = "#controlWidget {"
" background: #ccc;"
" border-left: 2px solid #eee;"
" border-top: 2px solid #eee;"
" border-right: 2px solid #777;"
" border-bottom: 2px solid #777;"
"}";
const QString MixerTrackPart::unselStyleDark = "#controlWidget {"
" background: #444;"
" border-left: 2px solid #888;"
" border-top: 2px solid #888;"
" border-right: 2px solid #000;"
" border-bottom: 2px solid #000;"
"}"
".expandBn {"
" background-color: #aaa;"
"}";
const QString MixerTrackPart::selStyleDark = "#controlWidget {"
" background: #666;"
" border-left: 2px solid #888;"
" border-top: 2px solid #888;"
" border-right: 2px solid #000;"
" border-bottom: 2px solid #000;"
"}"
".expandBn {"
" background-color: #aaa;"
"}";
//---------------------------------------------------------
// MixerTrack
//---------------------------------------------------------
MixerTrackPart::MixerTrackPart(QWidget *parent, MixerTrackItemPtr mti, bool expanded) :
QWidget(parent), _mti(mti), _selected(false), _group(0)
{
setupUi(this);
expandBn->setChecked(expanded);
connect(expandBn, SIGNAL(toggled(bool)), SLOT(expandToggled(bool)));
connect(soloBn, SIGNAL(toggled(bool)), SLOT(updateSolo(bool)));
connect(muteBn, SIGNAL(toggled(bool)), SLOT(updateMute(bool)));
updateNameLabel();
//set up rest
Channel* chan = _mti->focusedChan();
soloBn->setChecked(chan->solo());
muteBn->setChecked(chan->mute());
chan->addListener(this);
volumeSlider->setValue(chan->volume());
volumeSlider->setToolTip("Volume: " + QString::number(chan->volume()));
volumeSlider->setMaxValue(127);
volumeSlider->setNumMajorTicks(10);
volumeSlider->setNumMinorTicks(4);
QIcon iconSliderHead;
iconSliderHead.addFile(QStringLiteral(":/data/icons/mixer-slider-handle-vertical.svg"), QSize(), QIcon::Normal, QIcon::Off);
volumeSlider->setSliderHeadIcon(iconSliderHead);
panSlider->setValue(chan->pan());
panSlider->setToolTip("Pan: " + QString::number(chan->pan()));
panSlider->setMaxValue(127);
panSlider->setMinValue(0);
connect(volumeSlider, SIGNAL(valueChanged(double)), SLOT(volumeChanged(double)));
connect(panSlider, SIGNAL(valueChanged(double, int)), SLOT(panChanged(double)));
connect(volumeSlider, SIGNAL(sliderPressed()), SLOT(controlSelected()));
connect(panSlider, SIGNAL(sliderPressed(int)), SLOT(controlSelected()));
applyStyle();
}
//---------------------------------------------------------
// ~MixerTrack
//---------------------------------------------------------
MixerTrackPart::~MixerTrackPart()
{
if (_mti) {
Channel* chan = _mti->focusedChan();
chan->removeListener(this);
}
}
//---------------------------------------------------------
// expandToggled
//---------------------------------------------------------
void MixerTrackPart::applyStyle()
{
QString style;
switch (preferences.globalStyle()){
case MuseScoreStyleType::DARK_FUSION:
style = _selected ? selStyleDark : unselStyleDark;
break;
case MuseScoreStyleType::LIGHT_FUSION:
style = _selected ? selStyleLight : unselStyleLight;
break;
}
setStyleSheet(style);
}
//---------------------------------------------------------
// expandToggled
//---------------------------------------------------------
void MixerTrackPart::expandToggled(bool expanded)
{
_group->expandToggled(_mti->part(), expanded);
}
//---------------------------------------------------------
// updateNameLabel
//---------------------------------------------------------
void MixerTrackPart::updateNameLabel()
{
Part* part = _mti->part();
Channel* chan = _mti->focusedChan();
QString text = QString("%1")
.arg(part->partName());
trackLabel->setText(text);
MidiPatch* mp = synti->getPatchInfo(chan->synti(), chan->bank(), chan->program());
QString tooltip = QString("Part Name: %1\n"
"Primary Instrument: %2\n"
"Bank: %3\n"
"Program: %4\n"
"Patch: %5")
.arg(part->partName(),
part->longName(),
QString::number(chan->bank()),
QString::number(chan->program()),
mp ? mp->name : "~no patch~");
trackLabel->setToolTip(tooltip);
QColor bgCol((QRgb)part->color());
QString colName = bgCol.name();
int val = bgCol.value();
QString ss = QString(".QLabel {"
"border: 2px solid black;"
"background: %1;"
"color: %2;"
"padding: 6px 0px;"
"}").arg(colName, val > 128 ? "black" : "white");
trackLabel->setStyleSheet(ss);
//Update component colors
qreal h, s, v;
bgCol.getHsvF(&h, &s, &v);
QColor brightCol = QColor::fromHsvF(h, s, 1);
panSlider->setScaleValueColor(brightCol);
volumeSlider->setHilightColor(brightCol);
}
//---------------------------------------------------------
// paintEvent
//---------------------------------------------------------
void MixerTrackPart::paintEvent(QPaintEvent* evt)
{
applyStyle();
}
//---------------------------------------------------------
// disconnectChannelListener
//---------------------------------------------------------
void MixerTrackPart::disconnectChannelListener()
{
//Channel has been destroyed. Don't remove listener when invoking destructor.
_mti = nullptr;
}
//---------------------------------------------------------
// propertyChanged
//---------------------------------------------------------
void MixerTrackPart::propertyChanged(Channel::Prop property)
{
Channel* chan = _mti->focusedChan();
switch (property) {
case Channel::Prop::VOLUME: {
volumeSlider->blockSignals(true);
volumeSlider->setValue(chan->volume());
volumeSlider->setToolTip("Volume: " + QString::number(chan->volume()));
volumeSlider->blockSignals(false);
break;
}
case Channel::Prop::PAN: {
panSlider->blockSignals(true);
panSlider->setValue(chan->pan());
panSlider->setToolTip("Pan: " + QString::number(chan->pan()));
panSlider->blockSignals(false);
break;
}
case Channel::Prop::MUTE: {
muteBn->blockSignals(true);
muteBn->setChecked(chan->mute());
muteBn->blockSignals(false);
break;
}
case Channel::Prop::SOLO: {
soloBn->blockSignals(true);
soloBn->setChecked(chan->solo());
soloBn->blockSignals(false);
break;
}
case Channel::Prop::COLOR: {
updateNameLabel();
break;
}
default:
break;
}
}
//---------------------------------------------------------
// volumeChanged
//---------------------------------------------------------
void MixerTrackPart::volumeChanged(double value)
{
_mti->setVolume(value);
volumeSlider->setToolTip("Volume: " + QString::number(value));
}
//---------------------------------------------------------
// panChanged
//---------------------------------------------------------
void MixerTrackPart::panChanged(double value)
{
_mti->setPan(value);
panSlider->setToolTip("Pan: " + QString::number(value));
}
//---------------------------------------------------------
// updateSolo
//---------------------------------------------------------
void MixerTrackPart::updateSolo(bool val)
{
_mti->setSolo(val);
}
//---------------------------------------------------------
// udpateMute
//---------------------------------------------------------
void MixerTrackPart::updateMute(bool val)
{
_mti->setMute(val);
}
//---------------------------------------------------------
// controlSelected
//---------------------------------------------------------
void MixerTrackPart::controlSelected()
{
setSelected(true);
}
//---------------------------------------------------------
// mouseReleaseEvent
//---------------------------------------------------------
void MixerTrackPart::mouseReleaseEvent(QMouseEvent * event)
{
setSelected(true);
}
//---------------------------------------------------------
// setSelected
//---------------------------------------------------------
void MixerTrackPart::setSelected(bool sel)
{
if (_selected == sel)
return;
_selected = sel;
applyStyle();
emit(selectedChanged(sel));
if (_selected && _group)
_group->notifyTrackSelected(this);
}
}

87
mscore/mixertrackpart.h Normal file
View file

@ -0,0 +1,87 @@
//=============================================================================
// MuseScore
// Linux Music Score Editor
// $Id: mixer.h 4388 2011-06-18 13:17:58Z wschweer $
//
// Copyright (C) 2002-2016 Werner Schweer and others
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.
//
// This program 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 this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#ifndef __MIXERTRACKPART_H__
#define __MIXERTRACKPART_H__
#include "ui_mixertrackpart.h"
#include "mixertrackgroup.h"
#include "mixertrack.h"
#include "mixertrackitem.h"
#include "libmscore/instrument.h"
namespace Ms {
class MidiMapping;
class MixerTrackItem;
//---------------------------------------------------------
// MixerTrackPart
//---------------------------------------------------------
class MixerTrackPart : public QWidget, public Ui::MixerTrackPart, public ChannelListener, public MixerTrack
{
Q_OBJECT
MixerTrackItemPtr _mti;
bool _selected;
static const QString unselStyleDark;
static const QString selStyleDark;
static const QString unselStyleLight;
static const QString selStyleLight;
static const QString sliderStyle;
MixerTrackGroup* _group;
void updateNameLabel();
signals:
void selectedChanged(bool);
public slots:
void updateSolo(bool);
void updateMute(bool);
void setSelected(bool) override;
void volumeChanged(double);
void panChanged(double);
void expandToggled(bool);
void controlSelected();
void applyStyle();
protected:
void mouseReleaseEvent(QMouseEvent * event) override;
void propertyChanged(Channel::Prop property) override;
void disconnectChannelListener() override;
public:
explicit MixerTrackPart(QWidget *parent, MixerTrackItemPtr trackItem, bool expanded);
~MixerTrackPart() override;
bool selected() override { return _selected; }
QWidget* getWidget() override { return this; }
MixerTrackGroup* group() override { return _group; }
MixerTrackItemPtr mti() override { return _mti; }
void setGroup(MixerTrackGroup* group) { _group = group; }
void paintEvent(QPaintEvent* evt) override;
};
}
#endif // __MIXERTRACKPART_H__

340
mscore/mixertrackpart.ui Normal file
View file

@ -0,0 +1,340 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MixerTrackPart</class>
<widget class="QWidget" name="MixerTrackPart">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>80</width>
<height>383</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>80</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>80</width>
<height>16777215</height>
</size>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<property name="styleSheet">
<string notr="true">#controlWidget {
background: #444;
border-left: 2px solid #888;
border-top: 2px solid #888;
border-right: 2px solid #111;
border-bottom: 2px solid #111;
}
#expandBn {
color:white;
}</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QWidget" name="controlWidget" native="true">
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>2</number>
</property>
<property name="topMargin">
<number>2</number>
</property>
<property name="rightMargin">
<number>2</number>
</property>
<property name="bottomMargin">
<number>2</number>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="expandBn">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>28</height>
</size>
</property>
<property name="toolTip">
<string>Show Channels</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="musescore.qrc">
<normaloff>:/data/icons/go-next.svg</normaloff>
<normalon>:/data/icons/go-previous.svg</normalon>:/data/icons/go-next.svg</iconset>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="2" column="0">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="soloBn">
<property name="toolTip">
<string>Solo</string>
</property>
<property name="styleSheet">
<string notr="true">.QPushButton {
border: none;
background-color: none;
}
</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="musescore.qrc">
<normaloff>:/data/icons/mixer-solo-off.svg</normaloff>
<normalon>:/data/icons/mixer-solo-on.svg</normalon>:/data/icons/mixer-solo-off.svg</iconset>
</property>
<property name="iconSize">
<size>
<width>32</width>
<height>32</height>
</size>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item row="2" column="2">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="3" column="1">
<widget class="Awl::Knob" name="panSlider" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>40</width>
<height>40</height>
</size>
</property>
<property name="toolTip">
<string>Pan</string>
</property>
<property name="maxValue" stdset="0">
<double>127.000000000000000</double>
</property>
<property name="scaleValueColor" stdset="0">
<color>
<red>51</red>
<green>170</green>
<blue>255</blue>
</color>
</property>
<property name="scaleColor" stdset="0">
<color>
<red>17</red>
<green>17</green>
<blue>17</blue>
</color>
</property>
<property name="knobIcon" stdset="0">
<iconset resource="musescore.qrc">
<normaloff>:/data/icons/mixer-dial.svg</normaloff>:/data/icons/mixer-dial.svg</iconset>
</property>
<property name="minValue" stdset="0">
<double>0.000000000000000</double>
</property>
<property name="value" stdset="0">
<double>63.500000000000000</double>
</property>
<property name="center" stdset="0">
<bool>true</bool>
</property>
<property name="lineStep" stdset="0">
<double>1.000000000000000</double>
</property>
<property name="pageStep" stdset="0">
<double>10.000000000000000</double>
</property>
<property name="enableMouseWheel" stdset="0">
<bool>false</bool>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QPushButton" name="muteBn">
<property name="toolTip">
<string>Mute</string>
</property>
<property name="styleSheet">
<string notr="true">.QPushButton {
border: none;
background-color: none;
}
</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="musescore.qrc">
<normaloff>:/data/icons/mixer-mute-off.svg</normaloff>
<normalon>:/data/icons/mixer-mute-on.svg</normalon>:/data/icons/mixer-mute-off.svg</iconset>
</property>
<property name="iconSize">
<size>
<width>32</width>
<height>32</height>
</size>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="Awl::StyledSlider" name="volumeSlider" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>200</height>
</size>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="trackLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Part Name</string>
</property>
<property name="styleSheet">
<string notr="true">.QLabel {
border: 2px solid black;
background: red;
color: white;
padding: 6px 0px;
}
</string>
</property>
<property name="text">
<string>Part Name</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>Awl::StyledSlider</class>
<extends>QWidget</extends>
<header>awl/styledslider.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>Awl::Knob</class>
<extends>QWidget</extends>
<header>awl/knob.h</header>
</customwidget>
</customwidgets>
<resources>
<include location="musescore.qrc"/>
</resources>
<connections/>
</ui>

View file

@ -2355,7 +2355,7 @@ void MuseScore::setCurrentScoreView(ScoreView* view)
if (selectionWindow)
selectionWindow->setScore(cs);
if (mixer)
mixer->updateAll(cs ? cs->masterScore() : nullptr);
mixer->setScore(cs ? cs->masterScore() : nullptr);
#ifdef OMR
if (omrPanel) {
if (cv && cv->omrView())
@ -4214,7 +4214,7 @@ void MuseScore::play(Element* e) const
Instrument* instr = part->instrument(tick);
for (Note* n : c->notes()) {
const Channel* channel = instr->channel(n->subchannel());
seq->startNote(channel->channel, n->ppitch(), 80, n->tuning());
seq->startNote(channel->channel(), n->ppitch(), 80, n->tuning());
}
seq->startNoteTimer(MScore::defaultPlayDuration);
}
@ -4231,7 +4231,7 @@ void MuseScore::play(Element* e, int pitch) const
tick = 0;
Instrument* instr = note->part()->instrument(tick);
const Channel* channel = instr->channel(note->subchannel());
seq->startNote(channel->channel, pitch, 80, MScore::defaultPlayDuration, note->tuning());
seq->startNote(channel->channel(), pitch, 80, MScore::defaultPlayDuration, note->tuning());
}
}
@ -5579,7 +5579,7 @@ void MuseScore::cmd(QAction* a, const QString& cmd)
if (cmd == "instruments") {
editInstrList();
if (mixer)
mixer->updateAll(cs->masterScore());
mixer->setScore(cs->masterScore());
}
else if (cmd == "rewind") {
if (cs) {
@ -6050,7 +6050,7 @@ void MuseScore::noteTooShortForTupletDialog()
void MuseScore::instrumentChanged()
{
if (mixer)
mixer->updateAll(cs->masterScore());
mixer->setScore(cs->masterScore());
}
//---------------------------------------------------------
@ -6463,8 +6463,8 @@ bool MuseScore::saveMp3(Score* score, const QString& name)
for (MidiCoreEvent e : a->init) {
if (e.type() == ME_INVALID)
continue;
e.setChannel(a->channel);
int syntiIdx= synth->index(score->masterScore()->midiMapping(a->channel)->articulation->synti);
e.setChannel(a->channel());
int syntiIdx= synth->index(score->masterScore()->midiMapping(a->channel())->articulation->synti());
synth->play(e, syntiIdx);
}
}
@ -6515,8 +6515,8 @@ bool MuseScore::saveMp3(Score* score, const QString& name)
if (e.isChannelEvent()) {
int channelIdx = e.channel();
Channel* c = score->masterScore()->midiMapping(channelIdx)->articulation;
if (!c->mute) {
synth->play(e, synth->index(c->synti));
if (!c->mute()) {
synth->play(e, synth->index(c->synti()));
}
}
}

View file

@ -165,5 +165,12 @@
<file>data/icons/mail.svg</file>
<file>data/icons/bug.svg</file>
<file>data/icons/note_timewise.svg</file>
<file>data/icons/mixer-slider-handle.svg</file>
<file>data/icons/mixer-mute-off.svg</file>
<file>data/icons/mixer-mute-on.svg</file>
<file>data/icons/mixer-solo-off.svg</file>
<file>data/icons/mixer-solo-on.svg</file>
<file>data/icons/mixer-dial.svg</file>
<file>data/icons/mixer-slider-handle-vertical.svg</file>
</qresource>
</RCC>

View file

@ -29,6 +29,7 @@
#include "libmscore/note.h"
#include "libmscore/undo.h"
#include "mixer.h"
#include "parteditbase.h"
#include "scoreview.h"
#include "playpanel.h"
#include "preferences.h"
@ -294,10 +295,10 @@ void MuseScore::oscVolChannel(double val)
MidiMapping mm = mms->at(i);
Channel* channel = mm.articulation;
int iv = lrint(val*127);
seq->setController(channel->channel, CTRL_VOLUME, iv);
channel->volume = iv;
seq->setController(channel->channel(), CTRL_VOLUME, iv);
channel->setVolume(val * 100.0);
if (mixer)
mixer->partEdit(i)->volume->setValue(iv);
mixer->getPartAtIndex(i)->volume->setValue(val * 100.0);
}
}
@ -317,10 +318,10 @@ void MuseScore::oscPanChannel(double val)
MidiMapping mm = mms->at(i);
Channel* channel = mm.articulation;
int iv = lrint((val + 1) * 64);
seq->setController(channel->channel, CTRL_PANPOT, iv);
channel->volume = iv;
seq->setController(channel->channel(), CTRL_PANPOT, iv);
channel->setPan(val * 180.0);
if (mixer)
mixer->partEdit(i)->pan->setValue(iv);
mixer->getPartAtIndex(i)->pan->setValue(val * 100.0);
}
}
@ -339,9 +340,9 @@ void MuseScore::oscMuteChannel(double val)
if (i >= 0 && i < mms->size()) {
MidiMapping mm = mms->at(i);
Channel* channel = mm.articulation;
channel->mute = (val==0.0f ? false : true);
channel->setMute(val==0.0f ? false : true);
if (mixer)
mixer->partEdit(i)->mute->setChecked(channel->mute);
mixer->getPartAtIndex(i)->mute->setChecked(channel->mute());
}
}
#endif // #ifndef OSC

553
mscore/parteditbase.cpp Normal file
View file

@ -0,0 +1,553 @@
//=============================================================================
// MuseScore
// Linux Music Score Editor
// $Id: mixer.cpp 5651 2012-05-19 15:57:26Z lasconic $
//
// Copyright (C) 2002-2016 Werner Schweer and others
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.
//
// This program 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 this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#include "musescore.h"
#include "parteditbase.h"
#include "libmscore/score.h"
#include "libmscore/part.h"
#include "mixer.h"
#include "seq.h"
#include "libmscore/undo.h"
#include "synthcontrol.h"
#include "synthesizer/msynthesizer.h"
#include "preferences.h"
#include <qmessagebox.h>
#include <accessibletoolbutton.h>
namespace Ms {
#define _setValue(__x, __y) \
__x->blockSignals(true); \
__x->setValue(__y); \
__x->blockSignals(false);
#define _setChecked(__x, __y) \
__x->blockSignals(true); \
__x->setChecked(__y); \
__x->blockSignals(false);
//---------------------------------------------------------
// PartEdit
//---------------------------------------------------------
PartEdit::PartEdit(QWidget* parent)
: QWidget(parent, Qt::Dialog)
{
setupUi(this);
connect(patch, SIGNAL(activated(int)), SLOT(patchChanged(int)));
connect(volume, SIGNAL(valueChanged(double,int)), SLOT(volChanged(double)));
connect(pan, SIGNAL(valueChanged(double,int)), SLOT(panChanged(double)));
connect(chorus, SIGNAL(valueChanged(double,int)), SLOT(chorusChanged(double)));
connect(reverb, SIGNAL(valueChanged(double,int)), SLOT(reverbChanged(double)));
connect(mute, SIGNAL(toggled(bool)), SLOT(muteChanged(bool)));
connect(solo, SIGNAL(toggled(bool)), SLOT(soloToggled(bool)));
connect(drumset, SIGNAL(toggled(bool)), SLOT(drumsetToggled(bool)));
connect(portSpinBox, SIGNAL(valueChanged(int)), SLOT(midiChannelChanged(int)));
connect(channelSpinBox, SIGNAL(valueChanged(int)), SLOT(midiChannelChanged(int)));
connect(expand, SIGNAL(toggled(bool)), SLOT(expandToggled(bool)));
expandToggled(false);
}
//---------------------------------------------------------
// expandToggled
//---------------------------------------------------------
void PartEdit::expandToggled(bool val)
{
details->setVisible(val);
}
//---------------------------------------------------------
// setPart
//---------------------------------------------------------
void PartEdit::setPart(Part* p, Channel* a)
{
Channel dummy;
channel = a;
part = p;
QString s = part->partName();
if (!a->name().isEmpty()) {
if (a->name() != Channel::DEFAULT_NAME) {
s += "-";
s += qApp->translate("InstrumentsXML", a->name().toUtf8().data());
}
}
partName->setText(s);
_setValue(volume, a->volume());
volume->setDclickValue1(dummy.volume());
volume->setDclickValue2(dummy.volume());
_setValue(reverb, a->reverb());
reverb->setDclickValue1(dummy.reverb());
reverb->setDclickValue2(dummy.reverb());
_setValue(chorus, a->chorus());
chorus->setDclickValue1(dummy.chorus());
chorus->setDclickValue2(dummy.chorus());
_setValue(pan, a->pan());
pan->setDclickValue1(0);
pan->setDclickValue2(0);
for (int i = 0; i < patch->count(); ++i) {
MidiPatch* mp = (MidiPatch*)patch->itemData(i, Qt::UserRole).value<void*>();
if (a->synti() == mp->synti && a->program() == mp->prog && a->bank() == mp->bank) {
patch->setCurrentIndex(i);
break;
}
}
_setChecked(drumset, p->instrument()->useDrumset());
_setValue(portSpinBox, part->masterScore()->midiMapping(a->channel())->port + 1);
_setValue(channelSpinBox, part->masterScore()->midiMapping(a->channel())->channel + 1);
QHBoxLayout* hb = voiceButtonBox;
int idx = 0;
for (Staff* staff : *part->staves()) {
for (int voice = 0; voice < VOICES; ++voice) {
if (!voiceButtons.value(idx)) {
QToolButton* tb = new QToolButton;
tb->setText(QString("%1").arg(voice+1));
tb->setCheckable(true);
tb->setChecked(staff->playbackVoice(voice));
tb->setFocusPolicy(Qt::ClickFocus);
tb->setToolButtonStyle(Qt::ToolButtonTextOnly);
QPalette pal(tb->palette());
pal.setColor(QPalette::Base, MScore::selectColor[voice]);
tb->setPalette(pal);
hb->addWidget(tb);
voiceButtons.append(tb);
connect(tb, SIGNAL(clicked()), SLOT(playbackVoiceChanged()));
}
++idx;
}
hb->addStretch(5);
}
while (voiceButtons.value(idx)) {
QToolButton* tb = voiceButtons.value(idx);
if (!tb)
break;
voiceButtons.takeAt(idx);
delete tb;
}
}
//---------------------------------------------------------
// playbackVoiceChanged
//---------------------------------------------------------
void PartEdit::playbackVoiceChanged()
{
int idx = 0;
Score* score = part->score();
score->startCmd();
for (Staff* staff : *part->staves()) {
for (int voice = 0; voice < VOICES; ++voice) {
QToolButton* tb = voiceButtons[idx];
bool val = tb->isChecked();
if (val != staff->playbackVoice(voice)) {
switch (voice) {
case 0:
printf("undo\n");
staff->undoChangeProperty(Pid::PLAYBACK_VOICE1, val);
break;
case 1:
staff->undoChangeProperty(Pid::PLAYBACK_VOICE2, val);
break;
case 2:
staff->undoChangeProperty(Pid::PLAYBACK_VOICE3, val);
break;
case 3:
staff->undoChangeProperty(Pid::PLAYBACK_VOICE4, val);
break;
}
}
++idx;
}
}
score->endCmd();
}
//---------------------------------------------------------
// patchChanged
//---------------------------------------------------------
void PartEdit::patchChanged(int n, bool syncControls)
{
if (part == 0)
return;
const MidiPatch* p = (MidiPatch*)patch->itemData(n, Qt::UserRole).value<void*>();
if (p == 0) {
qDebug("PartEdit::patchChanged: no patch");
return;
}
Score* score = part->score();
if (score) {
score->startCmd();
score->undo(new ChangePatch(score, channel, p));
score->setLayoutAll();
score->endCmd();
}
channel->updateInitList();
sync(syncControls);
}
//---------------------------------------------------------
// volChanged
//---------------------------------------------------------
void PartEdit::volChanged(double val, bool syncControls)
{
int iv = lrint(val);
seq->setController(channel->channel(), CTRL_VOLUME, iv);
channel->setVolume(iv);
channel->updateInitList();
sync(syncControls);
}
//---------------------------------------------------------
// panChanged
//---------------------------------------------------------
void PartEdit::panChanged(double val, bool syncControls)
{
int iv = lrint(val);
seq->setController(channel->channel(), CTRL_PANPOT, iv);
channel->setPan(iv);
channel->updateInitList();
sync(syncControls);
}
//---------------------------------------------------------
// reverbChanged
//---------------------------------------------------------
void PartEdit::reverbChanged(double val, bool syncControls)
{
int iv = lrint(val);
seq->setController(channel->channel(), CTRL_REVERB_SEND, iv);
channel->setReverb(iv);
channel->updateInitList();
sync(syncControls);
}
//---------------------------------------------------------
// chorusChanged
//---------------------------------------------------------
void PartEdit::chorusChanged(double val, bool syncControls)
{
int iv = lrint(val);
seq->setController(channel->channel(), CTRL_CHORUS_SEND, iv);
channel->setChorus(iv);
channel->updateInitList();
sync(syncControls);
}
//---------------------------------------------------------
// muteChanged
//---------------------------------------------------------
void PartEdit::muteChanged(bool val, bool syncControls)
{
if (val)
seq->stopNotes(channel->channel());
channel->setMute(val);
sync(syncControls);
}
//---------------------------------------------------------
// soloToggled
//---------------------------------------------------------
void PartEdit::soloToggled(bool val, bool syncControls)
{
channel->setSolo(val);
channel->setSoloMute(!val);
if (val) {
mute->setChecked(false);
for (Part* p : part->score()->parts()) {
const InstrumentList* il = p->instruments();
for (auto i = il->begin(); i != il->end(); ++i) {
const Instrument* instr = i->second;
for (Channel* a : instr->channel()) {
a->setSoloMute((channel != a && !a->solo()));
a->setSolo(channel == a || a->solo());
if (a->soloMute())
seq->stopNotes(a->channel());
}
}
}
emit soloChanged(true);
}
else { //do nothing except if it's the last solo to be switched off
bool found = false;
for (Part* p : part->score()->parts()) {
const InstrumentList* il = p->instruments();
for (auto i = il->begin(); i != il->end(); ++i) {
const Instrument* instr = i->second;
for (Channel* a : instr->channel()) {
if (a->solo()){
found = true;
break;
}
}
}
}
if (!found){
foreach(Part* p, part->score()->parts()) {
const InstrumentList* il = p->instruments();
for (auto i = il->begin(); i != il->end(); ++i) {
const Instrument* instr = i->second;
for (Channel* a : instr->channel()) {
a->setSoloMute(false);
a->setSolo(false);
}
}
}
emit soloChanged(false);
}
}
sync(syncControls);
}
//---------------------------------------------------------
// drumsetToggled
//---------------------------------------------------------
void PartEdit::drumsetToggled(bool val, bool syncControls)
{
if (part == 0)
return;
Score* score = part->score();
score->startCmd();
part->undoChangeProperty(Pid::USE_DRUMSET, val);
patch->clear();
const QList<MidiPatch*> pl = synti->getPatchInfo();
for (const MidiPatch* p : pl) {
if (p->drum == val)
patch->addItem(p->name, QVariant::fromValue<void*>((void*)p));
}
// switch to first instrument
const MidiPatch* p = (MidiPatch*)patch->itemData(0, Qt::UserRole).value<void*>();
if (p == 0) {
qDebug("PartEdit::patchChanged: no patch");
return;
}
score->undo(new ChangePatch(score, channel, p));
score->setLayoutAll();
score->endCmd();
sync(syncControls);
}
//---------------------------------------------------------
// sync
// synchronizes controls with same MIDI port and channel
//---------------------------------------------------------
void PartEdit::sync(bool syncControls)
{
if (!syncControls)
return;
int count = this->parentWidget()->layout()->count();
for(int i = 0; i < count; i++) {
QWidgetItem* wi = (QWidgetItem*)(this->parentWidget()->layout()->itemAt(i));
PartEdit* pe = (PartEdit*)(wi->widget());
if (pe != 0 && pe != this
&& this->channelSpinBox->value() == pe->channelSpinBox->value()
&& this->portSpinBox->value() == pe->portSpinBox->value()) {
if (volume->value() != pe->volume->value()) {
_setValue(pe->volume, this->volume->value());
emit pe->volChanged(this->volume->value(), false);
}
if (pan->value() != pe->pan->value()) {
_setValue(pe->pan, this->pan->value());
emit pe->panChanged(this->pan->value(), false);
}
if (reverb->value() != pe->reverb->value()) {
_setValue(pe->reverb, this->reverb->value());
emit pe->reverbChanged(this->reverb->value(), false);
}
if (chorus->value() != pe->chorus->value()) {
_setValue(pe->chorus, this->chorus->value());
emit pe->chorusChanged(this->chorus->value(), false);
}
if (mute->isChecked() != pe->mute->isChecked()) {
_setChecked(pe->mute, channel->mute());
emit pe->muteChanged(channel->mute(), false);
}
if (solo->isChecked() != pe->solo->isChecked()) {
_setChecked(pe->solo, channel->solo());
emit pe->soloToggled(channel->solo(), false);
}
if (drumset->isChecked() != pe->drumset->isChecked()) {
_setChecked(pe->drumset, drumset->isChecked());
emit pe->drumsetToggled(drumset->isChecked(), false);
}
if (patch->currentIndex() != pe->patch->currentIndex()) {
pe->patch->blockSignals(true);
pe->patch->setCurrentIndex(this->patch->currentIndex());
pe->patch->blockSignals(false);
}
}
}
}
//---------------------------------------------------------
// midiChannelChanged
// handles MIDI port & channel change
//---------------------------------------------------------
void PartEdit::midiChannelChanged(int)
{
if (part == 0)
return;
seq->stopNotes(channel->channel());
int p = portSpinBox->value() - 1;
int c = channelSpinBox->value() - 1;
// 1 is for going up, -1 for going down
int direction = copysign(1, c - part->masterScore()->midiMapping(channel->channel())->channel);
// Channel 9 is special for drums
if (part->instrument()->useDrumset() && c != 9) {
_setValue(channelSpinBox, 10);
return;
}
else if (!part->instrument()->useDrumset() && c == 9) {
c = 9 + direction;
}
if (c == 16) {
c = 0;
p++;
}
int newChannel = p*16+c;
// If there is an instrument with the same MIDI port and channel, sync this instrument to a found one
bool needSync = true;
int elementsInMixer = parentWidget()->layout()->count();
for (int i = 0; i < elementsInMixer; i++) {
QWidgetItem* wi = (QWidgetItem*)(this->parentWidget()->layout()->itemAt(i));
PartEdit* pe = (PartEdit*)(wi->widget());
if (pe != 0 && pe != this
&& pe->channelSpinBox->value() == this->channelSpinBox->value()
&& pe->portSpinBox->value() == this->portSpinBox->value()) {
// Show datails if parameters are different
QString detailedText;
if (patch->currentIndex() != pe->patch->currentIndex())
detailedText += QString(tr("Sound: '%1'' vs '%2'\n")).arg(patch->itemText(patch->currentIndex()), pe->patch->itemText(pe->patch->currentIndex()));
if (this->volume->value() != pe->volume->value())
detailedText += QString(tr("Volume: %1 vs %2\n")).arg(QString::number(volume->value()), QString::number(pe->volume->value()));
if (this->pan->value() != pe->pan->value())
detailedText += QString(tr("Pan: %1 vs %2\n")).arg(QString::number(pan->value()), QString::number(pe->pan->value()));
if (this->reverb->value() != pe->reverb->value())
detailedText += QString(tr("Reverb: %1 vs %2\n")).arg(QString::number(reverb->value()), QString::number(pe->reverb->value()));
if (this->chorus->value() != pe->chorus->value())
detailedText += QString(tr("Chorus: %1 vs %2\n")).arg(QString::number(chorus->value()), QString::number(pe->chorus->value()));
if (this->solo->isChecked() != pe->solo->isChecked())
detailedText += QString(tr("Solo: %1 vs %2\n")).arg(solo->isChecked()?"Yes":"No", pe->solo->isChecked()?"Yes":"No");
if (this->mute->isChecked() != pe->mute->isChecked())
detailedText += QString(tr("Mute: %1 vs %2\n")).arg(mute->isChecked()?"Yes":"No", pe->mute->isChecked()?"Yes":"No");
if (!detailedText.isEmpty())
detailedText = QString(tr("Instrument '%1' Instrument '%2'\n")).arg(this->partName->text(), pe->partName->text())+ detailedText;
QMessageBox msgBox;
msgBox.setIcon(QMessageBox::Warning);
QString text = QString(tr("There is already an instrument '%1' with MIDI port = %2 and channel = %3.")).arg(pe->partName->text(), QString::number(pe->portSpinBox->value()), QString::number(pe->channelSpinBox->value()));
msgBox.setText(text);
msgBox.setInformativeText(tr("Do you want to synchronize current instrument with an existing one?"));
msgBox.setDetailedText(detailedText);
msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
QPushButton *assignFreeChannel = msgBox.addButton(tr("Assign next free MIDI channel"), QMessageBox::HelpRole);
msgBox.setDefaultButton(QMessageBox::Ok);
if (msgBox.exec() == QMessageBox::Cancel) {
_setValue(channelSpinBox, part->masterScore()->midiMapping(channel->channel())->channel + 1);
_setValue(portSpinBox, part->masterScore()->midiMapping(channel->channel())->port + 1);
needSync = false;
break;
}
if (msgBox.clickedButton() == assignFreeChannel) {
newChannel = part->masterScore()->getNextFreeMidiMapping();
break;
}
// Sync
_setValue(channelSpinBox, newChannel % 16 + 1);
_setValue(portSpinBox, newChannel / 16 + 1);
part->masterScore()->midiMapping(channel->channel())->channel = newChannel % 16;
part->masterScore()->midiMapping(channel->channel())->port = newChannel / 16;
channel->setVolume(lrint(pe->volume->value()));
channel->setPan(lrint(pe->pan->value()));
channel->setReverb(lrint(pe->reverb->value()));
channel->setChorus(lrint(pe->chorus->value()));
channel->setMute(pe->mute->isChecked());
channel->setSolo(pe->solo->isChecked());
MidiPatch* newPatch = (MidiPatch*)pe->patch->itemData(pe->patch->currentIndex(), Qt::UserRole).value<void*>();
if (newPatch == 0)
return;
patch->setCurrentIndex(pe->patch->currentIndex());
channel->setProgram(newPatch->prog);
channel->setBank(newPatch->bank);
channel->setSynti(newPatch->synti);
part->masterScore()->setSoloMute();
part->score()->setInstrumentsChanged(true);
part->score()->setLayoutAll();
break;
}
}
channel->updateInitList();
if (needSync) {
_setValue(channelSpinBox, newChannel % 16 + 1);
_setValue(portSpinBox, newChannel / 16 + 1);
part->masterScore()->midiMapping(channel->channel())->channel = newChannel % 16;
part->masterScore()->midiMapping(channel->channel())->port = newChannel / 16;
part->score()->setInstrumentsChanged(true);
part->score()->setLayoutAll();
seq->initInstruments();
}
else {
// Initializing an instrument with new channel
foreach(const MidiCoreEvent& e, channel->init) {
if (e.type() == ME_INVALID)
continue;
NPlayEvent event(e.type(), channel->channel(), e.dataA(), e.dataB());
seq->sendEvent(event);
}
}
// Update MIDI Out ports
int maxPort = max(p, part->score()->masterScore()->midiPortCount());
part->score()->masterScore()->setMidiPortCount(maxPort);
if (seq->driver() && (preferences.getBool(PREF_IO_JACK_USEJACKMIDI) || preferences.getBool(PREF_IO_ALSA_USEALSAAUDIO)))
seq->driver()->updateOutPortCount(maxPort + 1);
}
}

74
mscore/parteditbase.h Normal file
View file

@ -0,0 +1,74 @@
//=============================================================================
// MuseScore
// Linux Music Score Editor
// $Id: mixer.h 4388 2011-06-18 13:17:58Z wschweer $
//
// Copyright (C) 2002-2016 Werner Schweer and others
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2.
//
// This program 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 this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//=============================================================================
#ifndef __PARTEDITBASE_H__
#define __PARTEDITBASE_H__
#include "ui_parteditbase.h"
#include "libmscore/instrument.h"
#include "enableplayforwidget.h"
namespace Ms {
class Score;
class Channel;
class Part;
//---------------------------------------------------------
// PartEdit
// deprecated
// TODO: This class should no longer be used and will be removed at a future date
//---------------------------------------------------------
class PartEdit : public QWidget, public Ui::PartEditBase {
Q_OBJECT
Channel* channel;
Part* part;
QList<QToolButton*> voiceButtons;
private slots:
void patchChanged(int, bool syncControls = true);
void volChanged(double, bool syncControls = true);
void panChanged(double, bool syncControls = true);
void reverbChanged(double, bool syncControls = true);
void chorusChanged(double, bool syncControls = true);
void muteChanged(bool, bool syncControls = true);
void soloToggled(bool, bool syncControls = true);
void drumsetToggled(bool, bool syncControls = true);
void midiChannelChanged(int);
void sync(bool syncControls);
void expandToggled(bool);
void playbackVoiceChanged();
public slots:
signals:
void soloChanged(bool);
public:
PartEdit(QWidget* parent = 0);
void setPart(Part*, Channel*);
};
}
#endif // __PARTEDITBASE_H__

623
mscore/parteditbase.ui Normal file
View file

@ -0,0 +1,623 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>PartEditBase</class>
<widget class="QWidget" name="PartEditBase">
<property name="enabled">
<bool>true</bool>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>696</width>
<height>387</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="focusPolicy">
<enum>Qt::ClickFocus</enum>
</property>
<property name="windowTitle">
<string/>
</property>
<layout class="QVBoxLayout">
<property name="spacing">
<number>3</number>
</property>
<property name="leftMargin">
<number>1</number>
</property>
<property name="topMargin">
<number>1</number>
</property>
<property name="rightMargin">
<number>1</number>
</property>
<property name="bottomMargin">
<number>1</number>
</property>
<item>
<widget class="QGroupBox" name="groupBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string/>
</property>
<property name="flat">
<bool>true</bool>
</property>
<layout class="QGridLayout">
<property name="leftMargin">
<number>1</number>
</property>
<property name="topMargin">
<number>1</number>
</property>
<property name="rightMargin">
<number>1</number>
</property>
<property name="bottomMargin">
<number>1</number>
</property>
<property name="spacing">
<number>0</number>
</property>
<item row="0" column="0">
<widget class="QLineEdit" name="partName">
<property name="toolTip">
<string>Part name</string>
</property>
<property name="accessibleName">
<string>Part Name</string>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="1" rowspan="4">
<layout class="QGridLayout">
<property name="sizeConstraint">
<enum>QLayout::SetFixedSize</enum>
</property>
<property name="spacing">
<number>0</number>
</property>
<item row="0" column="0">
<widget class="Awl::Knob" name="volume" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Ignored">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>50</width>
<height>16777215</height>
</size>
</property>
<property name="focusPolicy">
<enum>Qt::TabFocus</enum>
</property>
<property name="toolTip">
<string>Volume</string>
</property>
<property name="accessibleName">
<string>Volume</string>
</property>
<property name="accessibleDescription">
<string>Use arrows to modify</string>
</property>
<property name="invertedAppearance" stdset="0">
<bool>false</bool>
</property>
<property name="scaleWidth" stdset="0">
<number>5</number>
</property>
<property name="scaleValueColor" stdset="0">
<color>
<red>238</red>
<green>80</green>
<blue>54</blue>
</color>
</property>
<property name="maxValue" stdset="0">
<double>127.000000000000000</double>
</property>
<property name="lineStep" stdset="0">
<double>1.000000000000000</double>
</property>
<property name="pageStep" stdset="0">
<double>10.000000000000000</double>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="Awl::MidiPanKnob" name="pan" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Ignored">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>50</width>
<height>16777215</height>
</size>
</property>
<property name="focusPolicy">
<enum>Qt::TabFocus</enum>
</property>
<property name="toolTip">
<string>Panorama position</string>
</property>
<property name="accessibleName">
<string>Panorama position</string>
</property>
<property name="accessibleDescription">
<string>Use arrows to modify</string>
</property>
<property name="scaleWidth" stdset="0">
<number>5</number>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="Awl::Knob" name="reverb" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Ignored">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>50</width>
<height>16777215</height>
</size>
</property>
<property name="focusPolicy">
<enum>Qt::TabFocus</enum>
</property>
<property name="toolTip">
<string>Reverb</string>
</property>
<property name="accessibleName">
<string>Reverb</string>
</property>
<property name="accessibleDescription">
<string>Use arrows to modify</string>
</property>
<property name="scaleWidth" stdset="0">
<number>5</number>
</property>
<property name="maxValue" stdset="0">
<double>127.000000000000000</double>
</property>
<property name="lineStep" stdset="0">
<double>1.000000000000000</double>
</property>
<property name="pageStep" stdset="0">
<double>10.000000000000000</double>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="Awl::Knob" name="chorus" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Ignored">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>50</width>
<height>16777215</height>
</size>
</property>
<property name="focusPolicy">
<enum>Qt::TabFocus</enum>
</property>
<property name="toolTip">
<string>Chorus</string>
</property>
<property name="accessibleName">
<string>Chorus</string>
</property>
<property name="accessibleDescription">
<string>Use arrows to modify</string>
</property>
<property name="scaleWidth" stdset="0">
<number>5</number>
</property>
<property name="maxValue" stdset="0">
<double>127.000000000000000</double>
</property>
<property name="lineStep" stdset="0">
<double>1.000000000000000</double>
</property>
<property name="pageStep" stdset="0">
<double>10.000000000000000</double>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>50</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Vol</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="label_3">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>50</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Pan</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QLabel" name="label_4">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>50</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Rev</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QLabel" name="label_5">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>50</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Cho</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="0">
<layout class="QHBoxLayout" name="midiportchannel">
<property name="spacing">
<number>5</number>
</property>
</layout>
</item>
<item row="1" column="0">
<layout class="QHBoxLayout">
<item>
<widget class="QToolButton" name="expand">
<property name="statusTip">
<string>show details</string>
</property>
<property name="text">
<string>+</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="mute">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>40</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>mute</string>
</property>
<property name="accessibleName">
<string>Mute</string>
</property>
<property name="text">
<string>M</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="solo">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>40</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>solo</string>
</property>
<property name="accessibleName">
<string>Solo</string>
</property>
<property name="text">
<string>S</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="patch">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>MIDI sound</string>
</property>
<property name="accessibleName">
<string>Sound</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="drumset">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Drumset</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="4" column="0" colspan="2">
<widget class="QWidget" name="details" native="true">
<property name="minimumSize">
<size>
<width>0</width>
<height>42</height>
</size>
</property>
<layout class="QGridLayout" name="gridLayout2">
<item row="0" column="1">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Midi: </string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLabel" name="portLabel">
<property name="text">
<string>Port:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Voice Playback:</string>
</property>
</widget>
</item>
<item row="0" column="4">
<widget class="QLabel" name="channelLabel">
<property name="text">
<string>Channel:</string>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QSpinBox" name="portSpinBox">
<property name="minimum">
<number>1</number>
</property>
</widget>
</item>
<item row="0" column="5">
<widget class="QSpinBox" name="channelSpinBox">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>17</number>
</property>
</widget>
</item>
<item row="1" column="2" colspan="4">
<layout class="QHBoxLayout" name="voiceButtonBox"/>
</item>
<item row="0" column="6">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>134</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="0">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>Awl::MidiPanKnob</class>
<extends>QWidget</extends>
<header>awl/midipanknob.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>Awl::Knob</class>
<extends>QWidget</extends>
<header>awl/knob.h</header>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>partName</tabstop>
<tabstop>patch</tabstop>
<tabstop>volume</tabstop>
<tabstop>pan</tabstop>
<tabstop>reverb</tabstop>
<tabstop>chorus</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>

View file

@ -576,7 +576,7 @@ void PianorollEditor::velocityChanged(int val)
void PianorollEditor::keyPressed(int p)
{
seq->startNote(staff->part()->instrument()->channel(0)->channel, p, 80, 0, 0.0);
seq->startNote(staff->part()->instrument()->channel(0)->channel(), p, 80, 0, 0.0);
}
//---------------------------------------------------------

View file

@ -517,7 +517,7 @@ void Seq::playEvent(const NPlayEvent& event, unsigned framePos)
Staff* staff = note->staff();
Instrument* instr = staff->part()->instrument(note->chord()->tick());
const Channel* a = instr->channel(note->subchannel());
mute = a->mute || a->soloMute || !staff->playbackVoice(note->voice());
mute = a->mute() || a->soloMute() || !staff->playbackVoice(note->voice());
}
if (!mute)
putEvent(event, framePos);
@ -964,7 +964,7 @@ void Seq::initInstruments(bool realTime)
for (const MidiCoreEvent& e : channel->init) {
if (e.type() == ME_INVALID)
continue;
NPlayEvent event(e.type(), channel->channel, e.dataA(), e.dataB());
NPlayEvent event(e.type(), channel->channel(), e.dataA(), e.dataB());
if (realTime)
putEvent(event);
else
@ -973,18 +973,18 @@ void Seq::initInstruments(bool realTime)
// Setting pitch bend sensitivity to 12 semitones for external synthesizers
if ((preferences.getBool(PREF_IO_JACK_USEJACKMIDI) || preferences.getBool(PREF_IO_ALSA_USEALSAAUDIO)) && mm.channel != 9) {
if (realTime) {
putEvent(NPlayEvent(ME_CONTROLLER, channel->channel, CTRL_LRPN, 0));
putEvent(NPlayEvent(ME_CONTROLLER, channel->channel, CTRL_HRPN, 0));
putEvent(NPlayEvent(ME_CONTROLLER, channel->channel, CTRL_HDATA,12));
putEvent(NPlayEvent(ME_CONTROLLER, channel->channel, CTRL_LRPN, 127));
putEvent(NPlayEvent(ME_CONTROLLER, channel->channel, CTRL_HRPN, 127));
putEvent(NPlayEvent(ME_CONTROLLER, channel->channel(), CTRL_LRPN, 0));
putEvent(NPlayEvent(ME_CONTROLLER, channel->channel(), CTRL_HRPN, 0));
putEvent(NPlayEvent(ME_CONTROLLER, channel->channel(), CTRL_HDATA,12));
putEvent(NPlayEvent(ME_CONTROLLER, channel->channel(), CTRL_LRPN, 127));
putEvent(NPlayEvent(ME_CONTROLLER, channel->channel(), CTRL_HRPN, 127));
}
else {
sendEvent(NPlayEvent(ME_CONTROLLER, channel->channel, CTRL_LRPN, 0));
sendEvent(NPlayEvent(ME_CONTROLLER, channel->channel, CTRL_HRPN, 0));
sendEvent(NPlayEvent(ME_CONTROLLER, channel->channel, CTRL_HDATA,12));
sendEvent(NPlayEvent(ME_CONTROLLER, channel->channel, CTRL_LRPN, 127));
sendEvent(NPlayEvent(ME_CONTROLLER, channel->channel, CTRL_HRPN, 127));
sendEvent(NPlayEvent(ME_CONTROLLER, channel->channel(), CTRL_LRPN, 0));
sendEvent(NPlayEvent(ME_CONTROLLER, channel->channel(), CTRL_HRPN, 0));
sendEvent(NPlayEvent(ME_CONTROLLER, channel->channel(), CTRL_HDATA,12));
sendEvent(NPlayEvent(ME_CONTROLLER, channel->channel(), CTRL_LRPN, 127));
sendEvent(NPlayEvent(ME_CONTROLLER, channel->channel(), CTRL_HRPN, 127));
}
}
}
@ -1420,7 +1420,7 @@ void Seq::putEvent(const NPlayEvent& event, unsigned framePos)
}
// audio
int syntiIdx= _synti->index(cs->midiMapping(channel)->articulation->synti);
int syntiIdx= _synti->index(cs->midiMapping(channel)->articulation->synti());
_synti->play(event, syntiIdx);
// midi

View file

@ -39,7 +39,7 @@ class Measure;
class Fraction;
class Driver;
class Part;
struct Channel;
class Channel;
class ScoreView;
class MasterSynthesizer;
class Segment;

View file

@ -38,10 +38,10 @@ static void initChannelCombo(QComboBox* cb, StaffTextBase* st)
Part* part = st->staff()->part();
int tick = static_cast<Segment*>(st->parent())->tick();
for (const Channel* a : part->instrument(tick)->channel()) {
if (a->name.isEmpty() || a->name == "normal")
cb->addItem(QObject::tr("normal"));
if (a->name().isEmpty() || a->name() == Channel::DEFAULT_NAME)
cb->addItem(QObject::tr(Channel::DEFAULT_NAME));
else
cb->addItem(qApp->translate("InstrumentsXML", a->name.toUtf8().data()));
cb->addItem(qApp->translate("InstrumentsXML", a->name().toUtf8().data()));
}
}
@ -113,7 +113,7 @@ StaffTextProperties::StaffTextProperties(const StaffTextBase* st, QWidget* paren
continue;
for (int i = 0; i < n; ++i) {
const Channel* a = part->instrument(tick)->channel(i);
if (a->name != _staffText->channelName(voice))
if (a->name() != _staffText->channelName(voice))
continue;
int row = 0;
for (row = 0; row < rows; ++row) {
@ -184,11 +184,11 @@ StaffTextProperties::StaffTextProperties(const StaffTextBase* st, QWidget* paren
const Channel* a = part->instrument(tick)->channel(i);
QTreeWidgetItem* item = new QTreeWidgetItem(channelList);
item->setData(0, Qt::UserRole, i);
if (a->name.isEmpty() || a->name == "normal")
item->setText(0, tr("normal"));
if (a->name().isEmpty() || a->name() == Channel::DEFAULT_NAME)
item->setText(0, tr(Channel::DEFAULT_NAME));
else
item->setText(0, qApp->translate("InstrumentsXML", a->name.toUtf8().data()));
item->setText(1, qApp->translate("InstrumentsXML", a->descr.toUtf8().data()));
item->setText(0, qApp->translate("InstrumentsXML", a->name().toUtf8().data()));
item->setText(1, qApp->translate("InstrumentsXML", a->descr().toUtf8().data()));
if (i == 0)
selectedItem = item;
}
@ -384,13 +384,13 @@ void StaffTextProperties::channelItemChanged(QTreeWidgetItem* item, QTreeWidgetI
int channelIdx = item->data(0, Qt::UserRole).toInt();
int tick = static_cast<Segment*>(_staffText->parent())->tick();
Channel* channel = part->instrument(tick)->channel(channelIdx);
QString channelName = channel->name;
QString channelName = channel->name();
for (const NamedEventList& e : part->instrument(tick)->midiActions()) {
QTreeWidgetItem* ti = new QTreeWidgetItem(actionList);
if (e.name.isEmpty() || e.name == "normal") {
ti->setText(0, tr("normal"));
ti->setData(0, Qt::UserRole, "normal");
if (e.name.isEmpty() || e.name == Channel::DEFAULT_NAME) {
ti->setText(0, tr(Channel::DEFAULT_NAME));
ti->setData(0, Qt::UserRole, Channel::DEFAULT_NAME);
}
else {
ti->setText(0, qApp->translate("InstrumentsXML", e.name.toUtf8().data()));
@ -400,9 +400,9 @@ void StaffTextProperties::channelItemChanged(QTreeWidgetItem* item, QTreeWidgetI
}
for (const NamedEventList& e : channel->midiActions) {
QTreeWidgetItem* ti = new QTreeWidgetItem(actionList);
if (e.name.isEmpty() || e.name == "normal") {
ti->setText(0, tr("normal"));
ti->setData(0, Qt::UserRole, "normal");
if (e.name.isEmpty() || e.name == Channel::DEFAULT_NAME) {
ti->setText(0, tr(Channel::DEFAULT_NAME));
ti->setData(0, Qt::UserRole, Channel::DEFAULT_NAME);
}
else {
ti->setText(0, qApp->translate("InstrumentsXML", e.name.toUtf8().data()));
@ -441,7 +441,7 @@ void StaffTextProperties::saveValues()
if (vb[voice][row]->isChecked()) {
int idx = channelCombo[row]->currentIndex();
int instrId = static_cast<Segment*>(_staffText->parent())->tick();
_staffText->setChannelName(voice, part->instrument(instrId)->channel()[idx]->name);
_staffText->setChannelName(voice, part->instrument(instrId)->channel()[idx]->name());
break;
}
}

View file

@ -2836,7 +2836,7 @@ void Timeline::requestInstrumentDialog()
QAction* act = getAction("instruments");
mscore->cmd(act);
if (mscore->getMixer())
mscore->getMixer()->updateAll(_score->masterScore());
mscore->getMixer()->setScore(_score->masterScore());
}
}

View file

@ -136,6 +136,21 @@ QList<MidiPatch*> MasterSynthesizer::getPatchInfo() const
return pl;
}
//---------------------------------------------------------
// getPatchInfo
//---------------------------------------------------------
MidiPatch* MasterSynthesizer::getPatchInfo(QString synti, int bank, int program)
{
for (Synthesizer* s : _synthesizer) {
for (MidiPatch* p: s->getPatchInfo()) {
if (p->synti == synti && p->bank == bank && p->prog == program)
return p;
}
}
return nullptr;
}
//---------------------------------------------------------
// allSoundsOff
//---------------------------------------------------------

View file

@ -82,6 +82,7 @@ class MasterSynthesizer : public QObject {
QString name(unsigned) const;
QList<MidiPatch*> getPatchInfo() const;
MidiPatch* getPatchInfo(QString synti, int bank, int program);
SynthesizerState state() const;
bool setState(const SynthesizerState&);