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:
Tobias Doerffel
2008-02-16 02:04:58 +00:00
parent 40017887e9
commit 5d5ad19021
79 changed files with 8453 additions and 6656 deletions

View File

@@ -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

View File

@@ -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;

View File

@@ -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"

View File

@@ -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"

View File

@@ -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();
}

View File

@@ -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"

View File

@@ -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 != "" )

View File

@@ -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;
}
}

View File

@@ -31,6 +31,7 @@
#include "engine.h"
#include "track_container.h"
#include "project_journal.h"
#include "automatable_model_templates.h"

View File

@@ -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 ) );
}

View 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

View File

@@ -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 );
}

View File

@@ -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"
/*

View File

@@ -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?

View File

@@ -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 );
}

View File

@@ -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;

View File

@@ -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() ) );

View File

@@ -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() );

View File

@@ -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 );

View File

@@ -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 );
}

View File

@@ -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 )
{

View File

@@ -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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -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;
}

File diff suppressed because it is too large Load Diff

View File

@@ -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"

View File

@@ -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() )

View File

@@ -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 );

View File

@@ -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();
}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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,

View File

@@ -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;
}
}

View File

@@ -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 );*/

View 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

View 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

View 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

View 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] );
}
}

View File

@@ -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();
}

View File

@@ -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 );
}