void AutomationTrackView::dropEvent( QDropEvent * _de )
{
	QString type = StringPairDrag::decodeKey( _de );
	QString val = StringPairDrag::decodeValue( _de );
	if( type == "automatable_model" )
	{
		AutomatableModel * mod = dynamic_cast<AutomatableModel *>(
				Engine::projectJournal()->
					journallingObject( val.toInt() ) );
		if( mod != NULL )
		{
			MidiTime pos = MidiTime( trackContainerView()->
							currentPosition() +
				( _de->pos().x() -
					getTrackContentWidget()->x() ) *
						MidiTime::ticksPerTact() /
		static_cast<int>( trackContainerView()->pixelsPerTact() ) )
				.toAbsoluteTact();

			if( pos.getTicks() < 0 )
			{
				pos.setTicks( 0 );
			}

			TrackContentObject * tco = getTrack()->createTCO( pos );
			AutomationPattern * pat = dynamic_cast<AutomationPattern *>( tco );
			pat->addObject( mod );
			pat->movePosition( pos );
		}
	}

	update();
}
Example #2
0
void TimeLineWidget::mouseMoveEvent( QMouseEvent* event )
{
	const MidiTime t = m_begin + static_cast<int>( qMax( event->x() - m_xOffset - m_moveXOff, 0 ) * MidiTime::ticksPerTact() / m_ppt );

	switch( m_action )
	{
		case MovePositionMarker:
			m_pos.setTicks(t.getTicks());
			Engine::getSong()->setToTime(t, m_mode);
			if (!( Engine::getSong()->isPlaying()))
			{
				//Song::Mode_None is used when nothing is being played.
				Engine::getSong()->setToTime(t, Song::Mode_None);
			}
			m_pos.setCurrentFrame( 0 );
			m_pos.setJumped( true );
			updatePosition();
			positionMarkerMoved();
			break;

		case MoveLoopBegin:
		case MoveLoopEnd:
		{
			const int i = m_action - MoveLoopBegin;
			if( event->modifiers() & Qt::ControlModifier )
			{
				// no ctrl-press-hint when having ctrl pressed
				delete m_hint;
				m_hint = NULL;
				m_loopPos[i] = t;
			}
			else
			{
				m_loopPos[i] = t.toNearestTact();
			}
			// Catch begin == end
			if( m_loopPos[0] == m_loopPos[1] )
			{
				// Note, swap 1 and 0 below and the behavior "skips" the other
				// marking instead of pushing it.
				if( m_action == MoveLoopBegin ) 
					m_loopPos[0] -= MidiTime::ticksPerTact();
				else
					m_loopPos[1] += MidiTime::ticksPerTact();
			}
			update();
			break;
		}
	case SelectSongTCO:
			emit regionSelectedFromPixels( m_initalXSelect , event->x() );
		break;

		default:
			break;
	}
}
Example #3
0
void timeLine::mouseMoveEvent( QMouseEvent* event )
{
	const MidiTime t = m_begin + static_cast<int>( qMax( event->x() - m_xOffset - m_moveXOff, 0 ) * MidiTime::ticksPerTact() / m_ppt );

	switch( m_action )
	{
		case MovePositionMarker:
			m_pos.setTicks( t.getTicks() );
			engine::getSong()->setMilliSeconds(((((t.getTicks()))*60*1000/48)/engine::getSong()->getTempo()));
			m_pos.setCurrentFrame( 0 );
			updatePosition();
			break;

		case MoveLoopBegin:
		case MoveLoopEnd:
		{
			const int i = m_action - MoveLoopBegin;
			if( event->modifiers() & Qt::ControlModifier )
			{
				// no ctrl-press-hint when having ctrl pressed
				delete m_hint;
				m_hint = NULL;
				m_loopPos[i] = t;
			}
			else
			{
				m_loopPos[i] = t.toNearestTact();
			}
			// Catch begin == end
			if( m_loopPos[0] == m_loopPos[1] )
			{
				// Note, swap 1 and 0 below and the behavior "skips" the other
				// marking instead of pushing it.
				if( m_action == MoveLoopBegin ) 
					m_loopPos[0] -= MidiTime::ticksPerTact();
				else
					m_loopPos[1] += MidiTime::ticksPerTact();
			}
			update();
			break;
		}

		default:
			break;
	}
}
Example #4
0
void InstrumentTrack::processInEvent( const MidiEvent& event, const MidiTime& time )
{
	engine::mixer()->lock();

	bool eventHandled = false;

	switch( event.type() )
	{
		// we don't send MidiNoteOn, MidiNoteOff and MidiKeyPressure
		// events to instrument as NotePlayHandle will send them on its
		// own
		case MidiNoteOn:
			if( event.velocity() > 0 )
			{
				if( m_notes[event.key()] == NULL )
				{
					// create (timed) note-play-handle
					NotePlayHandle* nph = new NotePlayHandle( this, time.frames( engine::framesPerTick() ),
																typeInfo<f_cnt_t>::max() / 2,
																note( MidiTime(), MidiTime(), event.key(), event.volume( midiPort()->baseVelocity() ) ),
																NULL, event.channel(),
																NotePlayHandle::OriginMidiInput );
					if( engine::mixer()->addPlayHandle( nph ) )
					{
						m_notes[event.key()] = nph;
					}
				}

				eventHandled = true;
				break;
			}

		case MidiNoteOff:
			if( m_notes[event.key()] != NULL )
			{
				// do actual note off and remove internal reference to NotePlayHandle (which itself will
				// be deleted later automatically)
				m_notes[event.key()]->noteOff();
				m_notes[event.key()] = NULL;
			}
			eventHandled = true;
			break;

		case MidiKeyPressure:
			if( m_notes[event.key()] != NULL )
			{
				// setVolume() calls processOutEvent() with MidiKeyPressure so the
				// attached instrument will receive the event as well
				m_notes[event.key()]->setVolume( event.volume( midiPort()->baseVelocity() ) );
			}
			eventHandled = true;
			break;

		case MidiPitchBend:
			// updatePitch() is connected to m_pitchModel::dataChanged() which will send out
			// MidiPitchBend events
			m_pitchModel.setValue( m_pitchModel.minValue() + event.pitchBend() * m_pitchModel.range() / MidiMaxPitchBend );
			break;

		case MidiControlChange:
			if( event.controllerNumber() == MidiControllerSustain )
			{
				if( event.controllerValue() > MidiMaxControllerValue/2 )
				{
					m_sustainPedalPressed = true;
				}
				else
				{
					m_sustainPedalPressed = false;
				}
			}
			if( event.controllerNumber() == MidiControllerAllSoundOff ||
			    event.controllerNumber() == MidiControllerAllNotesOff ||
			    event.controllerNumber() == MidiControllerOmniOn ||
			    event.controllerNumber() == MidiControllerOmniOff ||
			    event.controllerNumber() == MidiControllerMonoOn ||
			    event.controllerNumber() == MidiControllerPolyOn )
			{
				silenceAllNotes();
			}
			break;

		case MidiMetaEvent:
			// handle special cases such as note panning
			switch( event.metaEvent() )
			{
				case MidiNotePanning:
					if( m_notes[event.key()] != NULL )
					{
						eventHandled = true;
						m_notes[event.key()]->setPanning( event.panning() );
					}
					break;
				default:
					qWarning( "InstrumentTrack: unhandled MIDI meta event: %i", event.metaEvent() );
					break;
			}
			break;
			
		default:
			break;
	}

	if( eventHandled == false && instrument()->handleMidiEvent( event, time ) == false )
	{
		qWarning( "InstrumentTrack: unhandled MIDI event %d", event.type() );
	}

	engine::mixer()->unlock();
}