Added MidiControlListener for controlling LMMS via MIDI

MidiControlListener is MidiEventProcessor that listens for specific
MIDI events in order to control LMMS' transportation (currently only
start/stop). Can be advanced later to control other things in LMMS.
This commit is contained in:
Achim Settelmeier
2009-05-05 23:43:47 +02:00
committed by Tobias Doerffel
parent 515f0243b9
commit f4e929022e
4 changed files with 241 additions and 0 deletions

View File

@@ -45,6 +45,7 @@
#include "project_notes.h"
#include "song_editor.h"
#include "song.h"
#include "midi_control_listener.h"
#include "resources_db.h"
#include "local_resources_provider.h"
@@ -72,6 +73,7 @@ projectJournal * engine::s_projectJournal = NULL;
ladspa2LMMS * engine::s_ladspaManager = NULL;
dummyTrackContainer * engine::s_dummyTC = NULL;
controllerRackView * engine::s_controllerRackView = NULL;
MidiControlListener * engine::s_midiControlListener = NULL;
QMap<QString, QString> engine::s_pluginFileHandling;
LmmsStyle * engine::s_lmmsStyle = NULL;
@@ -117,6 +119,8 @@ void engine::init( const bool _has_gui )
s_mixer->initDevices();
s_midiControlListener = new MidiControlListener();
if( s_hasGUI )
{
s_mainWindow = new mainWindow;

View File

@@ -0,0 +1,163 @@
/*
* midi_control_listener.cpp - implementation of the MIDI listener that
* controls LMMS' transportation and other things
*
* Copyright (c) 2009 Achim Settelmeier <lmms/at/m1.sirlab.de>
*
* 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 "midi_control_listener.h"
#include "mixer.h"
#include "midi_client.h"
#include "midi_port.h"
#include "engine.h"
#include "note.h"
#include "song.h"
MidiControlListener::MidiControlListener() :
m_port( "unnamed_midi_controller",
engine::getMixer()->getMidiClient(), this, NULL,
midiPort::Input ),
m_controlKeyPressed( false )
{
// default settings
m_useControlKey = true; // use control key
m_controlKey = 60; // C5
m_controlChannel = -1; // listen on all channels
#warning TODO replace hard-coded defaults
// test config
m_port.subscribeReadablePort( "24:0", true );
m_actionMapKeys[57] = ActionPlay;
m_actionMapKeys[59] = ActionStop;
m_actionMapControllers[24] = ActionPlay;
m_actionMapControllers[23] = ActionStop;
}
MidiControlListener::~MidiControlListener()
{
}
void MidiControlListener::processInEvent( const midiEvent & _me,
const midiTime & _time )
{
// pre-check whether this MIDI packet suits our configuration
switch( _me.m_type )
{
case MidiNoteOn:
case MidiNoteOff:
case MidiControlChange:
// ignore commands for other channels
if( m_controlChannel != -1 &&
m_controlChannel != _me.channel() )
{
return;
}
break;
default:
// ignore commands other than note on/off and
// control change
return;
}
// check MIDI packet type and act upon
switch( _me.m_type )
{
case MidiNoteOn:
if( _me.key() == m_controlKey)
{
if( _me.velocity() == 0 )
{
// special case: key press with velocity 0
// means key release
m_controlKeyPressed = false;
break;
}
m_controlKeyPressed = true;
break;
}
else if( !m_useControlKey || m_controlKeyPressed )
{
if( _me.velocity() > 0 &&
m_actionMapKeys.contains( _me.key() ) )
{
act( m_actionMapKeys.value( _me.key(),
ActionNone ) );
}
}
break;
case MidiNoteOff:
if( _me.key() == m_controlKey )
{
m_controlKeyPressed = false;
}
break;
case MidiControlChange:
// controller changed to a value other than zero
if( _me.m_data.m_param[1] > 0 )
{
switch( m_actionMapControllers.value(
_me.m_data.m_param[0], ActionNone ) )
{
case ActionNone:
break;
case ActionPlay:
engine::getSong()->play();
break;
case ActionStop:
engine::getSong()->stop();
break;
}
}
break;
default:
// nop
break;
}
}
void MidiControlListener::act( EventAction _action )
{
switch( _action )
{
case ActionNone:
break;
case ActionPlay:
engine::getSong()->play();
break;
case ActionStop:
engine::getSong()->stop();
break;
}
}