view Source/TouchKeys/MidiInputController.h @ 7:353276611036

Move pitch wheel range into a central location in MidiKeyboardSegment, eliminating local copies in OscMidiConverter etc. Also suppress some unneeded debugging messages in TouchkeyDevice.
author Andrew McPherson <andrewm@eecs.qmul.ac.uk>
date Sun, 17 Nov 2013 13:53:21 +0000
parents 3580ffe87dc8
children 88287c1c2c92
line wrap: on
line source
/*
  TouchKeys: multi-touch musical keyboard control software
  Copyright (c) 2013 Andrew McPherson

  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 3 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.  If not, see <http://www.gnu.org/licenses/>.
 
  =====================================================================
 
  MidiInputController.h: handles incoming MIDI data and manages input
  ports. Detailed processing is broken down by keyboard segment; see
  MidiKeyboardSegment.h/cpp for more.
*/


#ifndef MIDI_INPUT_CONTROLLER_H
#define MIDI_INPUT_CONTROLLER_H

#include <iostream>
#include <vector>
#include <map>
#include <set>
#include "../JuceLibraryCode/JuceHeader.h"
#include "PianoKeyboard.h"
#include "Osc.h"
#include "MidiKeyboardSegment.h"

using namespace std;

class MidiOutputController;

// MIDI standard messages

enum {
	kMidiMessageNoteOff = 0x80,
	kMidiMessageNoteOn = 0x90,
	kMidiMessageAftertouchPoly = 0xA0,
	kMidiMessageControlChange = 0xB0,
	kMidiMessageProgramChange = 0xC0,
	kMidiMessageAftertouchChannel = 0xD0,
	kMidiMessagePitchWheel = 0xE0,
	kMidiMessageSysex = 0xF0,
	kMidiMessageSysexEnd = 0xF7,
	kMidiMessageActiveSense = 0xFE,
	kMidiMessageReset = 0xFF
};

enum {
	kMidiControlAllSoundOff = 120,
	kMidiControlAllControllersOff = 121,
	kMidiControlLocalControl = 122,
	kMidiControlAllNotesOff = 123
};

class MidiInputController : public MidiInputCallback {
public:
    /*
	// Operating modes for MIDI input
	enum {
		ModeOff = 0,
		ModePassThrough,
		ModeMonophonic,
		ModePolyphonic,
		ModeChannelSelect,
		ModeConstantControllers
	};
	
	// Switch types for Channel Select mode
	enum {
		ChannelSelectSwitchTypeUnknown = 0,
		ChannelSelectSwitchTypeLocation,
		ChannelSelectSwitchTypeSize,
		ChannelSelectSwitchTypeNumTouches,
		ChannelSelectSwitchTypeAngle
	};
     */
	
public:
	// Constructor
	MidiInputController(PianoKeyboard& keyboard);

	
	// Query available devices
	vector<pair<int, string> > availableMidiDevices();
	
	// Add/Remove MIDI input ports;
	// Enable methods return true on success (at least one port enabled) 
	bool enablePort(int portNumber);
	bool enableAllPorts();
	void disablePort(int portNumber);
	void disableAllPorts();
	vector<int> activePorts();

    //void touchkeyStandaloneTouchBegan(int noteNumber,  Node<KeyTouchFrame>* touchBuffer);
    //void touchkeyStandaloneTouchEnded(int noteNumber);
    
    /*
	// Set which channels we listen to
	bool enableChannel(int channelNumber);
	bool enableAllChannels();
	void disableChannel(int channelNumber);
	void disableAllChanels();
	*/
    
	// Set/query the output controller
	MidiOutputController* midiOutputController() { return midiOutputController_; }
	void setMidiOutputController(MidiOutputController* ct);
	
	// All Notes Off: can be sent by MIDI or controlled programmatically
	void allNotesOff();
    
    // Return the number of keyboard segments, and a specific segment
    int numSegments() {
        ScopedLock sl(segmentsMutex_);
        return segments_.size();
    }
    MidiKeyboardSegment* segment(int num) {
        ScopedLock sl(segmentsMutex_);
        if(num < 0 || num >= segments_.size())
            return 0;
        return segments_[num];
    }
    // Return a unique signature which tells us when the MIDI segments have changed,
    // allowing any listeners to re-query all the segments.
    int segmentUniqueIdentifier() {
        return segmentUniqueIdentifier_;
    }

    // Add a new keyboard segment. Returns a pointer to the newly created segment
    MidiKeyboardSegment* addSegment(int outputPortNumber, int noteMin = 0, int noteMax = 127, int channelMask = 0xFFFF);
    
    // Remove a segment by index or by object
    void removeSegment(int index);
    void removeSegment(MidiKeyboardSegment* segment);
    void removeAllSegments();
    
    /*
	// Change or query the operating mode of the controller
	int mode() { return mode_; }
	void setModeOff();
	void setModePassThrough();
    void setModeMonophonic();
	void setModePolyphonic();
	void setModeChannelSelect(int switchType, int numDivisions, int defaultChannel);

    int polyphony() { return retransmitMaxPolyphony_; }
    void setPolyphony(int polyphony);
    bool voiceStealingEnabled() { return useVoiceStealing_; }
    void setVoiceStealingEnabled(bool enable) { useVoiceStealing_ = enable; }
    */
    
    // Juce MIDI callbacks
    void handleIncomingMidiMessage(MidiInput* source, const MidiMessage& message);
    void handlePartialSysexMessage(MidiInput* source,
                                   const uint8* messageData,
                                   int numBytesSoFar,
                                   double timestamp) {}
	
	// OSC method: used to get touch callback data from the keyboard
	// bool oscHandlerMethod(const char *path, const char *types, int numValues, lo_arg **values, void *data);
    
    // for logging
    void createLogFile(string midiLog_filename, string path);
    void closeLogFile();
    void startLogging();
    void stopLogging();
    
    bool logFileCreated;
    bool loggingActive;

	// Destructor
	~MidiInputController();
	
private:
	// Filtering by channel: return whether this message concerns one of the active channels
	// we're listening to.
	// bool messageIsForActiveChannel(const MidiMessage& message);
	
    /*
	// Mode-specific MIDI input handlers
	void modePassThroughHandler(MidiInput* source, const MidiMessage& message);	
	void modeMonophonicHandler(MidiInput* source, const MidiMessage& message);

	void modePolyphonicHandler(MidiInput* source, const MidiMessage& message);
	void modePolyphonicNoteOn(unsigned char note, unsigned char velocity);
	void modePolyphonicNoteOff(unsigned char note);
	void modePolyphonicNoteOnCallback(const char *path, const char *types, int numValues, lo_arg **values);
	
	void modeChannelSelectHandler(MidiInput* source, const MidiMessage& message);
	void modeChannelSelectNoteOn(unsigned char note, unsigned char velocity);
	void modeChannelSelectNoteOff(unsigned char note);
	void modeChannelSelectNoteOnCallback(const char *path, const char *types, int numValues, lo_arg **values);
	
	void modeConstantControllersHandler(MidiInput* source, const MidiMessage& message);
	
    // Helper functions for polyphonic mode
    void modePolyphonicSetupHelper();
    int oldestNote();
    int newestNote();
     */
    
	// ***** Member Variables *****
	
	PianoKeyboard& keyboard_;						// Reference to main keyboard data
    MidiOutputController *midiOutputController_;	// Destination for MIDI output
    
	map<int, MidiInput*> activePorts_;              // Sources of MIDI data
    
    vector<MidiKeyboardSegment*> segments_;         // Segments of the keyboard
    CriticalSection segmentsMutex_;                 // Mutex protecting the segments list
    int segmentUniqueIdentifier_;                   // Identifier of when segment structure has changed
    

    /*

	
	// Current operating mode of the controller
	int mode_;
	
	// Mapping between input notes and output channels.  Depending on the mode of operation,
	// each note may be rebroadcast on its own MIDI channel.  Need to keep track of what goes where.
	// key is MIDI note #, value is output channel (0-15)
	map<int, int> retransmitChannelForNote_;
	set<int> retransmitChannelsAvailable_;
	int retransmitMaxPolyphony_;
    bool useVoiceStealing_;
    map<int, timestamp_type> noteOnsetTimestamps_; // When each currently active note began, for stealing
	
	// Parameters for Channel Select mode of operation
	int channelSelectSwitchType_;
	int channelSelectNumberOfDivisions_;
	int channelSelectDefaultChannel_;
	int channelSelectLastOnsetChannel_;
    */
    
    // for logging
    ofstream midiLog;
    
    // for generating timestamps
    // Scheduler eventScheduler_;
};

#endif /* MIDI_INPUT_CONTROLLER_H */