finally splitted rest of LMMS, i.e. tracks, track-containers, track-content-objects, whole instrument-track/instrument-track-window and so on - still a bit unstable but I'm sure we'll manage to get this one very stable\!
git-svn-id: https://lmms.svn.sf.net/svnroot/lmms/branches/lmms-mv@691 0778d3d1-df1d-0410-868b-ea421aaaa00d
This commit is contained in:
@@ -1,667 +0,0 @@
|
||||
#ifndef SINGLE_SOURCE_COMPILE
|
||||
|
||||
/*
|
||||
* arp_and_chords_tab_widget.cpp - widget for use in arp/chord-tab of
|
||||
* instrument-track-window
|
||||
*
|
||||
* Copyright (c) 2004-2008 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* 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 (see COPYING); if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <Qt/QtXml>
|
||||
#include <QtGui/QLabel>
|
||||
|
||||
|
||||
#include "arp_and_chords_tab_widget.h"
|
||||
#include "combobox.h"
|
||||
#include "embed.h"
|
||||
#include "engine.h"
|
||||
#include "group_box.h"
|
||||
#include "gui_templates.h"
|
||||
#include "instrument_track.h"
|
||||
#include "knob.h"
|
||||
#include "led_checkbox.h"
|
||||
#include "note_play_handle.h"
|
||||
#include "song_editor.h"
|
||||
#include "pixmap_button.h"
|
||||
#include "preset_preview_play_handle.h"
|
||||
#include "tempo_sync_knob.h"
|
||||
#include "tooltip.h"
|
||||
|
||||
|
||||
|
||||
arpAndChordsTabWidget::chord arpAndChordsTabWidget::s_chords[] =
|
||||
{
|
||||
{ arpAndChordsTabWidget::tr( "octave" ), { 0, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "Major" ), { 0, 4, 7, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "Majb5" ), { 0, 4, 6, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "minor" ), { 0, 3, 7, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "minb5" ), { 0, 3, 6, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "sus2" ), { 0, 2, 7, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "sus4" ), { 0, 5, 7, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "aug" ), { 0, 4, 8, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "augsus4" ), { 0, 5, 8, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "tri" ), { 0, 3, 6, 9, -1 } },
|
||||
|
||||
{ arpAndChordsTabWidget::tr( "6" ), { 0, 4, 7, 9, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "6sus4" ), { 0, 5, 7, 9, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "6add9" ), { 0, 4, 7, 12, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "m6" ), { 0, 3, 7, 9, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "m6add9" ), { 0, 3, 7, 9, 14, -1 } },
|
||||
|
||||
{ arpAndChordsTabWidget::tr( "7" ), { 0, 4, 7, 10, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "7sus4" ), { 0, 5, 7, 10, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "7#5" ), { 0, 4, 8, 10, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "7b5" ), { 0, 4, 6, 10, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "7#9" ), { 0, 4, 7, 10, 13, 18, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "7b9" ), { 0, 4, 7, 10, 13, 16, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "7#5#9" ), { 0, 4, 8, 12, 14, 19, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "7#5b9" ), { 0, 4, 8, 12, 14, 17, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "7b5b9" ), { 0, 4, 6, 10, 12, 15, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "7add11" ), { 0, 4, 7, 10, 17, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "7add13" ), { 0, 4, 7, 10, 21, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "7#11" ), { 0, 4, 7, 10, 18, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "Maj7" ), { 0, 4, 7, 11, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "Maj7b5" ), { 0, 4, 6, 11, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "Maj7#5" ), { 0, 4, 8, 11, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "Maj7#11" ), { 0, 4, 7, 11, 18, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "Maj7add13" ), { 0, 4, 7, 11, 21, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "m7" ), { 0, 3, 7, 10, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "m7b5" ), { 0, 3, 6, 10, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "m7b9" ), { 0, 3, 7, 10, 13, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "m7add11" ), { 0, 3, 7, 10, 17, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "m7add13" ), { 0, 3, 7, 10, 21, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "m-Maj7" ), { 0, 3, 7, 11, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "m-Maj7add11" ), { 0, 3, 7, 11, 17, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "m-Maj7add13" ), { 0, 3, 7, 11, 21, -1 } },
|
||||
|
||||
{ arpAndChordsTabWidget::tr( "9" ), { 0, 4, 7, 10, 14, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "9sus4" ), { 0, 5, 7, 10, 14, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "add9" ), { 0, 4, 7, 14, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "9#5" ), { 0, 4, 8, 10, 14, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "9b5" ), { 0, 4, 6, 10, 14, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "9#11" ), { 0, 4, 7, 10, 14, 18, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "9b13" ), { 0, 4, 7, 10, 14, 20, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "Maj9" ), { 0, 4, 7, 11, 14, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "Maj9sus4" ), { 0, 5, 7, 11, 15, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "Maj9#5" ), { 0, 4, 8, 11, 14, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "Maj9#11" ), { 0, 4, 7, 11, 14, 18, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "m9" ), { 0, 3, 7, 10, 14, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "madd9" ), { 0, 3, 7, 14, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "m9b5" ), { 0, 3, 6, 10, 14, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "m9-Maj7" ), { 0, 3, 7, 11, 14, -1 } },
|
||||
|
||||
{ arpAndChordsTabWidget::tr( "11" ), { 0, 4, 7, 10, 14, 17, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "11b9" ), { 0, 4, 7, 10, 13, 17, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "Maj11" ), { 0, 4, 7, 11, 14, 17, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "m11" ), { 0, 3, 7, 10, 14, 17, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "m-Maj11" ), { 0, 3, 7, 11, 14, 17, -1 } },
|
||||
|
||||
{ arpAndChordsTabWidget::tr( "13" ), { 0, 4, 7, 10, 14, 21, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "13#9" ), { 0, 4, 7, 10, 15, 21, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "13b9" ), { 0, 4, 7, 10, 13, 21, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "13b5b9" ), { 0, 4, 6, 10, 13, 21, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "Maj13" ), { 0, 4, 7, 11, 14, 21, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "m13" ), { 0, 3, 7, 10, 14, 21, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "m-Maj13" ), { 0, 3, 7, 11, 14, 21, -1 } },
|
||||
|
||||
{ arpAndChordsTabWidget::tr( "Major" ), { 0, 2, 4, 5, 7, 9, 11, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "Harmonic minor" ), { 0, 2, 3, 5, 7, 8,
|
||||
11, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "Melodic minor" ), { 0, 2, 3, 5, 7, 9,
|
||||
11, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "Whole tone" ), { 0, 2, 4, 6, 8, 10,
|
||||
-1 } },
|
||||
{ arpAndChordsTabWidget::tr( "Diminished" ), { 0, 2, 3, 5, 6, 8, 9,
|
||||
11, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "Major pentatonic" ), { 0, 2, 4, 7, 10,
|
||||
-1 } },
|
||||
{ arpAndChordsTabWidget::tr( "Minor pentatonic" ), { 0, 3, 5, 7, 10,
|
||||
-1 } },
|
||||
{ arpAndChordsTabWidget::tr( "Jap in sen" ), { 0, 1, 5, 7, 10, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "Major bebop" ), { 0, 2, 4, 5, 7, 8, 9,
|
||||
11, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "Dominant bebop" ), { 0, 2, 4, 5, 7, 9,
|
||||
10, 11, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "Blues" ), { 0, 3, 5, 6, 7, 10, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "Arabic" ), { 0, 1, 4, 5, 7, 8, 11, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "Enigmatic" ), { 0, 1, 4, 6, 8, 10, 11,
|
||||
-1 } },
|
||||
{ arpAndChordsTabWidget::tr( "Neopolitan" ), { 0, 1, 3, 5, 7, 9, 11,
|
||||
-1 } },
|
||||
{ arpAndChordsTabWidget::tr( "Neopolitan minor" ), { 0, 1, 3, 5, 7, 9,
|
||||
11, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "Hungarian minor" ), { 0, 2, 3, 6, 7, 9,
|
||||
11, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "Dorian" ), { 0, 2, 3, 5, 7, 9, 10, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "Phrygolydian" ), { 0, 1, 3, 5, 7, 8, 10,
|
||||
-1 } },
|
||||
{ arpAndChordsTabWidget::tr( "Lydian" ), { 0, 2, 4, 6, 7, 9, 11, -1 } },
|
||||
{ arpAndChordsTabWidget::tr( "Mixolydian" ), { 0, 2, 4, 5, 7, 9, 10,
|
||||
-1 } },
|
||||
{ arpAndChordsTabWidget::tr( "Aeolian" ), { 0, 2, 3, 5, 7, 8, 10,
|
||||
-1 } },
|
||||
{ arpAndChordsTabWidget::tr( "Locrian" ), { 0, 1, 3, 5, 6, 8, 10,
|
||||
-1 } },
|
||||
|
||||
{ "", { -1, -1 } }
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
const int CHORDS_GROUPBOX_X = 4;
|
||||
const int CHORDS_GROUPBOX_Y = 5;
|
||||
const int CHORDS_GROUPBOX_WIDTH = 238;
|
||||
const int CHORDS_GROUPBOX_HEIGHT = 65;
|
||||
const int ARP_GROUPBOX_X = CHORDS_GROUPBOX_X;
|
||||
const int ARP_GROUPBOX_Y = 10 + CHORDS_GROUPBOX_Y + CHORDS_GROUPBOX_HEIGHT;
|
||||
const int ARP_GROUPBOX_WIDTH = CHORDS_GROUPBOX_WIDTH;
|
||||
const int ARP_GROUPBOX_HEIGHT = 240 - ARP_GROUPBOX_Y;
|
||||
|
||||
|
||||
|
||||
arpAndChordsTabWidget::arpAndChordsTabWidget(
|
||||
instrumentTrack * _instrument_track ) :
|
||||
QWidget( _instrument_track->tabWidgetParent() ),
|
||||
m_chordsEnabledModel( new boolModel( FALSE ) ),
|
||||
m_chordsModel( new comboBoxModel( /* this */ ) ),
|
||||
m_chordRangeModel( new floatModel( 1.0f, 1.0f, 9.0f, 1.0f
|
||||
/* this */ ) ),
|
||||
m_arpEnabledModel( new boolModel( FALSE ) ),
|
||||
m_arpModel( new comboBoxModel( /* this */ ) ),
|
||||
m_arpRangeModel( new floatModel( 1.0f, 1.0f, 9.0f, 1.0f
|
||||
/* this */ ) ),
|
||||
m_arpTimeModel( new floatModel( 100.0f, 25.0f, 2000.0f, 1.0f
|
||||
/* this */ ) ),
|
||||
m_arpGateModel( new floatModel( 100.0f, 1.0f, 200.0f, 1.0f
|
||||
/* this */ ) ),
|
||||
m_arpDirectionModel( new intModel( /* this */ ) ),
|
||||
m_arpModeModel( new comboBoxModel( /* this */ ) )
|
||||
{
|
||||
m_chordsEnabledModel->setTrack( _instrument_track );
|
||||
m_chordsGroupBox = new groupBox( tr( "CHORDS" ), this );
|
||||
m_chordsGroupBox->setGeometry( CHORDS_GROUPBOX_X, CHORDS_GROUPBOX_Y,
|
||||
CHORDS_GROUPBOX_WIDTH,
|
||||
CHORDS_GROUPBOX_HEIGHT );
|
||||
m_chordsGroupBox->setModel( m_chordsEnabledModel );
|
||||
|
||||
|
||||
m_chordsModel->setTrack( _instrument_track );
|
||||
m_chordsComboBox = new comboBox( m_chordsGroupBox, tr( "Chord type" ) );
|
||||
m_chordsComboBox->setGeometry( 10, 25, 140, 22 );
|
||||
|
||||
for( int i = 0; s_chords[i].interval[0] != -1; ++i )
|
||||
{
|
||||
m_chordsModel->addItem( tr( s_chords[i].name.toAscii().
|
||||
constData() ) );
|
||||
}
|
||||
m_chordsComboBox->setModel( m_chordsModel );
|
||||
|
||||
|
||||
m_chordRangeModel->setTrack( _instrument_track );
|
||||
m_chordRangeModel->setInitValue( 1.0f );
|
||||
m_chordRangeKnob = new knob( knobBright_26, m_chordsGroupBox,
|
||||
tr( "Chord range" ) );
|
||||
m_chordRangeKnob->setModel( m_chordRangeModel );
|
||||
m_chordRangeKnob->setLabel( tr( "RANGE" ) );
|
||||
m_chordRangeKnob->move( 164, 24 );
|
||||
m_chordRangeKnob->setHintText( tr( "Chord range:" ) + " ", " " +
|
||||
tr( "octave(s)" ) );
|
||||
m_chordRangeKnob->setWhatsThis(
|
||||
tr( "Use this knob for setting the chord range in octaves. "
|
||||
"The selected chord will be played within specified "
|
||||
"amount of octaves." ) );
|
||||
|
||||
|
||||
|
||||
m_arpEnabledModel->setTrack( _instrument_track );
|
||||
m_arpGroupBox = new groupBox( tr( "ARPEGGIO" ), this );
|
||||
m_arpGroupBox->setModel( m_arpEnabledModel );
|
||||
m_arpGroupBox->setGeometry( ARP_GROUPBOX_X, ARP_GROUPBOX_Y,
|
||||
ARP_GROUPBOX_WIDTH,
|
||||
ARP_GROUPBOX_HEIGHT );
|
||||
|
||||
m_arpGroupBox->setWhatsThis(
|
||||
tr( "An arpeggio is a type of playing (especially plucked) "
|
||||
"instruments, which makes the music much livelier. "
|
||||
"The strings of such instruments (e.g. harps) are "
|
||||
"plucked like chords, the only difference is, that "
|
||||
"this is done in a sequential order, so the notes are "
|
||||
"not played at the same time. Typical arpeggios are "
|
||||
"major or minor triads. But there're a lot of other "
|
||||
"possible chords, you can select." ) );
|
||||
|
||||
|
||||
m_arpModel->setTrack( _instrument_track );
|
||||
m_arpComboBox = new comboBox( m_arpGroupBox, tr( "Arpeggio type" ) );
|
||||
m_arpComboBox->setGeometry( 10, 25, 140, 22 );
|
||||
|
||||
for( int i = 0; s_chords[i].interval[0] != -1; ++i )
|
||||
{
|
||||
m_arpModel->addItem( tr( s_chords[i].name.toAscii().
|
||||
constData() ) );
|
||||
}
|
||||
m_arpComboBox->setModel( m_arpModel );
|
||||
|
||||
|
||||
m_arpRangeModel->setTrack( _instrument_track );
|
||||
m_arpRangeModel->setInitValue( 1.0f );
|
||||
m_arpRangeKnob = new knob( knobBright_26, m_arpGroupBox,
|
||||
tr( "Arpeggio range" ) );
|
||||
m_arpRangeKnob->setModel( m_arpRangeModel );
|
||||
m_arpRangeKnob->setLabel( tr( "RANGE" ) );
|
||||
m_arpRangeKnob->move( 164, 24 );
|
||||
m_arpRangeKnob->setHintText( tr( "Arpeggio range:" ) + " ", " " +
|
||||
tr( "octave(s)" ) );
|
||||
m_arpRangeKnob->setWhatsThis(
|
||||
tr( "Use this knob for setting the arpeggio range in octaves. "
|
||||
"The selected arpeggio will be played within specified "
|
||||
"amount of octaves." ) );
|
||||
|
||||
|
||||
m_arpTimeModel->setTrack( _instrument_track );
|
||||
m_arpTimeModel->setInitValue( 100.0f );
|
||||
m_arpTimeKnob = new tempoSyncKnob( knobBright_26, m_arpGroupBox,
|
||||
tr( "Arpeggio time" ) );
|
||||
m_arpTimeKnob->setModel( m_arpTimeModel );
|
||||
m_arpTimeKnob->setLabel( tr( "TIME" ) );
|
||||
m_arpTimeKnob->move( 164, 70 );
|
||||
m_arpTimeKnob->setHintText( tr( "Arpeggio time:" ) + " ", " " +
|
||||
tr( "ms" ) );
|
||||
m_arpTimeKnob->setWhatsThis(
|
||||
tr( "Use this knob for setting the arpeggio time in "
|
||||
"milliseconds. The arpeggio time specifies how long "
|
||||
"each arpeggio-tone should be played." ) );
|
||||
|
||||
|
||||
m_arpGateModel->setTrack( _instrument_track );
|
||||
m_arpGateModel->setInitValue( 100.0f );
|
||||
m_arpGateKnob = new knob( knobBright_26, m_arpGroupBox,
|
||||
tr( "Arpeggio gate" ) );
|
||||
m_arpGateKnob->setModel( m_arpGateModel );
|
||||
m_arpGateKnob->setLabel( tr( "GATE" ) );
|
||||
m_arpGateKnob->move( 204, 70 );
|
||||
m_arpGateKnob->setHintText( tr( "Arpeggio gate:" ) + " ", tr( "%" ) );
|
||||
m_arpGateKnob->setWhatsThis(
|
||||
tr( "Use this knob for setting the arpeggio gate. The "
|
||||
"arpeggio gate specifies the percent of a whole "
|
||||
"arpeggio-tone that should be played. With this you "
|
||||
"can make cool staccato-arpeggios." ) );
|
||||
|
||||
m_arpDirectionLbl = new QLabel( tr( "Direction:" ), m_arpGroupBox );
|
||||
m_arpDirectionLbl->setGeometry( 10, 60, 64, 10 );
|
||||
m_arpDirectionLbl->setFont( pointSize<7>( m_arpDirectionLbl->font() ) );
|
||||
|
||||
|
||||
|
||||
pixmapButton * arp_up_btn = new pixmapButton( m_arpGroupBox, NULL );
|
||||
arp_up_btn->move( 10, 74 );
|
||||
arp_up_btn->setActiveGraphic( embed::getIconPixmap( "arp_up_on" ) );
|
||||
arp_up_btn->setInactiveGraphic( embed::getIconPixmap( "arp_up_off" ) );
|
||||
toolTip::add( arp_up_btn, tr( "arpeggio direction = up" ) );
|
||||
|
||||
|
||||
pixmapButton * arp_down_btn = new pixmapButton( m_arpGroupBox, NULL );
|
||||
arp_down_btn->move( 30, 74 );
|
||||
arp_down_btn->setActiveGraphic( embed::getIconPixmap( "arp_down_on" ) );
|
||||
arp_down_btn->setInactiveGraphic( embed::getIconPixmap(
|
||||
"arp_down_off" ) );
|
||||
toolTip::add( arp_down_btn, tr( "arpeggio direction = down" ) );
|
||||
|
||||
|
||||
pixmapButton * arp_up_and_down_btn = new pixmapButton( m_arpGroupBox,
|
||||
NULL );
|
||||
arp_up_and_down_btn->move( 50, 74 );
|
||||
arp_up_and_down_btn->setActiveGraphic( embed::getIconPixmap(
|
||||
"arp_up_and_down_on" ) );
|
||||
arp_up_and_down_btn->setInactiveGraphic( embed::getIconPixmap(
|
||||
"arp_up_and_down_off" ) );
|
||||
toolTip::add( arp_up_and_down_btn,
|
||||
tr( "arpeggio direction = up and down" ) );
|
||||
|
||||
|
||||
pixmapButton * arp_random_btn = new pixmapButton( m_arpGroupBox, NULL );
|
||||
arp_random_btn->move( 70, 74 );
|
||||
arp_random_btn->setActiveGraphic( embed::getIconPixmap(
|
||||
"arp_random_on" ) );
|
||||
arp_random_btn->setInactiveGraphic( embed::getIconPixmap(
|
||||
"arp_random_off" ) );
|
||||
toolTip::add( arp_random_btn, tr( "arpeggio direction = random" ) );
|
||||
|
||||
m_arpDirectionBtnGrp = new automatableButtonGroup( this,
|
||||
tr( "Arpeggio direction" ) );
|
||||
m_arpDirectionBtnGrp->setModel( m_arpDirectionModel );
|
||||
m_arpDirectionBtnGrp->addButton( arp_up_btn );
|
||||
m_arpDirectionBtnGrp->addButton( arp_down_btn );
|
||||
m_arpDirectionBtnGrp->addButton( arp_up_and_down_btn );
|
||||
m_arpDirectionBtnGrp->addButton( arp_random_btn );
|
||||
|
||||
m_arpDirectionModel->setTrack( _instrument_track );
|
||||
m_arpDirectionModel->setInitValue( UP );
|
||||
|
||||
|
||||
QLabel * mode_lbl = new QLabel( tr( "Mode:" ), m_arpGroupBox );
|
||||
mode_lbl->setGeometry( 10, 104, 64, 10 );
|
||||
mode_lbl->setFont( pointSize<7>( mode_lbl->font() ) );
|
||||
|
||||
m_arpModeComboBox = new comboBox( m_arpGroupBox,
|
||||
tr( "Arpeggio mode" ) );
|
||||
m_arpModeComboBox->setGeometry( 10, 118, 128, 22 );
|
||||
|
||||
m_arpModeModel->setTrack( _instrument_track );
|
||||
m_arpModeModel->addItem( tr( "Free" ), new QPixmap(
|
||||
embed::getIconPixmap( "arp_free" ) ) );
|
||||
m_arpModeModel->addItem( tr( "Sort" ), new QPixmap(
|
||||
embed::getIconPixmap( "arp_sort" ) ) );
|
||||
m_arpModeModel->addItem( tr( "Sync" ), new QPixmap(
|
||||
embed::getIconPixmap( "arp_sync" ) ) );
|
||||
m_arpModeComboBox->setModel( m_arpModeModel );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
arpAndChordsTabWidget::~arpAndChordsTabWidget()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void arpAndChordsTabWidget::processNote( notePlayHandle * _n )
|
||||
{
|
||||
const int base_note_key = _n->key();
|
||||
// we add chord-subnotes to note if either note is a base-note and
|
||||
// arpeggio is not used or note is part of an arpeggio
|
||||
// at the same time we only add sub-notes if nothing of the note was
|
||||
// played yet, because otherwise we would add chord-subnotes every
|
||||
// time an audio-buffer is rendered...
|
||||
if( ( ( _n->baseNote() && m_arpEnabledModel->value() == FALSE ) ||
|
||||
_n->arpNote() ) &&
|
||||
_n->totalFramesPlayed() == 0 &&
|
||||
m_chordsEnabledModel->value() == TRUE )
|
||||
{
|
||||
// then insert sub-notes for chord
|
||||
const int selected_chord = m_chordsComboBox->value();
|
||||
|
||||
for( int octave_cnt = 0;
|
||||
octave_cnt < m_chordRangeKnob->value(); ++octave_cnt )
|
||||
{
|
||||
const int sub_note_key_base = base_note_key +
|
||||
octave_cnt * NOTES_PER_OCTAVE;
|
||||
// if octave_cnt == 1 we're in the first octave and
|
||||
// the base-note is already done, so we don't have to
|
||||
// create it in the following loop, then we loop until
|
||||
// there's a -1 in the interval-array
|
||||
for( int i = ( octave_cnt == 0 ) ? 1 : 0;
|
||||
s_chords[selected_chord].interval[i] != -1;
|
||||
++i )
|
||||
{
|
||||
// add interval to sub-note-key
|
||||
const int sub_note_key = sub_note_key_base +
|
||||
(int) s_chords[
|
||||
selected_chord].interval[i];
|
||||
// maybe we're out of range -> let's get outta
|
||||
// here!
|
||||
if( sub_note_key > NOTES_PER_OCTAVE*OCTAVES )
|
||||
{
|
||||
break;
|
||||
}
|
||||
// create copy of base-note
|
||||
note note_copy( _n->length(), 0,
|
||||
(tones)( sub_note_key %
|
||||
NOTES_PER_OCTAVE ),
|
||||
(octaves)( sub_note_key /
|
||||
NOTES_PER_OCTAVE ),
|
||||
_n->getVolume(),
|
||||
_n->getPanning(),
|
||||
_n->detuning() );
|
||||
// create sub-note-play-handle, only note is
|
||||
// different
|
||||
new notePlayHandle( _n->getInstrumentTrack(),
|
||||
_n->offset(),
|
||||
_n->frames(), note_copy,
|
||||
_n );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// now follows code for arpeggio
|
||||
|
||||
if( _n->baseNote() == FALSE ||
|
||||
!m_arpEnabledModel->value() ||
|
||||
( _n->released() && _n->releaseFramesDone() >=
|
||||
_n->actualReleaseFramesToDo() ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
const int selected_arp = m_arpComboBox->value();
|
||||
|
||||
constNotePlayHandleVector cnphv = notePlayHandle::nphsOfInstrumentTrack(
|
||||
_n->getInstrumentTrack() );
|
||||
if( m_arpModeComboBox->value() != FREE && cnphv.size() == 0 )
|
||||
{
|
||||
// maybe we're playing only a preset-preview-note?
|
||||
cnphv = presetPreviewPlayHandle::nphsOfInstrumentTrack(
|
||||
_n->getInstrumentTrack() );
|
||||
if( cnphv.size() == 0 )
|
||||
{
|
||||
// still nothing found here, so lets return
|
||||
//return;
|
||||
cnphv.push_back( _n );
|
||||
}
|
||||
}
|
||||
|
||||
const int cur_chord_size = getChordSize( s_chords[selected_arp] );
|
||||
const int range = (int)( cur_chord_size * m_arpRangeKnob->value() );
|
||||
const int total_range = range * cnphv.size();
|
||||
|
||||
// number of frames that every note should be played
|
||||
const f_cnt_t arp_frames = (f_cnt_t)( m_arpTimeKnob->value() / 1000.0f *
|
||||
engine::getMixer()->sampleRate() );
|
||||
const f_cnt_t gated_frames = (f_cnt_t)( m_arpGateKnob->value() *
|
||||
arp_frames / 100.0f );
|
||||
|
||||
// used for calculating remaining frames for arp-note, we have to add
|
||||
// arp_frames-1, otherwise the first arp-note will not be setup
|
||||
// correctly... -> arp_frames frames silence at the start of every note!
|
||||
int cur_frame = ( ( m_arpModeComboBox->value() != FREE ) ?
|
||||
cnphv.first()->totalFramesPlayed() :
|
||||
_n->totalFramesPlayed() ) + arp_frames - 1;
|
||||
// used for loop
|
||||
f_cnt_t frames_processed = 0;
|
||||
|
||||
while( frames_processed < engine::getMixer()->framesPerPeriod() )
|
||||
{
|
||||
const f_cnt_t remaining_frames_for_cur_arp = arp_frames -
|
||||
( cur_frame % arp_frames );
|
||||
// does current arp-note fill whole audio-buffer?
|
||||
if( remaining_frames_for_cur_arp >
|
||||
engine::getMixer()->framesPerPeriod() )
|
||||
{
|
||||
// then we don't have to do something!
|
||||
break;
|
||||
}
|
||||
|
||||
frames_processed += remaining_frames_for_cur_arp;
|
||||
|
||||
// init with zero
|
||||
int cur_arp_idx = 0;
|
||||
|
||||
// in sorted mode: is it our turn or do we have to be quiet for
|
||||
// now?
|
||||
if( m_arpModeComboBox->value() == SORT &&
|
||||
( ( cur_frame / arp_frames ) % total_range ) /
|
||||
range != (f_cnt_t) _n->index() )
|
||||
{
|
||||
// update counters
|
||||
frames_processed += arp_frames;
|
||||
cur_frame += arp_frames;
|
||||
continue;
|
||||
}
|
||||
|
||||
const int dir = m_arpDirectionBtnGrp->value();
|
||||
// process according to arpeggio-direction...
|
||||
if( dir == UP )
|
||||
{
|
||||
cur_arp_idx = ( cur_frame / arp_frames ) % range;
|
||||
}
|
||||
else if( dir == DOWN )
|
||||
{
|
||||
cur_arp_idx = range - ( cur_frame / arp_frames ) %
|
||||
range - 1;
|
||||
}
|
||||
else if( dir == UP_AND_DOWN && range > 1 )
|
||||
{
|
||||
// imagine, we had to play the arp once up and then
|
||||
// once down -> makes 2 * range possible notes...
|
||||
// because we don't play the lower and upper notes
|
||||
// twice, we have to subtract 2
|
||||
cur_arp_idx = ( cur_frame / arp_frames ) %
|
||||
( range * 2 - 2 );
|
||||
// if greater than range, we have to play down...
|
||||
// looks like the code for arp_dir==DOWN... :)
|
||||
if( cur_arp_idx >= range )
|
||||
{
|
||||
cur_arp_idx = range - cur_arp_idx %
|
||||
( range - 1 ) - 1;
|
||||
}
|
||||
}
|
||||
else if( dir == RANDOM )
|
||||
{
|
||||
// just pick a random chord-index
|
||||
cur_arp_idx = (int)( range * ( (float) rand() /
|
||||
(float) RAND_MAX ) );
|
||||
}
|
||||
|
||||
// now calculate final key for our arp-note
|
||||
const int sub_note_key = base_note_key + (cur_arp_idx /
|
||||
cur_chord_size ) *
|
||||
NOTES_PER_OCTAVE +
|
||||
s_chords[selected_arp].interval[cur_arp_idx % cur_chord_size];
|
||||
|
||||
// range-checking
|
||||
if( sub_note_key >= NOTES_PER_OCTAVE * OCTAVES ||
|
||||
sub_note_key < 0 ||
|
||||
engine::getMixer()->criticalXRuns() )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
float vol_level = 1.0f;
|
||||
if( _n->released() )
|
||||
{
|
||||
vol_level = _n->volumeLevel( cur_frame + gated_frames );
|
||||
}
|
||||
|
||||
// create new arp-note
|
||||
note new_note( midiTime( 0 ), midiTime( 0 ),
|
||||
static_cast<tones>( sub_note_key %
|
||||
NOTES_PER_OCTAVE ),
|
||||
static_cast<octaves>( sub_note_key /
|
||||
NOTES_PER_OCTAVE ),
|
||||
static_cast<volume>( _n->getVolume() *
|
||||
vol_level ),
|
||||
_n->getPanning(), _n->detuning() );
|
||||
|
||||
// create sub-note-play-handle, only ptr to note is different
|
||||
// and is_arp_note=TRUE
|
||||
new notePlayHandle( _n->getInstrumentTrack(),
|
||||
( ( m_arpModeComboBox->value() != FREE ) ?
|
||||
cnphv.first()->offset() :
|
||||
_n->offset() ) +
|
||||
frames_processed,
|
||||
gated_frames,
|
||||
new_note,
|
||||
_n, TRUE );
|
||||
|
||||
// update counters
|
||||
frames_processed += arp_frames;
|
||||
cur_frame += arp_frames;
|
||||
}
|
||||
|
||||
// make sure, note is handled as arp-base-note, even if we didn't add a
|
||||
// sub-note so far
|
||||
if( m_arpModeComboBox->value() != FREE )
|
||||
{
|
||||
_n->setArpNote( TRUE );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void arpAndChordsTabWidget::saveSettings( QDomDocument & _doc,
|
||||
QDomElement & _this )
|
||||
{
|
||||
m_chordsEnabledModel->saveSettings( _doc, _this, "chord-enabled" );
|
||||
m_chordsModel->saveSettings( _doc, _this, "chord" );
|
||||
m_chordRangeModel->saveSettings( _doc, _this, "chordrange" );
|
||||
|
||||
m_arpEnabledModel->saveSettings( _doc, _this, "arp-enabled" );
|
||||
m_arpModel->saveSettings( _doc, _this, "arp" );
|
||||
m_arpRangeModel->saveSettings( _doc, _this, "arprange" );
|
||||
m_arpTimeModel->saveSettings( _doc, _this, "arptime" );
|
||||
m_arpGateModel->saveSettings( _doc, _this, "arpgate" );
|
||||
m_arpDirectionModel->saveSettings( _doc, _this, "arpdir" );
|
||||
|
||||
m_arpModeModel->saveSettings( _doc, _this, "arpmode" );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void arpAndChordsTabWidget::loadSettings( const QDomElement & _this )
|
||||
{
|
||||
m_chordsEnabledModel->loadSettings( _this, "chord-enabled" );
|
||||
m_chordsModel->loadSettings( _this, "chord" );
|
||||
m_chordRangeModel->loadSettings( _this, "chordrange" );
|
||||
|
||||
m_arpEnabledModel->loadSettings( _this, "arp-enabled" );
|
||||
m_arpModel->loadSettings( _this, "arp" );
|
||||
m_arpRangeModel->loadSettings( _this, "arprange" );
|
||||
m_arpTimeModel->loadSettings( _this, "arptime" );
|
||||
m_arpGateModel->loadSettings( _this, "arpgate" );
|
||||
m_arpDirectionModel->loadSettings( _this, "arpdir" );
|
||||
|
||||
// Keep compatibility with version 0.2.1 file format
|
||||
if( _this.hasAttribute( "arpsyncmode" ) )
|
||||
{
|
||||
m_arpTimeKnob->setSyncMode(
|
||||
( tempoSyncKnob::tempoSyncMode ) _this.attribute(
|
||||
"arpsyncmode" ).toInt() );
|
||||
}
|
||||
|
||||
m_arpModeModel->loadSettings( _this, "arpmode" );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#include "arp_and_chords_tab_widget.moc"
|
||||
|
||||
|
||||
#endif
|
||||
@@ -4,7 +4,7 @@
|
||||
* automation_editor.cpp - implementation of automationEditor which is used for
|
||||
* actual setting of dynamic values
|
||||
*
|
||||
* Copyright (c) 2006-2007 Javier Serrano Polo <jasp00/at/users.sourceforge.net>
|
||||
* Copyright (c) 2006-2008 Javier Serrano Polo <jasp00/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
@@ -115,8 +115,8 @@ automationEditor::automationEditor( void ) :
|
||||
|
||||
// add time-line
|
||||
m_timeLine = new timeLine( VALUES_WIDTH, 32, m_ppt,
|
||||
engine::getSongEditor()->getPlayPos(
|
||||
songEditor::PLAY_AUTOMATION_PATTERN ),
|
||||
engine::getSong()->getPlayPos(
|
||||
song::Mode_PlayAutomationPattern ),
|
||||
m_currentPosition, this );
|
||||
connect( this, SIGNAL( positionChanged( const midiTime & ) ),
|
||||
m_timeLine, SLOT( updatePosition( const midiTime & ) ) );
|
||||
@@ -612,7 +612,7 @@ void automationEditor::keyPressEvent( QKeyEvent * _ke )
|
||||
break;
|
||||
|
||||
case Qt::Key_Space:
|
||||
if( engine::getSongEditor()->playing() )
|
||||
if( engine::getSong()->playing() )
|
||||
{
|
||||
stop();
|
||||
}
|
||||
@@ -728,7 +728,7 @@ void automationEditor::mousePressEvent( QMouseEvent * _me )
|
||||
QCursor c( Qt::SizeAllCursor );
|
||||
QApplication::setOverrideCursor( c );
|
||||
|
||||
engine::getSongEditor()->setModified();
|
||||
engine::getSong()->setModified();
|
||||
}
|
||||
else if( ( _me->button() == Qt::RightButton &&
|
||||
m_editMode == DRAW ) ||
|
||||
@@ -739,7 +739,7 @@ void automationEditor::mousePressEvent( QMouseEvent * _me )
|
||||
if( it != time_map.end() )
|
||||
{
|
||||
m_pattern->removeValue( -it.key() );
|
||||
engine::getSongEditor()->setModified();
|
||||
engine::getSong()->setModified();
|
||||
}
|
||||
}
|
||||
else if( _me->button() == Qt::LeftButton &&
|
||||
@@ -773,7 +773,7 @@ void automationEditor::mousePressEvent( QMouseEvent * _me )
|
||||
|
||||
m_action = MOVE_SELECTION;
|
||||
|
||||
engine::getSongEditor()->setModified();
|
||||
engine::getSong()->setModified();
|
||||
}
|
||||
else if( _me->button() == Qt::RightButton &&
|
||||
m_editMode == MOVE )
|
||||
@@ -849,7 +849,7 @@ void automationEditor::mouseMoveEvent( QMouseEvent * _me )
|
||||
level );
|
||||
}
|
||||
|
||||
engine::getSongEditor()->setModified();
|
||||
engine::getSong()->setModified();
|
||||
|
||||
}
|
||||
else if( _me->buttons() & Qt::NoButton && m_editMode == DRAW )
|
||||
@@ -1533,10 +1533,9 @@ void automationEditor::resizeEvent( QResizeEvent * )
|
||||
|
||||
m_topBottomScroll->setValue( m_scroll_level );
|
||||
|
||||
if( engine::getSongEditor() )
|
||||
if( engine::getSong() )
|
||||
{
|
||||
engine::getSongEditor()->getPlayPos(
|
||||
songEditor::PLAY_AUTOMATION_PATTERN
|
||||
engine::getSong()->getPlayPos( song::Mode_PlayAutomationPattern
|
||||
).m_timeLine->setFixedWidth( width() );
|
||||
}
|
||||
m_toolBar->setFixedWidth( width() );
|
||||
@@ -1614,7 +1613,7 @@ int automationEditor::getLevel( int _y )
|
||||
inline bool automationEditor::inBBEditor( void )
|
||||
{
|
||||
return( m_pattern->getTrack()->getTrackContainer()
|
||||
== engine::getBBEditor() );
|
||||
== engine::getBBTrackContainer() );
|
||||
}
|
||||
|
||||
|
||||
@@ -1629,23 +1628,22 @@ void automationEditor::play( void )
|
||||
|
||||
if( !m_pattern->getTrack() )
|
||||
{
|
||||
if( engine::getSongEditor()->playMode() !=
|
||||
songEditor::PLAY_PATTERN )
|
||||
if( engine::getSong()->playMode() != song::Mode_PlayPattern )
|
||||
{
|
||||
engine::getSongEditor()->stop();
|
||||
engine::getSongEditor()->playPattern( (pattern *)
|
||||
engine::getSong()->stop();
|
||||
engine::getSong()->playPattern( (pattern *)
|
||||
engine::getPianoRoll()->currentPattern() );
|
||||
m_playButton->setIcon( embed::getIconPixmap(
|
||||
"pause" ) );
|
||||
}
|
||||
else if( engine::getSongEditor()->playing() )
|
||||
else if( engine::getSong()->playing() )
|
||||
{
|
||||
engine::getSongEditor()->pause();
|
||||
engine::getSong()->pause();
|
||||
m_playButton->setIcon( embed::getIconPixmap( "play" ) );
|
||||
}
|
||||
else if( engine::getSongEditor()->paused() )
|
||||
else if( engine::getSong()->paused() )
|
||||
{
|
||||
engine::getSongEditor()->resumeFromPause();
|
||||
engine::getSong()->resumeFromPause();
|
||||
m_playButton->setIcon( embed::getIconPixmap(
|
||||
"pause" ) );
|
||||
}
|
||||
@@ -1653,13 +1651,13 @@ void automationEditor::play( void )
|
||||
{
|
||||
m_playButton->setIcon( embed::getIconPixmap(
|
||||
"pause" ) );
|
||||
engine::getSongEditor()->playPattern( (pattern *)
|
||||
engine::getSong()->playPattern( (pattern *)
|
||||
engine::getPianoRoll()->currentPattern() );
|
||||
}
|
||||
}
|
||||
else if( inBBEditor() )
|
||||
{
|
||||
if( engine::getSongEditor()->playing() )
|
||||
if( engine::getSong()->playing() )
|
||||
{
|
||||
m_playButton->setIcon( embed::getIconPixmap( "play" ) );
|
||||
}
|
||||
@@ -1668,18 +1666,18 @@ void automationEditor::play( void )
|
||||
m_playButton->setIcon( embed::getIconPixmap(
|
||||
"pause" ) );
|
||||
}
|
||||
engine::getBBEditor()->play();
|
||||
engine::getBBTrackContainer()->play();
|
||||
}
|
||||
else
|
||||
{
|
||||
if( engine::getSongEditor()->playing() )
|
||||
if( engine::getSong()->playing() )
|
||||
{
|
||||
engine::getSongEditor()->pause();
|
||||
engine::getSong()->pause();
|
||||
m_playButton->setIcon( embed::getIconPixmap( "play" ) );
|
||||
}
|
||||
else if( engine::getSongEditor()->paused() )
|
||||
else if( engine::getSong()->paused() )
|
||||
{
|
||||
engine::getSongEditor()->resumeFromPause();
|
||||
engine::getSong()->resumeFromPause();
|
||||
m_playButton->setIcon( embed::getIconPixmap(
|
||||
"pause" ) );
|
||||
}
|
||||
@@ -1687,7 +1685,7 @@ void automationEditor::play( void )
|
||||
{
|
||||
m_playButton->setIcon( embed::getIconPixmap(
|
||||
"pause" ) );
|
||||
engine::getSongEditor()->play();
|
||||
engine::getSong()->play();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1703,11 +1701,11 @@ void automationEditor::stop( void )
|
||||
}
|
||||
if( m_pattern->getTrack() && inBBEditor() )
|
||||
{
|
||||
engine::getBBEditor()->stop();
|
||||
engine::getBBTrackContainer()->stop();
|
||||
}
|
||||
else
|
||||
{
|
||||
engine::getSongEditor()->stop();
|
||||
engine::getSong()->stop();
|
||||
}
|
||||
m_playButton->setIcon( embed::getIconPixmap( "play" ) );
|
||||
m_playButton->update();
|
||||
@@ -1901,7 +1899,7 @@ void automationEditor::cutSelectedValues( void )
|
||||
|
||||
if( !selected_values.isEmpty() )
|
||||
{
|
||||
engine::getSongEditor()->setModified();
|
||||
engine::getSong()->setModified();
|
||||
|
||||
for( timeMap::iterator it = selected_values.begin();
|
||||
it != selected_values.end(); ++it )
|
||||
@@ -1936,7 +1934,7 @@ void automationEditor::pasteValues( void )
|
||||
|
||||
// we only have to do the following lines if we pasted at
|
||||
// least one value...
|
||||
engine::getSongEditor()->setModified();
|
||||
engine::getSong()->setModified();
|
||||
update();
|
||||
engine::getSongEditor()->update();
|
||||
}
|
||||
@@ -1965,7 +1963,7 @@ void automationEditor::deleteSelectedValues( void )
|
||||
|
||||
if( update_after_delete == TRUE )
|
||||
{
|
||||
engine::getSongEditor()->setModified();
|
||||
engine::getSong()->setModified();
|
||||
update();
|
||||
engine::getSongEditor()->update();
|
||||
}
|
||||
@@ -1976,9 +1974,9 @@ void automationEditor::deleteSelectedValues( void )
|
||||
|
||||
void automationEditor::updatePosition( const midiTime & _t )
|
||||
{
|
||||
if( ( engine::getSongEditor()->playing() &&
|
||||
engine::getSongEditor()->playMode() ==
|
||||
songEditor::PLAY_AUTOMATION_PATTERN ) ||
|
||||
if( ( engine::getSong()->playing() &&
|
||||
engine::getSong()->playMode() ==
|
||||
song::Mode_PlayAutomationPattern ) ||
|
||||
m_scrollBack == TRUE )
|
||||
{
|
||||
const int w = width() - VALUES_WIDTH;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* automation_pattern.cpp - implementation of class automationPattern which
|
||||
* holds dynamic values
|
||||
*
|
||||
* Copyright (c) 2006-2007 Javier Serrano Polo <jasp00/at/users.sourceforge.net>
|
||||
* Copyright (c) 2006-2008 Javier Serrano Polo <jasp00/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
@@ -31,6 +31,7 @@
|
||||
|
||||
#include "automation_pattern.h"
|
||||
#include "automation_editor.h"
|
||||
#include "automatable_model_templates.h"
|
||||
#include "engine.h"
|
||||
#include "level_object.h"
|
||||
#include "note.h"
|
||||
|
||||
@@ -40,17 +40,280 @@
|
||||
#include "engine.h"
|
||||
#include "main_window.h"
|
||||
#include "name_label.h"
|
||||
#include "song_editor.h"
|
||||
#include "song.h"
|
||||
#include "templates.h"
|
||||
#include "tool_button.h"
|
||||
#include "tooltip.h"
|
||||
#include "track_container.h"
|
||||
|
||||
|
||||
bbTrackContainer::bbTrackContainer( void ) :
|
||||
trackContainer(),
|
||||
m_bbComboBoxModel( this )
|
||||
{
|
||||
connect( &m_bbComboBoxModel, SIGNAL( dataChanged() ),
|
||||
this, SLOT( currentBBChanged() ),
|
||||
Qt::QueuedConnection );
|
||||
// we *always* want to receive updates even in case BB actually did
|
||||
// not change upon setCurrentBB()-call
|
||||
connect( &m_bbComboBoxModel, SIGNAL( dataUnchanged() ),
|
||||
this, SLOT( currentBBChanged() ),
|
||||
Qt::QueuedConnection );
|
||||
}
|
||||
|
||||
|
||||
bbEditor::bbEditor( void ) :
|
||||
trackContainer()
|
||||
|
||||
|
||||
bbTrackContainer::~bbTrackContainer()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool bbTrackContainer::play( midiTime _start, fpp_t _frames,
|
||||
f_cnt_t _offset,
|
||||
Sint16 _tco_num )
|
||||
{
|
||||
bool played_a_note = FALSE;
|
||||
if( lengthOfBB( _tco_num ) <= 0 )
|
||||
{
|
||||
return( played_a_note );
|
||||
}
|
||||
|
||||
_start = ( _start.getTact() % lengthOfBB( _tco_num ) ) * 64 +
|
||||
_start.getTact64th();
|
||||
QList<track *> tl = tracks();
|
||||
for( int i = 0; i < tl.size(); ++i )
|
||||
{
|
||||
if( tl[i]->play( _start, _frames, _offset, _tco_num ) == TRUE )
|
||||
{
|
||||
played_a_note = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return( played_a_note );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
void bbTrackContainer::saveSettings( QDomDocument & _doc, QDomElement & _parent )
|
||||
{
|
||||
trackContainer::saveSettings( _doc, _parent );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void bbTrackContainer::loadSettings( const QDomElement & _this )
|
||||
{
|
||||
trackContainer::loadSettings( _this );
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
void bbTrackContainer::updateAfterTrackAdd( void )
|
||||
{
|
||||
// make sure, new track(s) have TCOs for every beat/bassline
|
||||
for( int i = 0; i < tMax<int>( 1, numOfBBs() ); ++i )
|
||||
{
|
||||
createTCOsForBB( i );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
tact bbTrackContainer::lengthOfBB( int _bb )
|
||||
{
|
||||
midiTime max_length;
|
||||
|
||||
QList<track *> tl = tracks();
|
||||
for( int i = 0; i < tl.size(); ++i )
|
||||
{
|
||||
trackContentObject * tco = tl[i]->getTCO( _bb );
|
||||
max_length = tMax( max_length, tco->length() );
|
||||
}
|
||||
if( max_length.getTact64th() == 0 )
|
||||
{
|
||||
return( max_length.getTact() );
|
||||
}
|
||||
|
||||
return( max_length.getTact() + 1 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int bbTrackContainer::numOfBBs( void ) const
|
||||
{
|
||||
return( engine::getSong()->countTracks( track::BBTrack ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void bbTrackContainer::removeBB( int _bb )
|
||||
{
|
||||
QList<track *> tl = tracks();
|
||||
for( int i = 0; i < tl.size(); ++i )
|
||||
{
|
||||
delete tl[i]->getTCO( _bb );
|
||||
tl[i]->removeTact( _bb * 64 );
|
||||
}
|
||||
if( _bb <= currentBB() )
|
||||
{
|
||||
setCurrentBB( tMax( currentBB() - 1, 0 ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void bbTrackContainer::swapBB( int _bb1, int _bb2 )
|
||||
{
|
||||
QList<track *> tl = tracks();
|
||||
for( int i = 0; i < tl.size(); ++i )
|
||||
{
|
||||
tl[i]->swapPositionOfTCOs( _bb1, _bb2 );
|
||||
}
|
||||
updateComboBox();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void bbTrackContainer::updateBBTrack( trackContentObject * _tco )
|
||||
{
|
||||
bbTrack * t = bbTrack::findBBTrack( _tco->startPosition() / 64 );
|
||||
if( t != NULL )
|
||||
{
|
||||
t->dataChanged();
|
||||
//t->getTrackContentWidget()->update();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void bbTrackContainer::play( void )
|
||||
{
|
||||
if( engine::getSong()->playing() )
|
||||
{
|
||||
if( engine::getSong()->playMode() != song::Mode_PlayBB )
|
||||
{
|
||||
engine::getSong()->stop();
|
||||
engine::getSong()->playBB();
|
||||
}
|
||||
else
|
||||
{
|
||||
engine::getSong()->pause();
|
||||
}
|
||||
}
|
||||
else if( engine::getSong()->paused() )
|
||||
{
|
||||
engine::getSong()->resumeFromPause();
|
||||
}
|
||||
else
|
||||
{
|
||||
engine::getSong()->playBB();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void bbTrackContainer::stop( void )
|
||||
{
|
||||
engine::getSong()->stop();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void bbTrackContainer::updateComboBox( void )
|
||||
{
|
||||
const int cur_bb = currentBB();
|
||||
|
||||
m_bbComboBoxModel.clear();
|
||||
|
||||
for( int i = 0; i < numOfBBs(); ++i )
|
||||
{
|
||||
bbTrack * bbt = bbTrack::findBBTrack( i );
|
||||
m_bbComboBoxModel.addItem( bbt->name(),
|
||||
bbt->pixmap() ? new QPixmap( *bbt->pixmap() )
|
||||
: NULL );
|
||||
}
|
||||
setCurrentBB( cur_bb );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void bbTrackContainer::currentBBChanged( void )
|
||||
{
|
||||
// first make sure, all channels have a TCO at current BB
|
||||
createTCOsForBB( currentBB() );
|
||||
|
||||
// now update all track-labels (the current one has to become white,
|
||||
// the others green)
|
||||
for( int i = 0; i < numOfBBs(); ++i )
|
||||
{
|
||||
bbTrack::findBBTrack( i )->dataChanged();
|
||||
//trackLabel()->update();
|
||||
}
|
||||
|
||||
//emit dataChanged();
|
||||
//emit positionChanged( NULL );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void bbTrackContainer::createTCOsForBB( int _bb )
|
||||
{
|
||||
if( numOfBBs() == 0 || engine::getSong()->isLoadingProject() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
QList<track *> tl = tracks();
|
||||
for( int i = 0; i < tl.size(); ++i )
|
||||
{
|
||||
while( tl[i]->numOfTCOs() < _bb + 1 )
|
||||
{
|
||||
midiTime position = midiTime( tl[i]->numOfTCOs(), 0 );
|
||||
trackContentObject * tco = tl[i]->addTCO(
|
||||
tl[i]->createTCO( position ) );
|
||||
tco->movePosition( position );
|
||||
tco->changeLength( midiTime( 1, 0 ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bbEditor::bbEditor( bbTrackContainer * _tc ) :
|
||||
trackContainerView( _tc ),
|
||||
m_bbtc( _tc )
|
||||
{
|
||||
// create toolbar
|
||||
m_toolBar = new QWidget;
|
||||
@@ -85,7 +348,7 @@ bbEditor::bbEditor( void ) :
|
||||
toolButton * add_bb_track = new toolButton(
|
||||
embed::getIconPixmap( "add_bb_track" ),
|
||||
tr( "Add beat/bassline" ),
|
||||
engine::getSongEditor(), SLOT( addBBTrack() ),
|
||||
engine::getSong(), SLOT( addBBTrack() ),
|
||||
m_toolBar );
|
||||
|
||||
|
||||
@@ -102,15 +365,7 @@ bbEditor::bbEditor( void ) :
|
||||
|
||||
m_bbComboBox = new comboBox( m_toolBar );
|
||||
m_bbComboBox->setFixedSize( 200, 22 );
|
||||
|
||||
m_bbComboBoxModel = new comboBoxModel( /* this */ );
|
||||
m_bbComboBox->setModel( m_bbComboBoxModel );
|
||||
connect( m_bbComboBoxModel, SIGNAL( dataChanged() ),
|
||||
this, SLOT( currentBBChanged() ) );
|
||||
// we *always* want to receive updates even in case BB actually did
|
||||
// not change upon setCurrentBB()-call
|
||||
connect( m_bbComboBoxModel, SIGNAL( dataUnchanged() ),
|
||||
this, SLOT( currentBBChanged() ) );
|
||||
m_bbComboBox->setModel( &_tc->m_bbComboBoxModel );
|
||||
|
||||
tb_layout->addSpacing( 5 );
|
||||
tb_layout->addWidget( m_playButton );
|
||||
@@ -144,6 +399,12 @@ bbEditor::bbEditor( void ) :
|
||||
}
|
||||
|
||||
w->show();
|
||||
|
||||
|
||||
setModel( _tc );
|
||||
connect( &_tc->m_bbComboBoxModel, SIGNAL( dataChanged() ),
|
||||
this, SLOT( updatePosition() ),
|
||||
Qt::QueuedConnection );
|
||||
}
|
||||
|
||||
|
||||
@@ -156,123 +417,66 @@ bbEditor::~bbEditor()
|
||||
|
||||
|
||||
|
||||
void bbEditor::currentBBChanged( void )
|
||||
void bbEditor::removeBBView( int _bb )
|
||||
{
|
||||
// first make sure, all channels have a TCO at current BB
|
||||
createTCOsForBB( currentBB() );
|
||||
|
||||
realignTracks();
|
||||
|
||||
// now update all track-labels (the current one has to become white,
|
||||
// the others green)
|
||||
for( int i = 0; i < numOfBBs(); ++i )
|
||||
QList<trackView *> tl = trackViews();
|
||||
for( int i = 0; i < tl.size(); ++i )
|
||||
{
|
||||
bbTrack::findBBTrack( i )->trackLabel()->update();
|
||||
tl[i]->getTrackContentWidget()->removeTCOView( _bb );
|
||||
}
|
||||
|
||||
emit positionChanged( NULL );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
tact bbEditor::lengthOfBB( int _bb )
|
||||
void bbEditor::play( void )
|
||||
{
|
||||
midiTime max_length;
|
||||
|
||||
QList<track *> tl = tracks();
|
||||
for( int i = 0; i < tl.size(); ++i )
|
||||
if( engine::getSong()->playing() )
|
||||
{
|
||||
trackContentObject * tco = tl[i]->getTCO( _bb );
|
||||
max_length = tMax( max_length, tco->length() );
|
||||
}
|
||||
if( max_length.getTact64th() == 0 )
|
||||
{
|
||||
return( max_length.getTact() );
|
||||
}
|
||||
|
||||
return( max_length.getTact() + 1 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool FASTCALL bbEditor::play( midiTime _start, fpp_t _frames,
|
||||
f_cnt_t _offset,
|
||||
Sint16 _tco_num )
|
||||
{
|
||||
bool played_a_note = FALSE;
|
||||
if( lengthOfBB( _tco_num ) <= 0 )
|
||||
{
|
||||
return( played_a_note );
|
||||
}
|
||||
|
||||
_start = ( _start.getTact() % lengthOfBB( _tco_num ) ) * 64 +
|
||||
_start.getTact64th();
|
||||
QList<track *> tl = tracks();
|
||||
for( int i = 0; i < tl.size(); ++i )
|
||||
{
|
||||
if( tl[i]->play( _start, _frames, _offset, _tco_num ) == TRUE )
|
||||
if( engine::getSong()->playMode() != song::Mode_PlayBB )
|
||||
{
|
||||
played_a_note = TRUE;
|
||||
engine::getSong()->stop();
|
||||
engine::getSong()->playBB();
|
||||
m_playButton->setIcon( embed::getIconPixmap(
|
||||
"pause" ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
engine::getSong()->pause();
|
||||
m_playButton->setIcon( embed::getIconPixmap(
|
||||
"play" ) );
|
||||
}
|
||||
}
|
||||
else if( engine::getSong()->paused() )
|
||||
{
|
||||
engine::getSong()->resumeFromPause();
|
||||
m_playButton->setIcon( embed::getIconPixmap( "pause" ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_playButton->setIcon( embed::getIconPixmap( "pause" ) );
|
||||
engine::getSong()->playBB();
|
||||
}
|
||||
|
||||
return( played_a_note );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int bbEditor::numOfBBs( void ) const
|
||||
void bbEditor::stop( void )
|
||||
{
|
||||
return( engine::getSongEditor()->countTracks( track::BB_TRACK ) );
|
||||
engine::getSong()->stop();
|
||||
m_playButton->setIcon( embed::getIconPixmap( "play" ) );
|
||||
m_playButton->update();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void bbEditor::removeBB( int _bb )
|
||||
void bbEditor::updatePosition( void )
|
||||
{
|
||||
QList<track *> tl = tracks();
|
||||
for( int i = 0; i < tl.size(); ++i )
|
||||
{
|
||||
tl[i]->removeTCO( _bb );
|
||||
tl[i]->getTrackContentWidget()->removeTact( _bb * 64 );
|
||||
}
|
||||
if( _bb <= currentBB() )
|
||||
{
|
||||
setCurrentBB( tMax( currentBB() - 1, 0 ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void bbEditor::updateBBTrack( trackContentObject * _tco )
|
||||
{
|
||||
bbTrack * t = bbTrack::findBBTrack( _tco->startPosition() / 64 );
|
||||
if( t != NULL )
|
||||
{
|
||||
t->getTrackContentWidget()->update();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void bbEditor::updateComboBox( void )
|
||||
{
|
||||
const int cur_bb = currentBB();
|
||||
|
||||
m_bbComboBoxModel->clear();
|
||||
|
||||
for( int i = 0; i < numOfBBs(); ++i )
|
||||
{
|
||||
bbTrack * bbt = bbTrack::findBBTrack( i );
|
||||
m_bbComboBoxModel->addItem( bbt->trackLabel()->text(),
|
||||
new QPixmap( bbt->trackLabel()->pixmap() ) );
|
||||
}
|
||||
setCurrentBB( cur_bb );
|
||||
//realignTracks();
|
||||
emit positionChanged( m_currentPosition );
|
||||
}
|
||||
|
||||
|
||||
@@ -282,7 +486,7 @@ void bbEditor::keyPressEvent( QKeyEvent * _ke )
|
||||
{
|
||||
if ( _ke->key() == Qt::Key_Space )
|
||||
{
|
||||
if( engine::getSongEditor()->playing() )
|
||||
if( engine::getSong()->playing() )
|
||||
{
|
||||
stop();
|
||||
}
|
||||
@@ -293,16 +497,16 @@ void bbEditor::keyPressEvent( QKeyEvent * _ke )
|
||||
}
|
||||
else if ( _ke->key() == Qt::Key_Plus )
|
||||
{
|
||||
if( currentBB()+ 1 < numOfBBs() )
|
||||
if( m_bbtc->currentBB()+ 1 < m_bbtc->numOfBBs() )
|
||||
{
|
||||
setCurrentBB( currentBB() + 1 );
|
||||
m_bbtc->setCurrentBB( m_bbtc->currentBB() + 1 );
|
||||
}
|
||||
}
|
||||
else if ( _ke->key() == Qt::Key_Minus )
|
||||
{
|
||||
if( currentBB() > 0 )
|
||||
if( m_bbtc->currentBB() > 0 )
|
||||
{
|
||||
setCurrentBB( currentBB() - 1 );
|
||||
m_bbtc->setCurrentBB( m_bbtc->currentBB() - 1 );
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -316,116 +520,6 @@ void bbEditor::keyPressEvent( QKeyEvent * _ke )
|
||||
|
||||
|
||||
|
||||
void bbEditor::play( void )
|
||||
{
|
||||
if( engine::getSongEditor()->playing() )
|
||||
{
|
||||
if( engine::getSongEditor()->playMode() != songEditor::PLAY_BB )
|
||||
{
|
||||
engine::getSongEditor()->stop();
|
||||
engine::getSongEditor()->playBB();
|
||||
m_playButton->setIcon( embed::getIconPixmap(
|
||||
"pause" ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
engine::getSongEditor()->pause();
|
||||
m_playButton->setIcon( embed::getIconPixmap(
|
||||
"play" ) );
|
||||
}
|
||||
}
|
||||
else if( engine::getSongEditor()->paused() )
|
||||
{
|
||||
engine::getSongEditor()->resumeFromPause();
|
||||
m_playButton->setIcon( embed::getIconPixmap( "pause" ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_playButton->setIcon( embed::getIconPixmap( "pause" ) );
|
||||
engine::getSongEditor()->playBB();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void bbEditor::stop( void )
|
||||
{
|
||||
engine::getSongEditor()->stop();
|
||||
m_playButton->setIcon( embed::getIconPixmap( "play" ) );
|
||||
m_playButton->update();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void bbEditor::saveSettings( QDomDocument & _doc, QDomElement & _parent )
|
||||
{
|
||||
trackContainer::saveSettings( _doc, _parent );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void bbEditor::loadSettings( const QDomElement & _this )
|
||||
{
|
||||
trackContainer::loadSettings( _this );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void bbEditor::updateAfterTrackAdd( void )
|
||||
{
|
||||
// make sure, new track(s) have TCOs for every beat/bassline
|
||||
for( int i = 0; i < tMax<int>( 1, numOfBBs() ); ++i )
|
||||
{
|
||||
createTCOsForBB( i );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void bbEditor::createTCOsForBB( int _bb )
|
||||
{
|
||||
if( numOfBBs() == 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
QList<track *> tl = tracks();
|
||||
for( int i = 0; i < tl.size(); ++i )
|
||||
{
|
||||
while( tl[i]->numOfTCOs() < _bb + 1 )
|
||||
{
|
||||
midiTime position = midiTime( tl[i]->numOfTCOs(), 0 );
|
||||
trackContentObject * tco = tl[i]->addTCO(
|
||||
tl[i]->createTCO( position ) );
|
||||
tco->movePosition( position );
|
||||
tco->changeLength( midiTime( 1, 0 ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void bbEditor::swapBB( int _bb1, int _bb2 )
|
||||
{
|
||||
QList<track *> tl = tracks();
|
||||
for( int i = 0; i < tl.size(); ++i )
|
||||
{
|
||||
tl[i]->swapPositionOfTCOs( _bb1, _bb2 );
|
||||
}
|
||||
updateComboBox();
|
||||
}
|
||||
|
||||
|
||||
|
||||
#include "bb_editor.moc"
|
||||
|
||||
|
||||
|
||||
@@ -38,12 +38,15 @@
|
||||
#include "project_journal.h"
|
||||
#include "project_notes.h"
|
||||
#include "song_editor.h"
|
||||
#include "song.h"
|
||||
|
||||
|
||||
bool engine::s_hasGUI = TRUE;
|
||||
float engine::s_framesPerTact64th;
|
||||
mixer * engine::s_mixer;
|
||||
mainWindow * engine::s_mainWindow;
|
||||
bbTrackContainer * engine::s_bbTrackContainer;
|
||||
song * engine::s_song;
|
||||
songEditor * engine::s_songEditor;
|
||||
automationEditor * engine::s_automationEditor;
|
||||
bbEditor * engine::s_bbEditor;
|
||||
@@ -63,11 +66,14 @@ void engine::init( const bool _has_gui )
|
||||
loadExtensions();
|
||||
|
||||
s_projectJournal = new projectJournal;
|
||||
s_mainWindow = new mainWindow;
|
||||
s_mixer = new mixer;
|
||||
s_songEditor = new songEditor;
|
||||
s_song = new song;
|
||||
s_bbTrackContainer = new bbTrackContainer;
|
||||
|
||||
s_mainWindow = new mainWindow;
|
||||
s_songEditor = new songEditor( s_song );
|
||||
s_projectNotes = new projectNotes;
|
||||
s_bbEditor = new bbEditor;
|
||||
s_bbEditor = new bbEditor( s_bbTrackContainer );
|
||||
s_pianoRoll = new pianoRoll;
|
||||
s_automationEditor = new automationEditor;
|
||||
s_ladspaManager = new ladspa2LMMS;
|
||||
@@ -120,7 +126,7 @@ void engine::destroy( void )
|
||||
void engine::updateFramesPerTact64th( void )
|
||||
{
|
||||
s_framesPerTact64th = s_mixer->sampleRate() * 60.0f * BEATS_PER_TACT
|
||||
/ 64.0f / s_songEditor->getTempo();
|
||||
/ 64.0f / s_song->getTempo();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
#ifndef SINGLE_SOURCE_COMPILE
|
||||
|
||||
/*
|
||||
* envelope_and_lfo_widget.cpp - widget which is m_used by envelope/lfo/filter-
|
||||
* tab of channel-window
|
||||
* envelope_and_lfo_parameters.cpp - class envelopeAndLFOParameters
|
||||
*
|
||||
* Copyright (c) 2004-2008 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
@@ -29,25 +28,12 @@
|
||||
#include "envelope_and_lfo_parameters.h"
|
||||
|
||||
|
||||
#include <QtGui/QMouseEvent>
|
||||
#include <QtGui/QPainter>
|
||||
#include <QtXml/QDomElement>
|
||||
|
||||
|
||||
#include "debug.h"
|
||||
#include "embed.h"
|
||||
#include "engine.h"
|
||||
#include "gui_templates.h"
|
||||
#include "knob.h"
|
||||
#include "led_checkbox.h"
|
||||
#include "mmp.h"
|
||||
#include "oscillator.h"
|
||||
#include "pixmap_button.h"
|
||||
#include "song_editor.h"
|
||||
#include "string_pair_drag.h"
|
||||
#include "tempo_sync_knob.h"
|
||||
#include "text_float.h"
|
||||
#include "tooltip.h"
|
||||
#include "automatable_model_templates.h"
|
||||
|
||||
|
||||
@@ -58,383 +44,99 @@ const float SECS_PER_ENV_SEGMENT = 5.0f;
|
||||
const float SECS_PER_LFO_OSCILLATION = 20.0f;
|
||||
|
||||
|
||||
const int ENV_GRAPH_X = 6;
|
||||
const int ENV_GRAPH_Y = 6;
|
||||
|
||||
const int ENV_KNOBS_Y = 43;
|
||||
const int ENV_KNOBS_LBL_Y = ENV_KNOBS_Y+35;
|
||||
const int KNOB_X_SPACING = 32;
|
||||
const int PREDELAY_KNOB_X = 6;
|
||||
const int ATTACK_KNOB_X = PREDELAY_KNOB_X+KNOB_X_SPACING;
|
||||
const int HOLD_KNOB_X = ATTACK_KNOB_X+KNOB_X_SPACING;
|
||||
const int DECAY_KNOB_X = HOLD_KNOB_X+KNOB_X_SPACING;
|
||||
const int SUSTAIN_KNOB_X = DECAY_KNOB_X+KNOB_X_SPACING;
|
||||
const int RELEASE_KNOB_X = SUSTAIN_KNOB_X+KNOB_X_SPACING;
|
||||
const int AMOUNT_KNOB_X = RELEASE_KNOB_X+KNOB_X_SPACING;
|
||||
|
||||
const float TIME_UNIT_WIDTH = 36.0;
|
||||
|
||||
|
||||
const int LFO_GRAPH_X = 6;
|
||||
const int LFO_GRAPH_Y = ENV_KNOBS_LBL_Y+14;
|
||||
const int LFO_KNOB_Y = LFO_GRAPH_Y-2;
|
||||
const int LFO_PREDELAY_KNOB_X = LFO_GRAPH_X + 100;
|
||||
const int LFO_ATTACK_KNOB_X = LFO_PREDELAY_KNOB_X+KNOB_X_SPACING;
|
||||
const int LFO_SPEED_KNOB_X = LFO_ATTACK_KNOB_X+KNOB_X_SPACING;
|
||||
const int LFO_AMOUNT_KNOB_X = LFO_SPEED_KNOB_X+KNOB_X_SPACING;
|
||||
const int LFO_SHAPES_X = LFO_GRAPH_X;//PREDELAY_KNOB_X;
|
||||
const int LFO_SHAPES_Y = LFO_GRAPH_Y + 50;
|
||||
|
||||
|
||||
QPixmap * envelopeAndLFOWidget::s_envGraph = NULL;
|
||||
QPixmap * envelopeAndLFOWidget::s_lfoGraph = NULL;
|
||||
|
||||
QVector<envelopeAndLFOWidget *> envelopeAndLFOWidget::s_EaLWidgets;
|
||||
QVector<envelopeAndLFOParameters *> envelopeAndLFOParameters::s_EaLParametersInstances;
|
||||
|
||||
|
||||
|
||||
envelopeAndLFOWidget::envelopeAndLFOWidget( float _value_for_zero_amount,
|
||||
QWidget * _parent,
|
||||
track * _track ) :
|
||||
QWidget( _parent ),
|
||||
envelopeAndLFOParameters::envelopeAndLFOParameters(
|
||||
float _value_for_zero_amount,
|
||||
track * _track,
|
||||
model * _parent ) :
|
||||
model( _parent ),
|
||||
m_used( FALSE ),
|
||||
m_predelayModel(),
|
||||
m_attackModel(),
|
||||
m_holdModel(),
|
||||
m_decayModel(),
|
||||
m_sustainModel(),
|
||||
m_releaseModel(),
|
||||
m_amountModel(),
|
||||
m_lfoPredelayModel(),
|
||||
m_lfoAttackModel(),
|
||||
m_lfoSpeedModel(),
|
||||
m_lfoAmountModel(),
|
||||
m_lfoWaveModel(),
|
||||
m_x100Model( FALSE, FALSE, TRUE ),
|
||||
m_controlEnvAmountModel( FALSE, FALSE, TRUE ),
|
||||
m_predelayModel( 0.0, 0.0, 1.0, 0.001, this ),
|
||||
m_attackModel( 0.0, 0.0, 1.0, 0.001, this ),
|
||||
m_holdModel( 0.5, 0.0, 1.0, 0.001, this ),
|
||||
m_decayModel( 0.5, 0.0, 1.0, 0.001, this ),
|
||||
m_sustainModel( 0.5, 0.0, 1.0, 0.001, this ),
|
||||
m_releaseModel( 0.1, 0.0, 1.0, 0.001, this ),
|
||||
m_amountModel( 0.0, -1.0, 1.0, 0.005, this ),
|
||||
m_valueForZeroAmount( _value_for_zero_amount ),
|
||||
m_pahdEnv( NULL ),
|
||||
m_rEnv( NULL ),
|
||||
m_lfoPredelayModel( 0.0, 0.0, 1.0, 0.001, this ),
|
||||
m_lfoAttackModel( 0.0, 0.0, 1.0, 0.001, this ),
|
||||
m_lfoSpeedModel( 0.1, 0.01, 1.0, 0.0001, this ),
|
||||
m_lfoAmountModel( 0.0, -1.0, 1.0, 0.005, this ),
|
||||
m_lfoWaveModel( SineWave, 0, NumLfoShapes, 1, this ),
|
||||
m_x100Model( FALSE, this ),
|
||||
m_controlEnvAmountModel( FALSE, this ),
|
||||
m_lfoFrame( 0 ),
|
||||
m_lfoAmountIsZero( FALSE ),
|
||||
m_lfoShapeData( NULL )
|
||||
{
|
||||
if( s_envGraph == NULL )
|
||||
{
|
||||
s_envGraph = new QPixmap( embed::getIconPixmap(
|
||||
"envelope_graph" ) );
|
||||
}
|
||||
if( s_lfoGraph == NULL )
|
||||
{
|
||||
s_lfoGraph = new QPixmap( embed::getIconPixmap( "lfo_graph" ) );
|
||||
}
|
||||
s_EaLParametersInstances.push_back( this );
|
||||
|
||||
s_EaLWidgets.push_back( this );
|
||||
|
||||
m_predelayModel.setTrack( _track );
|
||||
m_predelayModel.setRange( 0.0, 1.0, 0.001 );
|
||||
m_predelayModel.setInitValue( 0.0 );
|
||||
m_predelayKnob = new knob( knobBright_26, this, tr( "Predelay-time" ) );
|
||||
m_predelayKnob->setModel( &m_predelayModel );
|
||||
m_predelayKnob->setLabel( tr( "DEL" ) );
|
||||
m_predelayKnob->move( PREDELAY_KNOB_X, ENV_KNOBS_Y );
|
||||
m_predelayKnob->setHintText( tr( "Predelay:" ) + " ", "" );
|
||||
m_predelayKnob->setWhatsThis(
|
||||
tr( "Use this knob for setting predelay of the current "
|
||||
"envelope. The bigger this value the longer the time "
|
||||
"before start of actual envelope." ) );
|
||||
m_attackModel.setTrack( _track );
|
||||
m_holdModel.setTrack( _track );
|
||||
m_decayModel.setTrack( _track );
|
||||
m_sustainModel.setTrack( _track );
|
||||
m_releaseModel.setTrack( _track );
|
||||
m_amountModel.setTrack( _track );
|
||||
|
||||
m_lfoPredelayModel.setTrack( _track );
|
||||
m_lfoAttackModel.setTrack( _track );
|
||||
m_lfoSpeedModel.setTrack( _track );
|
||||
m_lfoAmountModel.setTrack( _track );
|
||||
m_lfoWaveModel.setTrack( _track );
|
||||
m_x100Model.setTrack( _track );
|
||||
m_controlEnvAmountModel.setTrack( _track );
|
||||
|
||||
|
||||
connect( &m_predelayModel, SIGNAL( dataChanged() ),
|
||||
this, SLOT( updateSampleVars() ) );
|
||||
|
||||
|
||||
m_attackModel.setTrack( _track );
|
||||
m_attackModel.setRange( 0.0, 1.0, 0.001 );
|
||||
m_attackModel.setInitValue( 0.0 );
|
||||
m_attackKnob = new knob( knobBright_26, this, tr( "Attack-time" ) );
|
||||
m_attackKnob->setModel( &m_attackModel );
|
||||
m_attackKnob->setLabel( tr( "ATT" ) );
|
||||
m_attackKnob->move( ATTACK_KNOB_X, ENV_KNOBS_Y );
|
||||
m_attackKnob->setHintText( tr( "Attack:" )+" ", "" );
|
||||
m_attackKnob->setWhatsThis(
|
||||
tr( "Use this knob for setting attack-time of the current "
|
||||
"envelope. The bigger this value the longer the "
|
||||
"envelope needs to increase to attack-level. "
|
||||
"Choose a small value for instruments like pianos "
|
||||
"and a big value for strings." ) );
|
||||
connect( &m_attackModel, SIGNAL( dataChanged() ),
|
||||
this, SLOT( updateSampleVars() ) );
|
||||
|
||||
m_holdModel.setTrack( _track );
|
||||
m_holdModel.setRange( 0.0, 1.0, 0.001 );
|
||||
m_holdModel.setInitValue( 0.5 );
|
||||
m_holdKnob = new knob( knobBright_26, this, tr( "Hold-time" ) );
|
||||
m_holdKnob->setModel( &m_holdModel );
|
||||
m_holdKnob->setLabel( tr( "HOLD" ) );
|
||||
m_holdKnob->move( HOLD_KNOB_X, ENV_KNOBS_Y );
|
||||
m_holdKnob->setHintText( tr( "Hold:" ) + " ", "" );
|
||||
m_holdKnob->setWhatsThis(
|
||||
tr( "Use this knob for setting hold-time of the current "
|
||||
"envelope. The bigger this value the longer the "
|
||||
"envelope holds attack-level before it begins to "
|
||||
"decrease to sustain-level." ) );
|
||||
connect( &m_holdModel, SIGNAL( dataChanged() ),
|
||||
this, SLOT( updateSampleVars() ) );
|
||||
|
||||
|
||||
m_decayModel.setTrack( _track );
|
||||
m_decayModel.setRange( 0.0, 1.0, 0.001 );
|
||||
m_decayModel.setInitValue( 0.5 );
|
||||
m_decayKnob = new knob( knobBright_26, this, tr( "Decay-time" ) );
|
||||
m_decayKnob->setModel( &m_decayModel );
|
||||
m_decayKnob->setLabel( tr( "DEC" ) );
|
||||
m_decayKnob->move( DECAY_KNOB_X, ENV_KNOBS_Y );
|
||||
m_decayKnob->setHintText( tr( "Decay:" ) + " ", "" );
|
||||
m_decayKnob->setWhatsThis(
|
||||
tr( "Use this knob for setting decay-time of the current "
|
||||
"envelope. The bigger this value the longer the "
|
||||
"envelope needs to decrease from attack-level to "
|
||||
"sustain-level. Choose a small value for instruments "
|
||||
"like pianos." ) );
|
||||
connect( &m_decayModel, SIGNAL( dataChanged() ),
|
||||
this, SLOT( updateSampleVars() ) );
|
||||
|
||||
|
||||
m_sustainModel.setTrack( _track );
|
||||
m_sustainModel.setRange( 0.0, 1.0, 0.001 );
|
||||
m_sustainModel.setInitValue( 0.5 );
|
||||
m_sustainKnob = new knob( knobBright_26, this, tr( "Sustain-level" ) );
|
||||
m_sustainKnob->setModel( &m_sustainModel );
|
||||
m_sustainKnob->setLabel( tr( "SUST" ) );
|
||||
m_sustainKnob->move( SUSTAIN_KNOB_X, ENV_KNOBS_Y );
|
||||
m_sustainKnob->setHintText( tr( "Sustain:" ) + " ", "" );
|
||||
m_sustainKnob->setWhatsThis(
|
||||
tr( "Use this knob for setting sustain-level of the current "
|
||||
"envelope. The bigger this value the higher the level "
|
||||
"on which the envelope stays before going down to "
|
||||
"zero." ) );
|
||||
connect( &m_sustainModel, SIGNAL( dataChanged() ),
|
||||
this, SLOT( updateSampleVars() ) );
|
||||
|
||||
|
||||
|
||||
m_releaseModel.setTrack( _track );
|
||||
m_releaseModel.setRange( 0.0, 1.0, 0.001 );
|
||||
m_releaseModel.setInitValue( 0.1 );
|
||||
m_releaseKnob = new knob( knobBright_26, this, tr( "Release-time" ) );
|
||||
m_releaseKnob->setModel( &m_releaseModel );
|
||||
m_releaseKnob->setLabel( tr( "REL" ) );
|
||||
m_releaseKnob->move( RELEASE_KNOB_X, ENV_KNOBS_Y );
|
||||
m_releaseKnob->setHintText( tr( "Release:" ) + " ", "" );
|
||||
m_releaseKnob->setWhatsThis(
|
||||
tr( "Use this knob for setting release-time of the current "
|
||||
"envelope. The bigger this value the longer the "
|
||||
"envelope needs to decrease from sustain-level to "
|
||||
"zero. Choose a big value for soft instruments like "
|
||||
"strings." ) );
|
||||
connect( &m_releaseModel, SIGNAL( dataChanged() ),
|
||||
this, SLOT( updateSampleVars() ) );
|
||||
|
||||
|
||||
m_amountModel.setTrack( _track );
|
||||
m_amountModel.setRange( -1.0, 1.0, 0.005 );
|
||||
m_amountModel.setInitValue( 0.0 );
|
||||
m_amountKnob = new knob( knobBright_26, this,
|
||||
tr( "Modulation amount" ) );
|
||||
m_amountKnob->setModel( &m_amountModel );
|
||||
m_amountKnob->setLabel( tr( "AMT" ) );
|
||||
m_amountKnob->move( AMOUNT_KNOB_X, ENV_GRAPH_Y );
|
||||
m_amountKnob->setHintText( tr( "Modulation amount:" ) + " ", "" );
|
||||
m_amountKnob->setWhatsThis(
|
||||
tr( "Use this knob for setting modulation amount of the "
|
||||
"current envelope. The bigger this value the more the "
|
||||
"according size (e.g. volume or cutoff-frequency) "
|
||||
"will be influenced by this envelope." ) );
|
||||
connect( &m_amountModel, SIGNAL( dataChanged() ),
|
||||
this, SLOT( updateSampleVars() ) );
|
||||
|
||||
|
||||
|
||||
|
||||
m_lfoPredelayModel.setTrack( _track );
|
||||
m_lfoPredelayModel.setRange( 0.0, 1.0, 0.001 );
|
||||
m_lfoPredelayModel.setInitValue( 0.0 );
|
||||
m_lfoPredelayKnob = new knob( knobBright_26, this,
|
||||
tr( "LFO-predelay-time" ) );
|
||||
m_lfoPredelayKnob->setModel( &m_lfoPredelayModel );
|
||||
m_lfoPredelayKnob->setLabel( tr( "DEL" ) );
|
||||
m_lfoPredelayKnob->move( LFO_PREDELAY_KNOB_X, LFO_KNOB_Y );
|
||||
m_lfoPredelayKnob->setHintText( tr( "LFO-predelay:" ) + " ", "" );
|
||||
m_lfoPredelayKnob->setWhatsThis(
|
||||
tr( "Use this knob for setting predelay-time of the current "
|
||||
"LFO. The bigger this value the the time until the "
|
||||
"LFO starts to oscillate." ) );
|
||||
connect( &m_lfoPredelayModel, SIGNAL( dataChanged() ),
|
||||
this, SLOT( updateSampleVars() ) );
|
||||
|
||||
|
||||
m_lfoAttackModel.setTrack( _track );
|
||||
m_lfoAttackModel.setRange( 0.0, 1.0, 0.001 );
|
||||
m_lfoAttackModel.setInitValue( 0.0 );
|
||||
m_lfoAttackKnob = new knob( knobBright_26, this,
|
||||
tr( "LFO-attack-time" ) );
|
||||
m_lfoAttackKnob->setModel( &m_lfoAttackModel );
|
||||
m_lfoAttackKnob->setLabel( tr( "ATT" ) );
|
||||
m_lfoAttackKnob->move( LFO_ATTACK_KNOB_X, LFO_KNOB_Y );
|
||||
m_lfoAttackKnob->setHintText( tr( "LFO-attack:" ) + " ", "" );
|
||||
m_lfoAttackKnob->setWhatsThis(
|
||||
tr( "Use this knob for setting attack-time of the current LFO. "
|
||||
"The bigger this value the longer the LFO needs to "
|
||||
"increase its amplitude to maximum." ) );
|
||||
connect( &m_lfoAttackModel, SIGNAL( dataChanged() ),
|
||||
this, SLOT( updateSampleVars() ) );
|
||||
|
||||
|
||||
m_lfoSpeedModel.setTrack( _track );
|
||||
m_lfoSpeedModel.setRange( 0.01, 1.0, 0.0001 );
|
||||
m_lfoSpeedModel.setInitValue( 0.1 );
|
||||
m_lfoSpeedKnob = new tempoSyncKnob( knobBright_26, this,
|
||||
tr( "LFO-speed" ), 20000.0 );
|
||||
m_lfoSpeedKnob->setModel( &m_lfoSpeedModel );
|
||||
m_lfoSpeedKnob->setLabel( tr( "SPD" ) );
|
||||
m_lfoSpeedKnob->move( LFO_SPEED_KNOB_X, LFO_KNOB_Y );
|
||||
m_lfoSpeedKnob->setHintText( tr( "LFO-speed:" ) + " ", "" );
|
||||
m_lfoSpeedKnob->setWhatsThis(
|
||||
tr( "Use this knob for setting speed of the current LFO. The "
|
||||
"bigger this value the faster the LFO oscillates and "
|
||||
"the faster will be your effect." ) );
|
||||
connect( &m_lfoSpeedModel, SIGNAL( dataChanged() ),
|
||||
this, SLOT( updateSampleVars() ) );
|
||||
|
||||
|
||||
m_lfoAmountModel.setTrack( _track );
|
||||
m_lfoAmountModel.setRange( -1.0, 1.0, 0.005 );
|
||||
m_lfoAmountModel.setInitValue( 0.0 );
|
||||
m_lfoAmountKnob = new knob( knobBright_26, this,
|
||||
tr( "LFO-modulation-amount" ) );
|
||||
m_lfoAmountKnob->setModel( &m_lfoAmountModel );
|
||||
m_lfoAmountKnob->setLabel( tr( "AMT" ) );
|
||||
m_lfoAmountKnob->move( LFO_AMOUNT_KNOB_X, LFO_KNOB_Y );
|
||||
m_lfoAmountKnob->setHintText( tr( "Modulation amount:" ) + " ", "" );
|
||||
m_lfoAmountKnob->setWhatsThis(
|
||||
tr( "Use this knob for setting modulation amount of the "
|
||||
"current LFO. The bigger this value the more the "
|
||||
"selected size (e.g. volume or cutoff-frequency) will "
|
||||
"be influenced by this LFO." ) );
|
||||
connect( &m_lfoAmountModel, SIGNAL( dataChanged() ),
|
||||
this, SLOT( updateSampleVars() ) );
|
||||
|
||||
|
||||
pixmapButton * sin_lfo_btn = new pixmapButton( this, NULL );
|
||||
sin_lfo_btn->move( LFO_SHAPES_X, LFO_SHAPES_Y );
|
||||
sin_lfo_btn->setActiveGraphic( embed::getIconPixmap(
|
||||
"sin_wave_active" ) );
|
||||
sin_lfo_btn->setInactiveGraphic( embed::getIconPixmap(
|
||||
"sin_wave_inactive" ) );
|
||||
sin_lfo_btn->setWhatsThis(
|
||||
tr( "Click here if you want a sine-wave for current "
|
||||
"oscillator." ) );
|
||||
|
||||
pixmapButton * triangle_lfo_btn = new pixmapButton( this, NULL );
|
||||
triangle_lfo_btn->move( LFO_SHAPES_X+15, LFO_SHAPES_Y );
|
||||
triangle_lfo_btn->setActiveGraphic( embed::getIconPixmap(
|
||||
"triangle_wave_active" ) );
|
||||
triangle_lfo_btn->setInactiveGraphic( embed::getIconPixmap(
|
||||
"triangle_wave_inactive" ) );
|
||||
triangle_lfo_btn->setWhatsThis(
|
||||
tr( "Click here if you want a triangle-wave for current "
|
||||
"oscillator." ) );
|
||||
|
||||
pixmapButton * saw_lfo_btn = new pixmapButton( this, NULL );
|
||||
saw_lfo_btn->move( LFO_SHAPES_X+30, LFO_SHAPES_Y );
|
||||
saw_lfo_btn->setActiveGraphic( embed::getIconPixmap(
|
||||
"saw_wave_active" ) );
|
||||
saw_lfo_btn->setInactiveGraphic( embed::getIconPixmap(
|
||||
"saw_wave_inactive" ) );
|
||||
saw_lfo_btn->setWhatsThis(
|
||||
tr( "Click here if you want a saw-wave for current "
|
||||
"oscillator." ) );
|
||||
|
||||
pixmapButton * sqr_lfo_btn = new pixmapButton( this, NULL );
|
||||
sqr_lfo_btn->move( LFO_SHAPES_X+45, LFO_SHAPES_Y );
|
||||
sqr_lfo_btn->setActiveGraphic( embed::getIconPixmap(
|
||||
"square_wave_active" ) );
|
||||
sqr_lfo_btn->setInactiveGraphic( embed::getIconPixmap(
|
||||
"square_wave_inactive" ) );
|
||||
sqr_lfo_btn->setWhatsThis(
|
||||
tr( "Click here if you want a square-wave for current "
|
||||
"oscillator." ) );
|
||||
|
||||
m_userLfoBtn = new pixmapButton( this, NULL );
|
||||
m_userLfoBtn->move( LFO_SHAPES_X+60, LFO_SHAPES_Y );
|
||||
m_userLfoBtn->setActiveGraphic( embed::getIconPixmap(
|
||||
"usr_wave_active" ) );
|
||||
m_userLfoBtn->setInactiveGraphic( embed::getIconPixmap(
|
||||
"usr_wave_inactive" ) );
|
||||
m_userLfoBtn->setWhatsThis(
|
||||
tr( "Click here if you want a user-defined wave for current "
|
||||
"oscillator. Afterwards drag an according sample-"
|
||||
"file into LFO-graph." ) );
|
||||
|
||||
connect( m_userLfoBtn, SIGNAL( toggled( bool ) ),
|
||||
this, SLOT( lfoUserWaveChanged() ) );
|
||||
|
||||
m_lfoWaveBtnGrp = new automatableButtonGroup( this,
|
||||
tr( "LFO wave shape" ) );
|
||||
m_lfoWaveBtnGrp->setModel( &m_lfoWaveModel );
|
||||
m_lfoWaveBtnGrp->addButton( sin_lfo_btn );
|
||||
m_lfoWaveBtnGrp->addButton( triangle_lfo_btn );
|
||||
m_lfoWaveBtnGrp->addButton( saw_lfo_btn );
|
||||
m_lfoWaveBtnGrp->addButton( sqr_lfo_btn );
|
||||
m_lfoWaveBtnGrp->addButton( m_userLfoBtn );
|
||||
|
||||
m_lfoWaveModel.setTrack( _track );
|
||||
m_lfoWaveModel.setInitValue( SIN );
|
||||
|
||||
connect( &m_lfoWaveModel, SIGNAL( dataChanged() ),
|
||||
this, SLOT( updateSampleVars() ) );
|
||||
|
||||
m_x100Model.setTrack( _track );
|
||||
m_x100Cb = new ledCheckBox( tr( "FREQ x 100" ), this,
|
||||
tr( "Freq x 100" ) );
|
||||
m_x100Cb->setModel( &m_x100Model );
|
||||
m_x100Cb->setFont( pointSize<6>( m_x100Cb->font() ) );
|
||||
m_x100Cb->move( LFO_PREDELAY_KNOB_X, LFO_GRAPH_Y + 36 );
|
||||
m_x100Cb->setWhatsThis(
|
||||
tr( "Click here if the frequency of this LFO should be "
|
||||
"multiplied with 100." ) );
|
||||
toolTip::add( m_x100Cb, tr( "multiply LFO-frequency with 100" ) );
|
||||
connect( &m_x100Model, SIGNAL( dataChanged() ),
|
||||
this, SLOT( updateSampleVars() ) );
|
||||
|
||||
connect( engine::getMixer(), SIGNAL( sampleRateChanged() ),
|
||||
this, SLOT( updateSampleVars() ) );
|
||||
|
||||
m_controlEnvAmountModel.setTrack( _track );
|
||||
m_controlEnvAmountCb = new ledCheckBox( tr( "MODULATE ENV-AMOUNT" ),
|
||||
this, tr( "Modulate Env-Amount" ) );
|
||||
m_controlEnvAmountCb->setModel( &m_controlEnvAmountModel );
|
||||
m_controlEnvAmountCb->move( LFO_PREDELAY_KNOB_X, LFO_GRAPH_Y + 54 );
|
||||
m_controlEnvAmountCb->setFont( pointSize<6>(
|
||||
m_controlEnvAmountCb->font() ) );
|
||||
m_controlEnvAmountCb ->setWhatsThis(
|
||||
tr( "Click here to make the envelope-amount controlled by this "
|
||||
"LFO." ) );
|
||||
toolTip::add( m_controlEnvAmountCb,
|
||||
tr( "control envelope-amount by this LFO" ) );
|
||||
|
||||
|
||||
setAcceptDrops( TRUE );
|
||||
|
||||
connect( engine::getMixer(), SIGNAL( sampleRateChanged() ), this,
|
||||
SLOT( updateSampleVars() ) );
|
||||
|
||||
m_lfoShapeData =
|
||||
new sample_t[engine::getMixer()->framesPerPeriod()];
|
||||
|
||||
updateSampleVars();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
envelopeAndLFOWidget::~envelopeAndLFOWidget()
|
||||
envelopeAndLFOParameters::~envelopeAndLFOParameters()
|
||||
{
|
||||
m_predelayModel.disconnect( this );
|
||||
m_attackModel.disconnect( this );
|
||||
@@ -454,19 +156,17 @@ envelopeAndLFOWidget::~envelopeAndLFOWidget()
|
||||
delete[] m_rEnv;
|
||||
delete[] m_lfoShapeData;
|
||||
|
||||
QVector<envelopeAndLFOWidget *> & v = s_EaLWidgets;
|
||||
QVector<envelopeAndLFOParameters *> & v = s_EaLParametersInstances;
|
||||
if( qFind( v.begin(), v.end(), this ) != v.end() )
|
||||
{
|
||||
v.erase( qFind( v.begin(), v.end(), this ) );
|
||||
}
|
||||
|
||||
delete m_lfoWaveBtnGrp;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
inline sample_t envelopeAndLFOWidget::lfoShapeSample( fpp_t _frame_offset )
|
||||
inline sample_t envelopeAndLFOParameters::lfoShapeSample( fpp_t _frame_offset )
|
||||
{
|
||||
f_cnt_t frame = ( m_lfoFrame + _frame_offset ) % m_lfoOscillationFrames;
|
||||
const float phase = frame / static_cast<float>(
|
||||
@@ -474,19 +174,19 @@ inline sample_t envelopeAndLFOWidget::lfoShapeSample( fpp_t _frame_offset )
|
||||
sample_t shape_sample;
|
||||
switch( m_lfoWaveModel.value() )
|
||||
{
|
||||
case TRIANGLE:
|
||||
case TriangleWave:
|
||||
shape_sample = oscillator::triangleSample( phase );
|
||||
break;
|
||||
case SQUARE:
|
||||
case SquareWave:
|
||||
shape_sample = oscillator::squareSample( phase );
|
||||
break;
|
||||
case SAW:
|
||||
case SawWave:
|
||||
shape_sample = oscillator::sawSample( phase );
|
||||
break;
|
||||
case USER:
|
||||
case UserDefinedWave:
|
||||
shape_sample = m_userWave.userWaveSample( phase );
|
||||
break;
|
||||
case SIN:
|
||||
case SineWave:
|
||||
default:
|
||||
shape_sample = oscillator::sinSample( phase );
|
||||
break;
|
||||
@@ -497,7 +197,7 @@ inline sample_t envelopeAndLFOWidget::lfoShapeSample( fpp_t _frame_offset )
|
||||
|
||||
|
||||
|
||||
void envelopeAndLFOWidget::updateLFOShapeData( void )
|
||||
void envelopeAndLFOParameters::updateLFOShapeData( void )
|
||||
{
|
||||
const fpp_t frames = engine::getMixer()->framesPerPeriod();
|
||||
for( fpp_t offset = 0; offset < frames; ++offset )
|
||||
@@ -510,10 +210,10 @@ void envelopeAndLFOWidget::updateLFOShapeData( void )
|
||||
|
||||
|
||||
|
||||
void envelopeAndLFOWidget::triggerLFO( void )
|
||||
void envelopeAndLFOParameters::triggerLFO( void )
|
||||
{
|
||||
QVector<envelopeAndLFOWidget *> & v = s_EaLWidgets;
|
||||
for( QVector<envelopeAndLFOWidget *>::iterator it = v.begin();
|
||||
QVector<envelopeAndLFOParameters *> & v = s_EaLParametersInstances;
|
||||
for( QVector<envelopeAndLFOParameters *>::iterator it = v.begin();
|
||||
it != v.end(); ++it )
|
||||
{
|
||||
( *it )->m_lfoFrame +=
|
||||
@@ -525,10 +225,10 @@ void envelopeAndLFOWidget::triggerLFO( void )
|
||||
|
||||
|
||||
|
||||
void envelopeAndLFOWidget::resetLFO( void )
|
||||
void envelopeAndLFOParameters::resetLFO( void )
|
||||
{
|
||||
QVector<envelopeAndLFOWidget *> & v = s_EaLWidgets;
|
||||
for( QVector<envelopeAndLFOWidget *>::iterator it = v.begin();
|
||||
QVector<envelopeAndLFOParameters *> & v = s_EaLParametersInstances;
|
||||
for( QVector<envelopeAndLFOParameters *>::iterator it = v.begin();
|
||||
it != v.end(); ++it )
|
||||
{
|
||||
( *it )->m_lfoFrame = 0;
|
||||
@@ -539,7 +239,7 @@ void envelopeAndLFOWidget::resetLFO( void )
|
||||
|
||||
|
||||
|
||||
inline void FASTCALL envelopeAndLFOWidget::fillLFOLevel( float * _buf,
|
||||
inline void FASTCALL envelopeAndLFOParameters::fillLFOLevel( float * _buf,
|
||||
f_cnt_t _frame,
|
||||
const fpp_t _frames )
|
||||
{
|
||||
@@ -573,7 +273,7 @@ inline void FASTCALL envelopeAndLFOWidget::fillLFOLevel( float * _buf,
|
||||
|
||||
|
||||
|
||||
void FASTCALL envelopeAndLFOWidget::fillLevel( float * _buf, f_cnt_t _frame,
|
||||
void FASTCALL envelopeAndLFOParameters::fillLevel( float * _buf, f_cnt_t _frame,
|
||||
const f_cnt_t _release_begin,
|
||||
const fpp_t _frames )
|
||||
{
|
||||
@@ -619,7 +319,7 @@ void FASTCALL envelopeAndLFOWidget::fillLevel( float * _buf, f_cnt_t _frame,
|
||||
|
||||
|
||||
|
||||
void envelopeAndLFOWidget::saveSettings( QDomDocument & _doc,
|
||||
void envelopeAndLFOParameters::saveSettings( QDomDocument & _doc,
|
||||
QDomElement & _parent )
|
||||
{
|
||||
m_predelayModel.saveSettings( _doc, _parent, "pdel" );
|
||||
@@ -642,7 +342,7 @@ void envelopeAndLFOWidget::saveSettings( QDomDocument & _doc,
|
||||
|
||||
|
||||
|
||||
void envelopeAndLFOWidget::loadSettings( const QDomElement & _this )
|
||||
void envelopeAndLFOParameters::loadSettings( const QDomElement & _this )
|
||||
{
|
||||
m_predelayModel.loadSettings( _this, "pdel" );
|
||||
m_attackModel.loadSettings( _this, "att" );
|
||||
@@ -658,14 +358,15 @@ void envelopeAndLFOWidget::loadSettings( const QDomElement & _this )
|
||||
m_lfoAmountModel.loadSettings( _this, "lamt" );
|
||||
m_x100Model.loadSettings( _this, "x100" );
|
||||
m_controlEnvAmountModel.loadSettings( _this, "ctlenvamt" );
|
||||
|
||||
// Keep compatibility with version 2.1 file format
|
||||
|
||||
// ### TODO:
|
||||
/* // Keep compatibility with version 2.1 file format
|
||||
if( _this.hasAttribute( "lfosyncmode" ) )
|
||||
{
|
||||
m_lfoSpeedKnob->setSyncMode(
|
||||
( tempoSyncKnob::tempoSyncMode ) _this.attribute(
|
||||
"lfosyncmode" ).toInt() );
|
||||
}
|
||||
}*/
|
||||
|
||||
m_userWave.setAudioFile( _this.attribute( "userwavefile" ) );
|
||||
|
||||
@@ -675,229 +376,7 @@ void envelopeAndLFOWidget::loadSettings( const QDomElement & _this )
|
||||
|
||||
|
||||
|
||||
void envelopeAndLFOWidget::mousePressEvent( QMouseEvent * _me )
|
||||
{
|
||||
if( _me->button() != Qt::LeftButton )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if( QRect( ENV_GRAPH_X, ENV_GRAPH_Y, s_envGraph->width(),
|
||||
s_envGraph->height() ).contains( _me->pos() ) == TRUE )
|
||||
{
|
||||
if( m_amountKnob->value() < 1.0f )
|
||||
{
|
||||
m_amountKnob->setValue( 1.0f );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_amountKnob->setValue( 0.0f );
|
||||
}
|
||||
updateSampleVars();
|
||||
}
|
||||
else if( QRect( LFO_GRAPH_X, LFO_GRAPH_Y, s_lfoGraph->width(),
|
||||
s_lfoGraph->height() ).contains( _me->pos() ) == TRUE )
|
||||
{
|
||||
if( m_lfoAmountKnob->value() < 1.0f )
|
||||
{
|
||||
m_lfoAmountKnob->setValue( 1.0f );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_lfoAmountKnob->setValue( 0.0f );
|
||||
}
|
||||
updateSampleVars();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void envelopeAndLFOWidget::dragEnterEvent( QDragEnterEvent * _dee )
|
||||
{
|
||||
stringPairDrag::processDragEnterEvent( _dee,
|
||||
QString( "samplefile,tco_%1" ).arg(
|
||||
track::SAMPLE_TRACK ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void envelopeAndLFOWidget::dropEvent( QDropEvent * _de )
|
||||
{
|
||||
QString type = stringPairDrag::decodeKey( _de );
|
||||
QString value = stringPairDrag::decodeValue( _de );
|
||||
if( type == "samplefile" )
|
||||
{
|
||||
m_userWave.setAudioFile( stringPairDrag::decodeValue( _de ) );
|
||||
m_userLfoBtn->model()->setValue( TRUE );
|
||||
_de->accept();
|
||||
}
|
||||
else if( type == QString( "tco_%1" ).arg( track::SAMPLE_TRACK ) )
|
||||
{
|
||||
multimediaProject mmp( value, FALSE );
|
||||
m_userWave.setAudioFile( mmp.content().firstChild().toElement().
|
||||
attribute( "src" ) );
|
||||
m_userLfoBtn->model()->setValue( TRUE );
|
||||
_de->accept();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void envelopeAndLFOWidget::paintEvent( QPaintEvent * )
|
||||
{
|
||||
QPainter p( this );
|
||||
p.setRenderHint( QPainter::Antialiasing );
|
||||
|
||||
// set smaller font
|
||||
p.setFont( pointSize<6>( p.font() ) );
|
||||
|
||||
// draw envelope-graph
|
||||
p.drawPixmap( ENV_GRAPH_X, ENV_GRAPH_Y, *s_envGraph );
|
||||
// draw LFO-graph
|
||||
p.drawPixmap( LFO_GRAPH_X, LFO_GRAPH_Y, *s_lfoGraph );
|
||||
|
||||
|
||||
p.setFont( pointSize<8>( p.font() ) );
|
||||
|
||||
const float gray_amount = 1.0f - fabsf( m_amountKnob->value() );
|
||||
|
||||
p.setPen( QPen( QColor( static_cast<int>( 96 * gray_amount ),
|
||||
static_cast<int>( 255 - 159 * gray_amount ),
|
||||
static_cast<int>( 128 - 32 * gray_amount ) ),
|
||||
2 ) );
|
||||
|
||||
const QColor end_points_color( 0xFF, 0xBF, 0x22 );
|
||||
const QColor end_points_bg_color( 0, 0, 2 );
|
||||
|
||||
const int y_base = ENV_GRAPH_Y + s_envGraph->height() - 3;
|
||||
const int avail_height = s_envGraph->height() - 6;
|
||||
|
||||
int x1 = ENV_GRAPH_X + 2 + static_cast<int>( m_predelayKnob->value() *
|
||||
TIME_UNIT_WIDTH );
|
||||
int x2 = x1 + static_cast<int>( m_attackKnob->value() *
|
||||
TIME_UNIT_WIDTH );
|
||||
|
||||
p.drawLine( x1, y_base, x2, y_base - avail_height );
|
||||
p.fillRect( x1 - 1, y_base - 2, 4, 4, end_points_bg_color );
|
||||
p.fillRect( x1, y_base - 1, 2, 2, end_points_color );
|
||||
x1 = x2;
|
||||
x2 = x1 + static_cast<int>( m_holdKnob->value() * TIME_UNIT_WIDTH );
|
||||
|
||||
p.drawLine( x1, y_base - avail_height, x2, y_base - avail_height );
|
||||
p.fillRect( x1 - 1, y_base - 2 - avail_height, 4, 4,
|
||||
end_points_bg_color );
|
||||
p.fillRect( x1, y_base-1-avail_height, 2, 2, end_points_color );
|
||||
x1 = x2;
|
||||
x2 = x1 + static_cast<int>( ( m_decayKnob->value() *
|
||||
m_sustainKnob->value() ) *
|
||||
TIME_UNIT_WIDTH );
|
||||
|
||||
p.drawLine( x1, y_base-avail_height, x2, static_cast<int>( y_base -
|
||||
avail_height +
|
||||
m_sustainKnob->value() * avail_height ) );
|
||||
p.fillRect( x1 - 1, y_base - 2 - avail_height, 4, 4,
|
||||
end_points_bg_color );
|
||||
p.fillRect( x1, y_base - 1 - avail_height, 2, 2, end_points_color );
|
||||
x1 = x2;
|
||||
x2 = x1 + static_cast<int>( m_releaseKnob->value() * TIME_UNIT_WIDTH );
|
||||
|
||||
p.drawLine( x1, static_cast<int>( y_base - avail_height +
|
||||
m_sustainKnob->value() *
|
||||
avail_height ), x2, y_base );
|
||||
p.fillRect( x1-1, static_cast<int>( y_base - avail_height +
|
||||
m_sustainKnob->value() *
|
||||
avail_height ) - 2, 4, 4,
|
||||
end_points_bg_color );
|
||||
p.fillRect( x1, static_cast<int>( y_base - avail_height +
|
||||
m_sustainKnob->value() *
|
||||
avail_height ) - 1, 2, 2,
|
||||
end_points_color );
|
||||
p.fillRect( x2 - 1, y_base - 2, 4, 4, end_points_bg_color );
|
||||
p.fillRect( x2, y_base - 1, 2, 2, end_points_color );
|
||||
|
||||
|
||||
int LFO_GRAPH_W = s_lfoGraph->width() - 6; // substract border
|
||||
int LFO_GRAPH_H = s_lfoGraph->height() - 6; // substract border
|
||||
int graph_x_base = LFO_GRAPH_X + 3;
|
||||
int graph_y_base = LFO_GRAPH_Y + 3 + LFO_GRAPH_H / 2;
|
||||
|
||||
const float frames_for_graph = SECS_PER_LFO_OSCILLATION *
|
||||
engine::getMixer()->sampleRate() / 10;
|
||||
|
||||
const float lfo_gray_amount = 1.0f - fabsf( m_lfoAmountKnob->value() );
|
||||
p.setPen( QPen( QColor( static_cast<int>( 96 * lfo_gray_amount ),
|
||||
static_cast<int>( 255 - 159 * lfo_gray_amount ),
|
||||
static_cast<int>( 128 - 32 *
|
||||
lfo_gray_amount ) ),
|
||||
1.5 ) );
|
||||
|
||||
|
||||
float osc_frames = m_lfoOscillationFrames;
|
||||
|
||||
if( m_x100Model.value() )
|
||||
{
|
||||
osc_frames *= 100.0f;
|
||||
}
|
||||
|
||||
float old_y = 0;
|
||||
for( int x = 0; x <= LFO_GRAPH_W; ++x )
|
||||
{
|
||||
float val = 0.0;
|
||||
float cur_sample = x * frames_for_graph / LFO_GRAPH_W;
|
||||
if( static_cast<f_cnt_t>( cur_sample ) > m_lfoPredelayFrames )
|
||||
{
|
||||
float phase = ( cur_sample -= m_lfoPredelayFrames ) /
|
||||
osc_frames;
|
||||
switch( m_lfoWaveModel.value() )
|
||||
{
|
||||
case SIN:
|
||||
val = oscillator::sinSample( phase );
|
||||
break;
|
||||
case TRIANGLE:
|
||||
val = oscillator::triangleSample(
|
||||
phase );
|
||||
break;
|
||||
case SAW:
|
||||
val = oscillator::sawSample( phase );
|
||||
break;
|
||||
case SQUARE:
|
||||
val = oscillator::squareSample( phase );
|
||||
break;
|
||||
case USER:
|
||||
val = m_userWave.userWaveSample(
|
||||
phase );
|
||||
}
|
||||
if( static_cast<f_cnt_t>( cur_sample ) <=
|
||||
m_lfoAttackFrames )
|
||||
{
|
||||
val *= cur_sample / m_lfoAttackFrames;
|
||||
}
|
||||
}
|
||||
float cur_y = -LFO_GRAPH_H / 2.0f * val;
|
||||
p.drawLine( QLineF( graph_x_base + x - 1, graph_y_base + old_y,
|
||||
graph_x_base + x,
|
||||
graph_y_base + cur_y ) );
|
||||
old_y = cur_y;
|
||||
}
|
||||
|
||||
p.setPen( QColor( 255, 192, 0 ) );
|
||||
int ms_per_osc = static_cast<int>( SECS_PER_LFO_OSCILLATION *
|
||||
m_lfoSpeedKnob->value() *
|
||||
1000.0f );
|
||||
p.drawText( LFO_GRAPH_X + 4, LFO_GRAPH_Y + s_lfoGraph->height() - 6,
|
||||
tr( "ms/LFO:" ) );
|
||||
p.drawText( LFO_GRAPH_X + 52, LFO_GRAPH_Y + s_lfoGraph->height() - 6,
|
||||
QString::number( ms_per_osc ) );
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void envelopeAndLFOWidget::updateSampleVars( void )
|
||||
void envelopeAndLFOParameters::updateSampleVars( void )
|
||||
{
|
||||
engine::getMixer()->lock();
|
||||
|
||||
@@ -906,20 +385,20 @@ void envelopeAndLFOWidget::updateSampleVars( void )
|
||||
// TODO: Remove the expKnobVals, time should be linear
|
||||
const f_cnt_t predelay_frames = static_cast<f_cnt_t>(
|
||||
frames_per_env_seg *
|
||||
expKnobVal( m_predelayKnob->value() ) );
|
||||
expKnobVal( m_predelayModel.value() ) );
|
||||
|
||||
const f_cnt_t attack_frames = static_cast<f_cnt_t>( frames_per_env_seg *
|
||||
expKnobVal( m_attackKnob->value() ) );
|
||||
expKnobVal( m_attackModel.value() ) );
|
||||
|
||||
const f_cnt_t hold_frames = static_cast<f_cnt_t>( frames_per_env_seg *
|
||||
expKnobVal( m_holdKnob->value() ) );
|
||||
expKnobVal( m_holdModel.value() ) );
|
||||
|
||||
const f_cnt_t decay_frames = static_cast<f_cnt_t>( frames_per_env_seg *
|
||||
expKnobVal( m_decayKnob->value() *
|
||||
m_sustainKnob->value() ) );
|
||||
expKnobVal( m_decayModel.value() *
|
||||
m_sustainModel.value() ) );
|
||||
|
||||
m_sustainLevel = 1.0f - m_sustainKnob->value();
|
||||
m_amount = m_amountKnob->value();
|
||||
m_sustainLevel = 1.0f - m_sustainModel.value();
|
||||
m_amount = m_amountModel.value();
|
||||
if( m_amount >= 0 )
|
||||
{
|
||||
m_amountAdd = ( 1.0f - m_amount ) * m_valueForZeroAmount;
|
||||
@@ -932,7 +411,7 @@ void envelopeAndLFOWidget::updateSampleVars( void )
|
||||
m_pahdFrames = predelay_frames + attack_frames + hold_frames +
|
||||
decay_frames;
|
||||
m_rFrames = static_cast<f_cnt_t>( frames_per_env_seg *
|
||||
expKnobVal( m_releaseKnob->value() ) );
|
||||
expKnobVal( m_releaseModel.value() ) );
|
||||
|
||||
if( static_cast<int>( floorf( m_amount * 1000.0f ) ) == 0 )
|
||||
{
|
||||
@@ -988,17 +467,17 @@ void envelopeAndLFOWidget::updateSampleVars( void )
|
||||
const float frames_per_lfo_oscillation = SECS_PER_LFO_OSCILLATION *
|
||||
engine::getMixer()->sampleRate();
|
||||
m_lfoPredelayFrames = static_cast<f_cnt_t>( frames_per_lfo_oscillation *
|
||||
expKnobVal( m_lfoPredelayKnob->value() ) );
|
||||
expKnobVal( m_lfoPredelayModel.value() ) );
|
||||
m_lfoAttackFrames = static_cast<f_cnt_t>( frames_per_lfo_oscillation *
|
||||
expKnobVal( m_lfoAttackKnob->value() ) );
|
||||
expKnobVal( m_lfoAttackModel.value() ) );
|
||||
m_lfoOscillationFrames = static_cast<f_cnt_t>(
|
||||
frames_per_lfo_oscillation *
|
||||
m_lfoSpeedKnob->value() );
|
||||
m_lfoSpeedModel.value() );
|
||||
if( m_x100Model.value() )
|
||||
{
|
||||
m_lfoOscillationFrames /= 100;
|
||||
}
|
||||
m_lfoAmount = m_lfoAmountKnob->value() * 0.5f;
|
||||
m_lfoAmount = m_lfoAmountModel.value() * 0.5f;
|
||||
|
||||
m_used = TRUE;
|
||||
if( static_cast<int>( floorf( m_lfoAmount * 1000.0f ) ) == 0 )
|
||||
@@ -1016,7 +495,7 @@ void envelopeAndLFOWidget::updateSampleVars( void )
|
||||
|
||||
m_bad_lfoShapeData = TRUE;
|
||||
|
||||
update();
|
||||
emit dataChanged();
|
||||
|
||||
engine::getMixer()->unlock();
|
||||
}
|
||||
@@ -1024,22 +503,6 @@ void envelopeAndLFOWidget::updateSampleVars( void )
|
||||
|
||||
|
||||
|
||||
void envelopeAndLFOWidget::lfoUserWaveChanged( void )
|
||||
{
|
||||
if( m_lfoWaveModel.value() == USER )
|
||||
{
|
||||
if( m_userWave.frames() <= 1 )
|
||||
{
|
||||
textFloat::displayMessage( tr( "Hint" ),
|
||||
tr( "Drag a sample from somewhere and drop "
|
||||
"it in this window." ),
|
||||
embed::getIconPixmap( "hint" ), 3000 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#include "envelope_and_lfo_parameters.moc"
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
|
||||
|
||||
#include "export_project_dialog.h"
|
||||
#include "song_editor.h"
|
||||
#include "song.h"
|
||||
#include "main_window.h"
|
||||
#include "combobox.h"
|
||||
#include "led_checkbox.h"
|
||||
@@ -243,7 +243,7 @@ void exportProjectDialog::keyPressEvent( QKeyEvent * _ke )
|
||||
{
|
||||
if( _ke->key() == Qt::Key_Escape )
|
||||
{
|
||||
if( engine::getSongEditor()->exporting() == FALSE )
|
||||
if( engine::getSong()->exporting() == FALSE )
|
||||
{
|
||||
accept();
|
||||
}
|
||||
@@ -259,7 +259,7 @@ void exportProjectDialog::keyPressEvent( QKeyEvent * _ke )
|
||||
|
||||
void exportProjectDialog::closeEvent( QCloseEvent * _ce )
|
||||
{
|
||||
if( engine::getSongEditor()->exporting() == TRUE )
|
||||
if( engine::getSong()->exporting() == TRUE )
|
||||
{
|
||||
abortProjectExport();
|
||||
_ce->ignore();
|
||||
@@ -359,21 +359,20 @@ void exportProjectDialog::exportBtnClicked( void )
|
||||
|
||||
|
||||
engine::getMixer()->setAudioDevice( dev, m_hqmCb->model()->value() );
|
||||
engine::getSongEditor()->startExport();
|
||||
engine::getSong()->startExport();
|
||||
|
||||
delete m_hqmCb;
|
||||
|
||||
songEditor::playPos & pp = engine::getSongEditor()->getPlayPos(
|
||||
songEditor::PLAY_SONG );
|
||||
song::playPos & pp = engine::getSong()->getPlayPos(
|
||||
song::Mode_PlaySong );
|
||||
|
||||
while( engine::getSongEditor()->exportDone() == FALSE &&
|
||||
engine::getSongEditor()->exporting() == TRUE
|
||||
while( engine::getSong()->exportDone() == FALSE &&
|
||||
engine::getSong()->exporting() == TRUE
|
||||
&& !m_deleteFile )
|
||||
{
|
||||
dev->processNextBuffer();
|
||||
int pval = pp * 100 /
|
||||
( ( engine::getSongEditor()->lengthInTacts() + 1 )
|
||||
* 64 );
|
||||
( ( engine::getSong()->lengthInTacts() + 1 ) * 64 );
|
||||
m_exportProgressBar->setValue( pval );
|
||||
// update lmms-main-win-caption
|
||||
engine::getMainWindow()->setWindowTitle( tr( "Rendering:" )
|
||||
@@ -391,7 +390,7 @@ void exportProjectDialog::exportBtnClicked( void )
|
||||
void exportProjectDialog::cancelBtnClicked( void )
|
||||
{
|
||||
// is song-export-thread active?
|
||||
if( engine::getSongEditor()->exporting() == TRUE )
|
||||
if( engine::getSong()->exporting() == TRUE )
|
||||
{
|
||||
// then dispose abort of export
|
||||
abortProjectExport();
|
||||
@@ -425,7 +424,7 @@ void exportProjectDialog::finishProjectExport( void )
|
||||
// restore window-title
|
||||
engine::getMainWindow()->resetWindowTitle();
|
||||
|
||||
engine::getSongEditor()->stopExport();
|
||||
engine::getSong()->stopExport();
|
||||
|
||||
// if we rendered file from command line, quit after export
|
||||
if( file_to_render != "" )
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
#include "mmp.h"
|
||||
#include "preset_preview_play_handle.h"
|
||||
#include "sample_play_handle.h"
|
||||
#include "song_editor.h"
|
||||
#include "song.h"
|
||||
#include "string_pair_drag.h"
|
||||
#include "text_float.h"
|
||||
|
||||
@@ -261,14 +261,14 @@ void listView::activateListItem( QTreeWidgetItem * _item, int _column )
|
||||
return;
|
||||
}
|
||||
|
||||
if( f->type() == fileItem::SAMPLE_FILE )
|
||||
if( f->type() == fileItem::SampleFile )
|
||||
{
|
||||
// samples are per default opened in bb-editor because they're
|
||||
// likely drum-samples etc.
|
||||
engine::getMixer()->lock();
|
||||
instrumentTrack * it = dynamic_cast<instrumentTrack *>(
|
||||
track::create( track::INSTRUMENT_TRACK,
|
||||
engine::getBBEditor() ) );
|
||||
track::create( track::InstrumentTrack,
|
||||
engine::getBBTrackContainer() ) );
|
||||
#ifdef LMMS_DEBUG
|
||||
assert( it != NULL );
|
||||
#endif
|
||||
@@ -278,31 +278,31 @@ void listView::activateListItem( QTreeWidgetItem * _item, int _column )
|
||||
{
|
||||
afp->setParameter( "samplefile", f->fullName() );
|
||||
}
|
||||
it->toggledInstrumentTrackButton( TRUE );
|
||||
//it->toggledInstrumentTrackButton( TRUE );
|
||||
engine::getMixer()->unlock();
|
||||
}
|
||||
else if( f->type() == fileItem::PRESET_FILE )
|
||||
else if( f->type() == fileItem::PresetFile )
|
||||
{
|
||||
// presets are per default opened in bb-editor
|
||||
multimediaProject mmp( f->fullName() );
|
||||
engine::getMixer()->lock();
|
||||
instrumentTrack * it = dynamic_cast<instrumentTrack *>(
|
||||
track::create( track::INSTRUMENT_TRACK,
|
||||
engine::getBBEditor() ) );
|
||||
track::create( track::InstrumentTrack,
|
||||
engine::getBBTrackContainer() ) );
|
||||
if( it != NULL )
|
||||
{
|
||||
it->loadTrackSpecificSettings( mmp.content().
|
||||
firstChild().
|
||||
toElement() );
|
||||
it->toggledInstrumentTrackButton( TRUE );
|
||||
//it->toggledInstrumentTrackButton( TRUE );
|
||||
}
|
||||
engine::getMixer()->unlock();
|
||||
}
|
||||
else if( f->type() == fileItem::PROJECT_FILE )
|
||||
else if( f->type() == fileItem::ProjectFile )
|
||||
{
|
||||
if( engine::getMainWindow()->mayChangeProject() )
|
||||
{
|
||||
engine::getSongEditor()->loadProject( f->fullName() );
|
||||
engine::getSong()->loadProject( f->fullName() );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -326,16 +326,16 @@ void listView::sendToActiveInstrumentTrack( void )
|
||||
// instrument-track
|
||||
while( w.hasPrevious() )
|
||||
{
|
||||
instrumentTrack * ct = dynamic_cast<instrumentTrack *>(
|
||||
instrumentTrackView * itv = dynamic_cast<instrumentTrackView *>(
|
||||
w.previous()->widget() );
|
||||
if( ct != NULL && ct->isHidden() == FALSE )
|
||||
if( itv != NULL && itv->isHidden() == FALSE )
|
||||
{
|
||||
// ok, it's an instrument-track, so we can apply the
|
||||
// sample or the preset
|
||||
engine::getMixer()->lock();
|
||||
if( m_contextMenuItem->type() == fileItem::SAMPLE_FILE )
|
||||
if( m_contextMenuItem->type() == fileItem::SampleFile )
|
||||
{
|
||||
instrument * afp = ct->loadInstrument(
|
||||
instrument * afp = itv->model()->loadInstrument(
|
||||
engine::sampleExtensions()
|
||||
[m_contextMenuItem
|
||||
->extension()] );
|
||||
@@ -346,15 +346,15 @@ void listView::sendToActiveInstrumentTrack( void )
|
||||
}
|
||||
}
|
||||
else if( m_contextMenuItem->type() ==
|
||||
fileItem::PRESET_FILE )
|
||||
fileItem::PresetFile )
|
||||
{
|
||||
multimediaProject mmp(
|
||||
m_contextMenuItem->fullName() );
|
||||
ct->loadTrackSpecificSettings( mmp.content().
|
||||
firstChild().
|
||||
itv->model()->loadTrackSpecificSettings(
|
||||
mmp.content().firstChild().
|
||||
toElement() );
|
||||
}
|
||||
ct->toggledInstrumentTrackButton( TRUE );
|
||||
//ct->toggledInstrumentTrackButton( TRUE );
|
||||
engine::getMixer()->unlock();
|
||||
break;
|
||||
}
|
||||
@@ -367,10 +367,10 @@ void listView::sendToActiveInstrumentTrack( void )
|
||||
void listView::openInNewInstrumentTrack( trackContainer * _tc )
|
||||
{
|
||||
engine::getMixer()->lock();
|
||||
if( m_contextMenuItem->type() == fileItem::SAMPLE_FILE )
|
||||
if( m_contextMenuItem->type() == fileItem::SampleFile )
|
||||
{
|
||||
instrumentTrack * ct = dynamic_cast<instrumentTrack *>(
|
||||
track::create( track::INSTRUMENT_TRACK, _tc ) );
|
||||
track::create( track::InstrumentTrack, _tc ) );
|
||||
#ifdef LMMS_DEBUG
|
||||
assert( ct != NULL );
|
||||
#endif
|
||||
@@ -383,19 +383,19 @@ void listView::openInNewInstrumentTrack( trackContainer * _tc )
|
||||
afp->setParameter( "samplefile",
|
||||
m_contextMenuItem->fullName() );
|
||||
}
|
||||
ct->toggledInstrumentTrackButton( TRUE );
|
||||
//ct->toggledInstrumentTrackButton( TRUE );
|
||||
}
|
||||
else if( m_contextMenuItem->type() == fileItem::PRESET_FILE )
|
||||
else if( m_contextMenuItem->type() == fileItem::PresetFile )
|
||||
{
|
||||
multimediaProject mmp( m_contextMenuItem->fullName() );
|
||||
track * t = track::create( track::INSTRUMENT_TRACK, _tc );
|
||||
track * t = track::create( track::InstrumentTrack, _tc );
|
||||
instrumentTrack * ct = dynamic_cast<instrumentTrack *>( t );
|
||||
if( ct != NULL )
|
||||
{
|
||||
ct->loadTrackSpecificSettings( mmp.content().
|
||||
firstChild().
|
||||
toElement() );
|
||||
ct->toggledInstrumentTrackButton( TRUE );
|
||||
//ct->toggledInstrumentTrackButton( TRUE );
|
||||
}
|
||||
}
|
||||
engine::getMixer()->unlock();
|
||||
@@ -406,7 +406,7 @@ void listView::openInNewInstrumentTrack( trackContainer * _tc )
|
||||
|
||||
void listView::openInNewInstrumentTrackBBE( void )
|
||||
{
|
||||
openInNewInstrumentTrack( engine::getBBEditor() );
|
||||
openInNewInstrumentTrack( engine::getBBTrackContainer() );
|
||||
}
|
||||
|
||||
|
||||
@@ -414,7 +414,7 @@ void listView::openInNewInstrumentTrackBBE( void )
|
||||
|
||||
void listView::openInNewInstrumentTrackSE( void )
|
||||
{
|
||||
openInNewInstrumentTrack( engine::getSongEditor() );
|
||||
openInNewInstrumentTrack( engine::getSong() );
|
||||
}
|
||||
|
||||
|
||||
@@ -435,8 +435,8 @@ void listView::updateDirectory( QTreeWidgetItem * _item )
|
||||
void listView::contextMenuEvent( QContextMenuEvent * _e )
|
||||
{
|
||||
fileItem * f = dynamic_cast<fileItem *>( itemAt( _e->pos() ) );
|
||||
if( f != NULL && ( f->type() == fileItem::SAMPLE_FILE ||
|
||||
f->type() == fileItem::PRESET_FILE ) )
|
||||
if( f != NULL && ( f->type() == fileItem::SampleFile ||
|
||||
f->type() == fileItem::PresetFile ) )
|
||||
{
|
||||
m_contextMenuItem = f;
|
||||
QMenu contextMenu( this );
|
||||
@@ -495,7 +495,7 @@ void listView::mousePressEvent( QMouseEvent * _me )
|
||||
m_previewPlayHandle );
|
||||
m_previewPlayHandle = NULL;
|
||||
}
|
||||
if( f->type() == fileItem::SAMPLE_FILE )
|
||||
if( f->type() == fileItem::SampleFile )
|
||||
{
|
||||
textFloat * tf = textFloat::displayMessage(
|
||||
tr( "Loading sample" ),
|
||||
@@ -510,7 +510,7 @@ void listView::mousePressEvent( QMouseEvent * _me )
|
||||
m_previewPlayHandle = s;
|
||||
delete tf;
|
||||
}
|
||||
else if( f->type() == fileItem::PRESET_FILE )
|
||||
else if( f->type() == fileItem::PresetFile )
|
||||
{
|
||||
m_previewPlayHandle = new presetPreviewPlayHandle(
|
||||
f->fullName() );
|
||||
@@ -539,7 +539,7 @@ void listView::mouseMoveEvent( QMouseEvent * _me )
|
||||
{
|
||||
switch( f->type() )
|
||||
{
|
||||
case fileItem::PRESET_FILE:
|
||||
case fileItem::PresetFile:
|
||||
new stringPairDrag( "presetfile",
|
||||
f->fullName(),
|
||||
embed::getIconPixmap(
|
||||
@@ -547,7 +547,7 @@ void listView::mouseMoveEvent( QMouseEvent * _me )
|
||||
this );
|
||||
break;
|
||||
|
||||
case fileItem::SAMPLE_FILE:
|
||||
case fileItem::SampleFile:
|
||||
new stringPairDrag( "samplefile",
|
||||
f->fullName(),
|
||||
embed::getIconPixmap(
|
||||
@@ -555,7 +555,7 @@ void listView::mouseMoveEvent( QMouseEvent * _me )
|
||||
this );
|
||||
break;
|
||||
|
||||
case fileItem::MIDI_FILE:
|
||||
case fileItem::MidiFile:
|
||||
new stringPairDrag( "midifile",
|
||||
f->fullName(),
|
||||
embed::getIconPixmap(
|
||||
@@ -842,22 +842,22 @@ void fileItem::initPixmapStuff( void )
|
||||
|
||||
switch( m_type )
|
||||
{
|
||||
case PROJECT_FILE:
|
||||
case ProjectFile:
|
||||
setIcon( 0, *s_projectFilePixmap );
|
||||
break;
|
||||
case PRESET_FILE:
|
||||
case PresetFile:
|
||||
setIcon( 0, *s_presetFilePixmap );
|
||||
break;
|
||||
case SAMPLE_FILE:
|
||||
case SampleFile:
|
||||
setIcon( 0, *s_sampleFilePixmap );
|
||||
break;
|
||||
case MIDI_FILE:
|
||||
case MidiFile:
|
||||
setIcon( 0, *s_midiFilePixmap );
|
||||
break;
|
||||
case FLP_FILE:
|
||||
case FlpFile:
|
||||
setIcon( 0, *s_flpFilePixmap );
|
||||
break;
|
||||
case UNKNOWN:
|
||||
case UnknownFile:
|
||||
default:
|
||||
setIcon( 0, *s_unknownFilePixmap );
|
||||
break;
|
||||
@@ -872,44 +872,44 @@ void fileItem::determineFileType( void )
|
||||
QString ext = extension();
|
||||
if( ext == "mmp" || ext == "mpt" || ext == "mmpz" )
|
||||
{
|
||||
m_type = PROJECT_FILE;
|
||||
m_type = ProjectFile;
|
||||
}
|
||||
else if( ext == "xml" )
|
||||
{
|
||||
multimediaProject::projectTypes t =
|
||||
multimediaProject::ProjectTypes t =
|
||||
multimediaProject::typeOfFile( fullName() );
|
||||
if( t == multimediaProject::SONG_PROJECT )
|
||||
if( t == multimediaProject::SongProject )
|
||||
{
|
||||
m_type = PROJECT_FILE;
|
||||
m_type = ProjectFile;
|
||||
}
|
||||
else if( t == multimediaProject::INSTRUMENT_TRACK_SETTINGS )
|
||||
else if( t == multimediaProject::InstrumentTrackSettings )
|
||||
{
|
||||
m_type = PRESET_FILE;
|
||||
m_type = PresetFile;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_type = UNKNOWN;
|
||||
m_type = UnknownFile;
|
||||
}
|
||||
}
|
||||
else if( ext == "csf" )
|
||||
{
|
||||
m_type = PRESET_FILE;
|
||||
m_type = PresetFile;
|
||||
}
|
||||
else if( engine::sampleExtensions().contains( ext ) )
|
||||
{
|
||||
m_type = SAMPLE_FILE;
|
||||
m_type = SampleFile;
|
||||
}
|
||||
else if( ext == "mid" )
|
||||
{
|
||||
m_type = MIDI_FILE;
|
||||
m_type = MidiFile;
|
||||
}
|
||||
else if( ext == "flp" )
|
||||
{
|
||||
m_type = FLP_FILE;
|
||||
m_type = FlpFile;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_type = UNKNOWN;
|
||||
m_type = UnknownFile;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "engine.h"
|
||||
#include "track_container.h"
|
||||
#include "project_journal.h"
|
||||
#include "automatable_model_templates.h"
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -82,7 +82,7 @@ f_cnt_t instrument::beatLen( notePlayHandle * ) const
|
||||
instrument * instrument::instantiate( const QString & _plugin_name,
|
||||
instrumentTrack * _instrument_track )
|
||||
{
|
||||
plugin * p = plugin::instantiate( _plugin_name, /*_instrument_track*/ NULL,
|
||||
plugin * p = plugin::instantiate( _plugin_name, _instrument_track,
|
||||
_instrument_track );
|
||||
// check whether instantiated plugin is an instrument
|
||||
if( dynamic_cast<instrument *>( p ) != NULL )
|
||||
@@ -155,9 +155,10 @@ void instrumentView::setModel( ::model * _model, bool )
|
||||
if( dynamic_cast<instrument *>( _model ) != NULL )
|
||||
{
|
||||
modelView::setModel( _model );
|
||||
if( dynamic_cast<instrumentTrack *>( parentWidget() ) != NULL )
|
||||
if( dynamic_cast<instrumentTrackView *>( parentWidget() ) !=
|
||||
NULL )
|
||||
{
|
||||
dynamic_cast<instrumentTrack *>( parentWidget() )->
|
||||
dynamic_cast<instrumentTrackView *>( parentWidget() )->
|
||||
setWindowIcon( *( model()->
|
||||
getDescriptor()->logo ) );
|
||||
}
|
||||
|
||||
540
src/core/instrument_functions.cpp
Normal file
540
src/core/instrument_functions.cpp
Normal file
@@ -0,0 +1,540 @@
|
||||
#ifndef SINGLE_SOURCE_COMPILE
|
||||
|
||||
/*
|
||||
* instrument_functions.cpp - models for instrument-function-tab
|
||||
*
|
||||
* Copyright (c) 2004-2008 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* 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 (see COPYING); if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <Qt/QtXml>
|
||||
|
||||
|
||||
#include "instrument_functions.h"
|
||||
#include "embed.h"
|
||||
#include "engine.h"
|
||||
#include "instrument_track.h"
|
||||
#include "note_play_handle.h"
|
||||
#include "preset_preview_play_handle.h"
|
||||
|
||||
|
||||
|
||||
chordCreator::chord chordCreator::s_chordTable[] =
|
||||
{
|
||||
{ chordCreator::tr( "octave" ), { 0, -1 } },
|
||||
{ chordCreator::tr( "Major" ), { 0, 4, 7, -1 } },
|
||||
{ chordCreator::tr( "Majb5" ), { 0, 4, 6, -1 } },
|
||||
{ chordCreator::tr( "minor" ), { 0, 3, 7, -1 } },
|
||||
{ chordCreator::tr( "minb5" ), { 0, 3, 6, -1 } },
|
||||
{ chordCreator::tr( "sus2" ), { 0, 2, 7, -1 } },
|
||||
{ chordCreator::tr( "sus4" ), { 0, 5, 7, -1 } },
|
||||
{ chordCreator::tr( "aug" ), { 0, 4, 8, -1 } },
|
||||
{ chordCreator::tr( "augsus4" ), { 0, 5, 8, -1 } },
|
||||
{ chordCreator::tr( "tri" ), { 0, 3, 6, 9, -1 } },
|
||||
|
||||
{ chordCreator::tr( "6" ), { 0, 4, 7, 9, -1 } },
|
||||
{ chordCreator::tr( "6sus4" ), { 0, 5, 7, 9, -1 } },
|
||||
{ chordCreator::tr( "6add9" ), { 0, 4, 7, 12, -1 } },
|
||||
{ chordCreator::tr( "m6" ), { 0, 3, 7, 9, -1 } },
|
||||
{ chordCreator::tr( "m6add9" ), { 0, 3, 7, 9, 14, -1 } },
|
||||
|
||||
{ chordCreator::tr( "7" ), { 0, 4, 7, 10, -1 } },
|
||||
{ chordCreator::tr( "7sus4" ), { 0, 5, 7, 10, -1 } },
|
||||
{ chordCreator::tr( "7#5" ), { 0, 4, 8, 10, -1 } },
|
||||
{ chordCreator::tr( "7b5" ), { 0, 4, 6, 10, -1 } },
|
||||
{ chordCreator::tr( "7#9" ), { 0, 4, 7, 10, 13, 18, -1 } },
|
||||
{ chordCreator::tr( "7b9" ), { 0, 4, 7, 10, 13, 16, -1 } },
|
||||
{ chordCreator::tr( "7#5#9" ), { 0, 4, 8, 12, 14, 19, -1 } },
|
||||
{ chordCreator::tr( "7#5b9" ), { 0, 4, 8, 12, 14, 17, -1 } },
|
||||
{ chordCreator::tr( "7b5b9" ), { 0, 4, 6, 10, 12, 15, -1 } },
|
||||
{ chordCreator::tr( "7add11" ), { 0, 4, 7, 10, 17, -1 } },
|
||||
{ chordCreator::tr( "7add13" ), { 0, 4, 7, 10, 21, -1 } },
|
||||
{ chordCreator::tr( "7#11" ), { 0, 4, 7, 10, 18, -1 } },
|
||||
{ chordCreator::tr( "Maj7" ), { 0, 4, 7, 11, -1 } },
|
||||
{ chordCreator::tr( "Maj7b5" ), { 0, 4, 6, 11, -1 } },
|
||||
{ chordCreator::tr( "Maj7#5" ), { 0, 4, 8, 11, -1 } },
|
||||
{ chordCreator::tr( "Maj7#11" ), { 0, 4, 7, 11, 18, -1 } },
|
||||
{ chordCreator::tr( "Maj7add13" ), { 0, 4, 7, 11, 21, -1 } },
|
||||
{ chordCreator::tr( "m7" ), { 0, 3, 7, 10, -1 } },
|
||||
{ chordCreator::tr( "m7b5" ), { 0, 3, 6, 10, -1 } },
|
||||
{ chordCreator::tr( "m7b9" ), { 0, 3, 7, 10, 13, -1 } },
|
||||
{ chordCreator::tr( "m7add11" ), { 0, 3, 7, 10, 17, -1 } },
|
||||
{ chordCreator::tr( "m7add13" ), { 0, 3, 7, 10, 21, -1 } },
|
||||
{ chordCreator::tr( "m-Maj7" ), { 0, 3, 7, 11, -1 } },
|
||||
{ chordCreator::tr( "m-Maj7add11" ), { 0, 3, 7, 11, 17, -1 } },
|
||||
{ chordCreator::tr( "m-Maj7add13" ), { 0, 3, 7, 11, 21, -1 } },
|
||||
|
||||
{ chordCreator::tr( "9" ), { 0, 4, 7, 10, 14, -1 } },
|
||||
{ chordCreator::tr( "9sus4" ), { 0, 5, 7, 10, 14, -1 } },
|
||||
{ chordCreator::tr( "add9" ), { 0, 4, 7, 14, -1 } },
|
||||
{ chordCreator::tr( "9#5" ), { 0, 4, 8, 10, 14, -1 } },
|
||||
{ chordCreator::tr( "9b5" ), { 0, 4, 6, 10, 14, -1 } },
|
||||
{ chordCreator::tr( "9#11" ), { 0, 4, 7, 10, 14, 18, -1 } },
|
||||
{ chordCreator::tr( "9b13" ), { 0, 4, 7, 10, 14, 20, -1 } },
|
||||
{ chordCreator::tr( "Maj9" ), { 0, 4, 7, 11, 14, -1 } },
|
||||
{ chordCreator::tr( "Maj9sus4" ), { 0, 5, 7, 11, 15, -1 } },
|
||||
{ chordCreator::tr( "Maj9#5" ), { 0, 4, 8, 11, 14, -1 } },
|
||||
{ chordCreator::tr( "Maj9#11" ), { 0, 4, 7, 11, 14, 18, -1 } },
|
||||
{ chordCreator::tr( "m9" ), { 0, 3, 7, 10, 14, -1 } },
|
||||
{ chordCreator::tr( "madd9" ), { 0, 3, 7, 14, -1 } },
|
||||
{ chordCreator::tr( "m9b5" ), { 0, 3, 6, 10, 14, -1 } },
|
||||
{ chordCreator::tr( "m9-Maj7" ), { 0, 3, 7, 11, 14, -1 } },
|
||||
|
||||
{ chordCreator::tr( "11" ), { 0, 4, 7, 10, 14, 17, -1 } },
|
||||
{ chordCreator::tr( "11b9" ), { 0, 4, 7, 10, 13, 17, -1 } },
|
||||
{ chordCreator::tr( "Maj11" ), { 0, 4, 7, 11, 14, 17, -1 } },
|
||||
{ chordCreator::tr( "m11" ), { 0, 3, 7, 10, 14, 17, -1 } },
|
||||
{ chordCreator::tr( "m-Maj11" ), { 0, 3, 7, 11, 14, 17, -1 } },
|
||||
|
||||
{ chordCreator::tr( "13" ), { 0, 4, 7, 10, 14, 21, -1 } },
|
||||
{ chordCreator::tr( "13#9" ), { 0, 4, 7, 10, 15, 21, -1 } },
|
||||
{ chordCreator::tr( "13b9" ), { 0, 4, 7, 10, 13, 21, -1 } },
|
||||
{ chordCreator::tr( "13b5b9" ), { 0, 4, 6, 10, 13, 21, -1 } },
|
||||
{ chordCreator::tr( "Maj13" ), { 0, 4, 7, 11, 14, 21, -1 } },
|
||||
{ chordCreator::tr( "m13" ), { 0, 3, 7, 10, 14, 21, -1 } },
|
||||
{ chordCreator::tr( "m-Maj13" ), { 0, 3, 7, 11, 14, 21, -1 } },
|
||||
|
||||
{ chordCreator::tr( "Major" ), { 0, 2, 4, 5, 7, 9, 11, -1 } },
|
||||
{ chordCreator::tr( "Harmonic minor" ), { 0, 2, 3, 5, 7, 8,
|
||||
11, -1 } },
|
||||
{ chordCreator::tr( "Melodic minor" ), { 0, 2, 3, 5, 7, 9,
|
||||
11, -1 } },
|
||||
{ chordCreator::tr( "Whole tone" ), { 0, 2, 4, 6, 8, 10,
|
||||
-1 } },
|
||||
{ chordCreator::tr( "Diminished" ), { 0, 2, 3, 5, 6, 8, 9,
|
||||
11, -1 } },
|
||||
{ chordCreator::tr( "Major pentatonic" ), { 0, 2, 4, 7, 10,
|
||||
-1 } },
|
||||
{ chordCreator::tr( "Minor pentatonic" ), { 0, 3, 5, 7, 10,
|
||||
-1 } },
|
||||
{ chordCreator::tr( "Jap in sen" ), { 0, 1, 5, 7, 10, -1 } },
|
||||
{ chordCreator::tr( "Major bebop" ), { 0, 2, 4, 5, 7, 8, 9,
|
||||
11, -1 } },
|
||||
{ chordCreator::tr( "Dominant bebop" ), { 0, 2, 4, 5, 7, 9,
|
||||
10, 11, -1 } },
|
||||
{ chordCreator::tr( "Blues" ), { 0, 3, 5, 6, 7, 10, -1 } },
|
||||
{ chordCreator::tr( "Arabic" ), { 0, 1, 4, 5, 7, 8, 11, -1 } },
|
||||
{ chordCreator::tr( "Enigmatic" ), { 0, 1, 4, 6, 8, 10, 11,
|
||||
-1 } },
|
||||
{ chordCreator::tr( "Neopolitan" ), { 0, 1, 3, 5, 7, 9, 11,
|
||||
-1 } },
|
||||
{ chordCreator::tr( "Neopolitan minor" ), { 0, 1, 3, 5, 7, 9,
|
||||
11, -1 } },
|
||||
{ chordCreator::tr( "Hungarian minor" ), { 0, 2, 3, 6, 7, 9,
|
||||
11, -1 } },
|
||||
{ chordCreator::tr( "Dorian" ), { 0, 2, 3, 5, 7, 9, 10, -1 } },
|
||||
{ chordCreator::tr( "Phrygolydian" ), { 0, 1, 3, 5, 7, 8, 10,
|
||||
-1 } },
|
||||
{ chordCreator::tr( "Lydian" ), { 0, 2, 4, 6, 7, 9, 11, -1 } },
|
||||
{ chordCreator::tr( "Mixolydian" ), { 0, 2, 4, 5, 7, 9, 10,
|
||||
-1 } },
|
||||
{ chordCreator::tr( "Aeolian" ), { 0, 2, 3, 5, 7, 8, 10,
|
||||
-1 } },
|
||||
{ chordCreator::tr( "Locrian" ), { 0, 1, 3, 5, 6, 8, 10,
|
||||
-1 } },
|
||||
|
||||
{ "", { -1, -1 } }
|
||||
|
||||
} ;
|
||||
|
||||
|
||||
const int CHORDS_GROUPBOX_X = 4;
|
||||
const int CHORDS_GROUPBOX_Y = 5;
|
||||
const int CHORDS_GROUPBOX_WIDTH = 238;
|
||||
const int CHORDS_GROUPBOX_HEIGHT = 65;
|
||||
const int ARP_GROUPBOX_X = CHORDS_GROUPBOX_X;
|
||||
const int ARP_GROUPBOX_Y = 10 + CHORDS_GROUPBOX_Y + CHORDS_GROUPBOX_HEIGHT;
|
||||
const int ARP_GROUPBOX_WIDTH = CHORDS_GROUPBOX_WIDTH;
|
||||
const int ARP_GROUPBOX_HEIGHT = 240 - ARP_GROUPBOX_Y;
|
||||
|
||||
|
||||
|
||||
chordCreator::chordCreator( instrumentTrack * _instrument_track ) :
|
||||
model( _instrument_track ),
|
||||
m_chordsEnabledModel( FALSE, this ),
|
||||
m_chordsModel( this ),
|
||||
m_chordRangeModel( 1.0f, 1.0f, 9.0f, 1.0f, this )
|
||||
{
|
||||
m_chordsEnabledModel.setTrack( _instrument_track );
|
||||
|
||||
m_chordsModel.setTrack( _instrument_track );
|
||||
for( int i = 0; s_chordTable[i].interval[0] != -1; ++i )
|
||||
{
|
||||
m_chordsModel.addItem( tr( s_chordTable[i].name.toAscii().
|
||||
constData() ) );
|
||||
}
|
||||
|
||||
m_chordRangeModel.setTrack( _instrument_track );
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
chordCreator::~chordCreator()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void chordCreator::processNote( notePlayHandle * _n )
|
||||
{
|
||||
const int base_note_key = _n->key();
|
||||
// we add chord-subnotes to note if either note is a base-note and
|
||||
// arpeggio is not used or note is part of an arpeggio
|
||||
// at the same time we only add sub-notes if nothing of the note was
|
||||
// played yet, because otherwise we would add chord-subnotes every
|
||||
// time an audio-buffer is rendered...
|
||||
if( ( ( _n->baseNote() &&
|
||||
_n->getInstrumentTrack()->arpeggiatorEnabled() == FALSE ) ||
|
||||
_n->arpNote() ) &&
|
||||
_n->totalFramesPlayed() == 0 &&
|
||||
m_chordsEnabledModel.value() == TRUE )
|
||||
{
|
||||
// then insert sub-notes for chord
|
||||
const int selected_chord = m_chordsModel.value();
|
||||
|
||||
for( int octave_cnt = 0;
|
||||
octave_cnt < m_chordRangeModel.value(); ++octave_cnt )
|
||||
{
|
||||
const int sub_note_key_base = base_note_key +
|
||||
octave_cnt * NOTES_PER_OCTAVE;
|
||||
// if octave_cnt == 1 we're in the first octave and
|
||||
// the base-note is already done, so we don't have to
|
||||
// create it in the following loop, then we loop until
|
||||
// there's a -1 in the interval-array
|
||||
for( int i = ( octave_cnt == 0 ) ? 1 : 0;
|
||||
s_chordTable[selected_chord].interval[i] != -1;
|
||||
++i )
|
||||
{
|
||||
// add interval to sub-note-key
|
||||
const int sub_note_key = sub_note_key_base +
|
||||
(int) s_chordTable[
|
||||
selected_chord].interval[i];
|
||||
// maybe we're out of range -> let's get outta
|
||||
// here!
|
||||
if( sub_note_key > NOTES_PER_OCTAVE*OCTAVES )
|
||||
{
|
||||
break;
|
||||
}
|
||||
// create copy of base-note
|
||||
note note_copy( _n->length(), 0,
|
||||
(tones)( sub_note_key %
|
||||
NOTES_PER_OCTAVE ),
|
||||
(octaves)( sub_note_key /
|
||||
NOTES_PER_OCTAVE ),
|
||||
_n->getVolume(),
|
||||
_n->getPanning(),
|
||||
_n->detuning() );
|
||||
// create sub-note-play-handle, only note is
|
||||
// different
|
||||
new notePlayHandle( _n->getInstrumentTrack(),
|
||||
_n->offset(),
|
||||
_n->frames(), note_copy,
|
||||
_n );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void chordCreator::saveSettings( QDomDocument & _doc, QDomElement & _this )
|
||||
{
|
||||
m_chordsEnabledModel.saveSettings( _doc, _this, "chord-enabled" );
|
||||
m_chordsModel.saveSettings( _doc, _this, "chord" );
|
||||
m_chordRangeModel.saveSettings( _doc, _this, "chordrange" );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void chordCreator::loadSettings( const QDomElement & _this )
|
||||
{
|
||||
m_chordsEnabledModel.loadSettings( _this, "chord-enabled" );
|
||||
m_chordsModel.loadSettings( _this, "chord" );
|
||||
m_chordRangeModel.loadSettings( _this, "chordrange" );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
arpeggiator::arpeggiator( instrumentTrack * _instrument_track ) :
|
||||
model( _instrument_track ),
|
||||
m_arpEnabledModel( FALSE ),
|
||||
m_arpModel( this ),
|
||||
m_arpRangeModel( 1.0f, 1.0f, 9.0f, 1.0f, this ),
|
||||
m_arpTimeModel( 100.0f, 25.0f, 2000.0f, 1.0f, this ),
|
||||
m_arpGateModel( 100.0f, 1.0f, 200.0f, 1.0f, this ),
|
||||
m_arpDirectionModel( 0, 0, 0, intModel::defaultRelStep(), this ),
|
||||
m_arpModeModel( this )
|
||||
{
|
||||
m_arpEnabledModel.setTrack( _instrument_track );
|
||||
|
||||
m_arpModel.setTrack( _instrument_track );
|
||||
for( int i = 0; chordCreator::s_chordTable[i].interval[0] != -1; ++i )
|
||||
{
|
||||
m_arpModel.addItem( tr( chordCreator::s_chordTable[i].
|
||||
name.toAscii().constData() ) );
|
||||
}
|
||||
|
||||
m_arpRangeModel.setTrack( _instrument_track );
|
||||
|
||||
m_arpTimeModel.setTrack( _instrument_track );
|
||||
|
||||
m_arpGateModel.setTrack( _instrument_track );
|
||||
|
||||
m_arpDirectionModel.setTrack( _instrument_track );
|
||||
m_arpDirectionModel.setInitValue( ArpDirUp );
|
||||
|
||||
m_arpModeModel.setTrack( _instrument_track );
|
||||
m_arpModeModel.addItem( tr( "Free" ), new QPixmap(
|
||||
embed::getIconPixmap( "arp_free" ) ) );
|
||||
m_arpModeModel.addItem( tr( "Sort" ), new QPixmap(
|
||||
embed::getIconPixmap( "arp_sort" ) ) );
|
||||
m_arpModeModel.addItem( tr( "Sync" ), new QPixmap(
|
||||
embed::getIconPixmap( "arp_sync" ) ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
arpeggiator::~arpeggiator()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void arpeggiator::processNote( notePlayHandle * _n )
|
||||
{
|
||||
const int base_note_key = _n->key();
|
||||
if( _n->baseNote() == FALSE ||
|
||||
!m_arpEnabledModel.value() ||
|
||||
( _n->released() && _n->releaseFramesDone() >=
|
||||
_n->actualReleaseFramesToDo() ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
const int selected_arp = m_arpModel.value();
|
||||
|
||||
constNotePlayHandleVector cnphv = notePlayHandle::nphsOfInstrumentTrack(
|
||||
_n->getInstrumentTrack() );
|
||||
if( m_arpModeModel.value() != FreeMode && cnphv.size() == 0 )
|
||||
{
|
||||
// maybe we're playing only a preset-preview-note?
|
||||
cnphv = presetPreviewPlayHandle::nphsOfInstrumentTrack(
|
||||
_n->getInstrumentTrack() );
|
||||
if( cnphv.size() == 0 )
|
||||
{
|
||||
// still nothing found here, so lets return
|
||||
//return;
|
||||
cnphv.push_back( _n );
|
||||
}
|
||||
}
|
||||
|
||||
const int cur_chord_size = chordCreator::getChordSize(
|
||||
chordCreator::s_chordTable[selected_arp] );
|
||||
const int range = (int)( cur_chord_size * m_arpRangeModel.value() );
|
||||
const int total_range = range * cnphv.size();
|
||||
|
||||
// number of frames that every note should be played
|
||||
const f_cnt_t arp_frames = (f_cnt_t)( m_arpTimeModel.value() / 1000.0f *
|
||||
engine::getMixer()->sampleRate() );
|
||||
const f_cnt_t gated_frames = (f_cnt_t)( m_arpGateModel.value() *
|
||||
arp_frames / 100.0f );
|
||||
|
||||
// used for calculating remaining frames for arp-note, we have to add
|
||||
// arp_frames-1, otherwise the first arp-note will not be setup
|
||||
// correctly... -> arp_frames frames silence at the start of every note!
|
||||
int cur_frame = ( ( m_arpModeModel.value() != FreeMode ) ?
|
||||
cnphv.first()->totalFramesPlayed() :
|
||||
_n->totalFramesPlayed() ) + arp_frames - 1;
|
||||
// used for loop
|
||||
f_cnt_t frames_processed = 0;
|
||||
|
||||
while( frames_processed < engine::getMixer()->framesPerPeriod() )
|
||||
{
|
||||
const f_cnt_t remaining_frames_for_cur_arp = arp_frames -
|
||||
( cur_frame % arp_frames );
|
||||
// does current arp-note fill whole audio-buffer?
|
||||
if( remaining_frames_for_cur_arp >
|
||||
engine::getMixer()->framesPerPeriod() )
|
||||
{
|
||||
// then we don't have to do something!
|
||||
break;
|
||||
}
|
||||
|
||||
frames_processed += remaining_frames_for_cur_arp;
|
||||
|
||||
// init with zero
|
||||
int cur_arp_idx = 0;
|
||||
|
||||
// in sorted mode: is it our turn or do we have to be quiet for
|
||||
// now?
|
||||
if( m_arpModeModel.value() == SortMode &&
|
||||
( ( cur_frame / arp_frames ) % total_range ) /
|
||||
range != (f_cnt_t) _n->index() )
|
||||
{
|
||||
// update counters
|
||||
frames_processed += arp_frames;
|
||||
cur_frame += arp_frames;
|
||||
continue;
|
||||
}
|
||||
|
||||
const int dir = m_arpDirectionModel.value();
|
||||
// process according to arpeggio-direction...
|
||||
if( dir == ArpDirUp )
|
||||
{
|
||||
cur_arp_idx = ( cur_frame / arp_frames ) % range;
|
||||
}
|
||||
else if( dir == ArpDirDown )
|
||||
{
|
||||
cur_arp_idx = range - ( cur_frame / arp_frames ) %
|
||||
range - 1;
|
||||
}
|
||||
else if( dir == ArpDirUpAndDown && range > 1 )
|
||||
{
|
||||
// imagine, we had to play the arp once up and then
|
||||
// once down -> makes 2 * range possible notes...
|
||||
// because we don't play the lower and upper notes
|
||||
// twice, we have to subtract 2
|
||||
cur_arp_idx = ( cur_frame / arp_frames ) %
|
||||
( range * 2 - 2 );
|
||||
// if greater than range, we have to play down...
|
||||
// looks like the code for arp_dir==DOWN... :)
|
||||
if( cur_arp_idx >= range )
|
||||
{
|
||||
cur_arp_idx = range - cur_arp_idx %
|
||||
( range - 1 ) - 1;
|
||||
}
|
||||
}
|
||||
else if( dir == ArpDirRandom )
|
||||
{
|
||||
// just pick a random chord-index
|
||||
cur_arp_idx = (int)( range * ( (float) rand() /
|
||||
(float) RAND_MAX ) );
|
||||
}
|
||||
|
||||
// now calculate final key for our arp-note
|
||||
const int sub_note_key = base_note_key + (cur_arp_idx /
|
||||
cur_chord_size ) *
|
||||
NOTES_PER_OCTAVE +
|
||||
chordCreator::s_chordTable[selected_arp].
|
||||
interval[cur_arp_idx % cur_chord_size];
|
||||
|
||||
// range-checking
|
||||
if( sub_note_key >= NOTES_PER_OCTAVE * OCTAVES ||
|
||||
sub_note_key < 0 ||
|
||||
engine::getMixer()->criticalXRuns() )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
float vol_level = 1.0f;
|
||||
if( _n->released() )
|
||||
{
|
||||
vol_level = _n->volumeLevel( cur_frame + gated_frames );
|
||||
}
|
||||
|
||||
// create new arp-note
|
||||
note new_note( midiTime( 0 ), midiTime( 0 ),
|
||||
static_cast<tones>( sub_note_key %
|
||||
NOTES_PER_OCTAVE ),
|
||||
static_cast<octaves>( sub_note_key /
|
||||
NOTES_PER_OCTAVE ),
|
||||
static_cast<volume>( _n->getVolume() *
|
||||
vol_level ),
|
||||
_n->getPanning(), _n->detuning() );
|
||||
|
||||
// create sub-note-play-handle, only ptr to note is different
|
||||
// and is_arp_note=TRUE
|
||||
new notePlayHandle( _n->getInstrumentTrack(),
|
||||
( ( m_arpModeModel.value() != FreeMode ) ?
|
||||
cnphv.first()->offset() :
|
||||
_n->offset() ) +
|
||||
frames_processed,
|
||||
gated_frames,
|
||||
new_note,
|
||||
_n, TRUE );
|
||||
|
||||
// update counters
|
||||
frames_processed += arp_frames;
|
||||
cur_frame += arp_frames;
|
||||
}
|
||||
|
||||
// make sure, note is handled as arp-base-note, even if we didn't add a
|
||||
// sub-note so far
|
||||
if( m_arpModeModel.value() != FreeMode )
|
||||
{
|
||||
_n->setArpNote( TRUE );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void arpeggiator::saveSettings( QDomDocument & _doc, QDomElement & _this )
|
||||
{
|
||||
m_arpEnabledModel.saveSettings( _doc, _this, "arp-enabled" );
|
||||
m_arpModel.saveSettings( _doc, _this, "arp" );
|
||||
m_arpRangeModel.saveSettings( _doc, _this, "arprange" );
|
||||
m_arpTimeModel.saveSettings( _doc, _this, "arptime" );
|
||||
m_arpGateModel.saveSettings( _doc, _this, "arpgate" );
|
||||
m_arpDirectionModel.saveSettings( _doc, _this, "arpdir" );
|
||||
|
||||
m_arpModeModel.saveSettings( _doc, _this, "arpmode" );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void arpeggiator::loadSettings( const QDomElement & _this )
|
||||
{
|
||||
m_arpEnabledModel.loadSettings( _this, "arp-enabled" );
|
||||
m_arpModel.loadSettings( _this, "arp" );
|
||||
m_arpRangeModel.loadSettings( _this, "arprange" );
|
||||
m_arpTimeModel.loadSettings( _this, "arptime" );
|
||||
m_arpGateModel.loadSettings( _this, "arpgate" );
|
||||
m_arpDirectionModel.loadSettings( _this, "arpdir" );
|
||||
/*
|
||||
// Keep compatibility with version 0.2.1 file format
|
||||
if( _this.hasAttribute( "arpsyncmode" ) )
|
||||
{
|
||||
m_arpTimeKnob->setSyncMode(
|
||||
( tempoSyncKnob::tempoSyncMode ) _this.attribute(
|
||||
"arpsyncmode" ).toInt() );
|
||||
}*/
|
||||
|
||||
m_arpModeModel.loadSettings( _this, "arpmode" );
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
@@ -1,10 +1,9 @@
|
||||
#ifndef SINGLE_SOURCE_COMPILE
|
||||
|
||||
/*
|
||||
* midi_tab_widget.cpp - tab-widget in channel-track-window for setting up
|
||||
* MIDI-related stuff
|
||||
* instrument_midi_io.cpp - class instrumentMidiIO
|
||||
*
|
||||
* Copyright (c) 2005-2007 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2005-2008 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
@@ -27,123 +26,56 @@
|
||||
|
||||
|
||||
#include <Qt/QtXml>
|
||||
#include <QtGui/QMenu>
|
||||
#include <QtGui/QToolButton>
|
||||
|
||||
|
||||
#include "instrument_midi_io.h"
|
||||
#include "embed.h"
|
||||
#include "engine.h"
|
||||
#include "gui_templates.h"
|
||||
#include "instrument_track.h"
|
||||
#include "midi_client.h"
|
||||
#include "midi_port.h"
|
||||
#include "led_checkbox.h"
|
||||
#include "lcd_spinbox.h"
|
||||
#include "song_editor.h"
|
||||
#include "tab_widget.h"
|
||||
#include "tooltip.h"
|
||||
#include "song.h"
|
||||
#include "automatable_model_templates.h"
|
||||
|
||||
|
||||
|
||||
midiTabWidget::midiTabWidget( instrumentTrack * _instrument_track,
|
||||
instrumentMidiIO::instrumentMidiIO( instrumentTrack * _instrument_track,
|
||||
midiPort * _port ) :
|
||||
QWidget( _instrument_track->tabWidgetParent() ),
|
||||
model( _instrument_track ),
|
||||
m_instrumentTrack( _instrument_track ),
|
||||
m_midiPort( _port ),
|
||||
m_inputChannelModel(),
|
||||
m_outputChannelModel(),
|
||||
m_receiveEnabledModel( FALSE, FALSE, TRUE ),
|
||||
m_sendEnabledModel( FALSE, FALSE, TRUE ),
|
||||
m_defaultVelocityInEnabledModel( FALSE, FALSE, TRUE ),
|
||||
m_defaultVelocityOutEnabledModel( FALSE, FALSE, TRUE ),
|
||||
m_readablePorts( NULL ),
|
||||
m_writeablePorts( NULL )
|
||||
m_inputChannelModel( m_midiPort->inputChannel() + 1,
|
||||
0, MIDI_CHANNEL_COUNT,
|
||||
intModel::defaultRelStep(), this ),
|
||||
m_outputChannelModel( m_midiPort->outputChannel() + 1,
|
||||
1, MIDI_CHANNEL_COUNT,
|
||||
intModel::defaultRelStep(), this ),
|
||||
m_receiveEnabledModel( FALSE, this ),
|
||||
m_sendEnabledModel( FALSE, this ),
|
||||
m_defaultVelocityInEnabledModel( FALSE, this ),
|
||||
m_defaultVelocityOutEnabledModel( FALSE, this )
|
||||
{
|
||||
m_setupTabWidget = new tabWidget( tr( "MIDI-SETUP FOR THIS CHANNEL" ),
|
||||
this );
|
||||
m_setupTabWidget->setGeometry( 4, 5, 238, 200 );
|
||||
|
||||
m_inputChannelModel.setTrack( m_instrumentTrack );
|
||||
m_inputChannelModel.setRange( 0, MIDI_CHANNEL_COUNT );
|
||||
m_inputChannelModel.setValue( m_midiPort->inputChannel() + 1 );
|
||||
m_outputChannelModel.setTrack( m_instrumentTrack );
|
||||
m_receiveEnabledModel.setTrack( m_instrumentTrack );
|
||||
m_defaultVelocityInEnabledModel.setTrack( m_instrumentTrack );
|
||||
m_sendEnabledModel.setTrack( m_instrumentTrack );
|
||||
m_defaultVelocityOutEnabledModel.setTrack( m_instrumentTrack );
|
||||
|
||||
connect( &m_inputChannelModel, SIGNAL( dataChanged() ),
|
||||
this, SLOT( inputChannelChanged() ) );
|
||||
|
||||
m_inputChannelSpinBox = new lcdSpinBox( 3, m_setupTabWidget,
|
||||
tr( "Input channel" ) );
|
||||
m_inputChannelSpinBox->setModel( &m_inputChannelModel );
|
||||
m_inputChannelSpinBox->addTextForValue( 0, "---" );
|
||||
m_inputChannelSpinBox->setLabel( tr( "CHANNEL" ) );
|
||||
m_inputChannelSpinBox->move( 28, 52 );
|
||||
m_inputChannelSpinBox->setEnabled( FALSE );
|
||||
inputChannelChanged();
|
||||
|
||||
|
||||
|
||||
m_outputChannelModel.setTrack( m_instrumentTrack );
|
||||
m_outputChannelModel.setRange( 1, MIDI_CHANNEL_COUNT );
|
||||
m_outputChannelModel.setValue( m_midiPort->outputChannel() + 1 );
|
||||
connect( &m_outputChannelModel, SIGNAL( dataChanged() ),
|
||||
this, SLOT( outputChannelChanged() ) );
|
||||
|
||||
m_outputChannelSpinBox = new lcdSpinBox( 3, m_setupTabWidget,
|
||||
tr( "Output channel" ) );
|
||||
m_outputChannelSpinBox->setLabel( tr( "CHANNEL" ) );
|
||||
m_outputChannelSpinBox->move( 28, 132 );
|
||||
m_outputChannelSpinBox->setEnabled( FALSE );
|
||||
outputChannelChanged();
|
||||
|
||||
|
||||
m_receiveEnabledModel.setTrack( m_instrumentTrack );
|
||||
m_receiveCheckBox = new ledCheckBox( tr( "Receive MIDI-events" ),
|
||||
m_setupTabWidget,
|
||||
tr( "Receive MIDI-events" ) );
|
||||
m_receiveCheckBox->setModel( &m_receiveEnabledModel );
|
||||
m_receiveCheckBox->move( 10, 34 );
|
||||
// enabling/disabling widgets is UI-stuff thus we do not use model here
|
||||
connect( m_receiveCheckBox, SIGNAL( toggled( bool ) ),
|
||||
m_inputChannelSpinBox, SLOT( setEnabled( bool ) ) );
|
||||
connect( &m_receiveEnabledModel, SIGNAL( dataChanged() ),
|
||||
this, SLOT( midiPortModeChanged() ) );
|
||||
|
||||
|
||||
m_defaultVelocityInEnabledModel.setTrack( m_instrumentTrack );
|
||||
m_defaultVelocityInCheckBox = new ledCheckBox( tr( "Default velocity "
|
||||
"for all input-events" ),
|
||||
m_setupTabWidget,
|
||||
tr( "Default input velocity" ) );
|
||||
m_defaultVelocityInCheckBox->setModel(
|
||||
&m_defaultVelocityInEnabledModel );
|
||||
m_defaultVelocityInCheckBox->move( 28, 84 );
|
||||
this, SLOT( midiPortModeChanged() ) );
|
||||
connect( &m_defaultVelocityInEnabledModel, SIGNAL( dataChanged() ),
|
||||
this, SLOT( defaultVelInChanged() ) );
|
||||
|
||||
|
||||
m_sendEnabledModel.setTrack( m_instrumentTrack );
|
||||
m_sendCheckBox = new ledCheckBox( tr( "Send MIDI-events" ),
|
||||
m_setupTabWidget,
|
||||
tr( "Send MIDI-events" ) );
|
||||
m_sendCheckBox->setModel( &m_sendEnabledModel );
|
||||
m_sendCheckBox->move( 10, 114 );
|
||||
connect( m_sendCheckBox, SIGNAL( toggled( bool ) ),
|
||||
m_outputChannelSpinBox, SLOT( setEnabled( bool ) ) );
|
||||
this, SLOT( defaultVelInChanged() ) );
|
||||
connect( &m_sendEnabledModel, SIGNAL( dataChanged() ),
|
||||
this, SLOT( midiPortModeChanged() ) );
|
||||
|
||||
|
||||
m_defaultVelocityOutEnabledModel.setTrack( m_instrumentTrack );
|
||||
m_defaultVelocityOutCheckBox = new ledCheckBox( tr( "Default velocity "
|
||||
"for all output-events" ),
|
||||
m_setupTabWidget,
|
||||
tr( "Default output velocity" ) );
|
||||
m_defaultVelocityOutCheckBox->setModel(
|
||||
&m_defaultVelocityOutEnabledModel );
|
||||
m_defaultVelocityOutCheckBox->move( 28, 164 );
|
||||
this, SLOT( midiPortModeChanged() ) );
|
||||
connect( &m_defaultVelocityOutEnabledModel, SIGNAL( dataChanged() ),
|
||||
this, SLOT( defaultVelOutChanged() ) );
|
||||
|
||||
inputChannelChanged();
|
||||
outputChannelChanged();
|
||||
|
||||
|
||||
const midiPort::modes m = m_midiPort->mode();
|
||||
@@ -157,38 +89,9 @@ midiTabWidget::midiTabWidget( instrumentTrack * _instrument_track,
|
||||
midiClient * mc = engine::getMixer()->getMIDIClient();
|
||||
if( mc->isRaw() == FALSE )
|
||||
{
|
||||
m_readablePorts = new QMenu( m_setupTabWidget );
|
||||
m_readablePorts->setFont( pointSize<9>(
|
||||
m_readablePorts->font() ) );
|
||||
connect( m_readablePorts, SIGNAL( triggered( QAction * ) ),
|
||||
this, SLOT( activatedReadablePort( QAction * ) ) );
|
||||
|
||||
m_writeablePorts = new QMenu( m_setupTabWidget );
|
||||
m_writeablePorts->setFont( pointSize<9>(
|
||||
m_writeablePorts->font() ) );
|
||||
connect( m_writeablePorts, SIGNAL( triggered( QAction * ) ),
|
||||
this, SLOT( activatedWriteablePort( QAction * ) ) );
|
||||
|
||||
// fill menus
|
||||
readablePortsChanged();
|
||||
writeablePortsChanged();
|
||||
|
||||
QToolButton * rp_btn = new QToolButton( m_setupTabWidget );
|
||||
rp_btn->setText( tr( "MIDI-devices to receive "
|
||||
"MIDI-events from" ) );
|
||||
rp_btn->setIcon( embed::getIconPixmap( "midi_in" ) );
|
||||
rp_btn->setGeometry( 186, 34, 40, 40 );
|
||||
rp_btn->setMenu( m_readablePorts );
|
||||
rp_btn->setPopupMode( QToolButton::InstantPopup );
|
||||
|
||||
QToolButton * wp_btn = new QToolButton( m_setupTabWidget );
|
||||
wp_btn->setText( tr( "MIDI-devices to send MIDI-events "
|
||||
"to" ) );
|
||||
wp_btn->setIcon( embed::getIconPixmap( "midi_out" ) );
|
||||
wp_btn->setGeometry( 186, 114, 40, 40 );
|
||||
wp_btn->setMenu( m_writeablePorts );
|
||||
wp_btn->setPopupMode( QToolButton::InstantPopup );
|
||||
|
||||
// we want to get informed about port-changes!
|
||||
mc->connectRPChanged( this, SLOT( readablePortsChanged() ) );
|
||||
mc->connectWPChanged( this, SLOT( writeablePortsChanged() ) );
|
||||
@@ -198,14 +101,14 @@ midiTabWidget::midiTabWidget( instrumentTrack * _instrument_track,
|
||||
|
||||
|
||||
|
||||
midiTabWidget::~midiTabWidget()
|
||||
instrumentMidiIO::~instrumentMidiIO()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void midiTabWidget::saveSettings( QDomDocument & _doc, QDomElement & _this )
|
||||
void instrumentMidiIO::saveSettings( QDomDocument & _doc, QDomElement & _this )
|
||||
{
|
||||
m_inputChannelModel.saveSettings( _doc, _this, "inputchannel" );
|
||||
m_outputChannelModel.saveSettings( _doc, _this, "outputchannel" );
|
||||
@@ -214,17 +117,15 @@ void midiTabWidget::saveSettings( QDomDocument & _doc, QDomElement & _this )
|
||||
m_defaultVelocityInEnabledModel.saveSettings( _doc, _this, "defvelin" );
|
||||
m_defaultVelocityOutEnabledModel.saveSettings( _doc, _this, "defvelout" );
|
||||
|
||||
if( m_readablePorts != NULL && m_receiveEnabledModel.value() == TRUE )
|
||||
if( m_receiveEnabledModel.value() == TRUE )
|
||||
{
|
||||
// TODO: M/V-split!
|
||||
QString rp;
|
||||
QList<QAction *> actions = m_readablePorts->actions();
|
||||
for( QList<QAction *>::iterator it = actions.begin();
|
||||
it != actions.end(); ++it )
|
||||
for( midiPortMap::iterator it = m_readablePorts.begin();
|
||||
it != m_readablePorts.end(); ++it )
|
||||
{
|
||||
if( ( *it )->isChecked() )
|
||||
if( it->second )
|
||||
{
|
||||
rp += ( *it )->text() + ",";
|
||||
rp += it->first + ",";
|
||||
}
|
||||
}
|
||||
// cut off comma
|
||||
@@ -235,17 +136,15 @@ void midiTabWidget::saveSettings( QDomDocument & _doc, QDomElement & _this )
|
||||
_this.setAttribute( "inports", rp );
|
||||
}
|
||||
|
||||
if( m_writeablePorts != NULL && m_sendEnabledModel.value() == TRUE )
|
||||
if( m_sendEnabledModel.value() == TRUE )
|
||||
{
|
||||
// TODO: M/V-split!
|
||||
QString wp;
|
||||
QList<QAction *> actions = m_writeablePorts->actions();
|
||||
for( QList<QAction *>::iterator it = actions.begin();
|
||||
it != actions.end(); ++it )
|
||||
for( midiPortMap::iterator it = m_writeablePorts.begin();
|
||||
it != m_writeablePorts.end(); ++it )
|
||||
{
|
||||
if( ( *it )->isChecked() )
|
||||
if( it->second )
|
||||
{
|
||||
wp += ( *it )->text() + ",";
|
||||
wp += it->first + ",";
|
||||
}
|
||||
}
|
||||
// cut off comma
|
||||
@@ -260,7 +159,7 @@ void midiTabWidget::saveSettings( QDomDocument & _doc, QDomElement & _this )
|
||||
|
||||
|
||||
|
||||
void midiTabWidget::loadSettings( const QDomElement & _this )
|
||||
void instrumentMidiIO::loadSettings( const QDomElement & _this )
|
||||
{
|
||||
m_inputChannelModel.loadSettings( _this, "inputchannel" );
|
||||
m_outputChannelModel.loadSettings( _this, "outputchannel" );
|
||||
@@ -271,35 +170,29 @@ void midiTabWidget::loadSettings( const QDomElement & _this )
|
||||
|
||||
// restore connections
|
||||
|
||||
if( m_readablePorts != NULL && m_receiveEnabledModel.value() == TRUE )
|
||||
if( m_receiveEnabledModel.value() == TRUE )
|
||||
{
|
||||
// TODO: M/V-split!
|
||||
QStringList rp = _this.attribute( "inports" ).split( ',' );
|
||||
QList<QAction *> actions = m_readablePorts->actions();
|
||||
for( QList<QAction *>::iterator it = actions.begin();
|
||||
it != actions.end(); ++it )
|
||||
for( midiPortMap::iterator it = m_readablePorts.begin();
|
||||
it != m_readablePorts.end(); ++it )
|
||||
{
|
||||
if( ( *it )->isChecked() !=
|
||||
( rp.indexOf( ( *it )->text() ) != -1 ) )
|
||||
if( it->second != ( rp.indexOf( it->first ) != -1 ) )
|
||||
{
|
||||
( *it )->setChecked( TRUE );
|
||||
it->second = TRUE;
|
||||
activatedReadablePort( *it );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( m_writeablePorts != NULL && m_sendEnabledModel.value() == TRUE )
|
||||
if( m_sendEnabledModel.value() == TRUE )
|
||||
{
|
||||
// TODO: M/V-split!
|
||||
QStringList wp = _this.attribute( "outports" ).split( ',' );
|
||||
QList<QAction *> actions = m_writeablePorts->actions();
|
||||
for( QList<QAction *>::iterator it = actions.begin();
|
||||
it != actions.end(); ++it )
|
||||
for( midiPortMap::iterator it = m_writeablePorts.begin();
|
||||
it != m_writeablePorts.end(); ++it )
|
||||
{
|
||||
if( ( *it )->isChecked() !=
|
||||
( wp.indexOf( ( *it )->text() ) != -1 ) )
|
||||
if( it->second != ( wp.indexOf( it->first ) != -1 ) )
|
||||
{
|
||||
( *it )->setChecked( TRUE );
|
||||
it->second = TRUE;
|
||||
activatedWriteablePort( *it );
|
||||
}
|
||||
}
|
||||
@@ -309,25 +202,25 @@ void midiTabWidget::loadSettings( const QDomElement & _this )
|
||||
|
||||
|
||||
|
||||
void midiTabWidget::inputChannelChanged( void )
|
||||
void instrumentMidiIO::inputChannelChanged( void )
|
||||
{
|
||||
m_midiPort->setInputChannel( m_inputChannelModel.value() - 1 );
|
||||
engine::getSongEditor()->setModified();
|
||||
engine::getSong()->setModified();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void midiTabWidget::outputChannelChanged( void )
|
||||
void instrumentMidiIO::outputChannelChanged( void )
|
||||
{
|
||||
m_midiPort->setOutputChannel( m_outputChannelModel.value() - 1 );
|
||||
engine::getSongEditor()->setModified();
|
||||
engine::getSong()->setModified();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void midiTabWidget::defaultVelInChanged( void )
|
||||
void instrumentMidiIO::defaultVelInChanged( void )
|
||||
{
|
||||
m_midiPort->enableDefaultVelocityForInEvents(
|
||||
m_defaultVelocityInEnabledModel.value() );
|
||||
@@ -336,7 +229,7 @@ void midiTabWidget::defaultVelInChanged( void )
|
||||
|
||||
|
||||
|
||||
void midiTabWidget::defaultVelOutChanged( void )
|
||||
void instrumentMidiIO::defaultVelOutChanged( void )
|
||||
{
|
||||
m_midiPort->enableDefaultVelocityForOutEvents(
|
||||
m_defaultVelocityOutEnabledModel.value() );
|
||||
@@ -345,7 +238,7 @@ void midiTabWidget::defaultVelOutChanged( void )
|
||||
|
||||
|
||||
|
||||
void midiTabWidget::midiPortModeChanged( void )
|
||||
void instrumentMidiIO::midiPortModeChanged( void )
|
||||
{
|
||||
// this small lookup-table makes everything easier
|
||||
static const midiPort::modes modeTable[2][2] =
|
||||
@@ -357,130 +250,122 @@ void midiTabWidget::midiPortModeChanged( void )
|
||||
[m_sendEnabledModel.value()] );
|
||||
|
||||
// check whether we have to dis-check items in connection-menu
|
||||
if( m_readablePorts != NULL && m_receiveEnabledModel.value() == FALSE )
|
||||
if( m_receiveEnabledModel.value() == FALSE )
|
||||
{
|
||||
QList<QAction *> actions = m_readablePorts->actions();
|
||||
for( QList<QAction *>::iterator it = actions.begin();
|
||||
it != actions.end(); ++it )
|
||||
for( midiPortMap::iterator it = m_readablePorts.begin();
|
||||
it != m_readablePorts.end(); ++it )
|
||||
{
|
||||
if( ( *it )->isChecked() == TRUE )
|
||||
if( it->second == TRUE )
|
||||
{
|
||||
( *it )->setChecked( FALSE );
|
||||
it->second = FALSE;
|
||||
activatedReadablePort( *it );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( m_writeablePorts != NULL && m_sendEnabledModel.value() == FALSE )
|
||||
if( m_sendEnabledModel.value() == FALSE )
|
||||
{
|
||||
QList<QAction *> actions = m_writeablePorts->actions();
|
||||
for( QList<QAction *>::iterator it = actions.begin();
|
||||
it != actions.end(); ++it )
|
||||
for( midiPortMap::iterator it = m_writeablePorts.begin();
|
||||
it != m_writeablePorts.end(); ++it )
|
||||
{
|
||||
if( ( *it )->isChecked() == TRUE )
|
||||
if( it->second == TRUE )
|
||||
{
|
||||
( *it )->setChecked( FALSE );
|
||||
it->second = FALSE;
|
||||
activatedWriteablePort( *it );
|
||||
}
|
||||
}
|
||||
}
|
||||
engine::getSongEditor()->setModified();
|
||||
engine::getSong()->setModified();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void midiTabWidget::readablePortsChanged( void )
|
||||
void instrumentMidiIO::readablePortsChanged( void )
|
||||
{
|
||||
// first save all selected ports
|
||||
QStringList selected_ports;
|
||||
QList<QAction *> actions = m_readablePorts->actions();
|
||||
for( QList<QAction *>::iterator it = actions.begin();
|
||||
it != actions.end(); ++it )
|
||||
for( midiPortMap::iterator it = m_readablePorts.begin();
|
||||
it != m_readablePorts.end(); ++it )
|
||||
{
|
||||
if( ( *it )->isChecked() == TRUE )
|
||||
if( it->second == TRUE )
|
||||
{
|
||||
selected_ports.push_back( ( *it )->text() );
|
||||
selected_ports.push_back( it->first );
|
||||
}
|
||||
}
|
||||
|
||||
m_readablePorts->clear();
|
||||
const QStringList & rp = engine::getMixer()->getMIDIClient()->
|
||||
m_readablePorts.clear();
|
||||
const QStringList & wp = engine::getMixer()->getMIDIClient()->
|
||||
readablePorts();
|
||||
// now insert new ports and restore selections
|
||||
for( QStringList::const_iterator it = rp.begin(); it != rp.end(); ++it )
|
||||
for( QStringList::const_iterator it = wp.begin(); it != wp.end(); ++it )
|
||||
{
|
||||
QAction * item = m_readablePorts->addAction( *it );
|
||||
item->setCheckable( TRUE );
|
||||
if( selected_ports.indexOf( *it ) != -1 )
|
||||
{
|
||||
item->setChecked( TRUE );
|
||||
}
|
||||
m_readablePorts.push_back( qMakePair( *it,
|
||||
selected_ports.indexOf( *it ) != -1 ) );
|
||||
}
|
||||
emit dataChanged();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void midiTabWidget::writeablePortsChanged( void )
|
||||
void instrumentMidiIO::writeablePortsChanged( void )
|
||||
{
|
||||
// first save all selected ports
|
||||
QStringList selected_ports;
|
||||
QList<QAction *> actions = m_writeablePorts->actions();
|
||||
for( QList<QAction *>::iterator it = actions.begin();
|
||||
it != actions.end(); ++it )
|
||||
for( midiPortMap::iterator it = m_writeablePorts.begin();
|
||||
it != m_writeablePorts.end(); ++it )
|
||||
{
|
||||
if( ( *it )->isChecked() == TRUE )
|
||||
if( it->second == TRUE )
|
||||
{
|
||||
selected_ports.push_back( ( *it )->text() );
|
||||
selected_ports.push_back( it->first );
|
||||
}
|
||||
}
|
||||
|
||||
m_writeablePorts->clear();
|
||||
m_writeablePorts.clear();
|
||||
const QStringList & wp = engine::getMixer()->getMIDIClient()->
|
||||
writeablePorts();
|
||||
// now insert new ports and restore selections
|
||||
for( QStringList::const_iterator it = wp.begin(); it != wp.end(); ++it )
|
||||
{
|
||||
QAction * item = m_writeablePorts->addAction( *it );
|
||||
item->setCheckable( TRUE );
|
||||
if( selected_ports.indexOf( *it ) != -1 )
|
||||
{
|
||||
item->setChecked( TRUE );
|
||||
}
|
||||
m_writeablePorts.push_back( qMakePair( *it,
|
||||
selected_ports.indexOf( *it ) != -1 ) );
|
||||
}
|
||||
emit dataChanged();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void midiTabWidget::activatedReadablePort( QAction * _item )
|
||||
void instrumentMidiIO::activatedReadablePort(
|
||||
const descriptiveMidiPort & _port )
|
||||
{
|
||||
// make sure, MIDI-port is configured for input
|
||||
if( _item->isChecked() == TRUE &&
|
||||
if( _port.second == TRUE &&
|
||||
m_midiPort->mode() != midiPort::INPUT &&
|
||||
m_midiPort->mode() != midiPort::DUPLEX )
|
||||
{
|
||||
m_receiveEnabledModel.setValue( TRUE );
|
||||
}
|
||||
engine::getMixer()->getMIDIClient()->subscribeReadablePort( m_midiPort,
|
||||
_item->text(), !_item->isChecked() );
|
||||
_port.first, !_port.second );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void midiTabWidget::activatedWriteablePort( QAction * _item )
|
||||
void instrumentMidiIO::activatedWriteablePort(
|
||||
const descriptiveMidiPort & _port )
|
||||
{
|
||||
// make sure, MIDI-port is configured for output
|
||||
if( _item->isChecked() == TRUE &&
|
||||
if( _port.second == TRUE &&
|
||||
m_midiPort->mode() != midiPort::OUTPUT &&
|
||||
m_midiPort->mode() != midiPort::DUPLEX )
|
||||
{
|
||||
m_sendEnabledModel.setValue( TRUE );
|
||||
}
|
||||
engine::getMixer()->getMIDIClient()->subscribeWriteablePort( m_midiPort,
|
||||
_item->text(), !_item->isChecked() );
|
||||
_port.first, !_port.second );
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
#ifndef SINGLE_SOURCE_COMPILE
|
||||
|
||||
/*
|
||||
* envelope_tab_widget.cpp - widget for use in envelope/lfo/filter-tab of
|
||||
* instrument-track-window
|
||||
* instrument_sound_shaping.cpp - class instrumentSoundShaping
|
||||
*
|
||||
* Copyright (c) 2004-2008 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
@@ -30,29 +29,14 @@
|
||||
|
||||
|
||||
#include "instrument_sound_shaping.h"
|
||||
#include "combobox.h"
|
||||
#include "embed.h"
|
||||
#include "engine.h"
|
||||
#include "envelope_and_lfo_parameters.h"
|
||||
#include "group_box.h"
|
||||
#include "gui_templates.h"
|
||||
#include "instrument_track.h"
|
||||
#include "knob.h"
|
||||
#include "note_play_handle.h"
|
||||
#include "tab_widget.h"
|
||||
|
||||
|
||||
|
||||
const int TARGETS_TABWIDGET_X = 4;
|
||||
const int TARGETS_TABWIDGET_Y = 5;
|
||||
const int TARGETS_TABWIDGET_WIDTH = 238;
|
||||
const int TARGETS_TABWIDGET_HEIGTH = 175;
|
||||
|
||||
const int FILTER_GROUPBOX_X = TARGETS_TABWIDGET_X;
|
||||
const int FILTER_GROUPBOX_Y = TARGETS_TABWIDGET_Y+TARGETS_TABWIDGET_HEIGTH+5;
|
||||
const int FILTER_GROUPBOX_WIDTH = TARGETS_TABWIDGET_WIDTH;
|
||||
const int FILTER_GROUPBOX_HEIGHT = 245-FILTER_GROUPBOX_Y;
|
||||
|
||||
const float CUT_FREQ_MULTIPLIER = 6000.0f;
|
||||
const float RES_MULTIPLIER = 2.0f;
|
||||
const float RES_PRECISION = 1000.0f;
|
||||
@@ -60,149 +44,75 @@ const float RES_PRECISION = 1000.0f;
|
||||
|
||||
// names for env- and lfo-targets - first is name being displayed to user
|
||||
// and second one is used internally, e.g. for saving/restoring settings
|
||||
static const QString targetNames[envelopeTabWidget::TARGET_COUNT][2] =
|
||||
const QString __targetNames[instrumentSoundShaping::NumTargets][2] =
|
||||
{
|
||||
{ envelopeTabWidget::tr( "VOLUME" ), "vol" },
|
||||
/* envelopeTabWidget::tr( "Pan" ),
|
||||
envelopeTabWidget::tr( "Pitch" ),*/
|
||||
{ envelopeTabWidget::tr( "CUTOFF" ), "cut" },
|
||||
{ envelopeTabWidget::tr( "Q/RESO" ), "res" }
|
||||
{ instrumentSoundShaping::tr( "VOLUME" ), "vol" },
|
||||
/* instrumentSoundShaping::tr( "Pan" ),
|
||||
instrumentSoundShaping::tr( "Pitch" ),*/
|
||||
{ instrumentSoundShaping::tr( "CUTOFF" ), "cut" },
|
||||
{ instrumentSoundShaping::tr( "Q/RESO" ), "res" }
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
envelopeTabWidget::envelopeTabWidget( instrumentTrack * _instrument_track ) :
|
||||
QWidget( _instrument_track->tabWidgetParent() ),
|
||||
instrumentSoundShaping::instrumentSoundShaping(
|
||||
instrumentTrack * _instrument_track ) :
|
||||
model( _instrument_track ),
|
||||
m_instrumentTrack( _instrument_track ),
|
||||
m_filterEnabledModel( new boolModel( FALSE /* this */ ) ),
|
||||
m_filterModel( new comboBoxModel( /* this */ ) ),
|
||||
m_filterCutModel( new floatModel( /* this */ ) ),
|
||||
m_filterResModel( new floatModel( /* this */ ) )
|
||||
m_filterEnabledModel( FALSE, this ),
|
||||
m_filterModel( this ),
|
||||
m_filterCutModel( 16000.0, 0.0, 14000.0, 1.0, this ),
|
||||
m_filterResModel( 0.5, basicFilters<>::minQ(), 10.0, 0.01, this )
|
||||
{
|
||||
m_targetsTabWidget = new tabWidget( tr( "TARGET" ), this );
|
||||
m_targetsTabWidget->setGeometry( TARGETS_TABWIDGET_X,
|
||||
TARGETS_TABWIDGET_Y,
|
||||
TARGETS_TABWIDGET_WIDTH,
|
||||
TARGETS_TABWIDGET_HEIGTH );
|
||||
m_targetsTabWidget->setWhatsThis(
|
||||
tr( "These tabs contain envelopes. They're very important for "
|
||||
"modifying a sound, for not saying that they're almost "
|
||||
"always neccessary for substractive synthesis. For "
|
||||
"example if you have a volume-envelope, you can set "
|
||||
"when the sound should have which volume-level. "
|
||||
"Maybe you want to create some soft strings. Then your "
|
||||
"sound has to fade in and out very softly. This can be "
|
||||
"done by setting a large attack- and release-time. "
|
||||
"It's the same for other envelope-targets like "
|
||||
"panning, cutoff-frequency of used filter and so on. "
|
||||
"Just monkey around with it! You can really make cool "
|
||||
"sounds out of a saw-wave with just some "
|
||||
"envelopes...!" ) );
|
||||
|
||||
for( int i = 0; i < TARGET_COUNT; ++i )
|
||||
for( int i = 0; i < NumTargets; ++i )
|
||||
{
|
||||
float value_for_zero_amount = 0.0;
|
||||
if( i == VOLUME )
|
||||
if( i == Volume )
|
||||
{
|
||||
value_for_zero_amount = 1.0;
|
||||
}
|
||||
m_envLFOWidgets[i] = new envelopeAndLFOWidget(
|
||||
value_for_zero_amount,
|
||||
m_targetsTabWidget,
|
||||
_instrument_track );
|
||||
m_targetsTabWidget->addTab( m_envLFOWidgets[i],
|
||||
tr( targetNames[i][0]
|
||||
.toAscii().constData() ) );
|
||||
m_envLFOParameters[i] = new envelopeAndLFOParameters(
|
||||
value_for_zero_amount,
|
||||
_instrument_track,
|
||||
this );
|
||||
}
|
||||
|
||||
m_filterEnabledModel.setTrack( _instrument_track );
|
||||
|
||||
m_filterEnabledModel->setTrack( _instrument_track );
|
||||
m_filterGroupBox = new groupBox( tr( "FILTER" ), this );
|
||||
m_filterGroupBox->setModel( m_filterEnabledModel );
|
||||
m_filterGroupBox->setGeometry( FILTER_GROUPBOX_X, FILTER_GROUPBOX_Y,
|
||||
FILTER_GROUPBOX_WIDTH,
|
||||
FILTER_GROUPBOX_HEIGHT );
|
||||
|
||||
|
||||
m_filterModel->addItem( tr( "LowPass" ), new QPixmap(
|
||||
m_filterModel.addItem( tr( "LowPass" ), new QPixmap(
|
||||
embed::getIconPixmap( "filter_lp" ) ) );
|
||||
m_filterModel->addItem( tr( "HiPass" ), new QPixmap(
|
||||
m_filterModel.addItem( tr( "HiPass" ), new QPixmap(
|
||||
embed::getIconPixmap( "filter_hp" ) ) );
|
||||
m_filterModel->addItem( tr( "BandPass csg" ), new QPixmap(
|
||||
m_filterModel.addItem( tr( "BandPass csg" ), new QPixmap(
|
||||
embed::getIconPixmap( "filter_bp" ) ) );
|
||||
m_filterModel->addItem( tr( "BandPass czpg" ), new QPixmap(
|
||||
m_filterModel.addItem( tr( "BandPass czpg" ), new QPixmap(
|
||||
embed::getIconPixmap( "filter_bp" ) ) );
|
||||
m_filterModel->addItem( tr( "Notch" ), new QPixmap(
|
||||
m_filterModel.addItem( tr( "Notch" ), new QPixmap(
|
||||
embed::getIconPixmap( "filter_notch" ) ) );
|
||||
m_filterModel->addItem( tr( "Allpass" ), new QPixmap(
|
||||
m_filterModel.addItem( tr( "Allpass" ), new QPixmap(
|
||||
embed::getIconPixmap( "filter_ap" ) ) );
|
||||
m_filterModel->addItem( tr( "Moog" ), new QPixmap(
|
||||
m_filterModel.addItem( tr( "Moog" ), new QPixmap(
|
||||
embed::getIconPixmap( "filter_lp" ) ) );
|
||||
m_filterModel->addItem( tr( "2x LowPass" ), new QPixmap(
|
||||
m_filterModel.addItem( tr( "2x LowPass" ), new QPixmap(
|
||||
embed::getIconPixmap( "filter_2lp" ) ) );
|
||||
|
||||
m_filterModel->setTrack( _instrument_track );
|
||||
m_filterComboBox = new comboBox( m_filterGroupBox, tr( "Filter type" ) );
|
||||
m_filterComboBox->setModel( m_filterModel );
|
||||
m_filterComboBox->setGeometry( 14, 22, 120, 22 );
|
||||
m_filterComboBox->setFont( pointSize<8>( m_filterComboBox->font() ) );
|
||||
|
||||
m_filterComboBox->setWhatsThis(
|
||||
tr( "Here you can select the built-in filter you want to use "
|
||||
"for this instrument-track. Filters are very important "
|
||||
"for changing the characteristics of a sound." ) );
|
||||
|
||||
|
||||
m_filterCutModel->setTrack( _instrument_track );
|
||||
m_filterCutModel->setRange( 0.0, 14000.0, 1.0 );
|
||||
m_filterCutModel->setInitValue( 16000.0 );
|
||||
|
||||
m_filterCutKnob = new knob( knobBright_26, m_filterGroupBox,
|
||||
tr( "cutoff-frequency" ) );
|
||||
m_filterCutKnob->setModel( m_filterCutModel );
|
||||
m_filterCutKnob->setLabel( tr( "CUTOFF" ) );
|
||||
m_filterCutKnob->move( 140, 18 );
|
||||
m_filterCutKnob->setHintText( tr( "cutoff-frequency:" ) + " ", " " +
|
||||
tr( "Hz" ) );
|
||||
m_filterCutKnob->setWhatsThis(
|
||||
tr( "Use this knob for setting the cutoff-frequency for the "
|
||||
"selected filter. The cutoff-frequency specifies the "
|
||||
"frequency for cutting the signal by a filter. For "
|
||||
"example a lowpass-filter cuts all frequencies above "
|
||||
"the cutoff-frequency. A highpass-filter cuts all "
|
||||
"frequencies below cutoff-frequency and so on..." ) );
|
||||
|
||||
|
||||
|
||||
m_filterResModel->setTrack( _instrument_track );
|
||||
m_filterResModel->setRange( basicFilters<>::minQ(), 10.0, 0.01 );
|
||||
m_filterResModel->setInitValue( 0.5 );
|
||||
|
||||
m_filterResKnob = new knob( knobBright_26, m_filterGroupBox,
|
||||
tr( "Q/Resonance" ) );
|
||||
m_filterResKnob->setModel( m_filterResModel );
|
||||
m_filterResKnob->setLabel( tr( "Q/RESO" ) );
|
||||
m_filterResKnob->move( 190, 18 );
|
||||
m_filterResKnob->setHintText( tr( "Q/Resonance:" ) + " ", "" );
|
||||
m_filterResKnob->setWhatsThis(
|
||||
tr( "Use this knob for setting Q/Resonance for the selected "
|
||||
"filter. Q/Resonance tells the filter, how much it "
|
||||
"should amplify frequencies near Cutoff-frequency." ) );
|
||||
m_filterModel.setTrack( _instrument_track );
|
||||
m_filterCutModel.setTrack( _instrument_track );
|
||||
m_filterResModel.setTrack( _instrument_track );
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
envelopeTabWidget::~envelopeTabWidget()
|
||||
instrumentSoundShaping::~instrumentSoundShaping()
|
||||
{
|
||||
delete m_targetsTabWidget;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
float FASTCALL envelopeTabWidget::volumeLevel( notePlayHandle * _n,
|
||||
float instrumentSoundShaping::volumeLevel( notePlayHandle * _n,
|
||||
const f_cnt_t _frame )
|
||||
{
|
||||
f_cnt_t release_begin = _frame - _n->releaseFramesDone() +
|
||||
@@ -214,7 +124,7 @@ float FASTCALL envelopeTabWidget::volumeLevel( notePlayHandle * _n,
|
||||
}
|
||||
|
||||
float volume_level;
|
||||
m_envLFOWidgets[VOLUME]->fillLevel( &volume_level, _frame,
|
||||
m_envLFOParameters[Volume]->fillLevel( &volume_level, _frame,
|
||||
release_begin, 1 );
|
||||
|
||||
return( volume_level );
|
||||
@@ -223,7 +133,7 @@ float FASTCALL envelopeTabWidget::volumeLevel( notePlayHandle * _n,
|
||||
|
||||
|
||||
|
||||
void envelopeTabWidget::processAudioBuffer( sampleFrame * _ab,
|
||||
void instrumentSoundShaping::processAudioBuffer( sampleFrame * _ab,
|
||||
const fpp_t _frames,
|
||||
notePlayHandle * _n )
|
||||
{
|
||||
@@ -244,7 +154,7 @@ void envelopeTabWidget::processAudioBuffer( sampleFrame * _ab,
|
||||
|
||||
// only use filter, if it is really needed
|
||||
|
||||
if( m_filterEnabledModel->value() )
|
||||
if( m_filterEnabledModel.value() )
|
||||
{
|
||||
int old_filter_cut = 0;
|
||||
int old_filter_res = 0;
|
||||
@@ -254,33 +164,34 @@ void envelopeTabWidget::processAudioBuffer( sampleFrame * _ab,
|
||||
_n->m_filter = new basicFilters<>(
|
||||
engine::getMixer()->sampleRate() );
|
||||
}
|
||||
_n->m_filter->setFilterType( m_filterComboBox->value() );
|
||||
_n->m_filter->setFilterType( m_filterModel.value() );
|
||||
|
||||
float * cut_buf = NULL;
|
||||
float * res_buf = NULL;
|
||||
|
||||
if( m_envLFOWidgets[CUT]->used() )
|
||||
if( m_envLFOParameters[Cut]->used() )
|
||||
{
|
||||
cut_buf = new float[_frames];
|
||||
m_envLFOWidgets[CUT]->fillLevel( cut_buf, total_frames,
|
||||
m_envLFOParameters[Cut]->fillLevel( cut_buf, total_frames,
|
||||
release_begin, _frames );
|
||||
}
|
||||
if( m_envLFOWidgets[RES]->used() )
|
||||
if( m_envLFOParameters[Resonance]->used() )
|
||||
{
|
||||
res_buf = new float[_frames];
|
||||
m_envLFOWidgets[RES]->fillLevel( res_buf, total_frames,
|
||||
release_begin, _frames );
|
||||
m_envLFOParameters[Resonance]->fillLevel( res_buf,
|
||||
total_frames, release_begin,
|
||||
_frames );
|
||||
}
|
||||
|
||||
if( m_envLFOWidgets[CUT]->used() &&
|
||||
m_envLFOWidgets[RES]->used() )
|
||||
if( m_envLFOParameters[Cut]->used() &&
|
||||
m_envLFOParameters[Resonance]->used() )
|
||||
{
|
||||
for( fpp_t frame = 0; frame < _frames; ++frame )
|
||||
{
|
||||
float new_cut_val = envelopeAndLFOWidget::expKnobVal( cut_buf[frame] ) * CUT_FREQ_MULTIPLIER +
|
||||
m_filterCutKnob->value();
|
||||
float new_cut_val = envelopeAndLFOParameters::expKnobVal( cut_buf[frame] ) * CUT_FREQ_MULTIPLIER +
|
||||
m_filterCutModel.value();
|
||||
|
||||
float new_res_val = m_filterResKnob->value() + RES_MULTIPLIER *
|
||||
float new_res_val = m_filterResModel.value() + RES_MULTIPLIER *
|
||||
res_buf[frame];
|
||||
|
||||
if( static_cast<int>( new_cut_val ) != old_filter_cut ||
|
||||
@@ -297,16 +208,16 @@ void envelopeTabWidget::processAudioBuffer( sampleFrame * _ab,
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( m_envLFOWidgets[CUT]->used() )
|
||||
else if( m_envLFOParameters[Cut]->used() )
|
||||
{
|
||||
for( fpp_t frame = 0; frame < _frames; ++frame )
|
||||
{
|
||||
float new_cut_val = envelopeAndLFOWidget::expKnobVal( cut_buf[frame] ) * CUT_FREQ_MULTIPLIER +
|
||||
m_filterCutKnob->value();
|
||||
float new_cut_val = envelopeAndLFOParameters::expKnobVal( cut_buf[frame] ) * CUT_FREQ_MULTIPLIER +
|
||||
m_filterCutModel.value();
|
||||
|
||||
if( static_cast<int>( new_cut_val ) != old_filter_cut )
|
||||
{
|
||||
_n->m_filter->calcFilterCoeffs( new_cut_val, m_filterResKnob->value() );
|
||||
_n->m_filter->calcFilterCoeffs( new_cut_val, m_filterResModel.value() );
|
||||
old_filter_cut = static_cast<int>( new_cut_val );
|
||||
}
|
||||
|
||||
@@ -316,16 +227,16 @@ void envelopeTabWidget::processAudioBuffer( sampleFrame * _ab,
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( m_envLFOWidgets[RES]->used() )
|
||||
else if( m_envLFOParameters[Resonance]->used() )
|
||||
{
|
||||
for( fpp_t frame = 0; frame < _frames; ++frame )
|
||||
{
|
||||
float new_res_val = m_filterResKnob->value() + RES_MULTIPLIER *
|
||||
float new_res_val = m_filterResModel.value() + RES_MULTIPLIER *
|
||||
res_buf[frame];
|
||||
|
||||
if( static_cast<int>( new_res_val*RES_PRECISION ) != old_filter_res )
|
||||
{
|
||||
_n->m_filter->calcFilterCoeffs( m_filterCutKnob->value(), new_res_val );
|
||||
_n->m_filter->calcFilterCoeffs( m_filterCutModel.value(), new_res_val );
|
||||
old_filter_res = static_cast<int>( new_res_val*RES_PRECISION );
|
||||
}
|
||||
|
||||
@@ -337,7 +248,7 @@ void envelopeTabWidget::processAudioBuffer( sampleFrame * _ab,
|
||||
}
|
||||
else
|
||||
{
|
||||
_n->m_filter->calcFilterCoeffs( m_filterCutKnob->value(), m_filterResKnob->value() );
|
||||
_n->m_filter->calcFilterCoeffs( m_filterCutModel.value(), m_filterResModel.value() );
|
||||
|
||||
for( fpp_t frame = 0; frame < _frames; ++frame )
|
||||
{
|
||||
@@ -352,10 +263,10 @@ void envelopeTabWidget::processAudioBuffer( sampleFrame * _ab,
|
||||
delete[] res_buf;
|
||||
}
|
||||
|
||||
if( m_envLFOWidgets[VOLUME]->used() )
|
||||
if( m_envLFOParameters[Volume]->used() )
|
||||
{
|
||||
float * vol_buf = new float[_frames];
|
||||
m_envLFOWidgets[VOLUME]->fillLevel( vol_buf, total_frames,
|
||||
m_envLFOParameters[Volume]->fillLevel( vol_buf, total_frames,
|
||||
release_begin, _frames );
|
||||
|
||||
for( fpp_t frame = 0; frame < _frames; ++frame )
|
||||
@@ -371,7 +282,7 @@ void envelopeTabWidget::processAudioBuffer( sampleFrame * _ab,
|
||||
delete[] vol_buf;
|
||||
}
|
||||
|
||||
/* else if( m_envLFOWidgets[VOLUME]->used() == FALSE && m_envLFOWidgets[PANNING]->used() )
|
||||
/* else if( m_envLFOParameters[Volume]->used() == FALSE && m_envLFOParameters[PANNING]->used() )
|
||||
{
|
||||
// only use panning-envelope...
|
||||
for( fpp_t frame = 0; frame < _frames; ++frame )
|
||||
@@ -389,18 +300,18 @@ void envelopeTabWidget::processAudioBuffer( sampleFrame * _ab,
|
||||
|
||||
|
||||
|
||||
f_cnt_t envelopeTabWidget::envFrames( const bool _only_vol )
|
||||
f_cnt_t instrumentSoundShaping::envFrames( const bool _only_vol ) const
|
||||
{
|
||||
f_cnt_t ret_val = m_envLFOWidgets[VOLUME]->m_pahdFrames;
|
||||
f_cnt_t ret_val = m_envLFOParameters[Volume]->PAHD_Frames();
|
||||
|
||||
if( _only_vol == FALSE )
|
||||
{
|
||||
for( int i = VOLUME+1; i < TARGET_COUNT; ++i )
|
||||
for( int i = Volume+1; i < NumTargets; ++i )
|
||||
{
|
||||
if( m_envLFOWidgets[i]->used() &&
|
||||
m_envLFOWidgets[i]->m_pahdFrames > ret_val )
|
||||
if( m_envLFOParameters[i]->used() &&
|
||||
m_envLFOParameters[i]->PAHD_Frames() > ret_val )
|
||||
{
|
||||
ret_val = m_envLFOWidgets[i]->m_pahdFrames;
|
||||
ret_val = m_envLFOParameters[i]->PAHD_Frames();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -410,10 +321,10 @@ f_cnt_t envelopeTabWidget::envFrames( const bool _only_vol )
|
||||
|
||||
|
||||
|
||||
f_cnt_t envelopeTabWidget::releaseFrames( const bool _only_vol )
|
||||
f_cnt_t instrumentSoundShaping::releaseFrames( const bool _only_vol ) const
|
||||
{
|
||||
f_cnt_t ret_val = m_envLFOWidgets[VOLUME]->used() ?
|
||||
m_envLFOWidgets[VOLUME]->m_rFrames : 0;
|
||||
f_cnt_t ret_val = m_envLFOParameters[Volume]->used() ?
|
||||
m_envLFOParameters[Volume]->releaseFrames() : 0;
|
||||
if( m_instrumentTrack->getInstrument()->desiredReleaseFrames() >
|
||||
ret_val )
|
||||
{
|
||||
@@ -421,14 +332,15 @@ f_cnt_t envelopeTabWidget::releaseFrames( const bool _only_vol )
|
||||
desiredReleaseFrames();
|
||||
}
|
||||
|
||||
if( m_envLFOWidgets[VOLUME]->used() == FALSE )
|
||||
if( m_envLFOParameters[Volume]->used() == FALSE )
|
||||
{
|
||||
for( int i = VOLUME+1; i < TARGET_COUNT; ++i )
|
||||
for( int i = Volume+1; i < NumTargets; ++i )
|
||||
{
|
||||
if( m_envLFOWidgets[i]->used() &&
|
||||
m_envLFOWidgets[i]->m_rFrames > ret_val )
|
||||
if( m_envLFOParameters[i]->used() &&
|
||||
m_envLFOParameters[i]->releaseFrames() >
|
||||
ret_val )
|
||||
{
|
||||
ret_val = m_envLFOWidgets[i]->m_rFrames;
|
||||
ret_val = m_envLFOParameters[i]->releaseFrames();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -438,43 +350,44 @@ f_cnt_t envelopeTabWidget::releaseFrames( const bool _only_vol )
|
||||
|
||||
|
||||
|
||||
void envelopeTabWidget::saveSettings( QDomDocument & _doc, QDomElement & _this )
|
||||
void instrumentSoundShaping::saveSettings( QDomDocument & _doc, QDomElement & _this )
|
||||
{
|
||||
m_filterModel->saveSettings( _doc, _this, "ftype" );
|
||||
m_filterCutModel->saveSettings( _doc, _this, "fcut" );
|
||||
m_filterResModel->saveSettings( _doc, _this, "fres" );
|
||||
m_filterEnabledModel->saveSettings( _doc, _this, "fwet" );
|
||||
m_filterModel.saveSettings( _doc, _this, "ftype" );
|
||||
m_filterCutModel.saveSettings( _doc, _this, "fcut" );
|
||||
m_filterResModel.saveSettings( _doc, _this, "fres" );
|
||||
m_filterEnabledModel.saveSettings( _doc, _this, "fwet" );
|
||||
|
||||
for( int i = 0; i < TARGET_COUNT; ++i )
|
||||
for( int i = 0; i < NumTargets; ++i )
|
||||
{
|
||||
m_envLFOWidgets[i]->saveState( _doc, _this ).setTagName(
|
||||
m_envLFOWidgets[i]->nodeName() +
|
||||
QString( targetNames[i][1] ).toLower() );
|
||||
m_envLFOParameters[i]->saveState( _doc, _this ).setTagName(
|
||||
m_envLFOParameters[i]->nodeName() +
|
||||
QString( __targetNames[i][1] ).toLower() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void envelopeTabWidget::loadSettings( const QDomElement & _this )
|
||||
void instrumentSoundShaping::loadSettings( const QDomElement & _this )
|
||||
{
|
||||
m_filterModel->loadSettings( _this, "ftype" );
|
||||
m_filterCutModel->loadSettings( _this, "fcut" );
|
||||
m_filterResModel->loadSettings( _this, "fres" );
|
||||
m_filterEnabledModel->loadSettings( _this, "fwet" );
|
||||
m_filterModel.loadSettings( _this, "ftype" );
|
||||
m_filterCutModel.loadSettings( _this, "fcut" );
|
||||
m_filterResModel.loadSettings( _this, "fres" );
|
||||
m_filterEnabledModel.loadSettings( _this, "fwet" );
|
||||
|
||||
QDomNode node = _this.firstChild();
|
||||
while( !node.isNull() )
|
||||
{
|
||||
if( node.isElement() )
|
||||
{
|
||||
for( int i = 0; i < TARGET_COUNT; ++i )
|
||||
for( int i = 0; i < NumTargets; ++i )
|
||||
{
|
||||
if( node.nodeName() ==
|
||||
m_envLFOWidgets[i]->nodeName() +
|
||||
QString( targetNames[i][1] ).toLower() )
|
||||
m_envLFOParameters[i]->nodeName() +
|
||||
QString( __targetNames[i][1] ).
|
||||
toLower() )
|
||||
{
|
||||
m_envLFOWidgets[i]->restoreState(
|
||||
m_envLFOParameters[i]->restoreState(
|
||||
node.toElement() );
|
||||
}
|
||||
}
|
||||
@@ -486,9 +399,7 @@ void envelopeTabWidget::loadSettings( const QDomElement & _this )
|
||||
|
||||
|
||||
|
||||
#include "instrument_sound_shaping.moc"
|
||||
|
||||
|
||||
//#include "instrument_sound_shaping.moc"
|
||||
|
||||
/*
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
#include "engine.h"
|
||||
#include "config_mgr.h"
|
||||
#include "export_project_dialog.h"
|
||||
#include "song_editor.h"
|
||||
#include "song.h"
|
||||
#include "gui_templates.h"
|
||||
#include "automatable_model_templates.h"
|
||||
|
||||
@@ -200,11 +200,11 @@ int main( int argc, char * * argv )
|
||||
// we try to load given file
|
||||
if( file_to_load != "" )
|
||||
{
|
||||
engine::getSongEditor()->loadProject( file_to_load );
|
||||
engine::getSong()->loadProject( file_to_load );
|
||||
}
|
||||
else
|
||||
{
|
||||
engine::getSongEditor()->createNewProject();
|
||||
engine::getSong()->createNewProject();
|
||||
}
|
||||
|
||||
// MDI-mode?
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
|
||||
#include "bb_editor.h"
|
||||
#include "song_editor.h"
|
||||
#include "song.h"
|
||||
#include "piano_roll.h"
|
||||
#include "embed.h"
|
||||
#include "engine.h"
|
||||
@@ -77,8 +78,7 @@ mainWindow::mainWindow( void ) :
|
||||
m_workspace( NULL ),
|
||||
m_templatesMenu( NULL ),
|
||||
m_recentlyOpenedProjectsMenu( NULL ),
|
||||
m_toolsMenu( NULL ),
|
||||
m_modified( FALSE )
|
||||
m_toolsMenu( NULL )
|
||||
{
|
||||
setAttribute( Qt::WA_DeleteOnClose );
|
||||
|
||||
@@ -514,24 +514,23 @@ void mainWindow::addSpacingToToolBar( int _size )
|
||||
|
||||
|
||||
|
||||
void mainWindow::resetWindowTitle( bool _modified )
|
||||
void mainWindow::resetWindowTitle( void )
|
||||
{
|
||||
QString title = "";
|
||||
if( engine::getSongEditor()->projectFileName() != "" )
|
||||
if( engine::getSong()->projectFileName() != "" )
|
||||
{
|
||||
title = QFileInfo( engine::getSongEditor()->projectFileName()
|
||||
title = QFileInfo( engine::getSong()->projectFileName()
|
||||
).completeBaseName();
|
||||
}
|
||||
if( title == "" )
|
||||
{
|
||||
title = tr( "Untitled" );
|
||||
}
|
||||
if( _modified )
|
||||
if( engine::getSong()->isModified() )
|
||||
{
|
||||
title += '*';
|
||||
}
|
||||
setWindowTitle( title + " - " + tr( "LMMS %1" ).arg( VERSION ) );
|
||||
m_modified = _modified;
|
||||
}
|
||||
|
||||
|
||||
@@ -539,7 +538,7 @@ void mainWindow::resetWindowTitle( bool _modified )
|
||||
|
||||
bool mainWindow::mayChangeProject( void )
|
||||
{
|
||||
if( !m_modified )
|
||||
if( !engine::getSong()->isModified() )
|
||||
{
|
||||
return( TRUE );
|
||||
}
|
||||
@@ -626,7 +625,7 @@ void mainWindow::createNewProject( void )
|
||||
{
|
||||
if( mayChangeProject() )
|
||||
{
|
||||
engine::getSongEditor()->createNewProject();
|
||||
engine::getSong()->createNewProject();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -641,7 +640,7 @@ void mainWindow::createNewProjectFromTemplate( QAction * _idx )
|
||||
>= m_custom_templates_count ?
|
||||
configManager::inst()->factoryProjectsDir() :
|
||||
configManager::inst()->userProjectsDir();
|
||||
engine::getSongEditor()->createNewProjectFromTemplate(
|
||||
engine::getSong()->createNewProjectFromTemplate(
|
||||
dir_base + "templates/" + _idx->text() + ".mpt" );
|
||||
}
|
||||
}
|
||||
@@ -661,7 +660,7 @@ void mainWindow::openProject( void )
|
||||
if( ofd.exec () == QDialog::Accepted &&
|
||||
!ofd.selectedFiles().isEmpty() )
|
||||
{
|
||||
engine::getSongEditor()->loadProject(
|
||||
engine::getSong()->loadProject(
|
||||
ofd.selectedFiles()[0] );
|
||||
}
|
||||
}
|
||||
@@ -686,7 +685,7 @@ void mainWindow::updateRecentlyOpenedProjectsMenu( void )
|
||||
void mainWindow::openRecentlyOpenedProject( QAction * _action )
|
||||
{
|
||||
const QString & f = _action->text();
|
||||
engine::getSongEditor()->loadProject( f );
|
||||
engine::getSong()->loadProject( f );
|
||||
configManager::inst()->addRecentlyOpenedProject( f );
|
||||
}
|
||||
|
||||
@@ -695,13 +694,13 @@ void mainWindow::openRecentlyOpenedProject( QAction * _action )
|
||||
|
||||
bool mainWindow::saveProject( void )
|
||||
{
|
||||
if( engine::getSongEditor()->projectFileName() == "" )
|
||||
if( engine::getSong()->projectFileName() == "" )
|
||||
{
|
||||
return( saveProjectAs() );
|
||||
}
|
||||
else
|
||||
{
|
||||
engine::getSongEditor()->saveProject();
|
||||
engine::getSong()->saveProject();
|
||||
}
|
||||
return( TRUE );
|
||||
}
|
||||
@@ -716,7 +715,7 @@ bool mainWindow::saveProjectAs( void )
|
||||
"MultiMedia Project Template (*.mpt)" ) );
|
||||
sfd.setAcceptMode( QFileDialog::AcceptSave );
|
||||
sfd.setFileMode( QFileDialog::AnyFile );
|
||||
QString f = engine::getSongEditor()->projectFileName();
|
||||
QString f = engine::getSong()->projectFileName();
|
||||
if( f != "" )
|
||||
{
|
||||
sfd.selectFile( QFileInfo( f ).fileName() );
|
||||
@@ -730,7 +729,7 @@ bool mainWindow::saveProjectAs( void )
|
||||
if( sfd.exec () == QFileDialog::Accepted &&
|
||||
!sfd.selectedFiles().isEmpty() && sfd.selectedFiles()[0] != "" )
|
||||
{
|
||||
engine::getSongEditor()->saveProjectAs(
|
||||
engine::getSong()->saveProjectAs(
|
||||
sfd.selectedFiles()[0] );
|
||||
return( TRUE );
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
#include "mixer.h"
|
||||
#include "play_handle.h"
|
||||
#include "song_editor.h"
|
||||
#include "song.h"
|
||||
#include "templates.h"
|
||||
#include "envelope_and_lfo_parameters.h"
|
||||
#include "debug.h"
|
||||
@@ -177,7 +177,7 @@ void mixer::stopProcessing( void )
|
||||
bool mixer::criticalXRuns( void ) const
|
||||
{
|
||||
return( ( m_cpuLoad >= 99 &&
|
||||
engine::getSongEditor()->realTimeTask() == TRUE ) );
|
||||
engine::getSong()->realTimeTask() == TRUE ) );
|
||||
}
|
||||
|
||||
|
||||
@@ -230,11 +230,11 @@ void mixer::setClipScaling( bool _state )
|
||||
const surroundSampleFrame * mixer::renderNextBuffer( void )
|
||||
{
|
||||
microTimer timer;
|
||||
static songEditor::playPos last_metro_pos = -1;
|
||||
static song::playPos last_metro_pos = -1;
|
||||
|
||||
songEditor::playPos p = engine::getSongEditor()->getPlayPos(
|
||||
songEditor::PLAY_PATTERN );
|
||||
if( engine::getSongEditor()->playMode() == songEditor::PLAY_PATTERN &&
|
||||
song::playPos p = engine::getSong()->getPlayPos(
|
||||
song::Mode_PlayPattern );
|
||||
if( engine::getSong()->playMode() == song::Mode_PlayPattern &&
|
||||
engine::getPianoRoll()->isRecording() == TRUE &&
|
||||
p != last_metro_pos && p.getTact64th() % 16 == 0 )
|
||||
{
|
||||
@@ -288,7 +288,7 @@ const surroundSampleFrame * mixer::renderNextBuffer( void )
|
||||
//printf("---------------------------next period\n");
|
||||
// if( criticalXRuns() == FALSE )
|
||||
{
|
||||
engine::getSongEditor()->processNextBuffer();
|
||||
engine::getSong()->processNextBuffer();
|
||||
|
||||
lockPlayHandles();
|
||||
int idx = 0;
|
||||
@@ -382,7 +382,7 @@ const surroundSampleFrame * mixer::renderNextBuffer( void )
|
||||
emit nextAudioBuffer();
|
||||
|
||||
// and trigger LFOs
|
||||
envelopeAndLFOWidget::triggerLFO();
|
||||
envelopeAndLFOParameters::triggerLFO();
|
||||
|
||||
const float new_cpu_load = timer.elapsed() / 10000.0f * sampleRate() /
|
||||
m_framesPerPeriod;
|
||||
|
||||
@@ -35,6 +35,7 @@ void modelView::setModel( model * _model, bool _old_model_valid )
|
||||
QWidget * w = dynamic_cast<QWidget *>( this );
|
||||
assert( w != NULL );
|
||||
|
||||
//printf("w: %x m_model:%x _model:%x\n", w, m_model, _model);
|
||||
if( _old_model_valid && m_model != NULL )
|
||||
{
|
||||
if( m_model->defaultConstructed() )
|
||||
@@ -46,7 +47,6 @@ void modelView::setModel( model * _model, bool _old_model_valid )
|
||||
m_model->disconnect( w );
|
||||
}
|
||||
}
|
||||
|
||||
m_model = _model;
|
||||
QObject::connect( _model, SIGNAL( dataChanged() ),
|
||||
w, SLOT( update() ) );
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* name_label.cpp - implementation of class nameLabel, a label which
|
||||
* is renamable by double-clicking it
|
||||
*
|
||||
* Copyright (c) 2004-2007 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2004-2008 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
@@ -148,7 +148,6 @@ void nameLabel::rename( void )
|
||||
{
|
||||
setText( txt );
|
||||
emit nameChanged( txt );
|
||||
emit nameChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -222,13 +221,14 @@ void nameLabel::paintEvent( QPaintEvent * )
|
||||
text() );
|
||||
|
||||
p.setPen( QColor( 0, 224, 0 ) );
|
||||
bbTrack * bbt = bbTrack::findBBTrack(
|
||||
engine::getBBEditor()->currentBB() );
|
||||
#warning: TODO
|
||||
/* bbTrack * bbt = bbTrack::findBBTrack(
|
||||
engine::getBBTrackContainer()->currentBB() );
|
||||
if( bbt != NULL && bbt->getTrackSettingsWidget() ==
|
||||
dynamic_cast<trackSettingsWidget *>( parentWidget() ) )
|
||||
{
|
||||
p.setPen( QColor( 255, 255, 255 ) );
|
||||
}
|
||||
}*/
|
||||
p.drawText( x, height() / 2 + p.fontMetrics().height() / 2 - 4,
|
||||
text() );
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* note_play_handle.cpp - implementation of class notePlayHandle, part of
|
||||
* play-engine
|
||||
*
|
||||
* Copyright (c) 2004-2007 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2004-2008 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
@@ -33,7 +33,7 @@
|
||||
#include "instrument_sound_shaping.h"
|
||||
#include "instrument_track.h"
|
||||
#include "midi_port.h"
|
||||
#include "song_editor.h"
|
||||
#include "song.h"
|
||||
|
||||
|
||||
inline notePlayHandle::baseDetuning::baseDetuning(
|
||||
@@ -85,7 +85,7 @@ notePlayHandle::notePlayHandle( instrumentTrack * _it,
|
||||
#if SINGERBOT_SUPPORT
|
||||
m_patternIndex( 0 ),
|
||||
#endif
|
||||
m_orig_bpm( engine::getSongEditor()->getTempo() )
|
||||
m_orig_bpm( engine::getSong()->getTempo() )
|
||||
{
|
||||
if( m_baseNote )
|
||||
{
|
||||
@@ -306,7 +306,7 @@ void notePlayHandle::noteOff( const f_cnt_t _s )
|
||||
// then set some variables indicating release-state
|
||||
m_framesBeforeRelease = _s;
|
||||
m_releaseFramesToDo = tMax<f_cnt_t>( 0, // 10,
|
||||
m_instrumentTrack->m_envWidget->releaseFrames() );
|
||||
m_instrumentTrack->m_soundShaping.releaseFrames() );
|
||||
// send MIDI-note-off-event
|
||||
m_instrumentTrack->processOutEvent( midiEvent( NOTE_OFF,
|
||||
m_instrumentTrack->m_midiPort->outputChannel(),
|
||||
@@ -322,7 +322,7 @@ void notePlayHandle::noteOff( const f_cnt_t _s )
|
||||
|
||||
f_cnt_t notePlayHandle::actualReleaseFramesToDo( void ) const
|
||||
{
|
||||
return( m_instrumentTrack->m_envWidget->releaseFrames(
|
||||
return( m_instrumentTrack->m_soundShaping.releaseFrames(
|
||||
arpBaseNote() ) );
|
||||
}
|
||||
|
||||
@@ -344,7 +344,7 @@ void notePlayHandle::setFrames( const f_cnt_t _frames )
|
||||
|
||||
float notePlayHandle::volumeLevel( const f_cnt_t _frame )
|
||||
{
|
||||
return( m_instrumentTrack->m_envWidget->volumeLevel( this, _frame ) );
|
||||
return( m_instrumentTrack->m_soundShaping.volumeLevel( this, _frame ) );
|
||||
}
|
||||
|
||||
|
||||
@@ -441,7 +441,7 @@ void notePlayHandle::updateFrequency( void )
|
||||
const int base_octave = m_instrumentTrack->baseNoteModel()->value() /
|
||||
NOTES_PER_OCTAVE;
|
||||
const float pitch = (float)( tone() - base_tone +
|
||||
engine::getSongEditor()->masterPitch() ) / 12.0f +
|
||||
engine::getSong()->masterPitch() ) / 12.0f +
|
||||
(float)( octave() - base_octave ) +
|
||||
m_base_detuning->value() / 12.0f;
|
||||
m_frequency = BASE_FREQ * powf( 2.0f, pitch );
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* piano_roll.cpp - implementation of piano-roll which is used for actual
|
||||
* writing of melodies
|
||||
*
|
||||
* Copyright (c) 2004-2007 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2004-2008 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
@@ -61,6 +61,7 @@
|
||||
#include "pattern.h"
|
||||
#include "piano_widget.h"
|
||||
#include "pixmap_button.h"
|
||||
#include "song.h"
|
||||
#include "song_editor.h"
|
||||
#include "templates.h"
|
||||
#include "text_float.h"
|
||||
@@ -189,8 +190,8 @@ pianoRoll::pianoRoll( void ) :
|
||||
|
||||
// add time-line
|
||||
m_timeLine = new timeLine( WHITE_KEY_WIDTH, 32, m_ppt,
|
||||
engine::getSongEditor()->getPlayPos(
|
||||
songEditor::PLAY_PATTERN ),
|
||||
engine::getSong()->getPlayPos(
|
||||
song::Mode_PlayPattern ),
|
||||
m_currentPosition, this );
|
||||
connect( this, SIGNAL( positionChanged( const midiTime & ) ),
|
||||
m_timeLine, SLOT( updatePosition( const midiTime & ) ) );
|
||||
@@ -641,8 +642,9 @@ void pianoRoll::keyPressEvent( QKeyEvent * _ke )
|
||||
{
|
||||
if( validPattern() )
|
||||
{
|
||||
m_pattern->getInstrumentTrack()->getPianoWidget()
|
||||
->keyPressEvent( _ke );
|
||||
// TODO: move this to instrumentTrack-class
|
||||
/* m_pattern->getInstrumentTrack()->getPianoWidget()
|
||||
->keyPressEvent( _ke );*/
|
||||
}
|
||||
switch( _ke->key() )
|
||||
{
|
||||
@@ -768,7 +770,7 @@ void pianoRoll::keyPressEvent( QKeyEvent * _ke )
|
||||
break;
|
||||
|
||||
case Qt::Key_Space:
|
||||
if( engine::getSongEditor()->playing() )
|
||||
if( engine::getSong()->playing() )
|
||||
{
|
||||
stop();
|
||||
}
|
||||
@@ -806,8 +808,8 @@ void pianoRoll::keyReleaseEvent( QKeyEvent * _ke )
|
||||
{
|
||||
if( validPattern() )
|
||||
{
|
||||
m_pattern->getInstrumentTrack()->getPianoWidget()
|
||||
->keyReleaseEvent( _ke );
|
||||
/* m_pattern->getInstrumentTrack()->getPianoWidget()
|
||||
->keyReleaseEvent( _ke );*/
|
||||
}
|
||||
switch( _ke->key() )
|
||||
{
|
||||
@@ -934,7 +936,7 @@ void pianoRoll::mousePressEvent( QMouseEvent * _me )
|
||||
if( it == notes.end() )
|
||||
{
|
||||
m_pattern->setType(
|
||||
pattern::MELODY_PATTERN );
|
||||
pattern::MelodyPattern );
|
||||
|
||||
// then set new note
|
||||
midiTime note_pos( pos_tact_64th );
|
||||
@@ -991,7 +993,7 @@ void pianoRoll::mousePressEvent( QMouseEvent * _me )
|
||||
QApplication::setOverrideCursor( c );
|
||||
}
|
||||
|
||||
engine::getSongEditor()->setModified();
|
||||
engine::getSong()->setModified();
|
||||
}
|
||||
else if( ( _me->button() == Qt::RightButton &&
|
||||
m_editMode == DRAW ) ||
|
||||
@@ -1009,9 +1011,9 @@ void pianoRoll::mousePressEvent( QMouseEvent * _me )
|
||||
else
|
||||
{
|
||||
( *it )->setLength( 0 );
|
||||
m_pattern->update();
|
||||
m_pattern->dataChanged();
|
||||
}
|
||||
engine::getSongEditor()->setModified();
|
||||
engine::getSong()->setModified();
|
||||
}
|
||||
}
|
||||
else if( _me->button() == Qt::LeftButton &&
|
||||
@@ -1050,7 +1052,7 @@ void pianoRoll::mousePressEvent( QMouseEvent * _me )
|
||||
m_action = MOVE_SELECTION;
|
||||
|
||||
play_note = FALSE;
|
||||
engine::getSongEditor()->setModified();
|
||||
engine::getSong()->setModified();
|
||||
}
|
||||
else if( _me->button() == Qt::RightButton &&
|
||||
m_editMode == MOVE )
|
||||
@@ -1066,7 +1068,7 @@ void pianoRoll::mousePressEvent( QMouseEvent * _me )
|
||||
|
||||
// was there an action where should be played the note?
|
||||
if( play_note == TRUE && m_recording == FALSE &&
|
||||
engine::getSongEditor()->playing() == FALSE )
|
||||
engine::getSong()->playing() == FALSE )
|
||||
{
|
||||
m_lastKey = key_num;
|
||||
m_pattern->getInstrumentTrack()->processInEvent(
|
||||
@@ -1144,7 +1146,7 @@ void pianoRoll::mouseMoveEvent( QMouseEvent * _me )
|
||||
m_action != SELECT_NOTES &&
|
||||
m_action != MOVE_SELECTION &&
|
||||
m_recording == FALSE &&
|
||||
engine::getSongEditor()->playing() == FALSE )
|
||||
engine::getSong()->playing() == FALSE )
|
||||
{
|
||||
m_lastKey = key_num;
|
||||
m_pattern->getInstrumentTrack()->processInEvent(
|
||||
@@ -1171,7 +1173,7 @@ void pianoRoll::mouseMoveEvent( QMouseEvent * _me )
|
||||
MIN_VOLUME,
|
||||
MAX_VOLUME );
|
||||
m_currentNote->setVolume( vol );
|
||||
m_pattern->update();
|
||||
m_pattern->dataChanged();
|
||||
m_pattern->getInstrumentTrack()->processInEvent(
|
||||
midiEvent( KEY_PRESSURE, 0, key_num,
|
||||
vol * 127 / 100 ),
|
||||
@@ -1219,10 +1221,10 @@ void pianoRoll::mouseMoveEvent( QMouseEvent * _me )
|
||||
tact_64th_diff ) );
|
||||
m_currentNote->quantizeLength( quantization() );
|
||||
m_lenOfNewNotes = m_currentNote->length();
|
||||
m_pattern->update();
|
||||
m_pattern->dataChanged();
|
||||
}
|
||||
|
||||
engine::getSongEditor()->setModified();
|
||||
engine::getSong()->setModified();
|
||||
|
||||
}
|
||||
else if( _me->buttons() == Qt::NoButton && m_editMode == DRAW )
|
||||
@@ -1974,7 +1976,7 @@ void pianoRoll::resizeEvent( QResizeEvent * )
|
||||
}
|
||||
m_topBottomScroll->setValue( m_totalKeysToScroll - m_startKey );
|
||||
|
||||
engine::getSongEditor()->getPlayPos( songEditor::PLAY_PATTERN
|
||||
engine::getSong()->getPlayPos( song::Mode_PlayPattern
|
||||
).m_timeLine->setFixedWidth( width() );
|
||||
m_toolBar->setFixedWidth( width() );
|
||||
update();
|
||||
@@ -2052,31 +2054,30 @@ void pianoRoll::play( void )
|
||||
return;
|
||||
}
|
||||
|
||||
if( engine::getSongEditor()->playing() )
|
||||
if( engine::getSong()->playing() )
|
||||
{
|
||||
if( engine::getSongEditor()->playMode() !=
|
||||
songEditor::PLAY_PATTERN )
|
||||
if( engine::getSong()->playMode() != song::Mode_PlayPattern )
|
||||
{
|
||||
engine::getSongEditor()->stop();
|
||||
engine::getSongEditor()->playPattern( m_pattern );
|
||||
engine::getSong()->stop();
|
||||
engine::getSong()->playPattern( m_pattern );
|
||||
m_playButton->setIcon( embed::getIconPixmap(
|
||||
"pause" ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
engine::getSongEditor()->pause();
|
||||
engine::getSong()->pause();
|
||||
m_playButton->setIcon( embed::getIconPixmap( "play" ) );
|
||||
}
|
||||
}
|
||||
else if( engine::getSongEditor()->paused() )
|
||||
else if( engine::getSong()->paused() )
|
||||
{
|
||||
engine::getSongEditor()->resumeFromPause();
|
||||
engine::getSong()->resumeFromPause();
|
||||
m_playButton->setIcon( embed::getIconPixmap( "pause" ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_playButton->setIcon( embed::getIconPixmap( "pause" ) );
|
||||
engine::getSongEditor()->playPattern( m_pattern );
|
||||
engine::getSong()->playPattern( m_pattern );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2085,7 +2086,7 @@ void pianoRoll::play( void )
|
||||
|
||||
void pianoRoll::record( void )
|
||||
{
|
||||
if( engine::getSongEditor()->playing() )
|
||||
if( engine::getSong()->playing() )
|
||||
{
|
||||
stop();
|
||||
}
|
||||
@@ -2095,7 +2096,7 @@ void pianoRoll::record( void )
|
||||
}
|
||||
|
||||
m_recording = TRUE;
|
||||
engine::getSongEditor()->playPattern( m_pattern, FALSE );
|
||||
engine::getSong()->playPattern( m_pattern, FALSE );
|
||||
}
|
||||
|
||||
|
||||
@@ -2103,7 +2104,7 @@ void pianoRoll::record( void )
|
||||
|
||||
void pianoRoll::stop( void )
|
||||
{
|
||||
engine::getSongEditor()->stop();
|
||||
engine::getSong()->stop();
|
||||
m_playButton->setIcon( embed::getIconPixmap( "play" ) );
|
||||
m_playButton->update();
|
||||
m_recording = FALSE;
|
||||
@@ -2117,14 +2118,14 @@ void pianoRoll::recordNote( const note & _n )
|
||||
{
|
||||
if( m_recording == TRUE && validPattern() == TRUE )
|
||||
{
|
||||
note n( _n.length(), engine::getSongEditor()->getPlayPos(
|
||||
songEditor::PLAY_PATTERN ) - _n.length(),
|
||||
note n( _n.length(), engine::getSong()->getPlayPos(
|
||||
song::Mode_PlayPattern ) - _n.length(),
|
||||
_n.tone(), _n.octave(),
|
||||
_n.getVolume(), _n.getPanning() );
|
||||
n.quantizeLength( quantization() );
|
||||
m_pattern->addNote( n );
|
||||
update();
|
||||
engine::getSongEditor()->setModified();
|
||||
engine::getSong()->setModified();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2301,7 +2302,7 @@ void pianoRoll::getSelectedNotes( noteVector & _selected_notes )
|
||||
|
||||
void pianoRoll::copy_to_clipboard( const noteVector & _notes ) const
|
||||
{
|
||||
multimediaProject mmp( multimediaProject::CLIPBOARD_DATA );
|
||||
multimediaProject mmp( multimediaProject::ClipboardData );
|
||||
QDomElement note_list = mmp.createElement( "note-list" );
|
||||
mmp.content().appendChild( note_list );
|
||||
|
||||
@@ -2356,7 +2357,7 @@ void pianoRoll::cutSelectedNotes( void )
|
||||
{
|
||||
copy_to_clipboard( selected_notes );
|
||||
|
||||
engine::getSongEditor()->setModified();
|
||||
engine::getSong()->setModified();
|
||||
|
||||
for( noteVector::iterator it = selected_notes.begin();
|
||||
it != selected_notes.end(); ++it )
|
||||
@@ -2401,7 +2402,7 @@ void pianoRoll::pasteNotes( void )
|
||||
|
||||
// we only have to do the following lines if we pasted at
|
||||
// least one note...
|
||||
engine::getSongEditor()->setModified();
|
||||
engine::getSong()->setModified();
|
||||
update();
|
||||
engine::getSongEditor()->update();
|
||||
}
|
||||
@@ -2430,7 +2431,7 @@ void pianoRoll::deleteSelectedNotes( void )
|
||||
|
||||
if( update_after_delete == TRUE )
|
||||
{
|
||||
engine::getSongEditor()->setModified();
|
||||
engine::getSong()->setModified();
|
||||
update();
|
||||
engine::getSongEditor()->update();
|
||||
}
|
||||
@@ -2441,9 +2442,9 @@ void pianoRoll::deleteSelectedNotes( void )
|
||||
|
||||
void pianoRoll::updatePosition( const midiTime & _t )
|
||||
{
|
||||
if( ( engine::getSongEditor()->playing() &&
|
||||
engine::getSongEditor()->playMode() ==
|
||||
songEditor::PLAY_PATTERN ) ||
|
||||
if( ( engine::getSong()->playing() &&
|
||||
engine::getSong()->playMode() ==
|
||||
song::Mode_PlayPattern ) ||
|
||||
m_scrollBack == TRUE )
|
||||
{
|
||||
const int w = width() - WHITE_KEY_WIDTH;
|
||||
@@ -2564,8 +2565,8 @@ bool pianoRoll::x11Event( XEvent * _xe )
|
||||
{
|
||||
if( validPattern() )
|
||||
{
|
||||
return( m_pattern->getInstrumentTrack()->getPianoWidget()
|
||||
->x11Event( _xe ) );
|
||||
/* return( m_pattern->getInstrumentTrack()->getPianoWidget()
|
||||
->x11Event( _xe ) );*/
|
||||
}
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* piano_widget.cpp - implementation of piano-widget used in channel-window
|
||||
* for testing channel
|
||||
*
|
||||
* Copyright (c) 2004-2007 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2004-2008 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
@@ -52,25 +52,25 @@
|
||||
#endif
|
||||
|
||||
|
||||
const keyTypes KEY_ORDER[] =
|
||||
const KeyTypes KEY_ORDER[] =
|
||||
{
|
||||
// C CIS D DIS E F
|
||||
WHITE_KEY, BLACK_KEY, WHITE_KEY, BLACK_KEY, WHITE_KEY, WHITE_KEY,
|
||||
WhiteKey, BlackKey, WhiteKey, BlackKey, WhiteKey, WhiteKey,
|
||||
// FIS G GIS A B H
|
||||
BLACK_KEY, WHITE_KEY, BLACK_KEY, WHITE_KEY, BLACK_KEY, WHITE_KEY
|
||||
BlackKey, WhiteKey, BlackKey, WhiteKey, BlackKey, WhiteKey
|
||||
} ;
|
||||
|
||||
|
||||
tones WHITE_KEYS[] =
|
||||
tones WhiteKeyS[] =
|
||||
{
|
||||
C, D, E, F, G, A, H
|
||||
} ;
|
||||
|
||||
|
||||
QPixmap * pianoWidget::s_whiteKeyPm = NULL;
|
||||
QPixmap * pianoWidget::s_blackKeyPm = NULL;
|
||||
QPixmap * pianoWidget::s_whiteKeyPressedPm = NULL;
|
||||
QPixmap * pianoWidget::s_blackKeyPressedPm = NULL;
|
||||
QPixmap * pianoView::s_whiteKeyPm = NULL;
|
||||
QPixmap * pianoView::s_blackKeyPm = NULL;
|
||||
QPixmap * pianoView::s_whiteKeyPressedPm = NULL;
|
||||
QPixmap * pianoView::s_blackKeyPressedPm = NULL;
|
||||
|
||||
|
||||
const int PIANO_BASE = 11;
|
||||
@@ -81,287 +81,41 @@ const int PW_BLACK_KEY_HEIGHT = 38;
|
||||
const int LABEL_TEXT_SIZE = 7;
|
||||
|
||||
|
||||
pianoWidget::pianoWidget( instrumentTrack * _parent ) :
|
||||
QWidget( _parent ),
|
||||
m_instrumentTrack( _parent ),
|
||||
m_startTone( C ),
|
||||
m_startOctave( OCTAVE_3 ),
|
||||
m_lastKey( -1 ),
|
||||
m_keyCode( 0 )
|
||||
|
||||
|
||||
piano::piano( instrumentTrack * _it ) :
|
||||
model( _it ),
|
||||
m_instrumentTrack( _it )
|
||||
{
|
||||
connect( m_instrumentTrack->baseNoteModel(), SIGNAL( dataChanged() ),
|
||||
this, SLOT( update( void ) ) );
|
||||
|
||||
|
||||
setFocusPolicy( Qt::StrongFocus );
|
||||
|
||||
if( s_whiteKeyPm == NULL )
|
||||
{
|
||||
s_whiteKeyPm = new QPixmap( embed::getIconPixmap(
|
||||
"white_key" ) );
|
||||
}
|
||||
if( s_blackKeyPm == NULL )
|
||||
{
|
||||
s_blackKeyPm = new QPixmap( embed::getIconPixmap(
|
||||
"black_key" ) );
|
||||
}
|
||||
if( s_whiteKeyPressedPm == NULL )
|
||||
{
|
||||
s_whiteKeyPressedPm = new QPixmap( embed::getIconPixmap(
|
||||
"white_key_pressed" ) );
|
||||
}
|
||||
if ( s_blackKeyPressedPm == NULL )
|
||||
{
|
||||
s_blackKeyPressedPm = new QPixmap( embed::getIconPixmap(
|
||||
"black_key_pressed" ) );
|
||||
}
|
||||
|
||||
for( int i = 0; i < NOTES_PER_OCTAVE * OCTAVES; ++i )
|
||||
{
|
||||
m_pressedKeys[i] = FALSE;
|
||||
}
|
||||
|
||||
m_pianoScroll = new QScrollBar( Qt::Horizontal, this );
|
||||
m_pianoScroll->setRange( 0, WHITE_KEYS_PER_OCTAVE * ( OCTAVES - 3 ) -
|
||||
4 );
|
||||
m_pianoScroll->setSingleStep( 1 );
|
||||
m_pianoScroll->setPageStep( 20 );
|
||||
m_pianoScroll->setValue( OCTAVE_3 * WHITE_KEYS_PER_OCTAVE );
|
||||
m_pianoScroll->setGeometry( 0, PIANO_BASE + PW_WHITE_KEY_HEIGHT, 250,
|
||||
16 );
|
||||
// ...and connect it to this widget...
|
||||
connect( m_pianoScroll, SIGNAL( valueChanged( int ) ), this,
|
||||
SLOT( pianoScrolled( int ) ) );
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
pianoWidget::~pianoWidget()
|
||||
piano::~piano()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// gets the key from the given mouse-position
|
||||
int pianoWidget::getKeyFromMouse( const QPoint & _p ) const
|
||||
void piano::setKeyState( int _key, bool _on )
|
||||
{
|
||||
|
||||
int key_num = (int)( (float) _p.x() / (float) PW_WHITE_KEY_WIDTH );
|
||||
|
||||
for( int i = 0; i <= key_num; ++i )
|
||||
{
|
||||
if( KEY_ORDER[( m_startOctave * NOTES_PER_OCTAVE +
|
||||
m_startTone +i ) % NOTES_PER_OCTAVE] ==
|
||||
BLACK_KEY )
|
||||
{
|
||||
++key_num;
|
||||
}
|
||||
}
|
||||
|
||||
key_num += m_startOctave * NOTES_PER_OCTAVE + m_startTone;
|
||||
|
||||
// is it a black key?
|
||||
if( _p.y() < PIANO_BASE + PW_BLACK_KEY_HEIGHT )
|
||||
{
|
||||
// then do extra checking whether the mouse-cursor is over
|
||||
// a black key
|
||||
if( key_num > 0 &&
|
||||
KEY_ORDER[( key_num - 1 ) % NOTES_PER_OCTAVE] ==
|
||||
BLACK_KEY &&
|
||||
_p.x() % PW_WHITE_KEY_WIDTH <=
|
||||
( PW_WHITE_KEY_WIDTH / 2 ) -
|
||||
( PW_BLACK_KEY_WIDTH / 2 ) )
|
||||
{
|
||||
--key_num;
|
||||
}
|
||||
if( key_num < NOTES_PER_OCTAVE * OCTAVES - 1 &&
|
||||
KEY_ORDER[( key_num + 1 ) % NOTES_PER_OCTAVE] ==
|
||||
BLACK_KEY &&
|
||||
_p.x() % PW_WHITE_KEY_WIDTH >=
|
||||
( PW_WHITE_KEY_WIDTH -
|
||||
PW_BLACK_KEY_WIDTH / 2 ) )
|
||||
{
|
||||
++key_num;
|
||||
}
|
||||
}
|
||||
|
||||
// some range-checking-stuff
|
||||
return( tLimit( key_num, 0, NOTES_PER_OCTAVE * OCTAVES - 1 ) );
|
||||
m_pressedKeys[tLimit( _key, 0, NOTES_PER_OCTAVE * OCTAVES - 1 )] = _on;
|
||||
emit dataChanged();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// handler for scrolling-event
|
||||
void pianoWidget::pianoScrolled( int _new_pos )
|
||||
int piano::getKeyFromKeycode( int _k )
|
||||
{
|
||||
m_startTone = WHITE_KEYS[_new_pos % WHITE_KEYS_PER_OCTAVE];
|
||||
m_startOctave = (octaves)( _new_pos / WHITE_KEYS_PER_OCTAVE );
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void pianoWidget::contextMenuEvent( QContextMenuEvent * _me )
|
||||
{
|
||||
if( _me->pos().y() > PIANO_BASE )
|
||||
{
|
||||
QWidget::contextMenuEvent( _me );
|
||||
return;
|
||||
}
|
||||
|
||||
captionMenu contextMenu( tr( "Base note" ) );
|
||||
contextMenu.addAction( embed::getIconPixmap( "automation" ),
|
||||
tr( "&Open in automation editor" ),
|
||||
m_instrumentTrack->baseNoteModel()->getAutomationPattern(),
|
||||
SLOT( openInAutomationEditor() ) );
|
||||
contextMenu.exec( QCursor::pos() );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// handler for mouse-click-event
|
||||
void pianoWidget::mousePressEvent( QMouseEvent * _me )
|
||||
{
|
||||
if( _me->button() == Qt::LeftButton )
|
||||
{
|
||||
// get pressed key
|
||||
Uint32 key_num = getKeyFromMouse( _me->pos() );
|
||||
if( _me->pos().y() > PIANO_BASE )
|
||||
{
|
||||
int y_diff = _me->pos().y() - PIANO_BASE;
|
||||
volume vol = (volume)( ( float ) y_diff /
|
||||
( ( KEY_ORDER[key_num % NOTES_PER_OCTAVE] ==
|
||||
WHITE_KEY ) ?
|
||||
PW_WHITE_KEY_HEIGHT : PW_BLACK_KEY_HEIGHT ) *
|
||||
(float) DEFAULT_VOLUME);
|
||||
if( y_diff < 0 )
|
||||
{
|
||||
vol = 0;
|
||||
}
|
||||
else if( y_diff > ( ( KEY_ORDER[key_num %
|
||||
NOTES_PER_OCTAVE] ==
|
||||
WHITE_KEY ) ?
|
||||
PW_WHITE_KEY_HEIGHT : PW_BLACK_KEY_HEIGHT ) )
|
||||
{
|
||||
vol = DEFAULT_VOLUME;
|
||||
}
|
||||
// set note on
|
||||
m_instrumentTrack->processInEvent(
|
||||
midiEvent( NOTE_ON, 0, key_num,
|
||||
vol * 127 / 100 ),
|
||||
midiTime() );
|
||||
m_pressedKeys[key_num] = TRUE;
|
||||
m_lastKey = key_num;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_instrumentTrack->baseNoteModel()->
|
||||
setInitValue( key_num );
|
||||
}
|
||||
|
||||
// and let the user see that he pressed a key... :)
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// handler for mouse-release-event
|
||||
void pianoWidget::mouseReleaseEvent( QMouseEvent * _me )
|
||||
{
|
||||
if( m_lastKey != -1 )
|
||||
{
|
||||
m_instrumentTrack->processInEvent(
|
||||
midiEvent( NOTE_OFF, 0, m_lastKey, 0 ), midiTime() );
|
||||
m_pressedKeys[m_lastKey] = FALSE;
|
||||
|
||||
// and let the user see that he released a key... :)
|
||||
update();
|
||||
|
||||
m_lastKey = -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// handler for mouse-move-event
|
||||
void pianoWidget::mouseMoveEvent( QMouseEvent * _me )
|
||||
{
|
||||
int key_num = getKeyFromMouse( _me->pos() );
|
||||
int y_diff = _me->pos().y() - PIANO_BASE;
|
||||
volume vol = (volume)( (float) y_diff /
|
||||
( ( KEY_ORDER[key_num % NOTES_PER_OCTAVE] == WHITE_KEY ) ?
|
||||
PW_WHITE_KEY_HEIGHT : PW_BLACK_KEY_HEIGHT ) *
|
||||
(float)DEFAULT_VOLUME );
|
||||
// maybe the user moved the mouse-cursor above or under the
|
||||
// piano-widget while holding left button so check that and
|
||||
// correct volume if necessary
|
||||
if( y_diff < 0 )
|
||||
{
|
||||
vol = 0;
|
||||
}
|
||||
else if( y_diff >
|
||||
( ( KEY_ORDER[key_num % NOTES_PER_OCTAVE] == WHITE_KEY ) ?
|
||||
PW_WHITE_KEY_HEIGHT : PW_BLACK_KEY_HEIGHT ) )
|
||||
{
|
||||
vol = DEFAULT_VOLUME;
|
||||
}
|
||||
|
||||
// is the calculated key different from current key? (could be the
|
||||
// user just moved the cursor one pixel left but on the same key)
|
||||
if( key_num != m_lastKey )
|
||||
{
|
||||
if( m_lastKey != -1 )
|
||||
{
|
||||
m_instrumentTrack->processInEvent(
|
||||
midiEvent( NOTE_OFF, 0, m_lastKey, 0 ),
|
||||
midiTime() );
|
||||
m_pressedKeys[m_lastKey] = FALSE;
|
||||
m_lastKey = -1;
|
||||
}
|
||||
if( _me->buttons() & Qt::LeftButton )
|
||||
{
|
||||
if( _me->pos().y() > PIANO_BASE )
|
||||
{
|
||||
m_instrumentTrack->processInEvent(
|
||||
midiEvent( NOTE_ON, 0, key_num, vol ),
|
||||
midiTime() );
|
||||
m_pressedKeys[key_num] = TRUE;
|
||||
m_lastKey = key_num;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_instrumentTrack->baseNoteModel()->
|
||||
setInitValue( key_num );
|
||||
}
|
||||
}
|
||||
// and let the user see that he pressed a key... :)
|
||||
update();
|
||||
}
|
||||
else if( m_pressedKeys[key_num] == TRUE )
|
||||
{
|
||||
m_instrumentTrack->processInEvent(
|
||||
midiEvent( KEY_PRESSURE, 0, key_num, vol ),
|
||||
midiTime() );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int pianoWidget::getKeyFromKeyboard( int _k ) const
|
||||
{
|
||||
switch( m_keyCode )
|
||||
switch( _k )
|
||||
{
|
||||
case 52: return( 0 ); // Y
|
||||
case 39: return( 1 ); // S
|
||||
@@ -400,80 +154,367 @@ int pianoWidget::getKeyFromKeyboard( int _k ) const
|
||||
|
||||
|
||||
|
||||
void pianoWidget::keyPressEvent( QKeyEvent * _ke )
|
||||
{
|
||||
int key_num = getKeyFromKeyboard( _ke->key() ) +
|
||||
( DEFAULT_OCTAVE - 1 ) * NOTES_PER_OCTAVE;
|
||||
|
||||
if( _ke->isAutoRepeat() == FALSE && key_num > -1 )
|
||||
|
||||
pianoView::pianoView( QWidget * _parent ) :
|
||||
QWidget( _parent ),
|
||||
modelView( NULL ),
|
||||
m_piano( NULL ),
|
||||
m_startTone( C ),
|
||||
m_startOctave( OCTAVE_3 ),
|
||||
m_lastKey( -1 ),
|
||||
m_keyCode( 0 )
|
||||
{
|
||||
if( s_whiteKeyPm == NULL )
|
||||
{
|
||||
m_instrumentTrack->processInEvent(
|
||||
midiEvent( NOTE_ON, 0, key_num, DEFAULT_VOLUME ),
|
||||
midiTime() );
|
||||
m_pressedKeys[key_num] = TRUE;
|
||||
update();
|
||||
s_whiteKeyPm = new QPixmap( embed::getIconPixmap(
|
||||
"white_key" ) );
|
||||
}
|
||||
else
|
||||
if( s_blackKeyPm == NULL )
|
||||
{
|
||||
_ke->ignore();
|
||||
s_blackKeyPm = new QPixmap( embed::getIconPixmap(
|
||||
"black_key" ) );
|
||||
}
|
||||
if( s_whiteKeyPressedPm == NULL )
|
||||
{
|
||||
s_whiteKeyPressedPm = new QPixmap( embed::getIconPixmap(
|
||||
"white_key_pressed" ) );
|
||||
}
|
||||
if ( s_blackKeyPressedPm == NULL )
|
||||
{
|
||||
s_blackKeyPressedPm = new QPixmap( embed::getIconPixmap(
|
||||
"black_key_pressed" ) );
|
||||
}
|
||||
|
||||
setFocusPolicy( Qt::StrongFocus );
|
||||
|
||||
m_pianoScroll = new QScrollBar( Qt::Horizontal, this );
|
||||
m_pianoScroll->setRange( 0, WHITE_KEYS_PER_OCTAVE * ( OCTAVES - 3 ) -
|
||||
4 );
|
||||
m_pianoScroll->setSingleStep( 1 );
|
||||
m_pianoScroll->setPageStep( 20 );
|
||||
m_pianoScroll->setValue( OCTAVE_3 * WHITE_KEYS_PER_OCTAVE );
|
||||
m_pianoScroll->setGeometry( 0, PIANO_BASE + PW_WHITE_KEY_HEIGHT, 250,
|
||||
16 );
|
||||
// ...and connect it to this widget...
|
||||
connect( m_pianoScroll, SIGNAL( valueChanged( int ) ),
|
||||
this, SLOT( pianoScrolled( int ) ) );
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void pianoWidget::keyReleaseEvent( QKeyEvent * _ke )
|
||||
pianoView::~pianoView()
|
||||
{
|
||||
int key_num = getKeyFromKeyboard( _ke->key() ) +
|
||||
( DEFAULT_OCTAVE - 1 ) * NOTES_PER_OCTAVE;
|
||||
if( _ke->isAutoRepeat() == FALSE && key_num > -1 )
|
||||
{
|
||||
m_instrumentTrack->processInEvent(
|
||||
midiEvent( NOTE_OFF, 0, key_num, 0 ),
|
||||
midiTime() );
|
||||
m_pressedKeys[key_num] = FALSE;
|
||||
update();
|
||||
}
|
||||
else
|
||||
{
|
||||
_ke->ignore();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void pianoWidget::setKeyState( int _key, bool _on )
|
||||
void pianoView::modelChanged( void )
|
||||
{
|
||||
m_pressedKeys[tLimit( _key, 0, NOTES_PER_OCTAVE * OCTAVES - 1 )] = _on;
|
||||
QApplication::postEvent( this, new updateEvent() );
|
||||
m_piano = castModel<piano>();
|
||||
if( m_piano != NULL )
|
||||
{
|
||||
connect( m_piano->m_instrumentTrack->baseNoteModel(),
|
||||
SIGNAL( dataChanged() ), this, SLOT( update() ) );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void pianoWidget::customEvent( QEvent * )
|
||||
// gets the key from the given mouse-position
|
||||
int pianoView::getKeyFromMouse( const QPoint & _p ) const
|
||||
{
|
||||
int key_num = (int)( (float) _p.x() / (float) PW_WHITE_KEY_WIDTH );
|
||||
|
||||
for( int i = 0; i <= key_num; ++i )
|
||||
{
|
||||
if( KEY_ORDER[( m_startOctave * NOTES_PER_OCTAVE +
|
||||
m_startTone +i ) % NOTES_PER_OCTAVE] ==
|
||||
BlackKey )
|
||||
{
|
||||
++key_num;
|
||||
}
|
||||
}
|
||||
|
||||
key_num += m_startOctave * NOTES_PER_OCTAVE + m_startTone;
|
||||
|
||||
// is it a black key?
|
||||
if( _p.y() < PIANO_BASE + PW_BLACK_KEY_HEIGHT )
|
||||
{
|
||||
// then do extra checking whether the mouse-cursor is over
|
||||
// a black key
|
||||
if( key_num > 0 &&
|
||||
KEY_ORDER[( key_num - 1 ) % NOTES_PER_OCTAVE] ==
|
||||
BlackKey &&
|
||||
_p.x() % PW_WHITE_KEY_WIDTH <=
|
||||
( PW_WHITE_KEY_WIDTH / 2 ) -
|
||||
( PW_BLACK_KEY_WIDTH / 2 ) )
|
||||
{
|
||||
--key_num;
|
||||
}
|
||||
if( key_num < NOTES_PER_OCTAVE * OCTAVES - 1 &&
|
||||
KEY_ORDER[( key_num + 1 ) % NOTES_PER_OCTAVE] ==
|
||||
BlackKey &&
|
||||
_p.x() % PW_WHITE_KEY_WIDTH >=
|
||||
( PW_WHITE_KEY_WIDTH -
|
||||
PW_BLACK_KEY_WIDTH / 2 ) )
|
||||
{
|
||||
++key_num;
|
||||
}
|
||||
}
|
||||
|
||||
// some range-checking-stuff
|
||||
return( tLimit( key_num, 0, NOTES_PER_OCTAVE * OCTAVES - 1 ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// handler for scrolling-event
|
||||
void pianoView::pianoScrolled( int _new_pos )
|
||||
{
|
||||
m_startTone = WhiteKeyS[_new_pos % WHITE_KEYS_PER_OCTAVE];
|
||||
m_startOctave = (octaves)( _new_pos / WHITE_KEYS_PER_OCTAVE );
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void pianoWidget::focusOutEvent( QFocusEvent * )
|
||||
void pianoView::contextMenuEvent( QContextMenuEvent * _me )
|
||||
{
|
||||
if( _me->pos().y() > PIANO_BASE || m_piano == NULL )
|
||||
{
|
||||
QWidget::contextMenuEvent( _me );
|
||||
return;
|
||||
}
|
||||
|
||||
captionMenu contextMenu( tr( "Base note" ) );
|
||||
contextMenu.addAction( embed::getIconPixmap( "automation" ),
|
||||
tr( "&Open in automation editor" ),
|
||||
m_piano->m_instrumentTrack->baseNoteModel()->
|
||||
getAutomationPattern(),
|
||||
SLOT( openInAutomationEditor() ) );
|
||||
contextMenu.exec( QCursor::pos() );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// handler for mouse-click-event
|
||||
void pianoView::mousePressEvent( QMouseEvent * _me )
|
||||
{
|
||||
if( _me->button() == Qt::LeftButton && m_piano != NULL )
|
||||
{
|
||||
// get pressed key
|
||||
Uint32 key_num = getKeyFromMouse( _me->pos() );
|
||||
if( _me->pos().y() > PIANO_BASE )
|
||||
{
|
||||
int y_diff = _me->pos().y() - PIANO_BASE;
|
||||
volume vol = (volume)( ( float ) y_diff /
|
||||
( ( KEY_ORDER[key_num % NOTES_PER_OCTAVE] ==
|
||||
WhiteKey ) ?
|
||||
PW_WHITE_KEY_HEIGHT : PW_BLACK_KEY_HEIGHT ) *
|
||||
(float) DEFAULT_VOLUME);
|
||||
if( y_diff < 0 )
|
||||
{
|
||||
vol = 0;
|
||||
}
|
||||
else if( y_diff > ( ( KEY_ORDER[key_num %
|
||||
NOTES_PER_OCTAVE] ==
|
||||
WhiteKey ) ?
|
||||
PW_WHITE_KEY_HEIGHT : PW_BLACK_KEY_HEIGHT ) )
|
||||
{
|
||||
vol = DEFAULT_VOLUME;
|
||||
}
|
||||
// set note on
|
||||
m_piano->m_instrumentTrack->processInEvent(
|
||||
midiEvent( NOTE_ON, 0, key_num,
|
||||
vol * 127 / 100 ),
|
||||
midiTime() );
|
||||
m_piano->m_pressedKeys[key_num] = TRUE;
|
||||
m_lastKey = key_num;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_piano->m_instrumentTrack->baseNoteModel()->
|
||||
setInitValue( key_num );
|
||||
}
|
||||
|
||||
// and let the user see that he pressed a key... :)
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// handler for mouse-release-event
|
||||
void pianoView::mouseReleaseEvent( QMouseEvent * _me )
|
||||
{
|
||||
if( m_lastKey != -1 )
|
||||
{
|
||||
if( m_piano != NULL )
|
||||
{
|
||||
m_piano->m_instrumentTrack->processInEvent(
|
||||
midiEvent( NOTE_OFF, 0, m_lastKey, 0 ),
|
||||
midiTime() );
|
||||
m_piano->m_pressedKeys[m_lastKey] = FALSE;
|
||||
}
|
||||
|
||||
// and let the user see that he released a key... :)
|
||||
update();
|
||||
|
||||
m_lastKey = -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// handler for mouse-move-event
|
||||
void pianoView::mouseMoveEvent( QMouseEvent * _me )
|
||||
{
|
||||
if( m_piano == NULL )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int key_num = getKeyFromMouse( _me->pos() );
|
||||
int y_diff = _me->pos().y() - PIANO_BASE;
|
||||
volume vol = (volume)( (float) y_diff /
|
||||
( ( KEY_ORDER[key_num % NOTES_PER_OCTAVE] == WhiteKey ) ?
|
||||
PW_WHITE_KEY_HEIGHT : PW_BLACK_KEY_HEIGHT ) *
|
||||
(float)DEFAULT_VOLUME );
|
||||
// maybe the user moved the mouse-cursor above or under the
|
||||
// piano-widget while holding left button so check that and
|
||||
// correct volume if necessary
|
||||
if( y_diff < 0 )
|
||||
{
|
||||
vol = 0;
|
||||
}
|
||||
else if( y_diff >
|
||||
( ( KEY_ORDER[key_num % NOTES_PER_OCTAVE] == WhiteKey ) ?
|
||||
PW_WHITE_KEY_HEIGHT : PW_BLACK_KEY_HEIGHT ) )
|
||||
{
|
||||
vol = DEFAULT_VOLUME;
|
||||
}
|
||||
|
||||
// is the calculated key different from current key? (could be the
|
||||
// user just moved the cursor one pixel left but on the same key)
|
||||
if( key_num != m_lastKey )
|
||||
{
|
||||
if( m_lastKey != -1 )
|
||||
{
|
||||
m_piano->m_instrumentTrack->processInEvent(
|
||||
midiEvent( NOTE_OFF, 0, m_lastKey, 0 ),
|
||||
midiTime() );
|
||||
m_piano->m_pressedKeys[m_lastKey] = FALSE;
|
||||
m_lastKey = -1;
|
||||
}
|
||||
if( _me->buttons() & Qt::LeftButton )
|
||||
{
|
||||
if( _me->pos().y() > PIANO_BASE )
|
||||
{
|
||||
m_piano->m_instrumentTrack->processInEvent(
|
||||
midiEvent( NOTE_ON, 0, key_num, vol ),
|
||||
midiTime() );
|
||||
m_piano->m_pressedKeys[key_num] = TRUE;
|
||||
m_lastKey = key_num;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_piano->m_instrumentTrack->baseNoteModel()->
|
||||
setInitValue( key_num );
|
||||
}
|
||||
}
|
||||
// and let the user see that he pressed a key... :)
|
||||
update();
|
||||
}
|
||||
else if( m_piano->m_pressedKeys[key_num] == TRUE )
|
||||
{
|
||||
m_piano->m_instrumentTrack->processInEvent(
|
||||
midiEvent( KEY_PRESSURE, 0, key_num, vol ),
|
||||
midiTime() );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void pianoView::keyPressEvent( QKeyEvent * _ke )
|
||||
{
|
||||
int key_num = piano::getKeyFromKeycode( m_keyCode ) +
|
||||
( DEFAULT_OCTAVE - 1 ) * NOTES_PER_OCTAVE;
|
||||
|
||||
if( _ke->isAutoRepeat() == FALSE && key_num > -1 )
|
||||
{
|
||||
if( m_piano != NULL )
|
||||
{
|
||||
m_piano->m_instrumentTrack->processInEvent(
|
||||
midiEvent( NOTE_ON, 0, key_num,
|
||||
DEFAULT_VOLUME ), midiTime() );
|
||||
m_piano->m_pressedKeys[key_num] = TRUE;
|
||||
}
|
||||
update();
|
||||
}
|
||||
else
|
||||
{
|
||||
_ke->ignore();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void pianoView::keyReleaseEvent( QKeyEvent * _ke )
|
||||
{
|
||||
int key_num = piano::getKeyFromKeycode( m_keyCode ) +
|
||||
( DEFAULT_OCTAVE - 1 ) * NOTES_PER_OCTAVE;
|
||||
if( _ke->isAutoRepeat() == FALSE && key_num > -1 )
|
||||
{
|
||||
if( m_piano != NULL )
|
||||
{
|
||||
m_piano->m_instrumentTrack->processInEvent(
|
||||
midiEvent( NOTE_OFF, 0, key_num, 0 ),
|
||||
midiTime() );
|
||||
m_piano->m_pressedKeys[key_num] = FALSE;
|
||||
}
|
||||
update();
|
||||
}
|
||||
else
|
||||
{
|
||||
_ke->ignore();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void pianoView::focusOutEvent( QFocusEvent * )
|
||||
{
|
||||
if( m_piano == NULL )
|
||||
{
|
||||
return;
|
||||
}
|
||||
// if we loose focus, we HAVE to note off all running notes because
|
||||
// we don't receive key-release-events anymore and so the notes would
|
||||
// hang otherwise
|
||||
for( int i = 0; i < NOTES_PER_OCTAVE * OCTAVES; ++i )
|
||||
{
|
||||
if( m_pressedKeys[i] == TRUE )
|
||||
if( m_piano->m_pressedKeys[i] == TRUE )
|
||||
{
|
||||
m_instrumentTrack->processInEvent(
|
||||
m_piano->m_instrumentTrack->processInEvent(
|
||||
midiEvent( NOTE_OFF, 0, i, 0 ),
|
||||
midiTime() );
|
||||
m_pressedKeys[i] = FALSE;
|
||||
m_piano->m_pressedKeys[i] = FALSE;
|
||||
}
|
||||
}
|
||||
update();
|
||||
@@ -482,7 +523,7 @@ void pianoWidget::focusOutEvent( QFocusEvent * )
|
||||
|
||||
|
||||
|
||||
int pianoWidget::getKeyX( int _key_num ) const
|
||||
int pianoView::getKeyX( int _key_num ) const
|
||||
{
|
||||
int k = m_startOctave*NOTES_PER_OCTAVE + m_startTone;
|
||||
if( _key_num < k )
|
||||
@@ -495,7 +536,7 @@ int pianoWidget::getKeyX( int _key_num ) const
|
||||
|
||||
while( k <= _key_num )
|
||||
{
|
||||
if( KEY_ORDER[k % NOTES_PER_OCTAVE] == WHITE_KEY )
|
||||
if( KEY_ORDER[k % NOTES_PER_OCTAVE] == WhiteKey )
|
||||
{
|
||||
++white_cnt;
|
||||
if( white_cnt > 1 )
|
||||
@@ -524,7 +565,7 @@ int pianoWidget::getKeyX( int _key_num ) const
|
||||
|
||||
|
||||
|
||||
void pianoWidget::paintEvent( QPaintEvent * )
|
||||
void pianoView::paintEvent( QPaintEvent * )
|
||||
{
|
||||
QPainter p( this );
|
||||
|
||||
@@ -544,8 +585,9 @@ void pianoWidget::paintEvent( QPaintEvent * )
|
||||
|
||||
p.setPen( QColor ( 0xFF, 0xFF, 0xFF ) );
|
||||
|
||||
int base_key = m_instrumentTrack->baseNoteModel()->value();
|
||||
if( KEY_ORDER[base_key % NOTES_PER_OCTAVE] == WHITE_KEY )
|
||||
const int base_key = ( m_piano != NULL ) ?
|
||||
m_piano->m_instrumentTrack->baseNoteModel()->value() : 0;
|
||||
if( KEY_ORDER[base_key % NOTES_PER_OCTAVE] == WhiteKey )
|
||||
{
|
||||
p.fillRect( QRect( getKeyX( base_key ), 1, PW_WHITE_KEY_WIDTH-1,
|
||||
PIANO_BASE-2 ),
|
||||
@@ -564,14 +606,14 @@ void pianoWidget::paintEvent( QPaintEvent * )
|
||||
// draw all white keys...
|
||||
for( int x = 0; x < width(); )
|
||||
{
|
||||
while( KEY_ORDER[cur_key%NOTES_PER_OCTAVE] != WHITE_KEY )
|
||||
while( KEY_ORDER[cur_key%NOTES_PER_OCTAVE] != WhiteKey )
|
||||
{
|
||||
++cur_key;
|
||||
}
|
||||
|
||||
// draw pressed or not pressed key, depending on state of
|
||||
// current key
|
||||
if( m_pressedKeys[cur_key] == TRUE )
|
||||
if( m_piano && m_piano->m_pressedKeys[cur_key] == TRUE )
|
||||
{
|
||||
p.drawPixmap( x, PIANO_BASE, *s_whiteKeyPressedPm );
|
||||
}
|
||||
@@ -600,9 +642,9 @@ void pianoWidget::paintEvent( QPaintEvent * )
|
||||
|
||||
int s_key = m_startOctave*NOTES_PER_OCTAVE+m_startTone;
|
||||
if( s_key > 0 &&
|
||||
KEY_ORDER[(tones)( --s_key ) % NOTES_PER_OCTAVE] == BLACK_KEY )
|
||||
KEY_ORDER[(tones)( --s_key ) % NOTES_PER_OCTAVE] == BlackKey )
|
||||
{
|
||||
if( m_pressedKeys[s_key] == TRUE )
|
||||
if( m_piano && m_piano->m_pressedKeys[s_key] == TRUE )
|
||||
{
|
||||
p.drawPixmap( 0 - PW_WHITE_KEY_WIDTH / 2, PIANO_BASE,
|
||||
*s_blackKeyPressedPm );
|
||||
@@ -617,11 +659,11 @@ void pianoWidget::paintEvent( QPaintEvent * )
|
||||
// now draw all black keys...
|
||||
for( int x = 0; x < width(); )
|
||||
{
|
||||
if( KEY_ORDER[cur_key%NOTES_PER_OCTAVE] == BLACK_KEY )
|
||||
if( KEY_ORDER[cur_key%NOTES_PER_OCTAVE] == BlackKey )
|
||||
{
|
||||
// draw pressed or not pressed key, depending on
|
||||
// state of current key
|
||||
if( m_pressedKeys[cur_key] == TRUE )
|
||||
if( m_piano && m_piano->m_pressedKeys[cur_key] == TRUE )
|
||||
{
|
||||
p.drawPixmap( x + PW_WHITE_KEY_WIDTH / 2,
|
||||
PIANO_BASE,
|
||||
@@ -653,7 +695,7 @@ void pianoWidget::paintEvent( QPaintEvent * )
|
||||
|
||||
|
||||
#ifdef BUILD_LINUX
|
||||
bool pianoWidget::x11Event( XEvent * _xe )
|
||||
bool pianoView::x11Event( XEvent * _xe )
|
||||
{
|
||||
switch( _xe->type )
|
||||
{
|
||||
|
||||
@@ -53,10 +53,9 @@ public:
|
||||
{
|
||||
setJournalling( FALSE );
|
||||
m_previewInstrumentTrack = dynamic_cast<instrumentTrack *>(
|
||||
track::create( track::INSTRUMENT_TRACK,
|
||||
track::create( track::InstrumentTrack,
|
||||
this ) );
|
||||
m_previewInstrumentTrack->setJournalling( FALSE );
|
||||
hide();
|
||||
}
|
||||
|
||||
virtual ~previewTrackContainer()
|
||||
@@ -134,7 +133,7 @@ presetPreviewPlayHandle::presetPreviewPlayHandle(
|
||||
mmp.content().firstChild().toElement() );
|
||||
// preset also contains information about window-states etc. that's why
|
||||
// here we have to make sure that the instrument-track-window is hidden
|
||||
s_previewTC->previewInstrumentTrack()->hide();
|
||||
// s_previewTC->previewInstrumentTrack()->hide();
|
||||
|
||||
// make sure, our preset-preview-track does not appear in any MIDI-
|
||||
// devices list, so just disable receiving/sending MIDI-events at all
|
||||
|
||||
1019
src/core/song.cpp
Normal file
1019
src/core/song.cpp
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -51,12 +51,12 @@ QPixmap * timeLine::s_loopPointDisabledPixmap = NULL;
|
||||
|
||||
|
||||
timeLine::timeLine( const int _xoff, const int _yoff, const float _ppt,
|
||||
songEditor::playPos & _pos, const midiTime & _begin,
|
||||
song::playPos & _pos, const midiTime & _begin,
|
||||
QWidget * _parent ) :
|
||||
QWidget( _parent ),
|
||||
m_autoScroll( AUTOSCROLL_ENABLED ),
|
||||
m_loopPoints( LOOP_POINTS_DISABLED ),
|
||||
m_behaviourAtStop( BACK_TO_ZERO ),
|
||||
m_autoScroll( AutoScrollEnabled ),
|
||||
m_loopPoints( LoopPointsDisabled ),
|
||||
m_behaviourAtStop( BackToZero ),
|
||||
m_changedPosition( TRUE ),
|
||||
m_xOffset( _xoff ),
|
||||
m_posMarkerX( 0 ),
|
||||
@@ -65,7 +65,7 @@ timeLine::timeLine( const int _xoff, const int _yoff, const float _ppt,
|
||||
m_begin( _begin ),
|
||||
m_savedPos( -1 ),
|
||||
m_hint( NULL ),
|
||||
m_action( NONE ),
|
||||
m_action( NoAction ),
|
||||
m_moveXOff( 0 )
|
||||
{
|
||||
m_loopPos[0] = 0;
|
||||
@@ -175,7 +175,7 @@ void timeLine::loadSettings( const QDomElement & _this )
|
||||
{
|
||||
m_loopPos[0] = _this.attribute( "lp0pos" ).toInt();
|
||||
m_loopPos[1] = _this.attribute( "lp1pos" ).toInt();
|
||||
m_loopPoints = static_cast<loopPointStates>(
|
||||
m_loopPoints = static_cast<LoopPointStates>(
|
||||
_this.attribute( "lpstate" ).toInt() );
|
||||
update();
|
||||
emit loopPointStateLoaded( m_loopPoints );
|
||||
@@ -192,7 +192,7 @@ void timeLine::updatePosition( const midiTime & )
|
||||
{
|
||||
m_posMarkerX = new_x;
|
||||
m_changedPosition = TRUE;
|
||||
if( m_autoScroll == AUTOSCROLL_ENABLED )
|
||||
if( m_autoScroll == AutoScrollEnabled )
|
||||
{
|
||||
emit positionChanged( m_pos );
|
||||
}
|
||||
@@ -205,7 +205,7 @@ void timeLine::updatePosition( const midiTime & )
|
||||
|
||||
void timeLine::toggleAutoScroll( int _n )
|
||||
{
|
||||
m_autoScroll = static_cast<autoScrollStates>( _n );
|
||||
m_autoScroll = static_cast<AutoScrollStates>( _n );
|
||||
}
|
||||
|
||||
|
||||
@@ -213,7 +213,7 @@ void timeLine::toggleAutoScroll( int _n )
|
||||
|
||||
void timeLine::toggleLoopPoints( int _n )
|
||||
{
|
||||
m_loopPoints = static_cast<loopPointStates>( _n );
|
||||
m_loopPoints = static_cast<LoopPointStates>( _n );
|
||||
update();
|
||||
}
|
||||
|
||||
@@ -222,7 +222,7 @@ void timeLine::toggleLoopPoints( int _n )
|
||||
|
||||
void timeLine::toggleBehaviourAtStop( int _n )
|
||||
{
|
||||
m_behaviourAtStop = static_cast<behaviourAtStopStates>( _n );
|
||||
m_behaviourAtStop = static_cast<BehaviourAtStopStates>( _n );
|
||||
}
|
||||
|
||||
|
||||
@@ -280,7 +280,7 @@ void timeLine::mousePressEvent( QMouseEvent * _me )
|
||||
}
|
||||
if( _me->button() == Qt::LeftButton )
|
||||
{
|
||||
m_action = MOVE_POS_MARKER;
|
||||
m_action = MovePositionMarker;
|
||||
if( _me->x() - m_xOffset < s_posMarkerPixmap->width() )
|
||||
{
|
||||
m_moveXOff = _me->x() - m_xOffset;
|
||||
@@ -294,18 +294,18 @@ void timeLine::mousePressEvent( QMouseEvent * _me )
|
||||
{
|
||||
const midiTime t = m_begin +
|
||||
static_cast<Sint32>( _me->x() * 64 / m_ppt );
|
||||
m_action = MOVE_LOOP_BEGIN;
|
||||
m_action = MoveLoopBegin;
|
||||
if( m_loopPos[0] > m_loopPos[1] )
|
||||
{
|
||||
qSwap( m_loopPos[0], m_loopPos[1] );
|
||||
}
|
||||
if( _me->button() == Qt::RightButton )
|
||||
{
|
||||
m_action = MOVE_LOOP_END;
|
||||
m_action = MoveLoopEnd;
|
||||
}
|
||||
m_loopPos[( m_action == MOVE_LOOP_BEGIN ) ? 0 : 1] = t;
|
||||
m_loopPos[( m_action == MoveLoopBegin ) ? 0 : 1] = t;
|
||||
}
|
||||
if( m_action == MOVE_LOOP_BEGIN || m_action == MOVE_LOOP_END )
|
||||
if( m_action == MoveLoopBegin || m_action == MoveLoopEnd )
|
||||
{
|
||||
delete m_hint;
|
||||
m_hint = textFloat::displayMessage( tr( "Hint" ),
|
||||
@@ -325,17 +325,17 @@ void timeLine::mouseMoveEvent( QMouseEvent * _me )
|
||||
m_xOffset - m_moveXOff, 0 ) * 64 / m_ppt );
|
||||
switch( m_action )
|
||||
{
|
||||
case MOVE_POS_MARKER:
|
||||
case MovePositionMarker:
|
||||
m_pos.setTact( t.getTact() );
|
||||
m_pos.setTact64th( t.getTact64th() );
|
||||
m_pos.setCurrentFrame( 0 );
|
||||
updatePosition();
|
||||
break;
|
||||
|
||||
case MOVE_LOOP_BEGIN:
|
||||
case MOVE_LOOP_END:
|
||||
case MoveLoopBegin:
|
||||
case MoveLoopEnd:
|
||||
{
|
||||
const Uint8 i = m_action - MOVE_LOOP_BEGIN;
|
||||
const Uint8 i = m_action - MoveLoopBegin;
|
||||
if( engine::getMainWindow()->isCtrlPressed() == TRUE )
|
||||
{
|
||||
// no ctrl-press-hint when having ctrl pressed
|
||||
@@ -363,7 +363,7 @@ void timeLine::mouseReleaseEvent( QMouseEvent * _me )
|
||||
{
|
||||
delete m_hint;
|
||||
m_hint = NULL;
|
||||
m_action = NONE;
|
||||
m_action = NoAction;
|
||||
}
|
||||
|
||||
|
||||
|
||||
1570
src/core/track.cpp
1570
src/core/track.cpp
File diff suppressed because it is too large
Load Diff
@@ -4,7 +4,7 @@
|
||||
* track_container.cpp - implementation of base-class for all track-containers
|
||||
* like Song-Editor, BB-Editor...
|
||||
*
|
||||
* Copyright (c) 2004-2007 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2004-2008 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
@@ -50,35 +50,16 @@
|
||||
#include "mmp.h"
|
||||
#include "project_journal.h"
|
||||
#include "rubberband.h"
|
||||
#include "song_editor.h"
|
||||
#include "song.h"
|
||||
#include "string_pair_drag.h"
|
||||
#include "track.h"
|
||||
|
||||
|
||||
trackContainer::trackContainer( void ) :
|
||||
m_currentPosition( 0, 0 ),
|
||||
m_scrollArea( new scrollArea( this ) ),
|
||||
m_ppt( DEFAULT_PIXELS_PER_TACT ),
|
||||
m_rubberBand( new rubberBand( m_scrollArea ) ),
|
||||
m_origin()
|
||||
model( NULL ),
|
||||
journallingObject(),
|
||||
m_tracks()
|
||||
{
|
||||
QVBoxLayout * layout = new QVBoxLayout( this );
|
||||
layout->setMargin( 0 );
|
||||
layout->setSpacing( 0 );
|
||||
layout->addWidget( m_scrollArea );
|
||||
|
||||
QWidget * scrollContent = new QWidget;
|
||||
m_scrollLayout = new QVBoxLayout( scrollContent );
|
||||
m_scrollLayout->setMargin( 0 );
|
||||
m_scrollLayout->setSpacing( 0 );
|
||||
m_scrollLayout->setSizeConstraint( QLayout::SetMinimumSize );
|
||||
|
||||
m_scrollArea->setWidget( scrollContent );
|
||||
|
||||
m_scrollArea->show();
|
||||
m_rubberBand->hide();
|
||||
|
||||
setAcceptDrops( TRUE );
|
||||
}
|
||||
|
||||
|
||||
@@ -99,7 +80,8 @@ void trackContainer::saveSettings( QDomDocument & _doc, QDomElement & _this )
|
||||
{
|
||||
_this.setTagName( classNodeName() );
|
||||
_this.setAttribute( "type", nodeName() );
|
||||
mainWindow::saveWidgetState( this, _this );
|
||||
// ### TODO
|
||||
//mainWindow::saveWidgetState( this, _this );
|
||||
|
||||
// save settings of each track
|
||||
for( int i = 0; i < m_tracks.size(); ++i )
|
||||
@@ -150,9 +132,9 @@ void trackContainer::loadSettings( const QDomElement & _this )
|
||||
node = node.nextSibling();
|
||||
}
|
||||
|
||||
mainWindow::restoreWidgetState( this, _this );
|
||||
// ### TODO
|
||||
// mainWindow::restoreWidgetState( this, _this );
|
||||
|
||||
realignTracks();
|
||||
|
||||
pd->setValue( start_val + _this.childNodes().count() );
|
||||
|
||||
@@ -168,16 +150,11 @@ void trackContainer::loadSettings( const QDomElement & _this )
|
||||
|
||||
void trackContainer::addTrack( track * _track )
|
||||
{
|
||||
QMap<QString, QVariant> map;
|
||||
map["id"] = _track->id();
|
||||
addJournalEntry( journalEntry( ADD_TRACK, map ) );
|
||||
|
||||
m_tracks.push_back( _track );
|
||||
m_scrollLayout->addWidget( _track->getTrackWidget() );
|
||||
connect( this, SIGNAL( positionChanged( const midiTime & ) ),
|
||||
_track->getTrackWidget(),
|
||||
SLOT( changePosition( const midiTime & ) ) );
|
||||
realignTracks();
|
||||
if( _track->type() != track::AutomationTrack )
|
||||
{
|
||||
m_tracks.push_back( _track );
|
||||
emit trackAdded( _track );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -188,24 +165,11 @@ void trackContainer::removeTrack( track * _track )
|
||||
int index = m_tracks.indexOf( _track );
|
||||
if( index != -1 )
|
||||
{
|
||||
QMap<QString, QVariant> map;
|
||||
multimediaProject mmp( multimediaProject::JOURNAL_DATA );
|
||||
_track->saveState( mmp, mmp.content() );
|
||||
map["id"] = _track->id();
|
||||
map["state"] = mmp.toString();
|
||||
addJournalEntry( journalEntry( REMOVE_TRACK, map ) );
|
||||
|
||||
m_tracks.removeAt( index );
|
||||
|
||||
disconnect( _track->getTrackWidget() );
|
||||
m_scrollLayout->removeWidget( _track->getTrackWidget() );
|
||||
|
||||
delete _track;
|
||||
|
||||
realignTracks();
|
||||
if( engine::getSongEditor() )
|
||||
if( engine::getSong() )
|
||||
{
|
||||
engine::getSongEditor()->setModified();
|
||||
engine::getSong()->setModified();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -213,45 +177,6 @@ void trackContainer::removeTrack( track * _track )
|
||||
|
||||
|
||||
|
||||
void trackContainer::moveTrackUp( track * _track )
|
||||
{
|
||||
for( int i = 1; i < m_tracks.size(); ++i )
|
||||
{
|
||||
if( m_tracks[i] == _track )
|
||||
{
|
||||
bbTrack::swapBBTracks( m_tracks[i], m_tracks[i - 1] );
|
||||
QWidget * tw = m_tracks[i]->getTrackWidget();
|
||||
m_scrollLayout->removeWidget( tw );
|
||||
m_scrollLayout->insertWidget( i - 1, tw );
|
||||
m_tracks.swap( i - 1, i );
|
||||
realignTracks();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void trackContainer::moveTrackDown( track * _track )
|
||||
{
|
||||
for( int i = 0; i < m_tracks.size() - 1; ++i )
|
||||
{
|
||||
if( m_tracks[i] == _track )
|
||||
{
|
||||
bbTrack::swapBBTracks( m_tracks[i], m_tracks[i + 1] );
|
||||
QWidget * tw = m_tracks[i]->getTrackWidget();
|
||||
m_scrollLayout->removeWidget( tw );
|
||||
m_scrollLayout->insertWidget( i + 1, tw );
|
||||
m_tracks.swap( i, i + 1 );
|
||||
realignTracks();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void trackContainer::updateAfterTrackAdd( void )
|
||||
{
|
||||
@@ -260,69 +185,24 @@ void trackContainer::updateAfterTrackAdd( void )
|
||||
|
||||
|
||||
|
||||
void trackContainer::realignTracks( void )
|
||||
{
|
||||
QWidget * content = m_scrollArea->widget();
|
||||
content->setFixedWidth( width()
|
||||
- m_scrollArea->verticalScrollBar()->width() );
|
||||
content->setFixedHeight( content->minimumSizeHint().height() );
|
||||
|
||||
for( int i = 0; i < m_tracks.size(); ++i )
|
||||
{
|
||||
trackWidget * tw = m_tracks[i]->getTrackWidget();
|
||||
tw->show();
|
||||
tw->update();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void trackContainer::clearAllTracks( void )
|
||||
{
|
||||
while( !m_tracks.empty() )
|
||||
{
|
||||
removeTrack( m_tracks.last() );
|
||||
delete m_tracks.takeLast();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
const trackWidget * trackContainer::trackWidgetAt( const int _y ) const
|
||||
int trackContainer::countTracks( track::TrackTypes _tt ) const
|
||||
{
|
||||
const int abs_y = _y + m_scrollArea->viewport()->y();
|
||||
int y_cnt = 0;
|
||||
int cnt = 0;
|
||||
for( int i = 0; i < m_tracks.size(); ++i )
|
||||
{
|
||||
const int y_cnt1 = y_cnt;
|
||||
y_cnt += m_tracks[i]->getTrackWidget()->height();
|
||||
if( abs_y >= y_cnt1 && abs_y < y_cnt )
|
||||
{
|
||||
return( m_tracks[i]->getTrackWidget() );
|
||||
}
|
||||
}
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool trackContainer::allowRubberband( void ) const
|
||||
{
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Uint16 trackContainer::countTracks( track::trackTypes _tt ) const
|
||||
{
|
||||
Uint16 cnt = 0;
|
||||
for( int i = 0; i < m_tracks.size(); ++i )
|
||||
{
|
||||
if( m_tracks[i]->type() == _tt ||
|
||||
_tt == track::TOTAL_TRACK_TYPES )
|
||||
if( m_tracks[i]->type() == _tt || _tt == track::NumTrackTypes )
|
||||
{
|
||||
++cnt;
|
||||
}
|
||||
@@ -344,23 +224,208 @@ void trackContainer::setMutedOfAllTracks( bool _muted )
|
||||
|
||||
|
||||
|
||||
const QList<track *> trackContainer::tracks( void ) const
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
trackContainerView::trackContainerView( trackContainer * _tc ) :
|
||||
QWidget(),
|
||||
modelView( NULL ),
|
||||
m_currentPosition( 0, 0 ),
|
||||
m_tc( _tc ),
|
||||
m_trackViews(),
|
||||
m_scrollArea( new scrollArea( this ) ),
|
||||
m_ppt( DEFAULT_PIXELS_PER_TACT ),
|
||||
m_rubberBand( new rubberBand( m_scrollArea ) ),
|
||||
m_origin()
|
||||
{
|
||||
return( m_tracks );
|
||||
QVBoxLayout * layout = new QVBoxLayout( this );
|
||||
layout->setMargin( 0 );
|
||||
layout->setSpacing( 0 );
|
||||
layout->addWidget( m_scrollArea );
|
||||
|
||||
QWidget * scrollContent = new QWidget;
|
||||
m_scrollLayout = new QVBoxLayout( scrollContent );
|
||||
m_scrollLayout->setMargin( 0 );
|
||||
m_scrollLayout->setSpacing( 0 );
|
||||
m_scrollLayout->setSizeConstraint( QLayout::SetMinimumSize );
|
||||
|
||||
m_scrollArea->setWidget( scrollContent );
|
||||
|
||||
m_scrollArea->show();
|
||||
m_rubberBand->hide();
|
||||
|
||||
setAcceptDrops( TRUE );
|
||||
|
||||
connect( m_tc, SIGNAL( trackAdded( track * ) ),
|
||||
this, SLOT( createTrackView( track * ) ),
|
||||
Qt::QueuedConnection );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
QList<track *> trackContainer::tracks( void )
|
||||
trackContainerView::~trackContainerView()
|
||||
{
|
||||
return( m_tracks );
|
||||
while( !m_trackViews.empty() )
|
||||
{
|
||||
delete m_trackViews.takeLast();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void trackContainer::setPixelsPerTact( Uint16 _ppt )
|
||||
|
||||
trackView * trackContainerView::addTrackView( trackView * _tv )
|
||||
{
|
||||
QMap<QString, QVariant> map;
|
||||
map["id"] = _tv->getTrack()->id();
|
||||
addJournalEntry( journalEntry( AddTrack, map ) );
|
||||
|
||||
m_trackViews.push_back( _tv );
|
||||
m_scrollLayout->addWidget( _tv );
|
||||
connect( this, SIGNAL( positionChanged( const midiTime & ) ),
|
||||
_tv->getTrackContentWidget(),
|
||||
SLOT( changePosition( const midiTime & ) ) );
|
||||
realignTracks();
|
||||
return( _tv );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void trackContainerView::removeTrackView( trackView * _tv )
|
||||
{
|
||||
int index = m_trackViews.indexOf( _tv );
|
||||
if( index != -1 )
|
||||
{
|
||||
QMap<QString, QVariant> map;
|
||||
multimediaProject mmp( multimediaProject::JournalData );
|
||||
_tv->getTrack()->saveState( mmp, mmp.content() );
|
||||
map["id"] = _tv->getTrack()->id();
|
||||
map["state"] = mmp.toString();
|
||||
addJournalEntry( journalEntry( RemoveTrack, map ) );
|
||||
|
||||
m_trackViews.removeAt( index );
|
||||
|
||||
disconnect( _tv );
|
||||
m_scrollLayout->removeWidget( _tv );
|
||||
|
||||
realignTracks();
|
||||
if( engine::getSong() )
|
||||
{
|
||||
engine::getSong()->setModified();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void trackContainerView::moveTrackViewUp( trackView * _tv )
|
||||
{
|
||||
for( int i = 1; i < m_trackViews.size(); ++i )
|
||||
{
|
||||
trackView * t = m_trackViews[i];
|
||||
if( t == _tv )
|
||||
{
|
||||
bbTrack::swapBBTracks( t->getTrack(),
|
||||
m_trackViews[i - 1]->getTrack() );
|
||||
m_scrollLayout->removeWidget( t );
|
||||
m_scrollLayout->insertWidget( i - 1, t );
|
||||
m_tc->m_tracks.swap( i - 1, i );
|
||||
m_trackViews.swap( i - 1, i );
|
||||
realignTracks();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void trackContainerView::moveTrackViewDown( trackView * _tv )
|
||||
{
|
||||
for( int i = 0; i < m_trackViews.size()-1; ++i )
|
||||
{
|
||||
trackView * t = m_trackViews[i];
|
||||
if( t == _tv )
|
||||
{
|
||||
bbTrack::swapBBTracks( t->getTrack(),
|
||||
m_trackViews[i + 1]->getTrack() );
|
||||
m_scrollLayout->removeWidget( t );
|
||||
m_scrollLayout->insertWidget( i + 1, t );
|
||||
m_tc->m_tracks.swap( i, i + 1 );
|
||||
m_trackViews.swap( i, i + 1 );
|
||||
realignTracks();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void trackContainerView::realignTracks( void )
|
||||
{
|
||||
QWidget * content = m_scrollArea->widget();
|
||||
content->setFixedWidth( width()
|
||||
- m_scrollArea->verticalScrollBar()->width() );
|
||||
content->setFixedHeight( content->minimumSizeHint().height() );
|
||||
|
||||
for( trackViewList::iterator it = m_trackViews.begin();
|
||||
it != m_trackViews.end(); ++it )
|
||||
{
|
||||
( *it )->show();
|
||||
( *it )->update();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void trackContainerView::createTrackView( track * _t )
|
||||
{
|
||||
_t->createView( this );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
const trackView * trackContainerView::trackViewAt( const int _y ) const
|
||||
{
|
||||
const int abs_y = _y + m_scrollArea->viewport()->y();
|
||||
int y_cnt = 0;
|
||||
for( trackViewList::const_iterator it = m_trackViews.begin();
|
||||
it != m_trackViews.end(); ++it )
|
||||
{
|
||||
const int y_cnt1 = y_cnt;
|
||||
y_cnt += ( *it )->height();
|
||||
if( abs_y >= y_cnt1 && abs_y < y_cnt )
|
||||
{
|
||||
return( *it );
|
||||
}
|
||||
}
|
||||
return( NULL );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool trackContainerView::allowRubberband( void ) const
|
||||
{
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void trackContainerView::setPixelsPerTact( int _ppt )
|
||||
{
|
||||
m_ppt = _ppt;
|
||||
}
|
||||
@@ -368,34 +433,47 @@ void trackContainer::setPixelsPerTact( Uint16 _ppt )
|
||||
|
||||
|
||||
|
||||
void trackContainer::undoStep( journalEntry & _je )
|
||||
void trackContainerView::clearAllTracks( void )
|
||||
{
|
||||
while( !m_trackViews.empty() )
|
||||
{
|
||||
trackView * tv = m_trackViews.takeLast();
|
||||
track * t = tv->getTrack();
|
||||
delete tv;
|
||||
delete t;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void trackContainerView::undoStep( journalEntry & _je )
|
||||
{
|
||||
saveJournallingState( FALSE );
|
||||
switch( _je.actionID() )
|
||||
{
|
||||
case ADD_TRACK:
|
||||
case AddTrack:
|
||||
{
|
||||
QMap<QString, QVariant> map = _je.data().toMap();
|
||||
track * tr =
|
||||
track * t =
|
||||
dynamic_cast<track *>(
|
||||
engine::getProjectJournal()->getJournallingObject(
|
||||
map["id"].toInt() ) );
|
||||
assert( tr != NULL );
|
||||
multimediaProject mmp(
|
||||
multimediaProject::JOURNAL_DATA );
|
||||
tr->saveState( mmp, mmp.content() );
|
||||
assert( t != NULL );
|
||||
multimediaProject mmp( multimediaProject::JournalData );
|
||||
t->saveState( mmp, mmp.content() );
|
||||
map["state"] = mmp.toString();
|
||||
_je.data() = map;
|
||||
removeTrack( tr );
|
||||
t->deleteLater();
|
||||
break;
|
||||
}
|
||||
|
||||
case REMOVE_TRACK:
|
||||
case RemoveTrack:
|
||||
{
|
||||
multimediaProject mmp(
|
||||
_je.data().toMap()["state"].toString(), FALSE );
|
||||
track::create( mmp.content().firstChild().toElement(),
|
||||
this );
|
||||
m_tc );
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -405,17 +483,17 @@ void trackContainer::undoStep( journalEntry & _je )
|
||||
|
||||
|
||||
|
||||
void trackContainer::redoStep( journalEntry & _je )
|
||||
void trackContainerView::redoStep( journalEntry & _je )
|
||||
{
|
||||
switch( _je.actionID() )
|
||||
{
|
||||
case ADD_TRACK:
|
||||
case REMOVE_TRACK:
|
||||
_je.actionID() = ( _je.actionID() == ADD_TRACK ) ?
|
||||
REMOVE_TRACK : ADD_TRACK;
|
||||
case AddTrack:
|
||||
case RemoveTrack:
|
||||
_je.actionID() = ( _je.actionID() == AddTrack ) ?
|
||||
RemoveTrack : AddTrack;
|
||||
undoStep( _je );
|
||||
_je.actionID() = ( _je.actionID() == ADD_TRACK ) ?
|
||||
REMOVE_TRACK : ADD_TRACK;
|
||||
_je.actionID() = ( _je.actionID() == AddTrack ) ?
|
||||
RemoveTrack : AddTrack;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -423,19 +501,19 @@ void trackContainer::redoStep( journalEntry & _je )
|
||||
|
||||
|
||||
|
||||
void trackContainer::dragEnterEvent( QDragEnterEvent * _dee )
|
||||
void trackContainerView::dragEnterEvent( QDragEnterEvent * _dee )
|
||||
{
|
||||
stringPairDrag::processDragEnterEvent( _dee,
|
||||
QString( "presetfile,sampledata,samplefile,instrument,midifile,"
|
||||
"track_%1,track_%2" ).
|
||||
arg( track::INSTRUMENT_TRACK ).
|
||||
arg( track::SAMPLE_TRACK ) );
|
||||
arg( track::InstrumentTrack ).
|
||||
arg( track::SampleTrack ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void trackContainer::dropEvent( QDropEvent * _de )
|
||||
void trackContainerView::dropEvent( QDropEvent * _de )
|
||||
{
|
||||
QString type = stringPairDrag::decodeKey( _de );
|
||||
QString value = stringPairDrag::decodeValue( _de );
|
||||
@@ -443,45 +521,45 @@ void trackContainer::dropEvent( QDropEvent * _de )
|
||||
if( type == "instrument" )
|
||||
{
|
||||
instrumentTrack * it = dynamic_cast<instrumentTrack *>(
|
||||
track::create( track::INSTRUMENT_TRACK,
|
||||
this ) );
|
||||
track::create( track::InstrumentTrack,
|
||||
m_tc ) );
|
||||
it->loadInstrument( value );
|
||||
it->toggledInstrumentTrackButton( TRUE );
|
||||
//it->toggledInstrumentTrackButton( TRUE );
|
||||
_de->accept();
|
||||
}
|
||||
else if( type == "sampledata" || type == "samplefile" )
|
||||
{
|
||||
instrumentTrack * it = dynamic_cast<instrumentTrack *>(
|
||||
track::create( track::INSTRUMENT_TRACK,
|
||||
this ) );
|
||||
track::create( track::InstrumentTrack,
|
||||
m_tc ) );
|
||||
QString iname = type == "sampledata" ? "audiofileprocessor" :
|
||||
engine::sampleExtensions()[fileItem::extension(
|
||||
value )];
|
||||
instrument * i = it->loadInstrument( iname );
|
||||
i->setParameter( type, value );
|
||||
it->toggledInstrumentTrackButton( TRUE );
|
||||
//it->toggledInstrumentTrackButton( TRUE );
|
||||
_de->accept();
|
||||
}
|
||||
else if( type == "presetfile" )
|
||||
{
|
||||
multimediaProject mmp( value );
|
||||
instrumentTrack * it = dynamic_cast<instrumentTrack *>(
|
||||
track::create( track::INSTRUMENT_TRACK,
|
||||
this ) );
|
||||
track::create( track::InstrumentTrack,
|
||||
m_tc ) );
|
||||
it->loadTrackSpecificSettings( mmp.content().firstChild().
|
||||
toElement() );
|
||||
it->toggledInstrumentTrackButton( TRUE );
|
||||
//it->toggledInstrumentTrackButton( TRUE );
|
||||
_de->accept();
|
||||
}
|
||||
else if( type == "midifile" )
|
||||
{
|
||||
importFilter::import( value, this );
|
||||
importFilter::import( value, m_tc );
|
||||
_de->accept();
|
||||
}
|
||||
else if( type.left( 6 ) == "track_" )
|
||||
{
|
||||
multimediaProject mmp( value, FALSE );
|
||||
track::create( mmp.content().firstChild().toElement(), this );
|
||||
track::create( mmp.content().firstChild().toElement(), m_tc );
|
||||
_de->accept();
|
||||
}
|
||||
engine::getMixer()->unlock();
|
||||
@@ -490,7 +568,7 @@ void trackContainer::dropEvent( QDropEvent * _de )
|
||||
|
||||
|
||||
|
||||
void trackContainer::mousePressEvent( QMouseEvent * _me )
|
||||
void trackContainerView::mousePressEvent( QMouseEvent * _me )
|
||||
{
|
||||
if( allowRubberband() == TRUE )
|
||||
{
|
||||
@@ -498,12 +576,13 @@ void trackContainer::mousePressEvent( QMouseEvent * _me )
|
||||
m_rubberBand->setGeometry( QRect( m_origin, QSize() ) );
|
||||
m_rubberBand->show();
|
||||
}
|
||||
QWidget::mousePressEvent( _me );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void trackContainer::mouseMoveEvent( QMouseEvent * _me )
|
||||
void trackContainerView::mouseMoveEvent( QMouseEvent * _me )
|
||||
{
|
||||
if( rubberBandActive() == TRUE )
|
||||
{
|
||||
@@ -511,31 +590,34 @@ void trackContainer::mouseMoveEvent( QMouseEvent * _me )
|
||||
m_scrollArea->mapFromParent( _me->pos() ) ).
|
||||
normalized() );
|
||||
}
|
||||
QWidget::mouseMoveEvent( _me );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void trackContainer::mouseReleaseEvent( QMouseEvent * _me )
|
||||
void trackContainerView::mouseReleaseEvent( QMouseEvent * _me )
|
||||
{
|
||||
m_rubberBand->hide();
|
||||
QWidget::mouseReleaseEvent( _me );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void trackContainer::resizeEvent( QResizeEvent * )
|
||||
void trackContainerView::resizeEvent( QResizeEvent * _re )
|
||||
{
|
||||
realignTracks();
|
||||
QWidget::resizeEvent( _re );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
trackContainer::scrollArea::scrollArea( trackContainer * _parent ) :
|
||||
trackContainerView::scrollArea::scrollArea( trackContainerView * _parent ) :
|
||||
QScrollArea( _parent ),
|
||||
m_trackContainer( _parent )
|
||||
m_trackContainerView( _parent )
|
||||
{
|
||||
setFrameStyle( QFrame::NoFrame );
|
||||
setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
|
||||
@@ -545,20 +627,20 @@ trackContainer::scrollArea::scrollArea( trackContainer * _parent ) :
|
||||
|
||||
|
||||
|
||||
trackContainer::scrollArea::~scrollArea()
|
||||
trackContainerView::scrollArea::~scrollArea()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void trackContainer::scrollArea::wheelEvent( QWheelEvent * _we )
|
||||
void trackContainerView::scrollArea::wheelEvent( QWheelEvent * _we )
|
||||
{
|
||||
// always pass wheel-event to parent-widget (song-editor
|
||||
// bb-editor etc.) because they might want to use it for zooming
|
||||
// or scrolling left/right if a modifier-key is pressed, otherwise
|
||||
// they do not accept it and we pass it up to QScrollArea
|
||||
m_trackContainer->wheelEvent( _we );
|
||||
m_trackContainerView->wheelEvent( _we );
|
||||
if( !_we->isAccepted() )
|
||||
{
|
||||
QScrollArea::wheelEvent( _we );
|
||||
@@ -568,6 +650,7 @@ void trackContainer::scrollArea::wheelEvent( QWheelEvent * _we )
|
||||
|
||||
|
||||
|
||||
|
||||
#include "track_container.moc"
|
||||
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
* journalling_object.cpp - implementation of journalling-object related stuff
|
||||
*
|
||||
* Copyright (c) 2006-2007 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2006-2008 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
@@ -38,7 +38,9 @@ journallingObject::journallingObject( void ) :
|
||||
m_id( engine::getProjectJournal()->allocID( this ) ),
|
||||
m_journalEntries(),
|
||||
m_currentJournalEntry( m_journalEntries.end() ),
|
||||
m_journalling( TRUE )
|
||||
m_journalling( TRUE ),
|
||||
m_journallingStateStack(),
|
||||
m_hook( NULL )
|
||||
{
|
||||
}
|
||||
|
||||
@@ -47,6 +49,10 @@ journallingObject::journallingObject( void ) :
|
||||
|
||||
journallingObject::~journallingObject()
|
||||
{
|
||||
if( m_hook )
|
||||
{
|
||||
m_hook->m_hookedIn = NULL;
|
||||
}
|
||||
if( engine::getProjectJournal() )
|
||||
{
|
||||
engine::getProjectJournal()->freeID( id() );
|
||||
@@ -125,6 +131,15 @@ void journallingObject::restoreState( const QDomElement & _this )
|
||||
|
||||
|
||||
|
||||
void journallingObject::setHook( journallingObjectHook * _hook )
|
||||
{
|
||||
m_hook = _hook;
|
||||
m_hook->m_hookedIn = this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void journallingObject::addJournalEntry( const journalEntry & _je )
|
||||
{
|
||||
if( engine::getProjectJournal()->isJournalling() && isJournalling() )
|
||||
|
||||
@@ -40,26 +40,26 @@
|
||||
|
||||
|
||||
multimediaProject::typeDescStruct
|
||||
multimediaProject::s_types[multimediaProject::PROJ_TYPE_COUNT] =
|
||||
multimediaProject::s_types[multimediaProject::NumProjectTypes] =
|
||||
{
|
||||
{ multimediaProject::UNKNOWN, "unknown" },
|
||||
{ multimediaProject::SONG_PROJECT, "song" },
|
||||
{ multimediaProject::SONG_PROJECT_TEMPLATE, "songtemplate" },
|
||||
{ multimediaProject::UnknownType, "unknown" },
|
||||
{ multimediaProject::SongProject, "song" },
|
||||
{ multimediaProject::SongProjectTemplate, "songtemplate" },
|
||||
#warning compat-code, use upgrade feature
|
||||
{ multimediaProject::INSTRUMENT_TRACK_SETTINGS,
|
||||
{ multimediaProject::InstrumentTrackSettings,
|
||||
"instrumenttracksettings,channelsettings" },
|
||||
{ multimediaProject::DRAG_N_DROP_DATA, "dnddata" },
|
||||
{ multimediaProject::CLIPBOARD_DATA, "clipboard-data" },
|
||||
{ multimediaProject::JOURNAL_DATA, "journaldata" },
|
||||
{ multimediaProject::EFFECT_SETTINGS, "effectsettings" },
|
||||
{ multimediaProject::VIDEO_PROJECT, "videoproject" },
|
||||
{ multimediaProject::BURN_PROJECT, "burnproject" },
|
||||
{ multimediaProject::PLAYLIST, "playlist" }
|
||||
{ multimediaProject::DragNDropData, "dnddata" },
|
||||
{ multimediaProject::ClipboardData, "clipboard-data" },
|
||||
{ multimediaProject::JournalData, "journaldata" },
|
||||
{ multimediaProject::EffectSettings, "effectsettings" },
|
||||
{ multimediaProject::VideoProject, "videoproject" },
|
||||
{ multimediaProject::BurnProject, "burnproject" },
|
||||
{ multimediaProject::Playlist, "playlist" }
|
||||
} ;
|
||||
|
||||
|
||||
|
||||
multimediaProject::multimediaProject( projectTypes _project_type ) :
|
||||
multimediaProject::multimediaProject( ProjectTypes _project_type ) :
|
||||
QDomDocument( "multimedia-project" ),
|
||||
m_content(),
|
||||
m_head(),
|
||||
@@ -193,7 +193,7 @@ QString multimediaProject::nameWithExtension( const QString & _fn ) const
|
||||
{
|
||||
switch( type() )
|
||||
{
|
||||
case SONG_PROJECT:
|
||||
case SongProject:
|
||||
if( _fn.section( '.', -1 ) != "mmp" &&
|
||||
_fn.section( '.', -1 ) != "mpt" &&
|
||||
_fn.section( '.', -1 ) != "mmpz" )
|
||||
@@ -206,13 +206,13 @@ QString multimediaProject::nameWithExtension( const QString & _fn ) const
|
||||
return( _fn + ".mmp" );
|
||||
}
|
||||
break;
|
||||
case SONG_PROJECT_TEMPLATE:
|
||||
case SongProjectTemplate:
|
||||
if( _fn.section( '.',-1 ) != "mpt" )
|
||||
{
|
||||
return( _fn + ".mpt" );
|
||||
}
|
||||
break;
|
||||
case INSTRUMENT_TRACK_SETTINGS:
|
||||
case InstrumentTrackSettings:
|
||||
if( _fn.section( '.', -2, -1 ) != "cs.xml" )
|
||||
{
|
||||
return( _fn + ".cs.xml" );
|
||||
@@ -228,8 +228,8 @@ QString multimediaProject::nameWithExtension( const QString & _fn ) const
|
||||
|
||||
bool multimediaProject::writeFile( QString & _fn, bool _overwrite_check )
|
||||
{
|
||||
if( type() == SONG_PROJECT || type() == SONG_PROJECT_TEMPLATE
|
||||
|| type() == INSTRUMENT_TRACK_SETTINGS )
|
||||
if( type() == SongProject || type() == SongProjectTemplate
|
||||
|| type() == InstrumentTrackSettings )
|
||||
{
|
||||
cleanMetaNodes( documentElement() );
|
||||
}
|
||||
@@ -284,7 +284,7 @@ bool multimediaProject::writeFile( QString & _fn, bool _overwrite_check )
|
||||
|
||||
|
||||
|
||||
multimediaProject::projectTypes multimediaProject::typeOfFile(
|
||||
multimediaProject::ProjectTypes multimediaProject::typeOfFile(
|
||||
const QString & _fn )
|
||||
{
|
||||
multimediaProject m( _fn, TRUE, FALSE );
|
||||
@@ -294,10 +294,10 @@ multimediaProject::projectTypes multimediaProject::typeOfFile(
|
||||
|
||||
|
||||
|
||||
multimediaProject::projectTypes multimediaProject::type(
|
||||
multimediaProject::ProjectTypes multimediaProject::type(
|
||||
const QString & _type_name )
|
||||
{
|
||||
for( int i = 0; i < PROJ_TYPE_COUNT; ++i )
|
||||
for( int i = 0; i < NumProjectTypes; ++i )
|
||||
{
|
||||
if( s_types[i].m_name == _type_name || (
|
||||
s_types[i].m_name.contains( "," ) && (
|
||||
@@ -306,26 +306,26 @@ multimediaProject::projectTypes multimediaProject::type(
|
||||
)
|
||||
|
||||
{
|
||||
return( static_cast<multimediaProject::projectTypes>(
|
||||
return( static_cast<multimediaProject::ProjectTypes>(
|
||||
i ) );
|
||||
}
|
||||
}
|
||||
return( UNKNOWN );
|
||||
return( UnknownType );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
QString multimediaProject::typeName( projectTypes _project_type )
|
||||
QString multimediaProject::typeName( ProjectTypes _project_type )
|
||||
{
|
||||
if( _project_type >= UNKNOWN && _project_type < PROJ_TYPE_COUNT )
|
||||
if( _project_type >= UnknownType && _project_type < NumProjectTypes )
|
||||
{
|
||||
return( s_types[_project_type].m_name
|
||||
#warning compat-code, use upgrade feature
|
||||
.section( ',', 0, 0 )
|
||||
);
|
||||
}
|
||||
return( s_types[UNKNOWN].m_name );
|
||||
return( s_types[UnknownType].m_name );
|
||||
}
|
||||
|
||||
|
||||
@@ -606,6 +606,20 @@ void multimediaProject::upgrade( void )
|
||||
}
|
||||
}
|
||||
|
||||
if( version < "0.4.0-svn20080129" )
|
||||
{
|
||||
QDomNodeList list;
|
||||
while( !( list =
|
||||
elementsByTagName( "arpandchords" ) ).isEmpty() )
|
||||
{
|
||||
QDomElement aac = list.item( 0 ).toElement();
|
||||
aac.setTagName( "arpeggiator" );
|
||||
QDomNode cloned = aac.cloneNode();
|
||||
cloned.toElement().setTagName( "chordcreator" );
|
||||
aac.parentNode().appendChild( cloned );
|
||||
}
|
||||
}
|
||||
|
||||
if( !m_head.hasAttribute( "mastervol" ) )
|
||||
{
|
||||
m_head.setAttribute( "mastervol", 100 );
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
#include "project_journal.h"
|
||||
#include "engine.h"
|
||||
#include "journalling_object.h"
|
||||
#include "song_editor.h"
|
||||
#include "song.h"
|
||||
#include "automatable_model_templates.h"
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ void projectJournal::undo( void )
|
||||
( jo = m_joIDs[*--m_currentJournalEntry] ) != NULL )
|
||||
{
|
||||
jo->undo();
|
||||
engine::getSongEditor()->setModified();
|
||||
engine::getSong()->setModified();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ void projectJournal::redo( void )
|
||||
( jo = m_joIDs[*m_currentJournalEntry++] ) != NULL )
|
||||
{
|
||||
jo->redo();
|
||||
engine::getSongEditor()->setModified();
|
||||
engine::getSong()->setModified();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ void projectJournal::journalEntryAdded( const jo_id_t _id )
|
||||
m_journalEntries.erase( m_currentJournalEntry, m_journalEntries.end() );
|
||||
m_journalEntries.push_back( _id );
|
||||
m_currentJournalEntry = m_journalEntries.end();
|
||||
engine::getSongEditor()->setModified();
|
||||
engine::getSong()->setModified();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
#include "config_mgr.h"
|
||||
#include "engine.h"
|
||||
#include "gui_templates.h"
|
||||
#include "song_editor.h"
|
||||
#include "song.h"
|
||||
#include "midi_port.h"
|
||||
#include "note.h"
|
||||
#include "automatable_model_templates.h"
|
||||
@@ -63,14 +63,14 @@ midiALSASeq::midiALSASeq( void ) :
|
||||
snd_seq_queue_tempo_t * tempo;
|
||||
snd_seq_queue_tempo_malloc( &tempo );
|
||||
snd_seq_queue_tempo_set_tempo( tempo, 6000000 /
|
||||
engine::getSongEditor()->getTempo() );
|
||||
engine::getSong()->getTempo() );
|
||||
snd_seq_queue_tempo_set_ppq( tempo, 16 );
|
||||
snd_seq_set_queue_tempo( m_seqHandle, m_queueID, tempo );
|
||||
snd_seq_queue_tempo_free( tempo );
|
||||
|
||||
snd_seq_start_queue( m_seqHandle, m_queueID, NULL );
|
||||
changeQueueTempo( engine::getSongEditor()->getTempo() );
|
||||
connect( engine::getSongEditor(), SIGNAL( tempoChanged( bpm_t ) ),
|
||||
changeQueueTempo( engine::getSong()->getTempo() );
|
||||
connect( engine::getSong(), SIGNAL( tempoChanged( bpm_t ) ),
|
||||
this, SLOT( changeQueueTempo( bpm_t ) ) );
|
||||
|
||||
// initial list-update
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* automation_track.cpp - automationTrack handles automation of objects without
|
||||
* a track
|
||||
*
|
||||
* Copyright (c) 2006 Javier Serrano Polo <jasp00/at/users.sourceforge.net>
|
||||
* Copyright (c) 2006-2008 Javier Serrano Polo <jasp00/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
@@ -27,12 +27,13 @@
|
||||
|
||||
|
||||
#include "automation_track.h"
|
||||
#include "automatable_model_templates.h"
|
||||
|
||||
|
||||
|
||||
|
||||
automationTrack::automationTrack( trackContainer * _tc ) :
|
||||
track( _tc, FALSE )
|
||||
track( AutomationTrack, _tc )
|
||||
{
|
||||
}
|
||||
|
||||
@@ -46,18 +47,8 @@ automationTrack::~automationTrack()
|
||||
|
||||
|
||||
|
||||
track::trackTypes automationTrack::type( void ) const
|
||||
{
|
||||
return( AUTOMATION_TRACK );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool automationTrack::play( const midiTime & _start,
|
||||
const fpp_t _frames,
|
||||
const f_cnt_t _frame_base,
|
||||
Sint16 _tco_num )
|
||||
bool automationTrack::play( const midiTime & _start, const fpp_t _frames,
|
||||
const f_cnt_t _frame_base, Sint16 _tco_num )
|
||||
{
|
||||
sendMidiTime( _start );
|
||||
return( FALSE );
|
||||
@@ -88,8 +79,4 @@ void automationTrack::loadTrackSpecificSettings( const QDomElement & _this )
|
||||
|
||||
|
||||
|
||||
|
||||
#include "automation_track.moc"
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
* bb_track.cpp - implementation of class bbTrack and bbTCO
|
||||
*
|
||||
* Copyright (c) 2004-2007 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2004-2008 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
@@ -39,6 +39,7 @@
|
||||
#include "mixer.h"
|
||||
#include "name_label.h"
|
||||
#include "rename_dialog.h"
|
||||
#include "song.h"
|
||||
#include "song_editor.h"
|
||||
#include "templates.h"
|
||||
|
||||
@@ -47,14 +48,15 @@
|
||||
bbTrack::infoMap bbTrack::s_infoMap;
|
||||
|
||||
|
||||
bbTCO::bbTCO( track * _track, const QColor & _c ) :
|
||||
bbTCO::bbTCO( track * _track, unsigned int _color ) :
|
||||
trackContentObject( _track ),
|
||||
m_name( ( dynamic_cast<bbTrack *>( _track ) != NULL ) ?
|
||||
m_name(/* ( dynamic_cast<bbTrack *>( _track ) != NULL ) ?
|
||||
dynamic_cast<bbTrack *>( _track )->trackLabel()->text() :
|
||||
QString( "" ) ),
|
||||
m_color( _c.isValid() ? _c : QColor( 64, 128, 255 ) )
|
||||
QString( "" )*/
|
||||
"" ),
|
||||
m_color( _color > 0 ? _color : qRgb( 64, 128, 255 ) )
|
||||
{
|
||||
tact t = engine::getBBEditor()->lengthOfBB(
|
||||
tact t = engine::getBBTrackContainer()->lengthOfBB(
|
||||
bbTrack::numOfBBTrack( getTrack() ) );
|
||||
if( t > 0 )
|
||||
{
|
||||
@@ -74,86 +76,6 @@ bbTCO::~bbTCO()
|
||||
|
||||
|
||||
|
||||
void bbTCO::constructContextMenu( QMenu * _cm )
|
||||
{
|
||||
QAction * a = new QAction( embed::getIconPixmap( "bb_track" ),
|
||||
tr( "Open in Beat+Baseline-Editor" ),
|
||||
_cm );
|
||||
_cm->insertAction( _cm->actions()[0], a );
|
||||
connect( a, SIGNAL( triggered( bool ) ), this,
|
||||
SLOT( openInBBEditor( bool ) ) );
|
||||
_cm->insertSeparator( _cm->actions()[1] );
|
||||
_cm->addSeparator();
|
||||
_cm->addAction( embed::getIconPixmap( "reload" ), tr( "Reset name" ),
|
||||
this, SLOT( resetName() ) );
|
||||
_cm->addAction( embed::getIconPixmap( "rename" ), tr( "Change name" ),
|
||||
this, SLOT( changeName() ) );
|
||||
_cm->addAction( embed::getIconPixmap( "colorize" ),
|
||||
tr( "Change color" ), this, SLOT( changeColor() ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void bbTCO::mouseDoubleClickEvent( QMouseEvent * )
|
||||
{
|
||||
openInBBEditor();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void bbTCO::paintEvent( QPaintEvent * )
|
||||
{
|
||||
QColor col = m_color;
|
||||
if( getTrack()->muted() || muted() )
|
||||
{
|
||||
col = QColor( 160, 160, 160 );
|
||||
}
|
||||
if( isSelected() == TRUE )
|
||||
{
|
||||
col = QColor( tMax( col.red() - 128, 0 ),
|
||||
tMax( col.green() - 128, 0 ), 255 );
|
||||
}
|
||||
QPainter p( this );
|
||||
|
||||
QLinearGradient lingrad( 0, 0, 0, height() );
|
||||
lingrad.setColorAt( 0, col.light( 130 ) );
|
||||
lingrad.setColorAt( 1, col.light( 70 ) );
|
||||
p.fillRect( rect(), lingrad );
|
||||
|
||||
tact t = engine::getBBEditor()->lengthOfBB( bbTrack::numOfBBTrack(
|
||||
getTrack() ) );
|
||||
if( length() > 64 && t > 0 )
|
||||
{
|
||||
for( int x = static_cast<int>( t * pixelsPerTact() );
|
||||
x < width()-2;
|
||||
x += static_cast<int>( t * pixelsPerTact() ) )
|
||||
{
|
||||
p.setPen( col.light( 80 ) );
|
||||
p.drawLine( x, 1, x, 5 );
|
||||
p.setPen( col.light( 120 ) );
|
||||
p.drawLine( x, height() - 6, x, height() - 2 );
|
||||
}
|
||||
}
|
||||
|
||||
p.setPen( col.dark() );
|
||||
p.drawRect( 0, 0, rect().right(), rect().bottom() );
|
||||
|
||||
p.setFont( pointSize<7>( p.font() ) );
|
||||
p.setPen( QColor( 0, 0, 0 ) );
|
||||
p.drawText( 2, p.fontMetrics().height() - 1, m_name );
|
||||
|
||||
if( muted() )
|
||||
{
|
||||
p.drawPixmap( 3, p.fontMetrics().height() + 1,
|
||||
embed::getIconPixmap( "muted", 16, 16 ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void bbTCO::saveSettings( QDomDocument & _doc, QDomElement & _this )
|
||||
{
|
||||
_this.setAttribute( "name", m_name );
|
||||
@@ -167,7 +89,7 @@ void bbTCO::saveSettings( QDomDocument & _doc, QDomElement & _this )
|
||||
}
|
||||
_this.setAttribute( "len", length() );
|
||||
_this.setAttribute( "muted", muted() );
|
||||
_this.setAttribute( "color", m_color.rgb() );
|
||||
_this.setAttribute( "color", m_color );
|
||||
}
|
||||
|
||||
|
||||
@@ -188,17 +110,127 @@ void bbTCO::loadSettings( const QDomElement & _this )
|
||||
|
||||
if( _this.attribute( "color" ).toUInt() != 0 )
|
||||
{
|
||||
m_color.setRgb( _this.attribute( "color" ).toUInt() );
|
||||
m_color = _this.attribute( "color" ).toUInt();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void bbTCO::openInBBEditor( bool )
|
||||
trackContentObjectView * bbTCO::createView( trackView * _tv )
|
||||
{
|
||||
engine::getBBEditor()->setCurrentBB( bbTrack::numOfBBTrack(
|
||||
getTrack() ) );
|
||||
return( new bbTCOView( this, _tv ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bbTCOView::bbTCOView( trackContentObject * _tco, trackView * _tv ) :
|
||||
trackContentObjectView( _tco, _tv ),
|
||||
m_bbTCO( dynamic_cast<bbTCO *>( _tco ) )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bbTCOView::~bbTCOView()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void bbTCOView::constructContextMenu( QMenu * _cm )
|
||||
{
|
||||
QAction * a = new QAction( embed::getIconPixmap( "bb_track" ),
|
||||
tr( "Open in Beat+Baseline-Editor" ),
|
||||
_cm );
|
||||
_cm->insertAction( _cm->actions()[0], a );
|
||||
connect( a, SIGNAL( triggered( bool ) ),
|
||||
this, SLOT( openInBBEditor() ) );
|
||||
_cm->insertSeparator( _cm->actions()[1] );
|
||||
_cm->addSeparator();
|
||||
_cm->addAction( embed::getIconPixmap( "reload" ), tr( "Reset name" ),
|
||||
this, SLOT( resetName() ) );
|
||||
_cm->addAction( embed::getIconPixmap( "rename" ), tr( "Change name" ),
|
||||
this, SLOT( changeName() ) );
|
||||
_cm->addAction( embed::getIconPixmap( "colorize" ),
|
||||
tr( "Change color" ), this, SLOT( changeColor() ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void bbTCOView::mouseDoubleClickEvent( QMouseEvent * )
|
||||
{
|
||||
openInBBEditor();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void bbTCOView::paintEvent( QPaintEvent * )
|
||||
{
|
||||
QColor col( m_bbTCO->m_color );
|
||||
if( m_bbTCO->getTrack()->muted() || m_bbTCO->muted() )
|
||||
{
|
||||
col = QColor( 160, 160, 160 );
|
||||
}
|
||||
if( isSelected() == TRUE )
|
||||
{
|
||||
col = QColor( tMax( col.red() - 128, 0 ),
|
||||
tMax( col.green() - 128, 0 ), 255 );
|
||||
}
|
||||
QPainter p( this );
|
||||
|
||||
QLinearGradient lingrad( 0, 0, 0, height() );
|
||||
lingrad.setColorAt( 0, col.light( 130 ) );
|
||||
lingrad.setColorAt( 1, col.light( 70 ) );
|
||||
p.fillRect( rect(), lingrad );
|
||||
|
||||
tact t = engine::getBBTrackContainer()->lengthOfBB(
|
||||
bbTrack::numOfBBTrack( m_bbTCO->getTrack() ) );
|
||||
if( m_bbTCO->length() > 64 && t > 0 )
|
||||
{
|
||||
for( int x = static_cast<int>( t * pixelsPerTact() );
|
||||
x < width()-2;
|
||||
x += static_cast<int>( t * pixelsPerTact() ) )
|
||||
{
|
||||
p.setPen( col.light( 80 ) );
|
||||
p.drawLine( x, 1, x, 5 );
|
||||
p.setPen( col.light( 120 ) );
|
||||
p.drawLine( x, height() - 6, x, height() - 2 );
|
||||
}
|
||||
}
|
||||
|
||||
p.setPen( col.dark() );
|
||||
p.drawRect( 0, 0, rect().right(), rect().bottom() );
|
||||
|
||||
p.setFont( pointSize<7>( p.font() ) );
|
||||
p.setPen( QColor( 0, 0, 0 ) );
|
||||
p.drawText( 2, p.fontMetrics().height() - 1, m_bbTCO->m_name );
|
||||
|
||||
if( m_bbTCO->muted() )
|
||||
{
|
||||
p.drawPixmap( 3, p.fontMetrics().height() + 1,
|
||||
embed::getIconPixmap( "muted", 16, 16 ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void bbTCOView::openInBBEditor( void )
|
||||
{
|
||||
engine::getBBTrackContainer()->setCurrentBB( bbTrack::numOfBBTrack(
|
||||
m_bbTCO->getTrack() ) );
|
||||
engine::getBBEditor()->show();
|
||||
engine::getBBEditor()->setFocus();
|
||||
}
|
||||
@@ -206,19 +238,12 @@ void bbTCO::openInBBEditor( bool )
|
||||
|
||||
|
||||
|
||||
void bbTCO::openInBBEditor( void )
|
||||
void bbTCOView::resetName( void )
|
||||
{
|
||||
openInBBEditor( FALSE );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void bbTCO::resetName( void )
|
||||
{
|
||||
if( dynamic_cast<bbTrack *>( getTrack() ) != NULL )
|
||||
if( dynamic_cast<bbTrackView *>( getTrackView() ) != NULL )
|
||||
{
|
||||
m_name = dynamic_cast<bbTrack *>( getTrack() )->
|
||||
m_bbTCO->m_name =
|
||||
dynamic_cast<bbTrackView *>( getTrackView() )->
|
||||
trackLabel()->text();
|
||||
}
|
||||
}
|
||||
@@ -226,18 +251,18 @@ void bbTCO::resetName( void )
|
||||
|
||||
|
||||
|
||||
void bbTCO::changeName( void )
|
||||
void bbTCOView::changeName( void )
|
||||
{
|
||||
renameDialog rename_dlg( m_name );
|
||||
renameDialog rename_dlg( m_bbTCO->m_name );
|
||||
rename_dlg.exec();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void bbTCO::changeColor( void )
|
||||
void bbTCOView::changeColor( void )
|
||||
{
|
||||
QColor _new_color = QColorDialog::getColor( m_color );
|
||||
QColor _new_color = QColorDialog::getColor( m_bbTCO->m_color );
|
||||
if( !_new_color.isValid() )
|
||||
{
|
||||
return;
|
||||
@@ -250,10 +275,10 @@ void bbTCO::changeColor( void )
|
||||
selected.begin();
|
||||
it != selected.end(); ++it )
|
||||
{
|
||||
bbTCO * bb_tco = dynamic_cast<bbTCO *>( *it );
|
||||
if( bb_tco )
|
||||
bbTCOView * bb_tcov = dynamic_cast<bbTCOView *>( *it );
|
||||
if( bb_tcov )
|
||||
{
|
||||
bb_tco->setColor( _new_color );
|
||||
bb_tcov->setColor( _new_color );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -266,12 +291,12 @@ void bbTCO::changeColor( void )
|
||||
|
||||
|
||||
|
||||
void bbTCO::setColor( QColor _new_color )
|
||||
void bbTCOView::setColor( QColor _new_color )
|
||||
{
|
||||
if( _new_color != m_color )
|
||||
if( _new_color.rgb() != m_bbTCO->m_color )
|
||||
{
|
||||
m_color = _new_color;
|
||||
engine::getSongEditor()->setModified();
|
||||
m_bbTCO->m_color = _new_color.rgb();
|
||||
engine::getSong()->setModified();
|
||||
update();
|
||||
}
|
||||
}
|
||||
@@ -280,33 +305,17 @@ void bbTCO::setColor( QColor _new_color )
|
||||
|
||||
|
||||
|
||||
bbTrack::bbTrack( trackContainer * _tc ) :
|
||||
track( _tc )
|
||||
{
|
||||
getTrackWidget()->setFixedHeight( 32 );
|
||||
// drag'n'drop with bb-tracks only causes troubles (and makes no sense
|
||||
// too), so disable it
|
||||
getTrackWidget()->setAcceptDrops( FALSE );
|
||||
|
||||
|
||||
bbTrack::bbTrack( trackContainer * _tc ) :
|
||||
track( BBTrack, _tc )
|
||||
{
|
||||
int bbNum = s_infoMap.size();
|
||||
s_infoMap[this] = bbNum;
|
||||
|
||||
m_trackLabel = new nameLabel( tr( "Beat/Baseline %1" ).arg( bbNum ),
|
||||
getTrackSettingsWidget() );
|
||||
m_trackLabel->setPixmap( embed::getIconPixmap( "bb_track" ) );
|
||||
m_trackLabel->setGeometry( 1, 1, DEFAULT_SETTINGS_WIDGET_WIDTH - 2,
|
||||
29 );
|
||||
m_trackLabel->show();
|
||||
connect( m_trackLabel, SIGNAL( clicked() ),
|
||||
this, SLOT( clickedTrackLabel() ) );
|
||||
connect( m_trackLabel, SIGNAL( nameChanged() ),
|
||||
engine::getBBEditor(), SLOT( updateComboBox() ) );
|
||||
connect( m_trackLabel, SIGNAL( pixmapChanged() ),
|
||||
engine::getBBEditor(), SLOT( updateComboBox() ) );
|
||||
|
||||
|
||||
engine::getBBEditor()->setCurrentBB( bbNum );
|
||||
engine::getBBEditor()->updateComboBox();
|
||||
setName( tr( "Beat/Baseline %1" ).arg( bbNum ) );
|
||||
engine::getBBTrackContainer()->setCurrentBB( bbNum );
|
||||
engine::getBBTrackContainer()->updateComboBox();
|
||||
}
|
||||
|
||||
|
||||
@@ -316,8 +325,8 @@ bbTrack::~bbTrack()
|
||||
{
|
||||
engine::getMixer()->removePlayHandles( this );
|
||||
|
||||
int bb = s_infoMap[this];
|
||||
engine::getBBEditor()->removeBB( bb );
|
||||
const int bb = s_infoMap[this];
|
||||
engine::getBBTrackContainer()->removeBB( bb );
|
||||
for( infoMap::iterator it = s_infoMap.begin(); it != s_infoMap.end();
|
||||
++it )
|
||||
{
|
||||
@@ -327,30 +336,25 @@ bbTrack::~bbTrack()
|
||||
}
|
||||
}
|
||||
s_infoMap.remove( this );
|
||||
engine::getBBEditor()->updateComboBox();
|
||||
|
||||
// remove us from TC so bbTrackContainer::numOfBBs() returns a smaller
|
||||
// value and thus combobox-updating in bbTrackContainer works well
|
||||
getTrackContainer()->removeTrack( this );
|
||||
engine::getBBTrackContainer()->updateComboBox();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
track::trackTypes bbTrack::type( void ) const
|
||||
{
|
||||
return( BB_TRACK );
|
||||
}
|
||||
|
||||
|
||||
|
||||
// play _frames frames of given TCO within starting with _start
|
||||
bool FASTCALL bbTrack::play( const midiTime & _start,
|
||||
const fpp_t _frames,
|
||||
const f_cnt_t _offset,
|
||||
Sint16 _tco_num )
|
||||
bool bbTrack::play( const midiTime & _start, const fpp_t _frames,
|
||||
const f_cnt_t _offset, Sint16 _tco_num )
|
||||
{
|
||||
sendMidiTime( _start );
|
||||
|
||||
if( _tco_num >= 0 )
|
||||
{
|
||||
return( engine::getBBEditor()->play( _start, _frames,
|
||||
return( engine::getBBTrackContainer()->play( _start, _frames,
|
||||
_offset,
|
||||
s_infoMap[this] ) );
|
||||
}
|
||||
@@ -378,7 +382,8 @@ bool FASTCALL bbTrack::play( const midiTime & _start,
|
||||
}
|
||||
if( _start - lastPosition < lastLen )
|
||||
{
|
||||
return( engine::getBBEditor()->play( _start - lastPosition,
|
||||
return( engine::getBBTrackContainer()->play( _start -
|
||||
lastPosition,
|
||||
_frames,
|
||||
_offset,
|
||||
s_infoMap[this] ) );
|
||||
@@ -389,6 +394,14 @@ bool FASTCALL bbTrack::play( const midiTime & _start,
|
||||
|
||||
|
||||
|
||||
trackView * bbTrack::createView( trackContainerView * _tcv )
|
||||
{
|
||||
return( new bbTrackView( this, _tcv ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
trackContentObject * bbTrack::createTCO( const midiTime & _pos )
|
||||
{
|
||||
// if we're creating a new bbTCO, we colorize it according to the
|
||||
@@ -413,20 +426,20 @@ trackContentObject * bbTrack::createTCO( const midiTime & _pos )
|
||||
void bbTrack::saveTrackSpecificSettings( QDomDocument & _doc,
|
||||
QDomElement & _this )
|
||||
{
|
||||
_this.setAttribute( "name", m_trackLabel->text() );
|
||||
_this.setAttribute( "icon", m_trackLabel->pixmapFile() );
|
||||
_this.setAttribute( "name", name() );
|
||||
// _this.setAttribute( "icon", m_trackLabel->pixmapFile() );
|
||||
/* _this.setAttribute( "current", s_infoMap[this] ==
|
||||
engine::getBBEditor()->currentBB() );*/
|
||||
if( s_infoMap[this] == 0 &&
|
||||
_this.parentNode().parentNode().nodeName() != "clone" &&
|
||||
_this.parentNode().nodeName() != "journaldata" )
|
||||
{
|
||||
( (journallingObject *)( engine::getBBEditor() ) )->saveState(
|
||||
_doc, _this );
|
||||
( (journallingObject *)( engine::getBBTrackContainer() ) )->
|
||||
saveState( _doc, _this );
|
||||
}
|
||||
|
||||
int track_num = 0;
|
||||
QList<track *> tracks = engine::getBBEditor()->tracks();
|
||||
QList<track *> tracks = engine::getBBTrackContainer()->tracks();
|
||||
for( int i = 0; i < tracks.size(); ++i, ++track_num )
|
||||
{
|
||||
if( automationDisabled( tracks[i] ) )
|
||||
@@ -444,18 +457,18 @@ void bbTrack::saveTrackSpecificSettings( QDomDocument & _doc,
|
||||
|
||||
void bbTrack::loadTrackSpecificSettings( const QDomElement & _this )
|
||||
{
|
||||
m_trackLabel->setText( _this.attribute( "name" ) );
|
||||
if( _this.attribute( "icon" ) != "" )
|
||||
setName( _this.attribute( "name" ) );
|
||||
/* if( _this.attribute( "icon" ) != "" )
|
||||
{
|
||||
m_trackLabel->setPixmapFile( _this.attribute( "icon" ) );
|
||||
}
|
||||
engine::getBBEditor()->updateComboBox();
|
||||
}*/
|
||||
// engine::getBBTrackContainer()->updateComboBox();
|
||||
|
||||
QDomNode node = _this.namedItem( trackContainer::classNodeName() );
|
||||
if( node.isElement() )
|
||||
{
|
||||
( (journallingObject *)engine::getBBEditor() )->restoreState(
|
||||
node.toElement() );
|
||||
( (journallingObject *)engine::getBBTrackContainer() )->
|
||||
restoreState( node.toElement() );
|
||||
}
|
||||
/* doesn't work yet because bbTrack-ctor also sets current bb so if
|
||||
bb-tracks are created after this function is called, this doesn't
|
||||
@@ -465,7 +478,7 @@ void bbTrack::loadTrackSpecificSettings( const QDomElement & _this )
|
||||
engine::getBBEditor()->setCurrentBB( s_infoMap[this] );
|
||||
}*/
|
||||
|
||||
QList<track *> tracks = engine::getBBEditor()->tracks();
|
||||
QList<track *> tracks = engine::getBBTrackContainer()->tracks();
|
||||
node = _this.firstChild();
|
||||
while( !node.isNull() )
|
||||
{
|
||||
@@ -518,17 +531,70 @@ void bbTrack::swapBBTracks( track * _track1, track * _track2 )
|
||||
if( t1 != NULL && t2 != NULL )
|
||||
{
|
||||
qSwap( s_infoMap[t1], s_infoMap[t2] );
|
||||
engine::getBBEditor()->swapBB( s_infoMap[t1], s_infoMap[t2] );
|
||||
engine::getBBEditor()->setCurrentBB( s_infoMap[t1] );
|
||||
engine::getBBTrackContainer()->swapBB( s_infoMap[t1],
|
||||
s_infoMap[t2] );
|
||||
engine::getBBTrackContainer()->setCurrentBB( s_infoMap[t1] );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void bbTrack::clickedTrackLabel( void )
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bbTrackView::bbTrackView( bbTrack * _bbt, trackContainerView * _tcv ) :
|
||||
trackView( _bbt, _tcv ),
|
||||
m_bbTrack( _bbt )
|
||||
{
|
||||
engine::getBBEditor()->setCurrentBB( s_infoMap[this] );
|
||||
setFixedHeight( 32 );
|
||||
// drag'n'drop with bb-tracks only causes troubles (and makes no sense
|
||||
// too), so disable it
|
||||
setAcceptDrops( FALSE );
|
||||
|
||||
m_trackLabel = new nameLabel( _bbt->name(),
|
||||
getTrackSettingsWidget() );
|
||||
m_trackLabel->setPixmap( embed::getIconPixmap( "bb_track" ) );
|
||||
m_trackLabel->setGeometry( 1, 1, DEFAULT_SETTINGS_WIDGET_WIDTH - 2,
|
||||
29 );
|
||||
m_trackLabel->show();
|
||||
connect( m_trackLabel, SIGNAL( clicked() ),
|
||||
this, SLOT( clickedTrackLabel() ) );
|
||||
connect( m_trackLabel, SIGNAL( nameChanged( const QString & ) ),
|
||||
_bbt, SLOT( setName( const QString & ) ) );
|
||||
connect( m_trackLabel, SIGNAL( nameChanged( const QString & ) ),
|
||||
engine::getBBTrackContainer(), SLOT( updateComboBox() ) );
|
||||
connect( m_trackLabel, SIGNAL( pixmapChanged() ),
|
||||
engine::getBBTrackContainer(), SLOT( updateComboBox() ) );
|
||||
|
||||
setModel( _bbt );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bbTrackView::~bbTrackView()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool bbTrackView::close( void )
|
||||
{
|
||||
engine::getBBEditor()->removeBBView( bbTrack::s_infoMap[m_bbTrack] );
|
||||
trackView::close();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void bbTrackView::clickedTrackLabel( void )
|
||||
{
|
||||
engine::getBBTrackContainer()->setCurrentBB(
|
||||
bbTrack::numOfBBTrack( m_bbTrack ) );
|
||||
engine::getBBEditor()->show();
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -329,7 +329,7 @@ void sampleTCOSettingsDialog::setSampleFile( const QString & _f )
|
||||
|
||||
|
||||
sampleTrack::sampleTrack( trackContainer * _tc ) :
|
||||
track( _tc ),
|
||||
track( SampleTrack, _tc ),
|
||||
m_audioPort( tr( "Sample track" ), this ),
|
||||
m_volumeModel( DEFAULT_VOLUME, MIN_VOLUME, MAX_VOLUME, 1/*, this*/ )
|
||||
{
|
||||
@@ -377,14 +377,6 @@ sampleTrack::~sampleTrack()
|
||||
|
||||
|
||||
|
||||
track::trackTypes sampleTrack::type( void ) const
|
||||
{
|
||||
return( SAMPLE_TRACK );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool FASTCALL sampleTrack::play( const midiTime & _start,
|
||||
const fpp_t _frames,
|
||||
const f_cnt_t _offset,
|
||||
|
||||
@@ -176,9 +176,10 @@ automatableButtonGroup::automatableButtonGroup( QWidget * _parent,
|
||||
|
||||
automatableButtonGroup::~automatableButtonGroup()
|
||||
{
|
||||
while( m_buttons.empty() == FALSE )
|
||||
for( QList<automatableButton *>::iterator it = m_buttons.begin();
|
||||
it != m_buttons.end(); ++it )
|
||||
{
|
||||
removeButton( m_buttons.front() );
|
||||
( *it )->m_group = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ effectRackView::effectRackView( effectChain * _model, QWidget * _parent ) :
|
||||
modelView( NULL )
|
||||
{
|
||||
setFixedSize( 230, 184 );
|
||||
|
||||
|
||||
/* m_mainLayout = new QVBoxLayout( this );
|
||||
m_mainLayout->setMargin( 0 );
|
||||
m_mainLayout->setSpacing( 0 );*/
|
||||
|
||||
600
src/widgets/envelope_and_lfo_view.cpp
Normal file
600
src/widgets/envelope_and_lfo_view.cpp
Normal file
@@ -0,0 +1,600 @@
|
||||
#ifndef SINGLE_SOURCE_COMPILE
|
||||
|
||||
/*
|
||||
* envelope_and_lfo_view.cpp - widget which is m_used by envelope/lfo/filter-
|
||||
* tab of channel-window
|
||||
*
|
||||
* Copyright (c) 2004-2008 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* 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 (see COPYING); if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "envelope_and_lfo_view.h"
|
||||
|
||||
|
||||
#include <QtGui/QMouseEvent>
|
||||
#include <QtGui/QPainter>
|
||||
|
||||
|
||||
#include "envelope_and_lfo_parameters.h"
|
||||
#include "embed.h"
|
||||
#include "engine.h"
|
||||
#include "gui_templates.h"
|
||||
#include "knob.h"
|
||||
#include "led_checkbox.h"
|
||||
#include "mmp.h"
|
||||
#include "oscillator.h"
|
||||
#include "pixmap_button.h"
|
||||
#include "string_pair_drag.h"
|
||||
#include "tempo_sync_knob.h"
|
||||
#include "text_float.h"
|
||||
#include "tooltip.h"
|
||||
#include "track.h"
|
||||
#include "automatable_model_templates.h"
|
||||
|
||||
|
||||
|
||||
// how long should be each envelope-segment maximal (e.g. attack)?
|
||||
const float SECS_PER_ENV_SEGMENT = 5.0f;
|
||||
// how long should be one LFO-oscillation maximal?
|
||||
const float SECS_PER_LFO_OSCILLATION = 20.0f;
|
||||
|
||||
|
||||
const int ENV_GRAPH_X = 6;
|
||||
const int ENV_GRAPH_Y = 6;
|
||||
|
||||
const int ENV_KNOBS_Y = 43;
|
||||
const int ENV_KNOBS_LBL_Y = ENV_KNOBS_Y+35;
|
||||
const int KNOB_X_SPACING = 32;
|
||||
const int PREDELAY_KNOB_X = 6;
|
||||
const int ATTACK_KNOB_X = PREDELAY_KNOB_X+KNOB_X_SPACING;
|
||||
const int HOLD_KNOB_X = ATTACK_KNOB_X+KNOB_X_SPACING;
|
||||
const int DECAY_KNOB_X = HOLD_KNOB_X+KNOB_X_SPACING;
|
||||
const int SUSTAIN_KNOB_X = DECAY_KNOB_X+KNOB_X_SPACING;
|
||||
const int RELEASE_KNOB_X = SUSTAIN_KNOB_X+KNOB_X_SPACING;
|
||||
const int AMOUNT_KNOB_X = RELEASE_KNOB_X+KNOB_X_SPACING;
|
||||
|
||||
const float TIME_UNIT_WIDTH = 36.0;
|
||||
|
||||
|
||||
const int LFO_GRAPH_X = 6;
|
||||
const int LFO_GRAPH_Y = ENV_KNOBS_LBL_Y+14;
|
||||
const int LFO_KNOB_Y = LFO_GRAPH_Y-2;
|
||||
const int LFO_PREDELAY_KNOB_X = LFO_GRAPH_X + 100;
|
||||
const int LFO_ATTACK_KNOB_X = LFO_PREDELAY_KNOB_X+KNOB_X_SPACING;
|
||||
const int LFO_SPEED_KNOB_X = LFO_ATTACK_KNOB_X+KNOB_X_SPACING;
|
||||
const int LFO_AMOUNT_KNOB_X = LFO_SPEED_KNOB_X+KNOB_X_SPACING;
|
||||
const int LFO_SHAPES_X = LFO_GRAPH_X;//PREDELAY_KNOB_X;
|
||||
const int LFO_SHAPES_Y = LFO_GRAPH_Y + 50;
|
||||
|
||||
|
||||
QPixmap * envelopeAndLFOView::s_envGraph = NULL;
|
||||
QPixmap * envelopeAndLFOView::s_lfoGraph = NULL;
|
||||
|
||||
|
||||
|
||||
envelopeAndLFOView::envelopeAndLFOView( QWidget * _parent ) :
|
||||
QWidget( _parent ),
|
||||
modelView( NULL ),
|
||||
m_params( NULL )
|
||||
{
|
||||
if( s_envGraph == NULL )
|
||||
{
|
||||
s_envGraph = new QPixmap( embed::getIconPixmap(
|
||||
"envelope_graph" ) );
|
||||
}
|
||||
if( s_lfoGraph == NULL )
|
||||
{
|
||||
s_lfoGraph = new QPixmap( embed::getIconPixmap( "lfo_graph" ) );
|
||||
}
|
||||
|
||||
m_predelayKnob = new knob( knobBright_26, this, tr( "Predelay-time" ) );
|
||||
m_predelayKnob->setLabel( tr( "DEL" ) );
|
||||
m_predelayKnob->move( PREDELAY_KNOB_X, ENV_KNOBS_Y );
|
||||
m_predelayKnob->setHintText( tr( "Predelay:" ) + " ", "" );
|
||||
m_predelayKnob->setWhatsThis(
|
||||
tr( "Use this knob for setting predelay of the current "
|
||||
"envelope. The bigger this value the longer the time "
|
||||
"before start of actual envelope." ) );
|
||||
|
||||
|
||||
m_attackKnob = new knob( knobBright_26, this, tr( "Attack-time" ) );
|
||||
m_attackKnob->setLabel( tr( "ATT" ) );
|
||||
m_attackKnob->move( ATTACK_KNOB_X, ENV_KNOBS_Y );
|
||||
m_attackKnob->setHintText( tr( "Attack:" )+" ", "" );
|
||||
m_attackKnob->setWhatsThis(
|
||||
tr( "Use this knob for setting attack-time of the current "
|
||||
"envelope. The bigger this value the longer the "
|
||||
"envelope needs to increase to attack-level. "
|
||||
"Choose a small value for instruments like pianos "
|
||||
"and a big value for strings." ) );
|
||||
|
||||
m_holdKnob = new knob( knobBright_26, this, tr( "Hold-time" ) );
|
||||
m_holdKnob->setLabel( tr( "HOLD" ) );
|
||||
m_holdKnob->move( HOLD_KNOB_X, ENV_KNOBS_Y );
|
||||
m_holdKnob->setHintText( tr( "Hold:" ) + " ", "" );
|
||||
m_holdKnob->setWhatsThis(
|
||||
tr( "Use this knob for setting hold-time of the current "
|
||||
"envelope. The bigger this value the longer the "
|
||||
"envelope holds attack-level before it begins to "
|
||||
"decrease to sustain-level." ) );
|
||||
|
||||
m_decayKnob = new knob( knobBright_26, this, tr( "Decay-time" ) );
|
||||
m_decayKnob->setLabel( tr( "DEC" ) );
|
||||
m_decayKnob->move( DECAY_KNOB_X, ENV_KNOBS_Y );
|
||||
m_decayKnob->setHintText( tr( "Decay:" ) + " ", "" );
|
||||
m_decayKnob->setWhatsThis(
|
||||
tr( "Use this knob for setting decay-time of the current "
|
||||
"envelope. The bigger this value the longer the "
|
||||
"envelope needs to decrease from attack-level to "
|
||||
"sustain-level. Choose a small value for instruments "
|
||||
"like pianos." ) );
|
||||
|
||||
|
||||
m_sustainKnob = new knob( knobBright_26, this, tr( "Sustain-level" ) );
|
||||
m_sustainKnob->setLabel( tr( "SUST" ) );
|
||||
m_sustainKnob->move( SUSTAIN_KNOB_X, ENV_KNOBS_Y );
|
||||
m_sustainKnob->setHintText( tr( "Sustain:" ) + " ", "" );
|
||||
m_sustainKnob->setWhatsThis(
|
||||
tr( "Use this knob for setting sustain-level of the current "
|
||||
"envelope. The bigger this value the higher the level "
|
||||
"on which the envelope stays before going down to "
|
||||
"zero." ) );
|
||||
|
||||
|
||||
m_releaseKnob = new knob( knobBright_26, this, tr( "Release-time" ) );
|
||||
m_releaseKnob->setLabel( tr( "REL" ) );
|
||||
m_releaseKnob->move( RELEASE_KNOB_X, ENV_KNOBS_Y );
|
||||
m_releaseKnob->setHintText( tr( "Release:" ) + " ", "" );
|
||||
m_releaseKnob->setWhatsThis(
|
||||
tr( "Use this knob for setting release-time of the current "
|
||||
"envelope. The bigger this value the longer the "
|
||||
"envelope needs to decrease from sustain-level to "
|
||||
"zero. Choose a big value for soft instruments like "
|
||||
"strings." ) );
|
||||
|
||||
|
||||
m_amountKnob = new knob( knobBright_26, this,
|
||||
tr( "Modulation amount" ) );
|
||||
m_amountKnob->setLabel( tr( "AMT" ) );
|
||||
m_amountKnob->move( AMOUNT_KNOB_X, ENV_GRAPH_Y );
|
||||
m_amountKnob->setHintText( tr( "Modulation amount:" ) + " ", "" );
|
||||
m_amountKnob->setWhatsThis(
|
||||
tr( "Use this knob for setting modulation amount of the "
|
||||
"current envelope. The bigger this value the more the "
|
||||
"according size (e.g. volume or cutoff-frequency) "
|
||||
"will be influenced by this envelope." ) );
|
||||
|
||||
|
||||
|
||||
|
||||
m_lfoPredelayKnob = new knob( knobBright_26, this,
|
||||
tr( "LFO-predelay-time" ) );
|
||||
m_lfoPredelayKnob->setLabel( tr( "DEL" ) );
|
||||
m_lfoPredelayKnob->move( LFO_PREDELAY_KNOB_X, LFO_KNOB_Y );
|
||||
m_lfoPredelayKnob->setHintText( tr( "LFO-predelay:" ) + " ", "" );
|
||||
m_lfoPredelayKnob->setWhatsThis(
|
||||
tr( "Use this knob for setting predelay-time of the current "
|
||||
"LFO. The bigger this value the the time until the "
|
||||
"LFO starts to oscillate." ) );
|
||||
|
||||
|
||||
m_lfoAttackKnob = new knob( knobBright_26, this,
|
||||
tr( "LFO-attack-time" ) );
|
||||
m_lfoAttackKnob->setLabel( tr( "ATT" ) );
|
||||
m_lfoAttackKnob->move( LFO_ATTACK_KNOB_X, LFO_KNOB_Y );
|
||||
m_lfoAttackKnob->setHintText( tr( "LFO-attack:" ) + " ", "" );
|
||||
m_lfoAttackKnob->setWhatsThis(
|
||||
tr( "Use this knob for setting attack-time of the current LFO. "
|
||||
"The bigger this value the longer the LFO needs to "
|
||||
"increase its amplitude to maximum." ) );
|
||||
|
||||
|
||||
m_lfoSpeedKnob = new tempoSyncKnob( knobBright_26, this,
|
||||
tr( "LFO-speed" ), 20000.0 );
|
||||
m_lfoSpeedKnob->setLabel( tr( "SPD" ) );
|
||||
m_lfoSpeedKnob->move( LFO_SPEED_KNOB_X, LFO_KNOB_Y );
|
||||
m_lfoSpeedKnob->setHintText( tr( "LFO-speed:" ) + " ", "" );
|
||||
m_lfoSpeedKnob->setWhatsThis(
|
||||
tr( "Use this knob for setting speed of the current LFO. The "
|
||||
"bigger this value the faster the LFO oscillates and "
|
||||
"the faster will be your effect." ) );
|
||||
|
||||
|
||||
m_lfoAmountKnob = new knob( knobBright_26, this,
|
||||
tr( "LFO-modulation-amount" ) );
|
||||
m_lfoAmountKnob->setLabel( tr( "AMT" ) );
|
||||
m_lfoAmountKnob->move( LFO_AMOUNT_KNOB_X, LFO_KNOB_Y );
|
||||
m_lfoAmountKnob->setHintText( tr( "Modulation amount:" ) + " ", "" );
|
||||
m_lfoAmountKnob->setWhatsThis(
|
||||
tr( "Use this knob for setting modulation amount of the "
|
||||
"current LFO. The bigger this value the more the "
|
||||
"selected size (e.g. volume or cutoff-frequency) will "
|
||||
"be influenced by this LFO." ) );
|
||||
|
||||
|
||||
pixmapButton * sin_lfo_btn = new pixmapButton( this, NULL );
|
||||
sin_lfo_btn->move( LFO_SHAPES_X, LFO_SHAPES_Y );
|
||||
sin_lfo_btn->setActiveGraphic( embed::getIconPixmap(
|
||||
"sin_wave_active" ) );
|
||||
sin_lfo_btn->setInactiveGraphic( embed::getIconPixmap(
|
||||
"sin_wave_inactive" ) );
|
||||
sin_lfo_btn->setWhatsThis(
|
||||
tr( "Click here if you want a sine-wave for current "
|
||||
"oscillator." ) );
|
||||
|
||||
pixmapButton * triangle_lfo_btn = new pixmapButton( this, NULL );
|
||||
triangle_lfo_btn->move( LFO_SHAPES_X+15, LFO_SHAPES_Y );
|
||||
triangle_lfo_btn->setActiveGraphic( embed::getIconPixmap(
|
||||
"triangle_wave_active" ) );
|
||||
triangle_lfo_btn->setInactiveGraphic( embed::getIconPixmap(
|
||||
"triangle_wave_inactive" ) );
|
||||
triangle_lfo_btn->setWhatsThis(
|
||||
tr( "Click here if you want a triangle-wave for current "
|
||||
"oscillator." ) );
|
||||
|
||||
pixmapButton * saw_lfo_btn = new pixmapButton( this, NULL );
|
||||
saw_lfo_btn->move( LFO_SHAPES_X+30, LFO_SHAPES_Y );
|
||||
saw_lfo_btn->setActiveGraphic( embed::getIconPixmap(
|
||||
"saw_wave_active" ) );
|
||||
saw_lfo_btn->setInactiveGraphic( embed::getIconPixmap(
|
||||
"saw_wave_inactive" ) );
|
||||
saw_lfo_btn->setWhatsThis(
|
||||
tr( "Click here if you want a saw-wave for current "
|
||||
"oscillator." ) );
|
||||
|
||||
pixmapButton * sqr_lfo_btn = new pixmapButton( this, NULL );
|
||||
sqr_lfo_btn->move( LFO_SHAPES_X+45, LFO_SHAPES_Y );
|
||||
sqr_lfo_btn->setActiveGraphic( embed::getIconPixmap(
|
||||
"square_wave_active" ) );
|
||||
sqr_lfo_btn->setInactiveGraphic( embed::getIconPixmap(
|
||||
"square_wave_inactive" ) );
|
||||
sqr_lfo_btn->setWhatsThis(
|
||||
tr( "Click here if you want a square-wave for current "
|
||||
"oscillator." ) );
|
||||
|
||||
m_userLfoBtn = new pixmapButton( this, NULL );
|
||||
m_userLfoBtn->move( LFO_SHAPES_X+60, LFO_SHAPES_Y );
|
||||
m_userLfoBtn->setActiveGraphic( embed::getIconPixmap(
|
||||
"usr_wave_active" ) );
|
||||
m_userLfoBtn->setInactiveGraphic( embed::getIconPixmap(
|
||||
"usr_wave_inactive" ) );
|
||||
m_userLfoBtn->setWhatsThis(
|
||||
tr( "Click here if you want a user-defined wave for current "
|
||||
"oscillator. Afterwards drag an according sample-"
|
||||
"file into LFO-graph." ) );
|
||||
|
||||
connect( m_userLfoBtn, SIGNAL( toggled( bool ) ),
|
||||
this, SLOT( lfoUserWaveChanged() ) );
|
||||
|
||||
m_lfoWaveBtnGrp = new automatableButtonGroup( this,
|
||||
tr( "LFO wave shape" ) );
|
||||
m_lfoWaveBtnGrp->addButton( sin_lfo_btn );
|
||||
m_lfoWaveBtnGrp->addButton( triangle_lfo_btn );
|
||||
m_lfoWaveBtnGrp->addButton( saw_lfo_btn );
|
||||
m_lfoWaveBtnGrp->addButton( sqr_lfo_btn );
|
||||
m_lfoWaveBtnGrp->addButton( m_userLfoBtn );
|
||||
|
||||
|
||||
m_x100Cb = new ledCheckBox( tr( "FREQ x 100" ), this,
|
||||
tr( "Freq x 100" ) );
|
||||
m_x100Cb->setFont( pointSize<6>( m_x100Cb->font() ) );
|
||||
m_x100Cb->move( LFO_PREDELAY_KNOB_X, LFO_GRAPH_Y + 36 );
|
||||
m_x100Cb->setWhatsThis(
|
||||
tr( "Click here if the frequency of this LFO should be "
|
||||
"multiplied with 100." ) );
|
||||
toolTip::add( m_x100Cb, tr( "multiply LFO-frequency with 100" ) );
|
||||
|
||||
|
||||
m_controlEnvAmountCb = new ledCheckBox( tr( "MODULATE ENV-AMOUNT" ),
|
||||
this, tr( "Modulate Env-Amount" ) );
|
||||
m_controlEnvAmountCb->move( LFO_PREDELAY_KNOB_X, LFO_GRAPH_Y + 54 );
|
||||
m_controlEnvAmountCb->setFont( pointSize<6>(
|
||||
m_controlEnvAmountCb->font() ) );
|
||||
m_controlEnvAmountCb ->setWhatsThis(
|
||||
tr( "Click here to make the envelope-amount controlled by this "
|
||||
"LFO." ) );
|
||||
toolTip::add( m_controlEnvAmountCb,
|
||||
tr( "control envelope-amount by this LFO" ) );
|
||||
|
||||
|
||||
setAcceptDrops( TRUE );
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
envelopeAndLFOView::~envelopeAndLFOView()
|
||||
{
|
||||
delete m_lfoWaveBtnGrp;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void envelopeAndLFOView::modelChanged( void )
|
||||
{
|
||||
m_params = castModel<envelopeAndLFOParameters>();
|
||||
m_predelayKnob->setModel( &m_params->m_predelayModel );
|
||||
m_attackKnob->setModel( &m_params->m_attackModel );
|
||||
m_holdKnob->setModel( &m_params->m_holdModel );
|
||||
m_decayKnob->setModel( &m_params->m_decayModel );
|
||||
m_sustainKnob->setModel( &m_params->m_sustainModel );
|
||||
m_releaseKnob->setModel( &m_params->m_releaseModel );
|
||||
m_amountKnob->setModel( &m_params->m_amountModel );
|
||||
m_lfoPredelayKnob->setModel( &m_params->m_lfoPredelayModel );
|
||||
m_lfoAttackKnob->setModel( &m_params->m_lfoAttackModel );
|
||||
m_lfoSpeedKnob->setModel( &m_params->m_lfoSpeedModel );
|
||||
m_lfoAmountKnob->setModel( &m_params->m_lfoAmountModel );
|
||||
m_lfoWaveBtnGrp->setModel( &m_params->m_lfoWaveModel );
|
||||
m_x100Cb->setModel( &m_params->m_x100Model );
|
||||
m_controlEnvAmountCb->setModel( &m_params->m_controlEnvAmountModel );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void envelopeAndLFOView::mousePressEvent( QMouseEvent * _me )
|
||||
{
|
||||
if( _me->button() != Qt::LeftButton )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if( QRect( ENV_GRAPH_X, ENV_GRAPH_Y, s_envGraph->width(),
|
||||
s_envGraph->height() ).contains( _me->pos() ) == TRUE )
|
||||
{
|
||||
if( m_amountKnob->value() < 1.0f )
|
||||
{
|
||||
m_amountKnob->setValue( 1.0f );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_amountKnob->setValue( 0.0f );
|
||||
}
|
||||
}
|
||||
else if( QRect( LFO_GRAPH_X, LFO_GRAPH_Y, s_lfoGraph->width(),
|
||||
s_lfoGraph->height() ).contains( _me->pos() ) == TRUE )
|
||||
{
|
||||
if( m_lfoAmountKnob->value() < 1.0f )
|
||||
{
|
||||
m_lfoAmountKnob->setValue( 1.0f );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_lfoAmountKnob->setValue( 0.0f );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void envelopeAndLFOView::dragEnterEvent( QDragEnterEvent * _dee )
|
||||
{
|
||||
stringPairDrag::processDragEnterEvent( _dee,
|
||||
QString( "samplefile,tco_%1" ).arg(
|
||||
track::SampleTrack ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void envelopeAndLFOView::dropEvent( QDropEvent * _de )
|
||||
{
|
||||
QString type = stringPairDrag::decodeKey( _de );
|
||||
QString value = stringPairDrag::decodeValue( _de );
|
||||
if( type == "samplefile" )
|
||||
{
|
||||
m_params->m_userWave.setAudioFile(
|
||||
stringPairDrag::decodeValue( _de ) );
|
||||
m_userLfoBtn->model()->setValue( TRUE );
|
||||
_de->accept();
|
||||
}
|
||||
else if( type == QString( "tco_%1" ).arg( track::SampleTrack ) )
|
||||
{
|
||||
multimediaProject mmp( value, FALSE );
|
||||
m_params->m_userWave.setAudioFile(
|
||||
mmp.content().firstChild().toElement().
|
||||
attribute( "src" ) );
|
||||
m_userLfoBtn->model()->setValue( TRUE );
|
||||
_de->accept();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void envelopeAndLFOView::paintEvent( QPaintEvent * )
|
||||
{
|
||||
QPainter p( this );
|
||||
p.setRenderHint( QPainter::Antialiasing );
|
||||
|
||||
// set smaller font
|
||||
p.setFont( pointSize<6>( p.font() ) );
|
||||
|
||||
// draw envelope-graph
|
||||
p.drawPixmap( ENV_GRAPH_X, ENV_GRAPH_Y, *s_envGraph );
|
||||
// draw LFO-graph
|
||||
p.drawPixmap( LFO_GRAPH_X, LFO_GRAPH_Y, *s_lfoGraph );
|
||||
|
||||
|
||||
p.setFont( pointSize<8>( p.font() ) );
|
||||
|
||||
const float gray_amount = 1.0f - fabsf( m_amountKnob->value() );
|
||||
|
||||
p.setPen( QPen( QColor( static_cast<int>( 96 * gray_amount ),
|
||||
static_cast<int>( 255 - 159 * gray_amount ),
|
||||
static_cast<int>( 128 - 32 * gray_amount ) ),
|
||||
2 ) );
|
||||
|
||||
const QColor end_points_color( 0xFF, 0xBF, 0x22 );
|
||||
const QColor end_points_bg_color( 0, 0, 2 );
|
||||
|
||||
const int y_base = ENV_GRAPH_Y + s_envGraph->height() - 3;
|
||||
const int avail_height = s_envGraph->height() - 6;
|
||||
|
||||
int x1 = ENV_GRAPH_X + 2 + static_cast<int>( m_predelayKnob->value() *
|
||||
TIME_UNIT_WIDTH );
|
||||
int x2 = x1 + static_cast<int>( m_attackKnob->value() *
|
||||
TIME_UNIT_WIDTH );
|
||||
|
||||
p.drawLine( x1, y_base, x2, y_base - avail_height );
|
||||
p.fillRect( x1 - 1, y_base - 2, 4, 4, end_points_bg_color );
|
||||
p.fillRect( x1, y_base - 1, 2, 2, end_points_color );
|
||||
x1 = x2;
|
||||
x2 = x1 + static_cast<int>( m_holdKnob->value() * TIME_UNIT_WIDTH );
|
||||
|
||||
p.drawLine( x1, y_base - avail_height, x2, y_base - avail_height );
|
||||
p.fillRect( x1 - 1, y_base - 2 - avail_height, 4, 4,
|
||||
end_points_bg_color );
|
||||
p.fillRect( x1, y_base-1-avail_height, 2, 2, end_points_color );
|
||||
x1 = x2;
|
||||
x2 = x1 + static_cast<int>( ( m_decayKnob->value() *
|
||||
m_sustainKnob->value() ) *
|
||||
TIME_UNIT_WIDTH );
|
||||
|
||||
p.drawLine( x1, y_base-avail_height, x2, static_cast<int>( y_base -
|
||||
avail_height +
|
||||
m_sustainKnob->value() * avail_height ) );
|
||||
p.fillRect( x1 - 1, y_base - 2 - avail_height, 4, 4,
|
||||
end_points_bg_color );
|
||||
p.fillRect( x1, y_base - 1 - avail_height, 2, 2, end_points_color );
|
||||
x1 = x2;
|
||||
x2 = x1 + static_cast<int>( m_releaseKnob->value() * TIME_UNIT_WIDTH );
|
||||
|
||||
p.drawLine( x1, static_cast<int>( y_base - avail_height +
|
||||
m_sustainKnob->value() *
|
||||
avail_height ), x2, y_base );
|
||||
p.fillRect( x1-1, static_cast<int>( y_base - avail_height +
|
||||
m_sustainKnob->value() *
|
||||
avail_height ) - 2, 4, 4,
|
||||
end_points_bg_color );
|
||||
p.fillRect( x1, static_cast<int>( y_base - avail_height +
|
||||
m_sustainKnob->value() *
|
||||
avail_height ) - 1, 2, 2,
|
||||
end_points_color );
|
||||
p.fillRect( x2 - 1, y_base - 2, 4, 4, end_points_bg_color );
|
||||
p.fillRect( x2, y_base - 1, 2, 2, end_points_color );
|
||||
|
||||
|
||||
int LFO_GRAPH_W = s_lfoGraph->width() - 6; // substract border
|
||||
int LFO_GRAPH_H = s_lfoGraph->height() - 6; // substract border
|
||||
int graph_x_base = LFO_GRAPH_X + 3;
|
||||
int graph_y_base = LFO_GRAPH_Y + 3 + LFO_GRAPH_H / 2;
|
||||
|
||||
const float frames_for_graph = SECS_PER_LFO_OSCILLATION *
|
||||
engine::getMixer()->sampleRate() / 10;
|
||||
|
||||
const float lfo_gray_amount = 1.0f - fabsf( m_lfoAmountKnob->value() );
|
||||
p.setPen( QPen( QColor( static_cast<int>( 96 * lfo_gray_amount ),
|
||||
static_cast<int>( 255 - 159 * lfo_gray_amount ),
|
||||
static_cast<int>( 128 - 32 *
|
||||
lfo_gray_amount ) ),
|
||||
1.5 ) );
|
||||
|
||||
|
||||
float osc_frames = m_params->m_lfoOscillationFrames;
|
||||
|
||||
if( m_params->m_x100Model.value() )
|
||||
{
|
||||
osc_frames *= 100.0f;
|
||||
}
|
||||
|
||||
float old_y = 0;
|
||||
for( int x = 0; x <= LFO_GRAPH_W; ++x )
|
||||
{
|
||||
float val = 0.0;
|
||||
float cur_sample = x * frames_for_graph / LFO_GRAPH_W;
|
||||
if( static_cast<f_cnt_t>( cur_sample ) >
|
||||
m_params->m_lfoPredelayFrames )
|
||||
{
|
||||
float phase = ( cur_sample -=
|
||||
m_params->m_lfoPredelayFrames ) /
|
||||
osc_frames;
|
||||
switch( m_params->m_lfoWaveModel.value() )
|
||||
{
|
||||
case envelopeAndLFOParameters::SineWave:
|
||||
val = oscillator::sinSample( phase );
|
||||
break;
|
||||
case envelopeAndLFOParameters::TriangleWave:
|
||||
val = oscillator::triangleSample(
|
||||
phase );
|
||||
break;
|
||||
case envelopeAndLFOParameters::SawWave:
|
||||
val = oscillator::sawSample( phase );
|
||||
break;
|
||||
case envelopeAndLFOParameters::SquareWave:
|
||||
val = oscillator::squareSample( phase );
|
||||
break;
|
||||
case envelopeAndLFOParameters::UserDefinedWave:
|
||||
val = m_params->m_userWave.
|
||||
userWaveSample( phase );
|
||||
}
|
||||
if( static_cast<f_cnt_t>( cur_sample ) <=
|
||||
m_params->m_lfoAttackFrames )
|
||||
{
|
||||
val *= cur_sample / m_params->m_lfoAttackFrames;
|
||||
}
|
||||
}
|
||||
float cur_y = -LFO_GRAPH_H / 2.0f * val;
|
||||
p.drawLine( QLineF( graph_x_base + x - 1, graph_y_base + old_y,
|
||||
graph_x_base + x,
|
||||
graph_y_base + cur_y ) );
|
||||
old_y = cur_y;
|
||||
}
|
||||
|
||||
p.setPen( QColor( 255, 192, 0 ) );
|
||||
int ms_per_osc = static_cast<int>( SECS_PER_LFO_OSCILLATION *
|
||||
m_lfoSpeedKnob->value() *
|
||||
1000.0f );
|
||||
p.drawText( LFO_GRAPH_X + 4, LFO_GRAPH_Y + s_lfoGraph->height() - 6,
|
||||
tr( "ms/LFO:" ) );
|
||||
p.drawText( LFO_GRAPH_X + 52, LFO_GRAPH_Y + s_lfoGraph->height() - 6,
|
||||
QString::number( ms_per_osc ) );
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void envelopeAndLFOView::lfoUserWaveChanged( void )
|
||||
{
|
||||
if( m_params->m_lfoWaveModel.value() ==
|
||||
envelopeAndLFOParameters::UserDefinedWave )
|
||||
{
|
||||
if( m_params->m_userWave.frames() <= 1 )
|
||||
{
|
||||
textFloat::displayMessage( tr( "Hint" ),
|
||||
tr( "Drag a sample from somewhere and drop "
|
||||
"it in this window." ),
|
||||
embed::getIconPixmap( "hint" ), 3000 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#include "envelope_and_lfo_view.moc"
|
||||
|
||||
|
||||
#endif
|
||||
254
src/widgets/instrument_function_views.cpp
Normal file
254
src/widgets/instrument_function_views.cpp
Normal file
@@ -0,0 +1,254 @@
|
||||
#ifndef SINGLE_SOURCE_COMPILE
|
||||
|
||||
/*
|
||||
* instrument_function_views.cpp - view for instrument-functions-tab
|
||||
*
|
||||
* Copyright (c) 2004-2008 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* 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 (see COPYING); if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <QtGui/QLabel>
|
||||
|
||||
#include "instrument_functions.h"
|
||||
#include "instrument_function_views.h"
|
||||
#include "combobox.h"
|
||||
#include "embed.h"
|
||||
#include "engine.h"
|
||||
#include "group_box.h"
|
||||
#include "gui_templates.h"
|
||||
#include "knob.h"
|
||||
#include "led_checkbox.h"
|
||||
#include "pixmap_button.h"
|
||||
#include "tempo_sync_knob.h"
|
||||
#include "tooltip.h"
|
||||
|
||||
|
||||
|
||||
const int CHORDS_GROUPBOX_X = 4;
|
||||
const int CHORDS_GROUPBOX_Y = 5;
|
||||
const int CHORDS_GROUPBOX_WIDTH = 238;
|
||||
const int CHORDS_GROUPBOX_HEIGHT = 65;
|
||||
const int ARP_GROUPBOX_X = CHORDS_GROUPBOX_X;
|
||||
const int ARP_GROUPBOX_Y = 10 + CHORDS_GROUPBOX_Y + CHORDS_GROUPBOX_HEIGHT;
|
||||
const int ARP_GROUPBOX_WIDTH = CHORDS_GROUPBOX_WIDTH;
|
||||
const int ARP_GROUPBOX_HEIGHT = 240 - ARP_GROUPBOX_Y;
|
||||
|
||||
|
||||
|
||||
chordCreatorView::chordCreatorView( chordCreator * _cc, QWidget * _parent ) :
|
||||
QWidget( _parent ),
|
||||
modelView( NULL ),
|
||||
m_cc( _cc ),
|
||||
m_chordsGroupBox( new groupBox( tr( "CHORDS" ), this ) ),
|
||||
m_chordsComboBox( new comboBox( m_chordsGroupBox,
|
||||
tr( "Chord type" ) ) ),
|
||||
m_chordRangeKnob( new knob( knobBright_26, m_chordsGroupBox,
|
||||
tr( "Chord range" ) ) )
|
||||
{
|
||||
move( CHORDS_GROUPBOX_X, CHORDS_GROUPBOX_Y );
|
||||
setFixedSize( 250, CHORDS_GROUPBOX_HEIGHT );
|
||||
m_chordsGroupBox->setGeometry( 0, 0, CHORDS_GROUPBOX_WIDTH,
|
||||
CHORDS_GROUPBOX_HEIGHT );
|
||||
|
||||
|
||||
m_chordsComboBox->setGeometry( 10, 25, 140, 22 );
|
||||
|
||||
|
||||
m_chordRangeKnob->setLabel( tr( "RANGE" ) );
|
||||
m_chordRangeKnob->move( 164, 24 );
|
||||
m_chordRangeKnob->setHintText( tr( "Chord range:" ) + " ", " " +
|
||||
tr( "octave(s)" ) );
|
||||
m_chordRangeKnob->setWhatsThis(
|
||||
tr( "Use this knob for setting the chord range in octaves. "
|
||||
"The selected chord will be played within specified "
|
||||
"amount of octaves." ) );
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
chordCreatorView::~chordCreatorView()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void chordCreatorView::modelChanged( void )
|
||||
{
|
||||
m_cc = castModel<chordCreator>();
|
||||
m_chordsGroupBox->setModel( &m_cc->m_chordsEnabledModel );
|
||||
m_chordsComboBox->setModel( &m_cc->m_chordsModel );
|
||||
m_chordRangeKnob->setModel( &m_cc->m_chordRangeModel );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
arpeggiatorView::arpeggiatorView( arpeggiator * _arp, QWidget * _parent ) :
|
||||
QWidget( _parent ),
|
||||
modelView( NULL ),
|
||||
m_a( _arp ),
|
||||
m_arpGroupBox( new groupBox( tr( "ARPEGGIO" ), this ) ),
|
||||
m_arpComboBox( new comboBox( m_arpGroupBox, tr( "Arpeggio type" ) ) ),
|
||||
m_arpRangeKnob( new knob( knobBright_26, m_arpGroupBox,
|
||||
tr( "Arpeggio range" ) ) ),
|
||||
m_arpTimeKnob( new tempoSyncKnob( knobBright_26, m_arpGroupBox,
|
||||
tr( "Arpeggio time" ) ) ),
|
||||
m_arpGateKnob( new knob( knobBright_26, m_arpGroupBox,
|
||||
tr( "Arpeggio gate" ) ) ),
|
||||
m_arpModeComboBox( new comboBox( m_arpGroupBox,
|
||||
tr( "Arpeggio mode" ) ) )
|
||||
{
|
||||
move( ARP_GROUPBOX_X, ARP_GROUPBOX_Y );
|
||||
setFixedSize( 250, ARP_GROUPBOX_HEIGHT );
|
||||
m_arpGroupBox->setGeometry( 0, 0, ARP_GROUPBOX_WIDTH,
|
||||
ARP_GROUPBOX_HEIGHT );
|
||||
|
||||
m_arpGroupBox->setWhatsThis(
|
||||
tr( "An arpeggio is a type of playing (especially plucked) "
|
||||
"instruments, which makes the music much livelier. "
|
||||
"The strings of such instruments (e.g. harps) are "
|
||||
"plucked like chords, the only difference is, that "
|
||||
"this is done in a sequential order, so the notes are "
|
||||
"not played at the same time. Typical arpeggios are "
|
||||
"major or minor triads. But there're a lot of other "
|
||||
"possible chords, you can select." ) );
|
||||
|
||||
|
||||
m_arpComboBox->setGeometry( 10, 25, 140, 22 );
|
||||
|
||||
|
||||
m_arpRangeKnob->setLabel( tr( "RANGE" ) );
|
||||
m_arpRangeKnob->move( 164, 24 );
|
||||
m_arpRangeKnob->setHintText( tr( "Arpeggio range:" ) + " ", " " +
|
||||
tr( "octave(s)" ) );
|
||||
m_arpRangeKnob->setWhatsThis(
|
||||
tr( "Use this knob for setting the arpeggio range in octaves. "
|
||||
"The selected arpeggio will be played within specified "
|
||||
"amount of octaves." ) );
|
||||
|
||||
|
||||
m_arpTimeKnob->setLabel( tr( "TIME" ) );
|
||||
m_arpTimeKnob->move( 164, 70 );
|
||||
m_arpTimeKnob->setHintText( tr( "Arpeggio time:" ) + " ", " " +
|
||||
tr( "ms" ) );
|
||||
m_arpTimeKnob->setWhatsThis(
|
||||
tr( "Use this knob for setting the arpeggio time in "
|
||||
"milliseconds. The arpeggio time specifies how long "
|
||||
"each arpeggio-tone should be played." ) );
|
||||
|
||||
|
||||
m_arpGateKnob->setLabel( tr( "GATE" ) );
|
||||
m_arpGateKnob->move( 204, 70 );
|
||||
m_arpGateKnob->setHintText( tr( "Arpeggio gate:" ) + " ", tr( "%" ) );
|
||||
m_arpGateKnob->setWhatsThis(
|
||||
tr( "Use this knob for setting the arpeggio gate. The "
|
||||
"arpeggio gate specifies the percent of a whole "
|
||||
"arpeggio-tone that should be played. With this you "
|
||||
"can make cool staccato-arpeggios." ) );
|
||||
|
||||
m_arpDirectionLbl = new QLabel( tr( "Direction:" ), m_arpGroupBox );
|
||||
m_arpDirectionLbl->setGeometry( 10, 60, 64, 10 );
|
||||
m_arpDirectionLbl->setFont( pointSize<7>( m_arpDirectionLbl->font() ) );
|
||||
|
||||
|
||||
|
||||
pixmapButton * arp_up_btn = new pixmapButton( m_arpGroupBox, NULL );
|
||||
arp_up_btn->move( 10, 74 );
|
||||
arp_up_btn->setActiveGraphic( embed::getIconPixmap( "arp_up_on" ) );
|
||||
arp_up_btn->setInactiveGraphic( embed::getIconPixmap( "arp_up_off" ) );
|
||||
toolTip::add( arp_up_btn, tr( "arpeggio direction = up" ) );
|
||||
|
||||
|
||||
pixmapButton * arp_down_btn = new pixmapButton( m_arpGroupBox, NULL );
|
||||
arp_down_btn->move( 30, 74 );
|
||||
arp_down_btn->setActiveGraphic( embed::getIconPixmap( "arp_down_on" ) );
|
||||
arp_down_btn->setInactiveGraphic( embed::getIconPixmap(
|
||||
"arp_down_off" ) );
|
||||
toolTip::add( arp_down_btn, tr( "arpeggio direction = down" ) );
|
||||
|
||||
|
||||
pixmapButton * arp_up_and_down_btn = new pixmapButton( m_arpGroupBox,
|
||||
NULL );
|
||||
arp_up_and_down_btn->move( 50, 74 );
|
||||
arp_up_and_down_btn->setActiveGraphic( embed::getIconPixmap(
|
||||
"arp_up_and_down_on" ) );
|
||||
arp_up_and_down_btn->setInactiveGraphic( embed::getIconPixmap(
|
||||
"arp_up_and_down_off" ) );
|
||||
toolTip::add( arp_up_and_down_btn,
|
||||
tr( "arpeggio direction = up and down" ) );
|
||||
|
||||
|
||||
pixmapButton * arp_random_btn = new pixmapButton( m_arpGroupBox, NULL );
|
||||
arp_random_btn->move( 70, 74 );
|
||||
arp_random_btn->setActiveGraphic( embed::getIconPixmap(
|
||||
"arp_random_on" ) );
|
||||
arp_random_btn->setInactiveGraphic( embed::getIconPixmap(
|
||||
"arp_random_off" ) );
|
||||
toolTip::add( arp_random_btn, tr( "arpeggio direction = random" ) );
|
||||
|
||||
m_arpDirectionBtnGrp = new automatableButtonGroup( this,
|
||||
tr( "Arpeggio direction" ) );
|
||||
m_arpDirectionBtnGrp->addButton( arp_up_btn );
|
||||
m_arpDirectionBtnGrp->addButton( arp_down_btn );
|
||||
m_arpDirectionBtnGrp->addButton( arp_up_and_down_btn );
|
||||
m_arpDirectionBtnGrp->addButton( arp_random_btn );
|
||||
|
||||
|
||||
|
||||
QLabel * mode_lbl = new QLabel( tr( "Mode:" ), m_arpGroupBox );
|
||||
mode_lbl->setGeometry( 10, 104, 64, 10 );
|
||||
mode_lbl->setFont( pointSize<7>( mode_lbl->font() ) );
|
||||
|
||||
m_arpModeComboBox->setGeometry( 10, 118, 128, 22 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
arpeggiatorView::~arpeggiatorView()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void arpeggiatorView::modelChanged( void )
|
||||
{
|
||||
m_a = castModel<arpeggiator>();
|
||||
m_arpGroupBox->setModel( &m_a->m_arpEnabledModel );
|
||||
m_arpComboBox->setModel( &m_a->m_arpModel );
|
||||
m_arpRangeKnob->setModel( &m_a->m_arpRangeModel );
|
||||
m_arpTimeKnob->setModel( &m_a->m_arpTimeModel );
|
||||
m_arpGateKnob->setModel( &m_a->m_arpGateModel );
|
||||
m_arpDirectionBtnGrp->setModel( &m_a->m_arpDirectionModel );
|
||||
m_arpModeComboBox->setModel( &m_a->m_arpModeModel );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
207
src/widgets/instrument_midi_io_view.cpp
Normal file
207
src/widgets/instrument_midi_io_view.cpp
Normal file
@@ -0,0 +1,207 @@
|
||||
#ifndef SINGLE_SOURCE_COMPILE
|
||||
|
||||
/*
|
||||
* instrument_midi_io_view.cpp - MIDI-IO-View
|
||||
*
|
||||
* Copyright (c) 2005-2008 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* 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 (see COPYING); if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <QtGui/QMenu>
|
||||
#include <QtGui/QToolButton>
|
||||
|
||||
|
||||
#include "instrument_midi_io_view.h"
|
||||
#include "instrument_midi_io.h"
|
||||
#include "embed.h"
|
||||
#include "engine.h"
|
||||
#include "gui_templates.h"
|
||||
#include "midi_client.h"
|
||||
#include "midi_port.h"
|
||||
#include "mixer.h"
|
||||
#include "led_checkbox.h"
|
||||
#include "lcd_spinbox.h"
|
||||
#include "tab_widget.h"
|
||||
#include "tooltip.h"
|
||||
#include "automatable_model_templates.h"
|
||||
|
||||
|
||||
|
||||
instrumentMidiIOView::instrumentMidiIOView( QWidget * _parent ) :
|
||||
QWidget( _parent ),
|
||||
modelView( NULL ),
|
||||
m_readablePorts( NULL ),
|
||||
m_writeablePorts( NULL )
|
||||
{
|
||||
m_setupTabWidget = new tabWidget( tr( "MIDI-SETUP FOR THIS CHANNEL" ),
|
||||
this );
|
||||
m_setupTabWidget->setGeometry( 4, 5, 238, 200 );
|
||||
|
||||
m_inputChannelSpinBox = new lcdSpinBox( 3, m_setupTabWidget,
|
||||
tr( "Input channel" ) );
|
||||
m_inputChannelSpinBox->addTextForValue( 0, "---" );
|
||||
m_inputChannelSpinBox->setLabel( tr( "CHANNEL" ) );
|
||||
m_inputChannelSpinBox->move( 28, 52 );
|
||||
m_inputChannelSpinBox->setEnabled( FALSE );
|
||||
|
||||
|
||||
|
||||
m_outputChannelSpinBox = new lcdSpinBox( 3, m_setupTabWidget,
|
||||
tr( "Output channel" ) );
|
||||
m_outputChannelSpinBox->setLabel( tr( "CHANNEL" ) );
|
||||
m_outputChannelSpinBox->move( 28, 132 );
|
||||
m_outputChannelSpinBox->setEnabled( FALSE );
|
||||
|
||||
|
||||
m_receiveCheckBox = new ledCheckBox( tr( "Receive MIDI-events" ),
|
||||
m_setupTabWidget,
|
||||
tr( "Receive MIDI-events" ) );
|
||||
m_receiveCheckBox->move( 10, 34 );
|
||||
// enabling/disabling widgets is UI-stuff thus we do not use model here
|
||||
connect( m_receiveCheckBox, SIGNAL( toggled( bool ) ),
|
||||
m_inputChannelSpinBox, SLOT( setEnabled( bool ) ) );
|
||||
|
||||
|
||||
m_defaultVelocityInCheckBox = new ledCheckBox(
|
||||
tr( "Default velocity for all input-events" ),
|
||||
m_setupTabWidget,
|
||||
tr( "Default input velocity" ) );
|
||||
m_defaultVelocityInCheckBox->move( 28, 84 );
|
||||
|
||||
|
||||
m_sendCheckBox = new ledCheckBox( tr( "Send MIDI-events" ),
|
||||
m_setupTabWidget,
|
||||
tr( "Send MIDI-events" ) );
|
||||
m_sendCheckBox->move( 10, 114 );
|
||||
connect( m_sendCheckBox, SIGNAL( toggled( bool ) ),
|
||||
m_outputChannelSpinBox, SLOT( setEnabled( bool ) ) );
|
||||
|
||||
|
||||
m_defaultVelocityOutCheckBox = new ledCheckBox(
|
||||
tr( "Default velocity for all output-events" ),
|
||||
m_setupTabWidget,
|
||||
tr( "Default output velocity" ) );
|
||||
m_defaultVelocityOutCheckBox->move( 28, 164 );
|
||||
|
||||
|
||||
|
||||
// when using with non-raw-clients we can provide buttons showing
|
||||
// our port-menus when being clicked
|
||||
midiClient * mc = engine::getMixer()->getMIDIClient();
|
||||
if( mc->isRaw() == FALSE )
|
||||
{
|
||||
m_readablePorts = new QMenu( m_setupTabWidget );
|
||||
m_readablePorts->setFont( pointSize<9>(
|
||||
m_readablePorts->font() ) );
|
||||
connect( m_readablePorts, SIGNAL( triggered( QAction * ) ),
|
||||
this, SLOT( activatedReadablePort( QAction * ) ) );
|
||||
|
||||
m_writeablePorts = new QMenu( m_setupTabWidget );
|
||||
m_writeablePorts->setFont( pointSize<9>(
|
||||
m_writeablePorts->font() ) );
|
||||
connect( m_writeablePorts, SIGNAL( triggered( QAction * ) ),
|
||||
this, SLOT( activatedWriteablePort( QAction * ) ) );
|
||||
|
||||
// fill menus
|
||||
/* readablePortsChanged();
|
||||
writeablePortsChanged();*/
|
||||
|
||||
QToolButton * rp_btn = new QToolButton( m_setupTabWidget );
|
||||
rp_btn->setText( tr( "MIDI-devices to receive "
|
||||
"MIDI-events from" ) );
|
||||
rp_btn->setIcon( embed::getIconPixmap( "midi_in" ) );
|
||||
rp_btn->setGeometry( 186, 34, 40, 40 );
|
||||
rp_btn->setMenu( m_readablePorts );
|
||||
rp_btn->setPopupMode( QToolButton::InstantPopup );
|
||||
|
||||
QToolButton * wp_btn = new QToolButton( m_setupTabWidget );
|
||||
wp_btn->setText( tr( "MIDI-devices to send MIDI-events "
|
||||
"to" ) );
|
||||
wp_btn->setIcon( embed::getIconPixmap( "midi_out" ) );
|
||||
wp_btn->setGeometry( 186, 114, 40, 40 );
|
||||
wp_btn->setMenu( m_writeablePorts );
|
||||
wp_btn->setPopupMode( QToolButton::InstantPopup );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
instrumentMidiIOView::~instrumentMidiIOView()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void instrumentMidiIOView::modelChanged( void )
|
||||
{
|
||||
instrumentMidiIO * mio = castModel<instrumentMidiIO>();
|
||||
m_inputChannelSpinBox->setModel( &mio->m_inputChannelModel );
|
||||
m_outputChannelSpinBox->setModel( &mio->m_outputChannelModel );
|
||||
m_receiveCheckBox->setModel( &mio->m_receiveEnabledModel );
|
||||
m_defaultVelocityInCheckBox->setModel(
|
||||
&mio->m_defaultVelocityInEnabledModel );
|
||||
m_sendCheckBox->setModel( &mio->m_sendEnabledModel );
|
||||
m_defaultVelocityOutCheckBox->setModel(
|
||||
&mio->m_defaultVelocityOutEnabledModel );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void instrumentMidiIOView::activatedReadablePort( QAction * _item )
|
||||
{
|
||||
instrumentMidiIO * mio = castModel<instrumentMidiIO>();
|
||||
// make sure, MIDI-port is configured for input
|
||||
if( _item->isChecked() == TRUE &&
|
||||
mio->m_midiPort->mode() != midiPort::INPUT &&
|
||||
mio->m_midiPort->mode() != midiPort::DUPLEX )
|
||||
{
|
||||
mio->m_receiveEnabledModel.setValue( TRUE );
|
||||
}
|
||||
engine::getMixer()->getMIDIClient()->subscribeReadablePort(
|
||||
mio->m_midiPort, _item->text(), !_item->isChecked() );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void instrumentMidiIOView::activatedWriteablePort( QAction * _item )
|
||||
{
|
||||
instrumentMidiIO * mio = castModel<instrumentMidiIO>();
|
||||
// make sure, MIDI-port is configured for output
|
||||
if( _item->isChecked() == TRUE &&
|
||||
mio->m_midiPort->mode() != midiPort::OUTPUT &&
|
||||
mio->m_midiPort->mode() != midiPort::DUPLEX )
|
||||
{
|
||||
mio->m_sendEnabledModel.setValue( TRUE );
|
||||
}
|
||||
engine::getMixer()->getMIDIClient()->subscribeWriteablePort(
|
||||
mio->m_midiPort, _item->text(), !_item->isChecked() );
|
||||
}
|
||||
|
||||
|
||||
|
||||
#include "instrument_midi_io_view.moc"
|
||||
|
||||
|
||||
#endif
|
||||
150
src/widgets/instrument_sound_shaping_view.cpp
Normal file
150
src/widgets/instrument_sound_shaping_view.cpp
Normal file
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* instrument_sound_shaping_view.cpp - view for instrumentSoundShaping-class
|
||||
*
|
||||
* Copyright (c) 2004-2008 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* 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 (see COPYING); if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "instrument_sound_shaping_view.h"
|
||||
#include "envelope_and_lfo_parameters.h"
|
||||
#include "envelope_and_lfo_view.h"
|
||||
#include "combobox.h"
|
||||
#include "group_box.h"
|
||||
#include "gui_templates.h"
|
||||
#include "knob.h"
|
||||
#include "tab_widget.h"
|
||||
|
||||
|
||||
|
||||
const int TARGETS_TABWIDGET_X = 4;
|
||||
const int TARGETS_TABWIDGET_Y = 5;
|
||||
const int TARGETS_TABWIDGET_WIDTH = 238;
|
||||
const int TARGETS_TABWIDGET_HEIGTH = 175;
|
||||
|
||||
const int FILTER_GROUPBOX_X = TARGETS_TABWIDGET_X;
|
||||
const int FILTER_GROUPBOX_Y = TARGETS_TABWIDGET_Y+TARGETS_TABWIDGET_HEIGTH+5;
|
||||
const int FILTER_GROUPBOX_WIDTH = TARGETS_TABWIDGET_WIDTH;
|
||||
const int FILTER_GROUPBOX_HEIGHT = 245-FILTER_GROUPBOX_Y;
|
||||
|
||||
|
||||
|
||||
instrumentSoundShapingView::instrumentSoundShapingView( QWidget * _parent ) :
|
||||
QWidget( _parent ),
|
||||
modelView( NULL ),
|
||||
m_ss( NULL )
|
||||
{
|
||||
m_targetsTabWidget = new tabWidget( tr( "TARGET" ), this );
|
||||
m_targetsTabWidget->setGeometry( TARGETS_TABWIDGET_X,
|
||||
TARGETS_TABWIDGET_Y,
|
||||
TARGETS_TABWIDGET_WIDTH,
|
||||
TARGETS_TABWIDGET_HEIGTH );
|
||||
m_targetsTabWidget->setWhatsThis(
|
||||
tr( "These tabs contain envelopes. They're very important for "
|
||||
"modifying a sound, for not saying that they're almost "
|
||||
"always neccessary for substractive synthesis. For "
|
||||
"example if you have a volume-envelope, you can set "
|
||||
"when the sound should have which volume-level. "
|
||||
"Maybe you want to create some soft strings. Then your "
|
||||
"sound has to fade in and out very softly. This can be "
|
||||
"done by setting a large attack- and release-time. "
|
||||
"It's the same for other envelope-targets like "
|
||||
"panning, cutoff-frequency of used filter and so on. "
|
||||
"Just monkey around with it! You can really make cool "
|
||||
"sounds out of a saw-wave with just some "
|
||||
"envelopes...!" ) );
|
||||
|
||||
for( int i = 0; i < instrumentSoundShaping::NumTargets; ++i )
|
||||
{
|
||||
m_envLFOViews[i] = new envelopeAndLFOView( m_targetsTabWidget );
|
||||
m_targetsTabWidget->addTab( m_envLFOViews[i],
|
||||
tr( __targetNames[i][0]
|
||||
.toAscii().constData() ) );
|
||||
}
|
||||
|
||||
|
||||
m_filterGroupBox = new groupBox( tr( "FILTER" ), this );
|
||||
m_filterGroupBox->setGeometry( FILTER_GROUPBOX_X, FILTER_GROUPBOX_Y,
|
||||
FILTER_GROUPBOX_WIDTH,
|
||||
FILTER_GROUPBOX_HEIGHT );
|
||||
|
||||
|
||||
m_filterComboBox = new comboBox( m_filterGroupBox,
|
||||
tr( "Filter type" ) );
|
||||
m_filterComboBox->setGeometry( 14, 22, 120, 22 );
|
||||
m_filterComboBox->setFont( pointSize<8>( m_filterComboBox->font() ) );
|
||||
|
||||
m_filterComboBox->setWhatsThis(
|
||||
tr( "Here you can select the built-in filter you want to use "
|
||||
"for this instrument-track. Filters are very important "
|
||||
"for changing the characteristics of a sound." ) );
|
||||
|
||||
|
||||
m_filterCutKnob = new knob( knobBright_26, m_filterGroupBox,
|
||||
tr( "cutoff-frequency" ) );
|
||||
m_filterCutKnob->setLabel( tr( "CUTOFF" ) );
|
||||
m_filterCutKnob->move( 140, 18 );
|
||||
m_filterCutKnob->setHintText( tr( "cutoff-frequency:" ) + " ", " " +
|
||||
tr( "Hz" ) );
|
||||
m_filterCutKnob->setWhatsThis(
|
||||
tr( "Use this knob for setting the cutoff-frequency for the "
|
||||
"selected filter. The cutoff-frequency specifies the "
|
||||
"frequency for cutting the signal by a filter. For "
|
||||
"example a lowpass-filter cuts all frequencies above "
|
||||
"the cutoff-frequency. A highpass-filter cuts all "
|
||||
"frequencies below cutoff-frequency and so on..." ) );
|
||||
|
||||
|
||||
m_filterResKnob = new knob( knobBright_26, m_filterGroupBox,
|
||||
tr( "Q/Resonance" ) );
|
||||
m_filterResKnob->setLabel( tr( "Q/RESO" ) );
|
||||
m_filterResKnob->move( 190, 18 );
|
||||
m_filterResKnob->setHintText( tr( "Q/Resonance:" ) + " ", "" );
|
||||
m_filterResKnob->setWhatsThis(
|
||||
tr( "Use this knob for setting Q/Resonance for the selected "
|
||||
"filter. Q/Resonance tells the filter, how much it "
|
||||
"should amplify frequencies near Cutoff-frequency." ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
instrumentSoundShapingView::~instrumentSoundShapingView()
|
||||
{
|
||||
delete m_targetsTabWidget;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void instrumentSoundShapingView::modelChanged( void )
|
||||
{
|
||||
m_ss = castModel<instrumentSoundShaping>();
|
||||
m_filterGroupBox->setModel( &m_ss->m_filterEnabledModel );
|
||||
m_filterComboBox->setModel( &m_ss->m_filterModel );
|
||||
m_filterCutKnob->setModel( &m_ss->m_filterCutModel );
|
||||
m_filterResKnob->setModel( &m_ss->m_filterResModel );
|
||||
for( int i = 0; i < instrumentSoundShaping::NumTargets; ++i )
|
||||
{
|
||||
m_envLFOViews[i]->setModel( m_ss->m_envLFOParameters[i] );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/*
|
||||
* project_notes.cpp - implementation of project-notes-editor
|
||||
*
|
||||
* Copyright (c) 2005-2007 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2005-2008 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
@@ -42,7 +42,7 @@
|
||||
#include "embed.h"
|
||||
#include "engine.h"
|
||||
#include "main_window.h"
|
||||
#include "song_editor.h"
|
||||
#include "song.h"
|
||||
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ projectNotes::projectNotes( void ) :
|
||||
// connect( m_edit, SIGNAL( currentAlignmentChanged( int ) ),
|
||||
// this, SLOT( alignmentChanged( int ) ) );
|
||||
connect( m_edit, SIGNAL( textChanged() ),
|
||||
engine::getSongEditor(), SLOT( setModified() ) );
|
||||
engine::getSong(), SLOT( setModified() ) );
|
||||
|
||||
setupActions();
|
||||
|
||||
@@ -258,7 +258,7 @@ void projectNotes::textBold()
|
||||
{
|
||||
m_edit->setFontWeight( m_actionTextBold->isChecked() ? QFont::Bold :
|
||||
QFont::Normal );
|
||||
engine::getSongEditor()->setModified();
|
||||
engine::getSong()->setModified();
|
||||
}
|
||||
|
||||
|
||||
@@ -267,7 +267,7 @@ void projectNotes::textBold()
|
||||
void projectNotes::textUnderline()
|
||||
{
|
||||
m_edit->setFontUnderline( m_actionTextUnderline->isChecked() );
|
||||
engine::getSongEditor()->setModified();
|
||||
engine::getSong()->setModified();
|
||||
}
|
||||
|
||||
|
||||
@@ -276,7 +276,7 @@ void projectNotes::textUnderline()
|
||||
void projectNotes::textItalic()
|
||||
{
|
||||
m_edit->setFontItalic( m_actionTextItalic->isChecked() );
|
||||
engine::getSongEditor()->setModified();
|
||||
engine::getSong()->setModified();
|
||||
}
|
||||
|
||||
|
||||
@@ -286,7 +286,7 @@ void projectNotes::textFamily( const QString & _f )
|
||||
{
|
||||
m_edit->setFontFamily( _f );
|
||||
m_edit->viewport()->setFocus();
|
||||
engine::getSongEditor()->setModified();
|
||||
engine::getSong()->setModified();
|
||||
}
|
||||
|
||||
|
||||
@@ -296,7 +296,7 @@ void projectNotes::textSize( const QString & _p )
|
||||
{
|
||||
m_edit->setFontPointSize( _p.toInt() );
|
||||
m_edit->viewport()->setFocus();
|
||||
engine::getSongEditor()->setModified();
|
||||
engine::getSong()->setModified();
|
||||
}
|
||||
|
||||
|
||||
@@ -354,7 +354,7 @@ void projectNotes::formatChanged( const QTextCharFormat & _f )
|
||||
pix.fill( _f.foreground().color() );
|
||||
m_actionTextColor->setIcon( pix );
|
||||
|
||||
engine::getSongEditor()->setModified();
|
||||
engine::getSong()->setModified();
|
||||
}
|
||||
|
||||
|
||||
@@ -378,7 +378,7 @@ void projectNotes::alignmentChanged( int _a )
|
||||
{
|
||||
m_actionAlignJustify->setChecked( TRUE );
|
||||
}
|
||||
engine::getSongEditor()->setModified();
|
||||
engine::getSong()->setModified();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* tempo_sync_knob.cpp - adds bpm to ms conversion for knob class
|
||||
*
|
||||
* Copyright (c) 2005-2007 Danny McRae <khjklujn/at/yahoo.com>
|
||||
* Copyright (c) 2005-2007 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
* Copyright (c) 2005-2008 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
|
||||
*
|
||||
@@ -37,7 +37,7 @@
|
||||
#include "embed.h"
|
||||
#include "main_window.h"
|
||||
#include "meter_dialog.h"
|
||||
#include "song_editor.h"
|
||||
#include "song.h"
|
||||
|
||||
|
||||
tempoSyncKnob::tempoSyncKnob( int _knob_num, QWidget * _parent,
|
||||
@@ -50,7 +50,7 @@ tempoSyncKnob::tempoSyncKnob( int _knob_num, QWidget * _parent,
|
||||
m_tempoSyncDescription( tr( "Tempo Sync" ) ),
|
||||
m_tempoLastSyncMode( NO_SYNC )
|
||||
{
|
||||
connect( engine::getSongEditor(), SIGNAL( tempoChanged( bpm_t ) ),
|
||||
connect( engine::getSong(), SIGNAL( tempoChanged( bpm_t ) ),
|
||||
this, SLOT( calculateTempoSyncTime( bpm_t ) ) );
|
||||
m_custom = new meterDialog( engine::getMainWindow()->workspace(),
|
||||
NULL );
|
||||
@@ -93,7 +93,7 @@ void tempoSyncKnob::contextMenuEvent( QContextMenuEvent * )
|
||||
this, SLOT( pasteValue() ) );
|
||||
contextMenu.addSeparator();
|
||||
|
||||
float limit = 60000.0f / ( engine::getSongEditor()->getTempo() *
|
||||
float limit = 60000.0f / ( engine::getSong()->getTempo() *
|
||||
m_scale );
|
||||
|
||||
QMenu * syncMenu = contextMenu.addMenu( m_tempoSyncIcon,
|
||||
@@ -173,7 +173,7 @@ void tempoSyncKnob::contextMenuEvent( QContextMenuEvent * )
|
||||
void tempoSyncKnob::mouseMoveEvent( QMouseEvent * _me )
|
||||
{
|
||||
m_tempoSyncMode = NO_SYNC;
|
||||
calculateTempoSyncTime( engine::getSongEditor()->getTempo() );
|
||||
calculateTempoSyncTime( engine::getSong()->getTempo() );
|
||||
knob::mouseMoveEvent( _me );
|
||||
}
|
||||
|
||||
@@ -184,7 +184,7 @@ void tempoSyncKnob::wheelEvent( QWheelEvent * _we )
|
||||
{
|
||||
knob::wheelEvent( _we );
|
||||
m_tempoSyncMode = NO_SYNC;
|
||||
calculateTempoSyncTime( engine::getSongEditor()->getTempo() );
|
||||
calculateTempoSyncTime( engine::getSong()->getTempo() );
|
||||
}
|
||||
|
||||
|
||||
@@ -201,7 +201,7 @@ void tempoSyncKnob::setTempoSync( QAction * _item )
|
||||
void tempoSyncKnob::setTempoSync( int _note_type )
|
||||
{
|
||||
setSyncMode( ( tempoSyncMode ) _note_type );
|
||||
engine::getSongEditor()->setModified();
|
||||
engine::getSong()->setModified();
|
||||
}
|
||||
|
||||
|
||||
@@ -380,7 +380,7 @@ void tempoSyncKnob::setSyncMode( tempoSyncMode _new_mode )
|
||||
this, SLOT( updateCustom() ) );
|
||||
}
|
||||
}
|
||||
calculateTempoSyncTime( engine::getSongEditor()->getTempo() );
|
||||
calculateTempoSyncTime( engine::getSong()->getTempo() );
|
||||
}
|
||||
|
||||
|
||||
@@ -397,7 +397,7 @@ float tempoSyncKnob::getScale( void )
|
||||
void tempoSyncKnob::setScale( float _new_scale )
|
||||
{
|
||||
m_scale = _new_scale;
|
||||
calculateTempoSyncTime( engine::getSongEditor()->getTempo() );
|
||||
calculateTempoSyncTime( engine::getSong()->getTempo() );
|
||||
emit scaleChanged( _new_scale );
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user