view Source/TouchKeys/MidiInputController.h @ 20:dfff66c07936

Lots of minor changes to support building on Visual Studio. A few MSVC-specific #ifdefs to eliminate things Visual Studio doesn't like. This version now compiles on Windows (provided liblo, Juce and pthread are present) but the TouchKeys device support is not yet enabled. Also, the code now needs to be re-checked on Mac and Linux.
author Andrew McPherson <andrewm@eecs.qmul.ac.uk>
date Sun, 09 Feb 2014 18:40:51 +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 */