From 73f7293b2e66ec63ae57293de0f48a0dd6515d04 Mon Sep 17 00:00:00 2001 From: Michael Gogins Date: Fri, 3 Nov 2023 08:08:59 -0400 Subject: [PATCH] Code cleanup (#1). --- src/jackops/jacko.cpp | 2641 +++++++++++++++++++++-------------------- 1 file changed, 1324 insertions(+), 1317 deletions(-) diff --git a/src/jackops/jacko.cpp b/src/jackops/jacko.cpp index 6665351..a6b72be 100644 --- a/src/jackops/jacko.cpp +++ b/src/jackops/jacko.cpp @@ -1,458 +1,458 @@ /* - jacko.cpp: +jacko.cpp: - Copyright (C) 2010nby Michael Gogins +Copyright (C) 2010nby Michael Gogins - This file is part of Csound. +This file is part of Csound. - The Csound Library is free software; you can redistribute it - and/or modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. +The Csound Library is free software; you can redistribute it +and/or modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. - Csound 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 Lesser General Public License for more details. +Csound 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 Lesser General Public License for more details. - You should have received a copy of the GNU Lesser General Public - License along with Csound; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - 02110-1301 USA +You should have received a copy of the GNU Lesser General Public +License along with Csound; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +02110-1301 USA */ /** - * T H E J A C K O P C O D E S - * Michael Gogins - * - * The Jack opcodes can be used to connect any number - * of Csound instances, instruments, or user-defined - * opcodes to any number of Jack ports - * in any number of external Jack servers. - * Audio and MIDI signal types are supported - * - * Sending MIDI and/or audio to external Jack clients, - * such as synthesizers, and receiving audio and/or - * MIDI back from them, is supported. - * - * Receiving MIDI and/or audio from external Jack clients, - * such as sequencers, and sending MIDI and/or audio - * back to them, is supported. - * - * Other uses also are supported. - * - * O P C O D E S - * - * JackoInit -- Initializes Csound as a Jack client. - * - * Description - * - * Initializes this instance of Csound as a Jack client. - * - * Csound's sr must be equal to the Jack daemon's - * frames per second. - * - * Csound's ksmps must be equal to the Jack daemon's - * frames per period. - * - * Frames per period must not only (a) be a power of 2, - * but also (b) go evenly into the frames per second, - * e.g. 128 frames per period goes into 48000 - * frames per second 375 times, for a latency or - * MIDI time granularity of about 2.7 milliseconds - * (as good as or better than the absolute best - * human performers). - * - * The order of processing of all signals that pass - * from Jack input ports, through Csound processing, - * and to Jack output ports, must be properly - * determined by sequence of instrument and - * opcode definition within the Csound orchestra. - * - * Syntax - * - * JackoInit SclientName, ServerName - * - * Initialization - * - * SclientName -- The name of the Jack client; - * normally, should be "csound". - * - * ServerName -- The name of the Jack daemon; - * normally, will be "default". - * - * This opcode must be called once and only once in the - * orchestra header, and before any other Jack opcodes. - * If more than one instance of Csound is using the Jack - * opcodes at the same time, then each instance of Csound - * must use a different client name. - * - * - * JackoInfo -- Prints information about the Jack system. - * - * Description - * - * Prints the Jack daemon and client names, the - * sampling rate and frames per period, - * and all active Jack port names, - * types, states, and connections. - * - * Syntax - * - * JackoInfo - * - * Initialization - * - * May be called any number of times in the orchestra header, - * for example both before and after creating Jack ports - * in the Csound orchestra header. - * - * - * JackoFreewheel -- Turns freewheeling mode on or off. - * - * Description - * - * Turns Jack's freewheeling mode on or off. - * - * When freewheeling is on, if supported by the rest - * of the Jack system, Csound will run as fast as possible, - * which may be either faster or slower than real time. - * - * This is essential for rendering scores that are too - * dense for real-time jacko_is_driving to a soundfile, - * without xruns or dropouts. - * - * Syntax - * - * JackoFreewheel [ienabled] - * - * Initialization - * - * ienabled -- Turns freewheeling on (the default) or off. - * - * - * JackoAudioInConnect -- Creates an audio connection - * from a Jack port to Csound. - * - * Description - * - * In the orchestra header, creates an audio connection - * from an external Jack audio output port to a - * Jack audio input port inside this instance of Csound. - * - * Syntax - * - * JackoAudioInConnect SexternalPortName, ScsoundPortName - * - * Initialization - * - * SexternalPortName -- The full name ("clientname:portname") - * of an external Jack audio output port. - * - * ScsoundPortName -- The short name ("portname") - * of the internal Jack audio input port. - * - * Performance - * - * The actual audio must be read with the JackoAudioIn opcode. - * - * - * JackoAudioOutConnect -- Creates an audio connection - * from Csound to a Jack port. - * - * Description - * - * In the orchestra header, creates an audio connection - * from a Jack audio output port inside this instance - * of Csound to an external Jack audio input port. - * - * Syntax - * - * JackoAudioOutConnect ScsoundPortName, SexternalPortName - * - * Initialization - * - * ScsoundPortName -- The short name ("portname") - * of the internal Jack audio input port. - * - * SexternalPortName -- The full name ("clientname:portname") - * of an external Jack audio output port. - * - * Performance - * - * The actual audio must be written with the JackoAudioOut - * opcode. - * - * - * JackoMidiInConnect -- Creates a MIDI connection from - * Jack to Csound. - * - * Description - * - * Creates a MIDI connection from an external Jack MIDI - * output port to this instance of Csound. - * - * Syntax - * - * JackoMidiInConnect SexternalPortName, ScsoundPortName - * - * Initialization - * - * SexternalPortName -- The full name ("clientname:portname") - * of an external Jack MIDI output port. - * - * ScsoundPortName -- The short name ("portname") - * of the internal Jack MIDI input port. - * - * Must be used in conjunction with the - * -M0 -+rtmidi=null Csound command-line options. - * Can be used in with the MIDI inter-operability - * command-line options and/or opcodes to enable the - * use of ordinary Csound instrument definitions to - * render external scores or MIDI sequences. - * - * Note that Csound can connect to ALSA ports through Jack, - * but in this case you will have to identify the port by - * its alias in the JackInfo printout. - * - * Performance - * - * The actual MIDI events will be received in the - * regular Csound way, i.e. through a MIDI driver - * and the sensevents mechanism, rather than through - * a Jack input port opcode. - * - * The granularity of timing is Csound's kperiod. - * - * - * JackoMidiOutConnect -- Creates a MIDI connection from - * Csound to Jack. - * - * Description - * - * In the orchestra header, creates a connection - * from a Jack MIDI output port inside this instance - * of Csound to an external Jack MIDI input port. - * - * Syntax - * - * JackoMidiOutConnect ScsoundPortName, SexternalPortName - * - * Initialization - * - * ScsoundPortName -- The short name ("portname") - * of the internal Jack audio input port. - * - * SexternalPortName -- The full name ("clientname:portname") - * of an external Jack audio output port. - * - * Performance - * - * The actual MIDI data must be written with the JackoMidiOut - * or JackoNoteOut opcodes. - * - * - * JackoOn -- Enables or disables all Jack ports. - * - * Description - * - * After all Jack connections have been created, enables - * or disables all Jack input and output opcodes - * inside this instance of Csound to read or write data. - * - * Syntax - * - * JackoOn [iactive] - * - * Initialization - * - * iactive -- A flag that turns the ports on (the default) - * or off. - * - * - * JackoAudioIn -- Receives an audio signal from a Jack port. - * - * Description - * - * Receives an audio signal from a Jack audio input port - * inside this instance of Csound, which in turn has - * received the signal from its connected external Jack - * audio output port. - * - * Syntax - * - * asignal JackoAudioIn ScsoundPortName - * - * Initialization - * - * ScsoundPortName -- The short name ("portname") - * of the internal Jack audio input port. - * - * Performance - * - * asignal -- Audio received from the external Jack - * output port to which ScsoundPortName is connected. - * - * - * JackoAudioOut -- Sends an audio signal to a Jack port. - * - * Description - * - * Sends an audio signal to an internal Jack audio - * output port, and in turn to its connected external - * Jack audio input port. - * - * Note that it is possible to send audio out via Jack - * to the system audio interface, while at the same time - * rendering to a regular Csound output soundfile. - * - * Syntax - * - * JackoAudioOut ScsoundPortName, asignal - * - * Initialization - * - * ScsoundPortName -- The short name ("portname") - * of the internal Jack audio output port. - * - * Performance - * - * asignal -- Audio to be sent to the external Jack audio - * input port to which CsoundPortName is connected. - * - * Audio from multiple instances of the opcode sending - * to the same Jack port is summed before sending. - * - * - * JackoMidiOut -- Sends a MIDI channel message to a - * Jack port. - * - * Description - * - * Sends a MIDI channel message to a Jack MIDI output port - * inside this instance of Csound, and in turn to its - * connected external Jack MIDI input port. - * - * Syntax - * - * JackoMidiOut ScsoundPortName, kstatus, kchannel, kdata1[, kdata2] - * - * Initialization - * - * ScsoundPortName -- The short name ("portname") - * of the internal Jack MIDI input port. - * - * Performance - * - * kstatus -- MIDI status byte; must indicate a MIDI channel - * message. - * - * kchannel -- MIDI channel (from 0 through 15). - * - * kdata1 -- First data byte of a MIDI channel message. - * - * kdata2 -- Optional second data byte of a MIDI channel message. - * - * This opcode can be called any number of times - * in the same kperiod. Messages from multiple instances - * of the opcode sending to the same port are collected - * before sending. - * - * Running status, system exclusive messages, and - * real-time messages are not supported. - * - * The granularity of timing is Csound's kperiod. - * - * - * JackoNoteOut -- Send one note to a Jack MIDI port. - * - * Description - * - * Sends one note to a Jack MIDI output port inside this - * instance of Csound, and in turn to the connected external - * Jack MIDI input port, with a duration - * specified by the score instrument statement. - * The matching MIDI note off message is generated - * and scheduled for later transmission. - * - * Notes from multiple instances of the opcode - * sending to the same output port are collected - * before sending. - * - * The granularity of timing is Csound's kperiod. - * - * Syntax - * - * JackoNoteOut ScsoundPortName, ichannel, ikey, ivelocity - * - * Initialization - * - * ScsoundPortName -- The short name ("portname") of the - * Jack MIDI output port created by jackmidioutconnect. - * - * ichannel -- The MIDI channel (from 0 through 15) to - * receive the note. - * - * ikey -- The MIDI key number (from 0 through 127, 60 is - * middle C) of the note. - * - * ivelocity -- The MIDI velocity number (from 0 through 127) - * of the note. - * - * - * JackoTransport -- Control the Jack transport. - * - * Description - * - * Starts, stops, or repositions the Jack transport. - * This is useful, e.g., for starting an external sequencer - * playing to send MIDI messages to Csound. - * - * Syntax - * - * JackoTransport kcommand, [kposition] - * - * Performance - * - * kcommand -- 0 means "no action", 1 starts the transport, - * 2 stops the transport, and 3 positions the transport - * to kposition seconds from the beginning of jacko_is_driving - * (i.e. time 0 in the score). - * - * This opcode can be used at init time or during jacko_is_driving. - * - * The granularity of timing is Csound's kperiod. - * - * - * I M P L E M E N T A T I O N - * - * Processing is done according to the callback model: - * - * 1. The jackinit opcode: - * 1.1. Creates a Jack client, - * which is associated with the - * running instance of Csound. - * 1.2. Registers a JackProcessCallback with Jack. - * 1.3. Registers a SenseEventCallback with Csound. - * 1.4. Installs a MIDI driver callback to consume - * MIDI events coming from Jack input ports. - * 1.5. Puts the Csound processing thread to sleep. - * 1.6. Activates the client. - * 2. The ports are created and connected in the orchestra header. - * 3. After all ports are connected, they are turned on in the - * orchestra header. - * 4. Every time the Jack callback fires: - * 4.1. Any MIDI events pending in the input ports are enqueued - * for dispatch via the MIDI driver callack through - * Csound's normal sensevents mechanism. - * 4.2. csoundPerformKsmps is called. - * 4.3. When the Csound jacko_is_driving is finished: - * 4.3.1. The Csound processing thread is re-awakened. - * 4.3.2. The Jack processing callback is deactivated. - * 4.3.2. The Jack client is closed. - * 5. At the end of processing, the module deinitialization - * function erases all Jack-related state. - */ +* T H E J A C K O P C O D E S +* Michael Gogins +* +* The Jack opcodes can be used to connect any number +* of Csound instances, instruments, or user-defined +* opcodes to any number of Jack ports +* in any number of external Jack servers. +* Audio and MIDI signal types are supported +* +* Sending MIDI and/or audio to external Jack clients, +* such as synthesizers, and receiving audio and/or +* MIDI back from them, is supported. +* +* Receiving MIDI and/or audio from external Jack clients, +* such as sequencers, and sending MIDI and/or audio +* back to them, is supported. +* +* Other uses also are supported. +* +* O P C O D E S +* +* JackoInit -- Initializes Csound as a Jack client. +* +* Description +* +* Initializes this instance of Csound as a Jack client. +* +* Csound's sr must be equal to the Jack daemon's +* frames per second. +* +* Csound's ksmps must be equal to the Jack daemon's +* frames per period. +* +* Frames per period must not only (a) be a power of 2, +* but also (b) go evenly into the frames per second, +* e.g. 128 frames per period goes into 48000 +* frames per second 375 times, for a latency or +* MIDI time granularity of about 2.7 milliseconds +* (as good as or better than the absolute best +* human performers). +* +* The order of processing of all signals that pass +* from Jack input ports, through Csound processing, +* and to Jack output ports, must be properly +* determined by sequence of instrument and +* opcode definition within the Csound orchestra. +* +* Syntax +* +* JackoInit SclientName, ServerName +* +* Initialization +* +* SclientName -- The name of the Jack client; +* normally, should be "csound". +* +* ServerName -- The name of the Jack daemon; +* normally, will be "default". +* +* This opcode must be called once and only once in the +* orchestra header, and before any other Jack opcodes. +* If more than one instance of Csound is using the Jack +* opcodes at the same time, then each instance of Csound +* must use a different client name. +* +* +* JackoInfo -- Prints information about the Jack system. +* +* Description +* +* Prints the Jack daemon and client names, the +* sampling rate and frames per period, +* and all active Jack port names, +* types, states, and connections. +* +* Syntax +* +* JackoInfo +* +* Initialization +* +* May be called any number of times in the orchestra header, +* for example both before and after creating Jack ports +* in the Csound orchestra header. +* +* +* JackoFreewheel -- Turns freewheeling mode on or off. +* +* Description +* +* Turns Jack's freewheeling mode on or off. +* +* When freewheeling is on, if supported by the rest +* of the Jack system, Csound will run as fast as possible, +* which may be either faster or slower than real time. +* +* This is essential for rendering scores that are too +* dense for real-time jacko_is_driving to a soundfile, +* without xruns or dropouts. +* +* Syntax +* +* JackoFreewheel [ienabled] +* +* Initialization +* +* ienabled -- Turns freewheeling on (the default) or off. +* +* +* JackoAudioInConnect -- Creates an audio connection +* from a Jack port to Csound. +* +* Description +* +* In the orchestra header, creates an audio connection +* from an external Jack audio output port to a +* Jack audio input port inside this instance of Csound. +* +* Syntax +* +* JackoAudioInConnect SexternalPortName, ScsoundPortName +* +* Initialization +* +* SexternalPortName -- The full name ("clientname:portname") +* of an external Jack audio output port. +* +* ScsoundPortName -- The short name ("portname") +* of the internal Jack audio input port. +* +* Performance +* +* The actual audio must be read with the JackoAudioIn opcode. +* +* +* JackoAudioOutConnect -- Creates an audio connection +* from Csound to a Jack port. +* +* Description +* +* In the orchestra header, creates an audio connection +* from a Jack audio output port inside this instance +* of Csound to an external Jack audio input port. +* +* Syntax +* +* JackoAudioOutConnect ScsoundPortName, SexternalPortName +* +* Initialization +* +* ScsoundPortName -- The short name ("portname") +* of the internal Jack audio input port. +* +* SexternalPortName -- The full name ("clientname:portname") +* of an external Jack audio output port. +* +* Performance +* +* The actual audio must be written with the JackoAudioOut +* opcode. +* +* +* JackoMidiInConnect -- Creates a MIDI connection from +* Jack to Csound. +* +* Description +* +* Creates a MIDI connection from an external Jack MIDI +* output port to this instance of Csound. +* +* Syntax +* +* JackoMidiInConnect SexternalPortName, ScsoundPortName +* +* Initialization +* +* SexternalPortName -- The full name ("clientname:portname") +* of an external Jack MIDI output port. +* +* ScsoundPortName -- The short name ("portname") +* of the internal Jack MIDI input port. +* +* Must be used in conjunction with the +* -M0 -+rtmidi=null Csound command-line options. +* Can be used in with the MIDI inter-operability +* command-line options and/or opcodes to enable the +* use of ordinary Csound instrument definitions to +* render external scores or MIDI sequences. +* +* Note that Csound can connect to ALSA ports through Jack, +* but in this case you will have to identify the port by +* its alias in the JackInfo printout. +* +* Performance +* +* The actual MIDI events will be received in the +* regular Csound way, i.e. through a MIDI driver +* and the sensevents mechanism, rather than through +* a Jack input port opcode. +* +* The granularity of timing is Csound's kperiod. +* +* +* JackoMidiOutConnect -- Creates a MIDI connection from +* Csound to Jack. +* +* Description +* +* In the orchestra header, creates a connection +* from a Jack MIDI output port inside this instance +* of Csound to an external Jack MIDI input port. +* +* Syntax +* +* JackoMidiOutConnect ScsoundPortName, SexternalPortName +* +* Initialization +* +* ScsoundPortName -- The short name ("portname") +* of the internal Jack audio input port. +* +* SexternalPortName -- The full name ("clientname:portname") +* of an external Jack audio output port. +* +* Performance +* +* The actual MIDI data must be written with the JackoMidiOut +* or JackoNoteOut opcodes. +* +* +* JackoOn -- Enables or disables all Jack ports. +* +* Description +* +* After all Jack connections have been created, enables +* or disables all Jack input and output opcodes +* inside this instance of Csound to read or write data. +* +* Syntax +* +* JackoOn [iactive] +* +* Initialization +* +* iactive -- A flag that turns the ports on (the default) +* or off. +* +* +* JackoAudioIn -- Receives an audio signal from a Jack port. +* +* Description +* +* Receives an audio signal from a Jack audio input port +* inside this instance of Csound, which in turn has +* received the signal from its connected external Jack +* audio output port. +* +* Syntax +* +* asignal JackoAudioIn ScsoundPortName +* +* Initialization +* +* ScsoundPortName -- The short name ("portname") +* of the internal Jack audio input port. +* +* Performance +* +* asignal -- Audio received from the external Jack +* output port to which ScsoundPortName is connected. +* +* +* JackoAudioOut -- Sends an audio signal to a Jack port. +* +* Description +* +* Sends an audio signal to an internal Jack audio +* output port, and in turn to its connected external +* Jack audio input port. +* +* Note that it is possible to send audio out via Jack +* to the system audio interface, while at the same time +* rendering to a regular Csound output soundfile. +* +* Syntax +* +* JackoAudioOut ScsoundPortName, asignal +* +* Initialization +* +* ScsoundPortName -- The short name ("portname") +* of the internal Jack audio output port. +* +* Performance +* +* asignal -- Audio to be sent to the external Jack audio +* input port to which CsoundPortName is connected. +* +* Audio from multiple instances of the opcode sending +* to the same Jack port is summed before sending. +* +* +* JackoMidiOut -- Sends a MIDI channel message to a +* Jack port. +* +* Description +* +* Sends a MIDI channel message to a Jack MIDI output port +* inside this instance of Csound, and in turn to its +* connected external Jack MIDI input port. +* +* Syntax +* +* JackoMidiOut ScsoundPortName, kstatus, kchannel, kdata1[, kdata2] +* +* Initialization +* +* ScsoundPortName -- The short name ("portname") +* of the internal Jack MIDI input port. +* +* Performance +* +* kstatus -- MIDI status byte; must indicate a MIDI channel +* message. +* +* kchannel -- MIDI channel (from 0 through 15). +* +* kdata1 -- First data byte of a MIDI channel message. +* +* kdata2 -- Optional second data byte of a MIDI channel message. +* +* This opcode can be called any number of times +* in the same kperiod. Messages from multiple instances +* of the opcode sending to the same port are collected +* before sending. +* +* Running status, system exclusive messages, and +* real-time messages are not supported. +* +* The granularity of timing is Csound's kperiod. +* +* +* JackoNoteOut -- Send one note to a Jack MIDI port. +* +* Description +* +* Sends one note to a Jack MIDI output port inside this +* instance of Csound, and in turn to the connected external +* Jack MIDI input port, with a duration +* specified by the score instrument statement. +* The matching MIDI note off message is generated +* and scheduled for later transmission. +* +* Notes from multiple instances of the opcode +* sending to the same output port are collected +* before sending. +* +* The granularity of timing is Csound's kperiod. +* +* Syntax +* +* JackoNoteOut ScsoundPortName, ichannel, ikey, ivelocity +* +* Initialization +* +* ScsoundPortName -- The short name ("portname") of the +* Jack MIDI output port created by jackmidioutconnect. +* +* ichannel -- The MIDI channel (from 0 through 15) to +* receive the note. +* +* ikey -- The MIDI key number (from 0 through 127, 60 is +* middle C) of the note. +* +* ivelocity -- The MIDI velocity number (from 0 through 127) +* of the note. +* +* +* JackoTransport -- Control the Jack transport. +* +* Description +* +* Starts, stops, or repositions the Jack transport. +* This is useful, e.g., for starting an external sequencer +* playing to send MIDI messages to Csound. +* +* Syntax +* +* JackoTransport kcommand, [kposition] +* +* Performance +* +* kcommand -- 0 means "no action", 1 starts the transport, +* 2 stops the transport, and 3 positions the transport +* to kposition seconds from the beginning of jacko_is_driving +* (i.e. time 0 in the score). +* +* This opcode can be used at init time or during jacko_is_driving. +* +* The granularity of timing is Csound's kperiod. +* +* +* I M P L E M E N T A T I O N +* +* Processing is done according to the callback model: +* +* 1. The jackinit opcode: +* 1.1. Creates a Jack client, +* which is associated with the +* running instance of Csound. +* 1.2. Registers a JackProcessCallback with Jack. +* 1.3. Registers a SenseEventCallback with Csound. +* 1.4. Installs a MIDI driver callback to consume +* MIDI events coming from Jack input ports. +* 1.5. Puts the Csound processing thread to sleep. +* 1.6. Activates the client. +* 2. The ports are created and connected in the orchestra header. +* 3. After all ports are connected, they are turned on in the +* orchestra header. +* 4. Every time the Jack callback fires: +* 4.1. Any MIDI events pending in the input ports are enqueued +* for dispatch via the MIDI driver callack through +* Csound's normal sensevents mechanism. +* 4.2. csoundPerformKsmps is called. +* 4.3. When the Csound jacko_is_driving is finished: +* 4.3.1. The Csound processing thread is re-awakened. +* 4.3.2. The Jack processing callback is deactivated. +* 4.3.2. The Jack client is closed. +* 5. At the end of processing, the module deinitialization +* function erases all Jack-related state. +*/ #include "OpcodeBase.hpp" #include #include @@ -483,9 +483,9 @@ struct JackoTransport; struct JackoState; /** - * There is one and only one JackoState instance per instance of Csound. - * It is created by and only by the JackoInit opcode. - */ +* There is one and only one JackoState instance per instance of Csound. +* It is created by and only by the JackoInit opcode. +*/ // static JackoState *jackoState = 0; static void SenseEventCallback_(CSOUND *csound, void *data); @@ -497,977 +497,984 @@ static int midiRead_(CSOUND *csound, void *userData, unsigned char *midiData, int nbytes); /** - * Manages all state relevant to the global - * interaction between Jack and Csound for a particular - * client and instance of Csound. The actual reading - * and writing of data is done by the input and output - * opcodes. - */ +* Manages all state relevant to the global +* interaction between Jack and Csound for a particular +* client and instance of Csound. The actual reading +* and writing of data is done by the input and output +* opcodes. +*/ struct JackoState { - CSOUND *csound; - const char *serverName; - const char *clientName; - jack_client_t *jackClient; - std::atomic jacko_is_driving; - std::atomic jack_active; - std::atomic jacko_finished; - jack_nframes_t csoundFramesPerTick; - jack_nframes_t jackFramesPerTick; - jack_nframes_t csoundFramesPerSecond; - jack_nframes_t jackFramesPerSecond; - jack_nframes_t jackFrameTime; - std::map audioInPorts; - std::map audioOutPorts; - std::map midiInPorts; - std::map midiOutPorts; - std::list midiInputQueue; - jack_position_t jack_position; - pthread_t closeThread; - pthread_mutex_t csoundPerformanceThreadConditionMutex; - pthread_mutexattr_t csoundPerformanceThreadConditionMutexAttribute; - pthread_cond_t csoundPerformanceThreadCondition; - size_t sample_size; - JackoState(CSOUND *csound_, const char *serverName_, const char *clientName_) - : csound(csound_), serverName(serverName_), clientName(clientName_), - jacko_is_driving(false), jack_active(false), jacko_finished(true) { - int result = 0; - csound = csound_; - sample_size = sizeof(jack_default_audio_sample_t); - csoundFramesPerTick = csound->GetKsmps(csound); - csoundFramesPerSecond = csound->GetSr(csound); - pthread_mutexattr_init(&csoundPerformanceThreadConditionMutexAttribute); - pthread_mutexattr_settype(&csoundPerformanceThreadConditionMutexAttribute, - PTHREAD_MUTEX_RECURSIVE); - result |= - pthread_mutex_init(&csoundPerformanceThreadConditionMutex, - &csoundPerformanceThreadConditionMutexAttribute); - result |= pthread_cond_init(&csoundPerformanceThreadCondition, 0); - std::memset(&jack_position, 0, sizeof(jack_position_t)); - jack_options_t jack_options = - (jack_options_t)(JackServerName | JackNoStartServer | JackUseExactName); - jack_status_t status = jack_status_t(0); - jackClient = - jack_client_open(clientName, jack_options, &status, serverName); + CSOUND *csound; + const char *serverName; + const char *clientName; + jack_client_t *jackClient; + std::atomic jacko_is_driving; + ///std::atomic jack_active; + std::atomic jacko_has_finished; + jack_nframes_t csoundFramesPerTick; + jack_nframes_t jackFramesPerTick; + jack_nframes_t csoundFramesPerSecond; + jack_nframes_t jackFramesPerSecond; + jack_nframes_t jackFrameTime; + std::map audioInPorts; + std::map audioOutPorts; + std::map midiInPorts; + std::map midiOutPorts; + std::list midiInputQueue; + jack_position_t jack_position; + pthread_t closeThread; + pthread_mutex_t csoundPerformanceThreadConditionMutex; + pthread_mutexattr_t csoundPerformanceThreadConditionMutexAttribute; + pthread_cond_t csoundPerformanceThreadCondition; + size_t sample_size; + JackoState(CSOUND *csound_, const char *serverName_, const char *clientName_) + : csound(csound_), serverName(serverName_), clientName(clientName_), + jacko_is_driving(false), /*jack_active(false),*/ jacko_has_finished(true) { + int result = 0; + csound = csound_; + sample_size = sizeof(jack_default_audio_sample_t); + csoundFramesPerTick = csound->GetKsmps(csound); + csoundFramesPerSecond = csound->GetSr(csound); + pthread_mutexattr_init(&csoundPerformanceThreadConditionMutexAttribute); + pthread_mutexattr_settype(&csoundPerformanceThreadConditionMutexAttribute, + PTHREAD_MUTEX_RECURSIVE); + result |= + pthread_mutex_init(&csoundPerformanceThreadConditionMutex, + &csoundPerformanceThreadConditionMutexAttribute); + result |= pthread_cond_init(&csoundPerformanceThreadCondition, 0); + std::memset(&jack_position, 0, sizeof(jack_position_t)); + jack_options_t jack_options = + (jack_options_t)(JackServerName | JackNoStartServer | JackUseExactName); + jack_status_t status = jack_status_t(0); + jackClient = + jack_client_open(clientName, jack_options, &status, serverName); csound->Message(csound, - Str("jack_client_open: status: %d\n"), - status); - if (!jackClient) { - csound->Message(csound, - Str("Could not create Jack client \"%s\" -- " - "is Jack server \"%s\" running? Status: %d\n"), - clientName, serverName, status); - csound->LongJmp(csound, 1); - } else { - csound->Message( - csound, Str("Created Jack client \"%s\" for Jack server \"%s\". Status: %d\n"), - clientName, serverName, status); - } - jackFramesPerTick = jack_get_buffer_size(jackClient); - if (csoundFramesPerTick != jackFramesPerTick) { - csound->Message( - csound, Str("Jack buffer size %d != Csound ksmps %d, exiting...\n"), - jackFramesPerTick, csoundFramesPerTick); - csound->LongJmp(csound, 1); - } - jackFramesPerSecond = jack_get_sample_rate(jackClient); - if (csoundFramesPerSecond != jackFramesPerSecond) { - csound->Message( - csound, Str("Jack sampling rate %d != Csound sr %d, exiting...\n"), - jackFramesPerSecond, csoundFramesPerSecond); - csound->LongJmp(csound, 1); + Str("jack_client_open: status: %d\n"), + status); + if (!jackClient) { + csound->Message(csound, + Str("Could not create Jack client \"%s\" -- " + "is Jack server \"%s\" running? Status: %d\n"), + clientName, serverName, status); + csound->LongJmp(csound, 1); + } else { + csound->Message( + csound, Str("Created Jack client \"%s\" for Jack server \"%s\". Status: %d\n"), + clientName, serverName, status); + } + jackFramesPerTick = jack_get_buffer_size(jackClient); + if (csoundFramesPerTick != jackFramesPerTick) { + csound->Message( + csound, Str("Jack buffer size %d != Csound ksmps %d, exiting...\n"), + jackFramesPerTick, csoundFramesPerTick); + csound->LongJmp(csound, 1); + } + jackFramesPerSecond = jack_get_sample_rate(jackClient); + if (csoundFramesPerSecond != jackFramesPerSecond) { + csound->Message( + csound, Str("Jack sampling rate %d != Csound sr %d, exiting...\n"), + jackFramesPerSecond, csoundFramesPerSecond); + csound->LongJmp(csound, 1); + } + csound->SetExternalMidiInOpenCallback(csound, midiDeviceOpen_); + csound->SetExternalMidiReadCallback(csound, midiRead_); + csound->RegisterSenseEventCallback(csound, SenseEventCallback_, this); + jacko_has_finished = false; + result |= jack_set_process_callback(jackClient, JackProcessCallback_, this); + result |= jack_activate(jackClient); + if (!result) { + csound->Message(csound, Str("Activated Jack client \"%s\".\n"), + jack_get_client_name(jackClient)); + } else { + csound->Message( + csound, Str("Failed to activate Jack client \"%s\": status %d.\n"), + jack_get_client_name(jackClient), result); + return; + } +// jackInitialized = true; } - csound->SetExternalMidiInOpenCallback(csound, midiDeviceOpen_); - csound->SetExternalMidiReadCallback(csound, midiRead_); - csound->RegisterSenseEventCallback(csound, SenseEventCallback_, this); - jacko_finished = false; - result |= jack_set_process_callback(jackClient, JackProcessCallback_, this); - result |= jack_activate(jackClient); - if (!result) { - csound->Message(csound, Str("Activated Jack client \"%s\".\n"), - jack_get_client_name(jackClient)); - } else { - csound->Message( - csound, Str("Failed to activate Jack client \"%s\": status %d.\n"), - jack_get_client_name(jackClient), result); - return; + ~JackoState() { } - // jackInitialized = true; - } - ~JackoState() { - } - int SenseEventCallback() { - int result = 0; - if (jacko_finished) { - return result; - } - // Here we must wait once and only once, in order to put - // the original Csound processing thread to sleep -- - // but we must NOT put the Jack processing callback - // to sleep when it comes here! - if (jacko_is_driving == false) { - jacko_is_driving = true; - // While Jack is processing, wait here. - // The Jack process callback will then call csoundPerformKsmps - // until the Csound performance is complete. - csound->Message(csound, - "%s", Str("Jacko is now driving Csound performance...\n")); - result |= pthread_mutex_lock(&csoundPerformanceThreadConditionMutex); - while (jacko_is_driving == true) { - result |= pthread_cond_wait(&csoundPerformanceThreadCondition, - &csoundPerformanceThreadConditionMutex); - } - jacko_is_driving = false; - jack_active = false; - result |= pthread_mutex_unlock(&csoundPerformanceThreadConditionMutex); - csound->Message(csound, - "%s", Str("Jacko has quit driving Csound performance.\n")); - return 1; + int SenseEventCallback() { + int result = 0; + if (jacko_has_finished) { + return result; + } +// Here we must wait once and only once, in order to put +// the original Csound processing thread to sleep -- +// but we must NOT put the Jack processing callback +// to sleep when it comes here! + if (jacko_is_driving == false) { + jacko_is_driving = true; +// While Jack is processing, wait here. +// The Jack process callback will then call csoundPerformKsmps +// until the Csound performance is complete. + csound->Message(csound, + "%s", Str("Jacko is now driving Csound performance...\n")); + result |= pthread_mutex_lock(&csoundPerformanceThreadConditionMutex); + while (jacko_is_driving == true) { + result |= pthread_cond_wait(&csoundPerformanceThreadCondition, + &csoundPerformanceThreadConditionMutex); + } + jacko_is_driving = false; + ///jack_active = false; + result |= pthread_mutex_unlock(&csoundPerformanceThreadConditionMutex); + csound->Message(csound, + "%s", Str("Jacko has quit driving Csound performance.\n")); + return 1; + } + return result; } - return result; - } - int JackProcessCallback(jack_nframes_t frames) { - IGN(frames); - if (frames != csoundFramesPerTick) { - csound->Message(csound, "JackProcessCallback: frames (%d) != csoundFramesPerTick (%d)\n", frames, csoundFramesPerTick); - } - int result = 0; - // We must call PerformKsmps here ONLY after the original - // Csound jacko_is_driving thread is waiting on its condition. - jackFrameTime = jack_last_frame_time(jackClient); - if (jacko_is_driving == true) { - // Enqueue any MIDI messages pending in input ports. - for (std::map::iterator it = - midiInPorts.begin(); - it != midiInPorts.end(); ++it) { - jack_port_t *midiinport = it->second; - void *portbuffer = jack_port_get_buffer(midiinport, jackFramesPerTick); - if (portbuffer) { - jack_nframes_t eventN = jack_midi_get_event_count(portbuffer); - for (jack_nframes_t eventI = 0; eventI < eventN; ++eventI) { - jack_midi_event_t event; - int result = jack_midi_event_get(&event, portbuffer, eventI); - if (result == 0) { - for (size_t i = 0; i < event.size; ++i) { - midiInputQueue.push_back(event.buffer[i]); - } + int JackProcessCallback(jack_nframes_t frames) { + IGN(frames); + if (frames != csoundFramesPerTick) { + csound->Message(csound, "JackProcessCallback: frames (%d) != csoundFramesPerTick (%d)\n", frames, csoundFramesPerTick); + } + int result = 0; +// We must call PerformKsmps here ONLY after the original +// Csound jacko_is_driving thread is waiting on its condition. + jackFrameTime = jack_last_frame_time(jackClient); + if (jacko_is_driving == true) { +// Enqueue any MIDI messages pending in input ports. + for (std::map::iterator it = + midiInPorts.begin(); + it != midiInPorts.end(); ++it) { + jack_port_t *midiinport = it->second; + void *portbuffer = jack_port_get_buffer(midiinport, jackFramesPerTick); + if (portbuffer) { + jack_nframes_t eventN = jack_midi_get_event_count(portbuffer); + for (jack_nframes_t eventI = 0; eventI < eventN; ++eventI) { + jack_midi_event_t event; + int result = jack_midi_event_get(&event, portbuffer, eventI); + if (result == 0) { + for (size_t i = 0; i < event.size; ++i) { + midiInputQueue.push_back(event.buffer[i]); + } + } + } + } + } +// Clear MIDI output buffers. + for (std::map::iterator it = + midiOutPorts.begin(); + it != midiOutPorts.end(); ++it) { + void *buffer = jack_port_get_buffer(it->second, jackFramesPerTick); + jack_midi_clear_buffer(buffer); + } + int finished = csound->PerformKsmps(csound); +// We break here when the Csound performance is complete, and close +// the Jack connection in a separate thread. + if (finished /* && jack_active */) { + jacko_has_finished = true; + ///jack_active = false; + jacko_is_driving = false; + csound->Message(csound, "%s", Str("Jacko performance finished.\n")); +//~ // Create a thread to run the close routine. + result = pthread_create(&closeThread, 0, + &JackoState::closeThreadRoutine_, this); + return finished; } - } } - } - // Clear MIDI output buffers. - for (std::map::iterator it = - midiOutPorts.begin(); - it != midiOutPorts.end(); ++it) { - void *buffer = jack_port_get_buffer(it->second, jackFramesPerTick); - jack_midi_clear_buffer(buffer); - } - int finished = csound->PerformKsmps(csound); - // We break here when the Csound performance is complete, and close - // the Jack connection in a separate thread. - if (finished /* && jack_active */) { - jacko_finished = true; - jack_active = false; + return result; + } + int close() { + ///jack_active = false; + jacko_has_finished = true; + csound->Message(csound, "%s", Str("JackoState::close...\n")); jacko_is_driving = false; - csound->Message(csound, "%s", Str("Jacko performance finished.\n")); - //~ // Create a thread to run the close routine. - result = pthread_create(&closeThread, 0, - &JackoState::closeThreadRoutine_, this); - return finished; - } + int result = OK; +// Try not to do thread related operations more than once... + result = jack_deactivate(jackClient); + csound->Message(csound, "%s", Str("Jack client deactivated.\n")); +// Jack documentation says deactivating the client does the following also: + for (std::map::iterator it = + audioInPorts.begin(); + it != audioInPorts.end(); ++it) { + result = jack_port_unregister(jackClient, it->second); + } + for (std::map::iterator it = + audioOutPorts.begin(); + it != audioOutPorts.end(); ++it) { + result = jack_port_unregister(jackClient, it->second); + } + for (std::map::iterator it = + midiInPorts.begin(); + it != midiInPorts.end(); ++it) { + result = jack_port_unregister(jackClient, it->second); + } + for (std::map::iterator it = + midiOutPorts.begin(); + it != midiOutPorts.end(); ++it) { + result = jack_port_unregister(jackClient, it->second); + } + csound->Message(csound, "%s", Str("Jack ports unregistered.\n")); + result |= jack_client_close(jackClient); + csound->Message(csound, "%s", Str("Jack client closed.\n")); + result |= pthread_cond_broadcast(&csoundPerformanceThreadCondition); + result |= pthread_cond_destroy(&csoundPerformanceThreadCondition); + result |= pthread_mutex_unlock(&csoundPerformanceThreadConditionMutex); + result |= pthread_mutex_destroy(&csoundPerformanceThreadConditionMutex); + audioOutPorts.clear(); + audioInPorts.clear(); + midiInPorts.clear(); + midiOutPorts.clear(); + csound->Message(csound, "%s", Str("JackoState::close.\n")); + return result; + } + void *closeThreadRoutine() { + int result = 0; + close(); + void *result_ = 0; + memcpy(&result_, &result, std::min(sizeof(result), sizeof(result_))); + return result_; + } + static void *closeThreadRoutine_(void *userdata) { + void *result = ((JackoState *)userdata)->closeThreadRoutine(); + return result; } - return result; - } - int close() { - jack_active = false; - jacko_finished = true; - csound->Message(csound, "%s", Str("JackoState::close...\n")); - jacko_is_driving = false; - int result = OK; - // Try not to do thread related operations more than once... - result = jack_deactivate(jackClient); - csound->Message(csound, "%s", Str("Jack client deactivated.\n")); - // Jack documentation says deactivating the client does the following also: - for (std::map::iterator it = - audioInPorts.begin(); - it != audioInPorts.end(); ++it) { - result = jack_port_unregister(jackClient, it->second); + void startTransport() { + midiInputQueue.clear(); + jack_transport_start(jackClient); } - for (std::map::iterator it = - audioOutPorts.begin(); - it != audioOutPorts.end(); ++it) { - result = jack_port_unregister(jackClient, it->second); + void stopTransport() { + jack_transport_stop(jackClient); } - for (std::map::iterator it = - midiInPorts.begin(); - it != midiInPorts.end(); ++it) { - result = jack_port_unregister(jackClient, it->second); + int positionTransport(double timeSeconds) { + int result = OK; + jack_position.frame_time = timeSeconds; + midiInputQueue.clear(); + result = jack_transport_reposition(jackClient, &jack_position); + return result; } - for (std::map::iterator it = - midiOutPorts.begin(); - it != midiOutPorts.end(); ++it) { - result = jack_port_unregister(jackClient, it->second); + /** + * Return a MIDI output buffer, + * clearing it if not yet cleared for this tick. + */ + jack_midi_data_t *getMidiOutBuffer(jack_port_t *csoundPort) { + jack_midi_data_t *buffer = (jack_midi_data_t *)jack_port_get_buffer( + csoundPort, csoundFramesPerTick); + return buffer; } - csound->Message(csound, "%s", Str("Jack ports unregistered.\n")); - result |= jack_client_close(jackClient); - csound->Message(csound, "%s", Str("Jack client closed.\n")); - result |= pthread_cond_broadcast(&csoundPerformanceThreadCondition); - result |= pthread_cond_destroy(&csoundPerformanceThreadCondition); - result |= pthread_mutex_unlock(&csoundPerformanceThreadConditionMutex); - result |= pthread_mutex_destroy(&csoundPerformanceThreadConditionMutex); - audioOutPorts.clear(); - audioInPorts.clear(); - midiInPorts.clear(); - midiOutPorts.clear(); - csound->Message(csound, "%s", Str("JackoState::close.\n")); - return result; - } - void *closeThreadRoutine() { - int result = 0; - close(); - void *result_ = 0; - memcpy(&result_, &result, std::min(sizeof(result), sizeof(result_))); - return result_; - } - static void *closeThreadRoutine_(void *userdata) { - void *result = ((JackoState *)userdata)->closeThreadRoutine(); - return result; - } - void startTransport() { - midiInputQueue.clear(); - jack_transport_start(jackClient); - } - void stopTransport() { jack_transport_stop(jackClient); } - int positionTransport(double timeSeconds) { - int result = OK; - jack_position.frame_time = timeSeconds; - midiInputQueue.clear(); - result = jack_transport_reposition(jackClient, &jack_position); - return result; - } - /** - * Return a MIDI output buffer, - * clearing it if not yet cleared for this tick. - */ - jack_midi_data_t *getMidiOutBuffer(jack_port_t *csoundPort) { - jack_midi_data_t *buffer = (jack_midi_data_t *)jack_port_get_buffer( - csoundPort, csoundFramesPerTick); - return buffer; - } }; static int JackProcessCallback_(jack_nframes_t frames, void *data) { - return ((JackoState *)data)->JackProcessCallback(frames); + return ((JackoState *)data)->JackProcessCallback(frames); } static void SenseEventCallback_(CSOUND *csound, void *data) { - IGN(csound); - ((JackoState *)data)->SenseEventCallback(); + IGN(csound); + ((JackoState *)data)->SenseEventCallback(); } static int midiDeviceOpen_(CSOUND *csound, void **userData, const char *devName) { - IGN(devName); - JackoState *jackoState; - csound::QueryGlobalPointer(csound, "jackoState", jackoState); - *userData = jackoState; - return 0; + IGN(devName); + JackoState *jackoState; + csound::QueryGlobalPointer(csound, "jackoState", jackoState); + *userData = jackoState; + return 0; } /** - * Dispatch any MIDI channel messages that have - * been read from Jack MIDI input ports. - */ +* Dispatch any MIDI channel messages that have +* been read from Jack MIDI input ports. +*/ static int midiRead_(CSOUND *csound, void *userData, unsigned char *midiData, int midiN) { - IGN(csound); - JackoState *jackoState_ = (JackoState *)userData; - if (jackoState_->jacko_finished == true) { - return 0; - } - int midiI = 0; - while (!jackoState_->midiInputQueue.empty() && midiI < midiN) { - midiData[midiI] = jackoState_->midiInputQueue.front(); - jackoState_->midiInputQueue.pop_front(); - midiI++; - } - // if (midiI) { - // csound->Message(csound, "midiRead_: %d bytes.\n", midiI); - //} - return midiI; + IGN(csound); + JackoState *jackoState_ = (JackoState *)userData; + if (jackoState_->jacko_has_finished == true) { + return 0; + } + int midiI = 0; + while (!jackoState_->midiInputQueue.empty() && midiI < midiN) { + midiData[midiI] = jackoState_->midiInputQueue.front(); + jackoState_->midiInputQueue.pop_front(); + midiI++; + } +// if (midiI) { +// csound->Message(csound, "midiRead_: %d bytes.\n", midiI); +//} + return midiI; } struct JackoInit : public OpcodeBase { - STRINGDAT *ServerName; - STRINGDAT *SclientName; - const char *serverName; - const char *clientName; - int init(CSOUND *csound) { - serverName = csound->strarg2name(csound, (char *)0, ServerName->data, - (char *)"default", (int)1); - clientName = csound->strarg2name(csound, (char *)0, SclientName->data, - (char *)"csound", (int)1); - JackoState *jackoState = new JackoState(csound, serverName, clientName); - int result = csound::CreateGlobalPointer(csound, "jackoState", jackoState); - return result; - } + STRINGDAT *ServerName; + STRINGDAT *SclientName; + const char *serverName; + const char *clientName; + int init(CSOUND *csound) { + serverName = csound->strarg2name(csound, (char *)0, ServerName->data, + (char *)"default", (int)1); + clientName = csound->strarg2name(csound, (char *)0, SclientName->data, + (char *)"csound", (int)1); + JackoState *jackoState = new JackoState(csound, serverName, clientName); + int result = csound::CreateGlobalPointer(csound, "jackoState", jackoState); + return result; + } }; struct JackoInfo : public OpcodeBase { - int init(CSOUND *csound) { - JackoState *jackoState = 0; - csound::QueryGlobalPointer(csound, "jackoState", jackoState); - log(csound, "Jack information for client: %s\n", jackoState->clientName); - log(csound, " Daemon name: %s\n", jackoState->serverName); - log(csound, " Frames per second: %d\n", - jackoState->jackFramesPerSecond); - log(csound, " Frames per period: %d\n", - jackoState->jackFramesPerTick); - const char **ports = jack_get_ports(jackoState->jackClient, 0, 0, 0); - if (ports) { - log(csound, " Ports and connections:\n"); - for (size_t i = 0; ports[i]; ++i) { - const char *PortName = ports[i]; - jack_port_t *port = jack_port_by_name(jackoState->jackClient, PortName); - int flags = jack_port_flags(port); - const char *type = jack_port_type(port); - const char *portType = " "; - if ((flags & JackPortIsOutput) == JackPortIsOutput) { - portType = "Output"; - } else if ((flags & JackPortIsInput) == JackPortIsInput) { - portType = "Input "; - } - log(csound, " %3d: %s %-25s %s\n", (i + 1), portType, type, - (PortName ? PortName : "(no name)")); - char alias1[0x100]; - char alias2[0x100]; - char *const aliases[2] = {alias1, alias2}; - size_t aliasN = jack_port_get_aliases(port, aliases); - for (size_t aliasI = 0; aliasI < aliasN; ++aliasI) { - log(csound, " Alias: %s\n", aliases[aliasI]); - } - const char **connections = - jack_port_get_all_connections(jackoState->jackClient, port); - if (connections) { - for (size_t j = 0; connections[j]; ++j) { - if ((jack_port_flags(port) & JackPortIsOutput) == - JackPortIsOutput) { - log(csound, - " Sends to: >> %s\n", - connections[j]); - } else { - log(csound, - " Receives from: << %s\n", - connections[j]); + int init(CSOUND *csound) { + JackoState *jackoState = 0; + csound::QueryGlobalPointer(csound, "jackoState", jackoState); + log(csound, "Jack information for client: %s\n", jackoState->clientName); + log(csound, " Daemon name: %s\n", jackoState->serverName); + log(csound, " Frames per second: %d\n", + jackoState->jackFramesPerSecond); + log(csound, " Frames per period: %d\n", + jackoState->jackFramesPerTick); + const char **ports = jack_get_ports(jackoState->jackClient, 0, 0, 0); + if (ports) { + log(csound, " Ports and connections:\n"); + for (size_t i = 0; ports[i]; ++i) { + const char *PortName = ports[i]; + jack_port_t *port = jack_port_by_name(jackoState->jackClient, PortName); + int flags = jack_port_flags(port); + const char *type = jack_port_type(port); + const char *portType = " "; + if ((flags & JackPortIsOutput) == JackPortIsOutput) { + portType = "Output"; + } else if ((flags & JackPortIsInput) == JackPortIsInput) { + portType = "Input "; + } + log(csound, " %3d: %s %-25s %s\n", (i + 1), portType, type, + (PortName ? PortName : "(no name)")); + char alias1[0x100]; + char alias2[0x100]; + char *const aliases[2] = {alias1, alias2}; + size_t aliasN = jack_port_get_aliases(port, aliases); + for (size_t aliasI = 0; aliasI < aliasN; ++aliasI) { + log(csound, " Alias: %s\n", aliases[aliasI]); + } + const char **connections = + jack_port_get_all_connections(jackoState->jackClient, port); + if (connections) { + for (size_t j = 0; connections[j]; ++j) { + if ((jack_port_flags(port) & JackPortIsOutput) == + JackPortIsOutput) { + log(csound, + " Sends to: >> %s\n", + connections[j]); + } else { + log(csound, + " Receives from: << %s\n", + connections[j]); + } + } + } + std::free(connections); } - } + std::free(ports); } - std::free(connections); - } - std::free(ports); + return OK; } - return OK; - } }; struct JackoFreewheel : public OpcodeBase { - MYFLT *ifreewheel; - int init(CSOUND *csound) { - JackoState *jackoState = 0; - csound::QueryGlobalPointer(csound, "jackoState", jackoState); - int freewheel = (int)*ifreewheel; - int result = jack_set_freewheel(jackoState->jackClient, freewheel); - if (result) { - warn(csound, - Str("Failed to set Jack freewheeling mode to \"%s\": error %d.\n"), - (freewheel ? "on" : "off"), result); - } else { - log(csound, Str("Set Jack freewheeling mode to \"%s\".\n"), - (freewheel ? "on" : "off")); + MYFLT *ifreewheel; + int init(CSOUND *csound) { + JackoState *jackoState = 0; + csound::QueryGlobalPointer(csound, "jackoState", jackoState); + int freewheel = (int)*ifreewheel; + int result = jack_set_freewheel(jackoState->jackClient, freewheel); + if (result) { + warn(csound, + Str("Failed to set Jack freewheeling mode to \"%s\": error %d.\n"), + (freewheel ? "on" : "off"), result); + } else { + log(csound, Str("Set Jack freewheeling mode to \"%s\".\n"), + (freewheel ? "on" : "off")); + } + return result; } - return result; - } }; struct JackoOn : public OpcodeBase { - MYFLT *jon; - int init(CSOUND *csound) { - int result = OK; - JackoState *jackoState = 0; - csound::QueryGlobalPointer(csound, "jackoState", jackoState); - jackoState->jack_active = (char)*jon; - log(csound, Str("Turned Jack connections \"%s\".\n"), - (jackoState->jack_active ? "on" : "off")); - return result; - } + MYFLT *jon; + int init(CSOUND *csound) { + int result = OK; + JackoState *jackoState = 0; + csound::QueryGlobalPointer(csound, "jackoState", jackoState); + log(csound, Str("JackoOn is deprecated and now is a no-op.\n")); + return result; + } }; struct JackoAudioInConnect : public OpcodeBase { - // Out. - // Ins. - STRINGDAT *SexternalPortName; - STRINGDAT *ScsoundPortName; - // State. - const char *csoundPortName; - char csoundFullPortName[0x100]; - const char *externalPortName; - const char *clientName; - size_t frames; - jack_port_t *csoundPort; - jack_port_t *externalPort; - JackoState *jackoState; - int init(CSOUND *csound) { - csound::QueryGlobalPointer(csound, "jackoState", jackoState); - int result = OK; - frames = opds.insdshead->ksmps; - clientName = jack_get_client_name(jackoState->jackClient); - csoundPortName = csound->strarg2name( - csound, (char *)0, ScsoundPortName->data, (char *)"", (int)1); - std::sprintf(csoundFullPortName, "%s:%s", clientName, csoundPortName); - csoundPort = jack_port_by_name(jackoState->jackClient, csoundFullPortName); - if (csoundPort) { - log(csound, "Found Csound audio in port \"%s\".\n", csoundFullPortName); - } else { - csoundPort = - jack_port_register(jackoState->jackClient, csoundPortName, - JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); +// Out. +// Ins. + STRINGDAT *SexternalPortName; + STRINGDAT *ScsoundPortName; +// State. + const char *csoundPortName; + char csoundFullPortName[0x100]; + const char *externalPortName; + const char *clientName; + size_t frames; + jack_port_t *csoundPort; + jack_port_t *externalPort; + JackoState *jackoState; + int init(CSOUND *csound) { + csound::QueryGlobalPointer(csound, "jackoState", jackoState); + int result = OK; + frames = opds.insdshead->ksmps; + clientName = jack_get_client_name(jackoState->jackClient); + csoundPortName = csound->strarg2name( + csound, (char *)0, ScsoundPortName->data, (char *)"", (int)1); + std::sprintf(csoundFullPortName, "%s:%s", clientName, csoundPortName); + csoundPort = jack_port_by_name(jackoState->jackClient, csoundFullPortName); + if (csoundPort) { + log(csound, "Found Csound audio in port \"%s\".\n", csoundFullPortName); + } else { + csoundPort = + jack_port_register(jackoState->jackClient, csoundPortName, + JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); if (csoundPort) { log(csound, "Created Csound audio in port \"%s\".\n", csoundFullPortName); } else { - warn(csound, Str("Could not create Csound audio in port \"%s\".\n"), - csoundFullPortName); + warn(csound, Str("Could not create Csound audio in port \"%s\".\n"), + csoundFullPortName); + } } + externalPortName = csound->strarg2name( + csound, (char *)0, SexternalPortName->data, (char *)"csound", (int)1); + result = jack_connect(jackoState->jackClient, csoundPortName, + externalPortName); + if (result == EEXIST) { + log(csound, "Jack audio connection from \"%s\" to \"%s\" already exists.\n", + csoundFullPortName, externalPortName); + } else if (result) { + warn(csound, + Str("Could not create Jack audio connection from \"%s\" to \"%s\": " + "status %d.\n"), + csoundFullPortName, externalPortName, result); + return result; + } else { + log(csound, "Created Jack audio connection from \"%s\" to \"%s\".\n", + csoundFullPortName, externalPortName); + } + jackoState->audioInPorts[csoundPortName] = csoundPort; + return result; } - externalPortName = csound->strarg2name( - csound, (char *)0, SexternalPortName->data, (char *)"csound", (int)1); - result = jack_connect(jackoState->jackClient, csoundPortName, - externalPortName); - if (result == EEXIST) { - log(csound, "Jack audio connection from \"%s\" to \"%s\" already exists.\n", - csoundFullPortName, externalPortName); - } else if (result) { - warn(csound, - Str("Could not create Jack audio connection from \"%s\" to \"%s\": " - "status %d.\n"), - csoundFullPortName, externalPortName, result); - return result; - } else { - log(csound, "Created Jack audio connection from \"%s\" to \"%s\".\n", - csoundFullPortName, externalPortName); - } - jackoState->audioInPorts[csoundPortName] = csoundPort; - return result; - } }; struct JackoAudioIn : public OpcodeBase { - // Out. - MYFLT *asignal; - // Ins. - STRINGDAT *ScsoundPortName; - // State. - const char *csoundPortName; - jack_port_t *csoundPort; - jack_nframes_t csoundFramesPerTick; - JackoState *jackoState; - int init(CSOUND *csound) { - csound::QueryGlobalPointer(csound, "jackoState", jackoState); - int result = OK; - csoundFramesPerTick = jackoState->csoundFramesPerTick; - csoundPortName = csound->strarg2name( - csound, (char *)0, ScsoundPortName->data, (char *)"", (int)1); - csoundPort = jackoState->audioInPorts[csoundPortName]; - return result; - } - int audio(CSOUND *csound) { - IGN(csound); - if (jackoState->jacko_finished == true) { - return OK; +// Out. + MYFLT *asignal; +// Ins. + STRINGDAT *ScsoundPortName; +// State. + const char *csoundPortName; + jack_port_t *csoundPort; + jack_nframes_t csoundFramesPerTick; + JackoState *jackoState; + int init(CSOUND *csound) { + csound::QueryGlobalPointer(csound, "jackoState", jackoState); + int result = OK; + csoundFramesPerTick = jackoState->csoundFramesPerTick; + csoundPortName = csound->strarg2name( + csound, (char *)0, ScsoundPortName->data, (char *)"", (int)1); + csoundPort = jackoState->audioInPorts[csoundPortName]; + return result; } - jack_default_audio_sample_t *buffer = - (jack_default_audio_sample_t *)jack_port_get_buffer( - csoundPort, csoundFramesPerTick); - for (size_t frame = 0; frame < csoundFramesPerTick; ++frame) { - asignal[frame] = buffer[frame]; + int audio(CSOUND *csound) { + IGN(csound); + if (jackoState->jacko_has_finished == true) { + return OK; + } + jack_default_audio_sample_t *buffer = + (jack_default_audio_sample_t *)jack_port_get_buffer( + csoundPort, csoundFramesPerTick); + for (size_t frame = 0; frame < csoundFramesPerTick; ++frame) { + asignal[frame] = buffer[frame]; + } + return OK; } - return OK; - } }; struct JackoAudioOutConnect : public OpcodeBase { - // No outs. - // Ins. - STRINGDAT *ScsoundPortName; - STRINGDAT *SexternalPortName; - // State. - const char *csoundPortName; - char csoundFullPortName[0x100]; - const char *externalPortName; - const char *clientName; - size_t frames; - jack_port_t *csoundPort; - jack_port_t *externalPort; - JackoState *jackoState; - int init(CSOUND *csound) { - csound::QueryGlobalPointer(csound, "jackoState", jackoState); - int result = OK; - frames = opds.insdshead->ksmps; - clientName = jack_get_client_name(jackoState->jackClient); - csoundPortName = csound->strarg2name( - csound, (char *)0, ScsoundPortName->data, (char *)"", (int)1); - std::sprintf(csoundFullPortName, "%s:%s", clientName, csoundPortName); - externalPortName = csound->strarg2name( - csound, (char *)0, SexternalPortName->data, (char *)"csound", (int)1); - csoundPort = jack_port_by_name(jackoState->jackClient, csoundFullPortName); - if (!csoundPort) { - csoundPort = - jack_port_register(jackoState->jackClient, csoundPortName, - JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); - if (csoundPort) { - log(csound, "Created Csound audio out port \"%s\".\n", csoundFullPortName); - } else { - warn(csound, Str("Could not create Csound audio out port \"%s\".\n"), - csoundFullPortName); - } - } - externalPort = jack_port_by_name(jackoState->jackClient, externalPortName); - result = jack_connect(jackoState->jackClient, jack_port_name(csoundPort), - jack_port_name(externalPort)); - if (result == EEXIST) { - log(csound, "Connection from \"%s\" to \"%s\" already exists.\n", - csoundFullPortName, externalPortName); - } else if (result) { - warn(csound, - Str("Could not create Jack connection from \"%s\" to \"%s\": " - "status %d.\n"), - csoundFullPortName, externalPortName, result); - return result; - } else { - log(csound, "Created Jack connection from \"%s\" to \"%s\".\n", - csoundFullPortName, externalPortName); +// No outs. +// Ins. + STRINGDAT *ScsoundPortName; + STRINGDAT *SexternalPortName; +// State. + const char *csoundPortName; + char csoundFullPortName[0x100]; + const char *externalPortName; + const char *clientName; + size_t frames; + jack_port_t *csoundPort; + jack_port_t *externalPort; + JackoState *jackoState; + int init(CSOUND *csound) { + csound::QueryGlobalPointer(csound, "jackoState", jackoState); + int result = OK; + frames = opds.insdshead->ksmps; + clientName = jack_get_client_name(jackoState->jackClient); + csoundPortName = csound->strarg2name( + csound, (char *)0, ScsoundPortName->data, (char *)"", (int)1); + std::sprintf(csoundFullPortName, "%s:%s", clientName, csoundPortName); + externalPortName = csound->strarg2name( + csound, (char *)0, SexternalPortName->data, (char *)"csound", (int)1); + csoundPort = jack_port_by_name(jackoState->jackClient, csoundFullPortName); + if (!csoundPort) { + csoundPort = + jack_port_register(jackoState->jackClient, csoundPortName, + JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); + if (csoundPort) { + log(csound, "Created Csound audio out port \"%s\".\n", csoundFullPortName); + } else { + warn(csound, Str("Could not create Csound audio out port \"%s\".\n"), + csoundFullPortName); + } + } + externalPort = jack_port_by_name(jackoState->jackClient, externalPortName); + result = jack_connect(jackoState->jackClient, jack_port_name(csoundPort), + jack_port_name(externalPort)); + if (result == EEXIST) { + log(csound, "Connection from \"%s\" to \"%s\" already exists.\n", + csoundFullPortName, externalPortName); + } else if (result) { + warn(csound, + Str("Could not create Jack connection from \"%s\" to \"%s\": " + "status %d.\n"), + csoundFullPortName, externalPortName, result); + return result; + } else { + log(csound, "Created Jack connection from \"%s\" to \"%s\".\n", + csoundFullPortName, externalPortName); + } + jackoState->audioOutPorts[csoundPortName] = csoundPort; + return result; } - jackoState->audioOutPorts[csoundPortName] = csoundPort; - return result; - } }; struct JackoAudioOut : public OpcodeBase { - // No outs. - // Ins. - STRINGDAT *ScsoundPortName; - MYFLT *asignal; - // State. - const char *csoundPortName; - jack_port_t *csoundPort; - jack_nframes_t csoundFramesPerTick; - JackoState *jackoState; - int init(CSOUND *csound) { - csound::QueryGlobalPointer(csound, "jackoState", jackoState); - int result = OK; - csoundFramesPerTick = jackoState->csoundFramesPerTick; - csoundPortName = csound->strarg2name( - csound, (char *)0, ScsoundPortName->data, (char *)"", (int)1); - csoundPort = jackoState->audioOutPorts[csoundPortName]; - return result; - } - int audio(CSOUND *csound) { - IGN(csound); - if (jackoState->jacko_finished == true) { - return OK; +// No outs. +// Ins. + STRINGDAT *ScsoundPortName; + MYFLT *asignal; +// State. + const char *csoundPortName; + jack_port_t *csoundPort; + jack_nframes_t csoundFramesPerTick; + JackoState *jackoState; + int init(CSOUND *csound) { + csound::QueryGlobalPointer(csound, "jackoState", jackoState); + int result = OK; + csoundFramesPerTick = jackoState->csoundFramesPerTick; + csoundPortName = csound->strarg2name( + csound, (char *)0, ScsoundPortName->data, (char *)"", (int)1); + csoundPort = jackoState->audioOutPorts[csoundPortName]; + return result; } - jack_default_audio_sample_t *buffer = - (jack_default_audio_sample_t *)jack_port_get_buffer( - csoundPort, csoundFramesPerTick); - for (size_t frame = 0; frame < csoundFramesPerTick; ++frame) { - buffer[frame] = asignal[frame]; + int audio(CSOUND *csound) { + IGN(csound); + if (jackoState->jacko_has_finished == true) { + return OK; + } + jack_default_audio_sample_t *buffer = + (jack_default_audio_sample_t *)jack_port_get_buffer( + csoundPort, csoundFramesPerTick); + for (size_t frame = 0; frame < csoundFramesPerTick; ++frame) { + buffer[frame] = asignal[frame]; + } + return OK; } - return OK; - } }; struct JackoMidiInConnect : public OpcodeBase { - // No outs. - // Ins. - STRINGDAT *SexternalPortName; - STRINGDAT *ScsoundPortName; - // State. - const char *csoundPortName; - char csoundFullPortName[0x100]; - const char *externalPortName; - const char *clientName; - size_t frames; - jack_port_t *csoundPort; - jack_port_t *externalPort; - JackoState *jackoState; - int init(CSOUND *csound) { - csound::QueryGlobalPointer(csound, "jackoState", jackoState); - int result = OK; - frames = opds.insdshead->ksmps; - clientName = jack_get_client_name(jackoState->jackClient); - csoundPortName = csound->strarg2name( - csound, (char *)0, ScsoundPortName->data, (char *)"", (int)1); - std::sprintf(csoundFullPortName, "%s:%s", clientName, csoundPortName); - csoundPort = jack_port_by_name(jackoState->jackClient, csoundFullPortName); - if (csoundPort) { - log(csound, "Found Csound MIDI in port \"%s\".\n", csoundFullPortName); - } else { - csoundPort = - jack_port_register(jackoState->jackClient, csoundPortName, - JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0); +// No outs. +// Ins. + STRINGDAT *SexternalPortName; + STRINGDAT *ScsoundPortName; +// State. + const char *csoundPortName; + char csoundFullPortName[0x100]; + const char *externalPortName; + const char *clientName; + size_t frames; + jack_port_t *csoundPort; + jack_port_t *externalPort; + JackoState *jackoState; + int init(CSOUND *csound) { + csound::QueryGlobalPointer(csound, "jackoState", jackoState); + int result = OK; + frames = opds.insdshead->ksmps; + clientName = jack_get_client_name(jackoState->jackClient); + csoundPortName = csound->strarg2name( + csound, (char *)0, ScsoundPortName->data, (char *)"", (int)1); + std::sprintf(csoundFullPortName, "%s:%s", clientName, csoundPortName); + csoundPort = jack_port_by_name(jackoState->jackClient, csoundFullPortName); + if (csoundPort) { + log(csound, "Found Csound MIDI in port \"%s\".\n", csoundFullPortName); + } else { + csoundPort = + jack_port_register(jackoState->jackClient, csoundPortName, + JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0); if (csoundPort) { log(csound, "Created Csound MIDI in port \"%s\".\n", csoundFullPortName); } else { - warn(csound, Str("Could not create Csound MIDI in port \"%s\".\n"), - csoundFullPortName); + warn(csound, Str("Could not create Csound MIDI in port \"%s\".\n"), + csoundFullPortName); + } } + externalPortName = csound->strarg2name( + csound, (char *)0, SexternalPortName->data, (char *)"csound", (int)1); + result = jack_connect(jackoState->jackClient, externalPortName, csoundFullPortName); + if (result == EEXIST) { + log(csound, "Jack MIDI connection from \"%s\" to \"%s\" already exists.\n", + externalPortName, csoundFullPortName); + } else if (result) { + warn(csound, + Str("Could not create Jack MIDI connection from \"%s\" to \"%s\": " + "status %d.\n"), + externalPortName, csoundFullPortName, result); + return result; + } else { + log(csound, "Created Jack MIDI connection from \"%s\" to \"%s\".\n", + externalPortName, csoundFullPortName); + } + jackoState->midiOutPorts[csoundPortName] = csoundPort; + return result; } - externalPortName = csound->strarg2name( - csound, (char *)0, SexternalPortName->data, (char *)"csound", (int)1); - result = jack_connect(jackoState->jackClient, externalPortName, csoundFullPortName); - if (result == EEXIST) { - log(csound, "Jack MIDI connection from \"%s\" to \"%s\" already exists.\n", - externalPortName, csoundFullPortName); - } else if (result) { - warn(csound, - Str("Could not create Jack MIDI connection from \"%s\" to \"%s\": " - "status %d.\n"), - externalPortName, csoundFullPortName, result); - return result; - } else { - log(csound, "Created Jack MIDI connection from \"%s\" to \"%s\".\n", - externalPortName, csoundFullPortName); - } - jackoState->midiOutPorts[csoundPortName] = csoundPort; - return result; - } }; struct JackoMidiOutConnect : public OpcodeBase { - // No outs. - // Ins. - STRINGDAT *ScsoundPortName; - STRINGDAT *SexternalPortName; - // State. - const char *csoundPortName; - char csoundFullPortName[0x100]; - const char *externalPortName; - const char *clientName; - size_t frames; - jack_port_t *csoundPort; - jack_port_t *externalPort; - JackoState *jackoState; - int init(CSOUND *csound) { - csound::QueryGlobalPointer(csound, "jackoState", jackoState); - int result = OK; - frames = opds.insdshead->ksmps; - clientName = jack_get_client_name(jackoState->jackClient); - csoundPortName = csound->strarg2name( - csound, (char *)0, ScsoundPortName->data, (char *)"", (int)1); - std::sprintf(csoundFullPortName, "%s:%s", clientName, csoundPortName); - csoundPort = jack_port_by_name(jackoState->jackClient, csoundFullPortName); - if (csoundPort) { - log(csound, "Found Csound MIDI out port \"%s\".\n", csoundFullPortName); - } else { - csoundPort = - jack_port_register(jackoState->jackClient, csoundPortName, - JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0); +// No outs. +// Ins. + STRINGDAT *ScsoundPortName; + STRINGDAT *SexternalPortName; +// State. + const char *csoundPortName; + char csoundFullPortName[0x100]; + const char *externalPortName; + const char *clientName; + size_t frames; + jack_port_t *csoundPort; + jack_port_t *externalPort; + JackoState *jackoState; + int init(CSOUND *csound) { + csound::QueryGlobalPointer(csound, "jackoState", jackoState); + int result = OK; + frames = opds.insdshead->ksmps; + clientName = jack_get_client_name(jackoState->jackClient); + csoundPortName = csound->strarg2name( + csound, (char *)0, ScsoundPortName->data, (char *)"", (int)1); + std::sprintf(csoundFullPortName, "%s:%s", clientName, csoundPortName); + csoundPort = jack_port_by_name(jackoState->jackClient, csoundFullPortName); + if (csoundPort) { + log(csound, "Found Csound MIDI out port \"%s\".\n", csoundFullPortName); + } else { + csoundPort = + jack_port_register(jackoState->jackClient, csoundPortName, + JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0); if (csoundPort) { log(csound, "Created Csound MIDI out port \"%s\".\n", csoundFullPortName); } else { - warn(csound, Str("Could not create Csound out MIDI port \"%s\".\n"), - csoundFullPortName); + warn(csound, Str("Could not create Csound out MIDI port \"%s\".\n"), + csoundFullPortName); + } } + externalPortName = csound->strarg2name( + csound, (char *)0, SexternalPortName->data, (char *)"csound", (int)1); + result = jack_connect(jackoState->jackClient, csoundFullPortName, + externalPortName); + if (result == EEXIST) { + log(csound, "Jack MIDI connection from \"%s\" to \"%s\" already exists.\n", + csoundFullPortName, externalPortName); + } else if (result) { + warn(csound, + Str("Could not create Jack MIDI connection from \"%s\" to \"%s\": " + "status %d.\n"), + csoundFullPortName, externalPortName, result); + return result; + } else { + log(csound, "Created Jack MIDI connection from \"%s\" to \"%s\".\n", + csoundFullPortName, externalPortName); + } + jackoState->midiOutPorts[csoundPortName] = csoundPort; + return result; } - externalPortName = csound->strarg2name( - csound, (char *)0, SexternalPortName->data, (char *)"csound", (int)1); - result = jack_connect(jackoState->jackClient, csoundFullPortName, - externalPortName); - if (result == EEXIST) { - log(csound, "Jack MIDI connection from \"%s\" to \"%s\" already exists.\n", - csoundFullPortName, externalPortName); - } else if (result) { - warn(csound, - Str("Could not create Jack MIDI connection from \"%s\" to \"%s\": " - "status %d.\n"), - csoundFullPortName, externalPortName, result); - return result; - } else { - log(csound, "Created Jack MIDI connection from \"%s\" to \"%s\".\n", - csoundFullPortName, externalPortName); - } - jackoState->midiOutPorts[csoundPortName] = csoundPort; - return result; - } }; struct JackoMidiOut : public OpcodeBase { - // No outs. - // Ins. - STRINGDAT *ScsoundPortName; - MYFLT *kstatus; - MYFLT *kchannel; - MYFLT *kdata1; - MYFLT *kdata2; - char status; - char channel; - char data1; - char data2; - char priorstatus; - char priorchannel; - char priordata1; - char priordata2; - // State. - const char *csoundPortName; - jack_port_t *csoundPort; - jack_nframes_t csoundFramesPerTick; - jack_midi_data_t *buffer; - JackoState *jackoState; - int init(CSOUND *csound) { - csound::QueryGlobalPointer(csound, "jackoState", jackoState); - int result = OK; - csoundFramesPerTick = jackoState->csoundFramesPerTick; - csoundPortName = csound->strarg2name( - csound, (char *)0, ScsoundPortName->data, (char *)"", (int)1); - csoundPort = jackoState->midiOutPorts[csoundPortName]; - priorstatus = -1; - priorchannel = -1; - priordata1 = -1; - priordata2 = -1; - return result; - } - int kontrol(CSOUND *csound) { - IGN(csound); - if (jackoState->jacko_finished == true) { - return OK; +// No outs. +// Ins. + STRINGDAT *ScsoundPortName; + MYFLT *kstatus; + MYFLT *kchannel; + MYFLT *kdata1; + MYFLT *kdata2; + char status; + char channel; + char data1; + char data2; + char priorstatus; + char priorchannel; + char priordata1; + char priordata2; +// State. + const char *csoundPortName; + jack_port_t *csoundPort; + jack_nframes_t csoundFramesPerTick; + jack_midi_data_t *buffer; + JackoState *jackoState; + int init(CSOUND *csound) { + csound::QueryGlobalPointer(csound, "jackoState", jackoState); + int result = OK; + csoundFramesPerTick = jackoState->csoundFramesPerTick; + csoundPortName = csound->strarg2name( + csound, (char *)0, ScsoundPortName->data, (char *)"", (int)1); + csoundPort = jackoState->midiOutPorts[csoundPortName]; + priorstatus = -1; + priorchannel = -1; + priordata1 = -1; + priordata2 = -1; + return result; } - int result = OK; - status = *kstatus; - channel = *kchannel; - data1 = *kdata1; - data2 = *kdata2; - if (status != priorstatus || channel != priorchannel || - data1 != priordata1 || data2 != priordata2) { - size_t dataSize = 0; - if (data2 == -1) { - dataSize = 2; - } else { - dataSize = 3; - } - buffer = jackoState->getMidiOutBuffer(csoundPort); - jack_midi_data_t *data = jack_midi_event_reserve(buffer, 0, dataSize); - data[0] = (status + channel); - data[1] = data1; - if (data2 != -1) { - data[2] = data2; - // log(csound, "MIDI: %3d %3d %3d\n", data[0], data[1], data[2]); - } else { - // log(csound, "MIDI: %3d %3d\n", data[0], data[1]); - } + int kontrol(CSOUND *csound) { + IGN(csound); + if (jackoState->jacko_has_finished == true) { + return OK; + } + int result = OK; + status = *kstatus; + channel = *kchannel; + data1 = *kdata1; + data2 = *kdata2; + if (status != priorstatus || channel != priorchannel || + data1 != priordata1 || data2 != priordata2) { + size_t dataSize = 0; + if (data2 == -1) { + dataSize = 2; + } else { + dataSize = 3; + } + buffer = jackoState->getMidiOutBuffer(csoundPort); + jack_midi_data_t *data = jack_midi_event_reserve(buffer, 0, dataSize); + data[0] = (status + channel); + data[1] = data1; + if (data2 != -1) { + data[2] = data2; +// log(csound, "MIDI: %3d %3d %3d\n", data[0], data[1], data[2]); + } else { +// log(csound, "MIDI: %3d %3d\n", data[0], data[1]); + } + } + priorstatus = status; + priorchannel = channel; + priordata1 = data1; + priordata2 = data2; + return result; } - priorstatus = status; - priorchannel = channel; - priordata1 = data1; - priordata2 = data2; - return result; - } }; struct JackoNoteOut : public OpcodeNoteoffBase { - // No outs. - // Ins. - STRINGDAT *ScsoundPortName; - MYFLT *ichannel; - MYFLT *ikey; - MYFLT *ivelocity; - char status; - char channel; - char key; - char velocity; - // State. - const char *csoundPortName; - jack_port_t *csoundPort; - jack_nframes_t csoundFramesPerTick; - jack_midi_data_t *buffer; - JackoState *jackoState; - int init(CSOUND *csound) { - csound::QueryGlobalPointer(csound, "jackoState", jackoState); - int result = OK; - csoundFramesPerTick = jackoState->csoundFramesPerTick; - csoundPortName = csound->strarg2name( - csound, (char *)0, ScsoundPortName->data, (char *)"", (int)1); - csoundPort = jackoState->midiOutPorts[csoundPortName]; - channel = (char)*ichannel; - key = (char)*ikey; - velocity = (char)*ivelocity; - buffer = jackoState->getMidiOutBuffer(csoundPort); - jack_midi_data_t *data = jack_midi_event_reserve(buffer, 0, 3); - data[0] = (144 + channel); - data[1] = key; - data[2] = velocity; - log(csound, "noteon: %3d %3d %3d\n", data[0], data[1], data[2]); - return result; - } - int noteoff(CSOUND *csound) { - IGN(csound); - if (jackoState->jacko_finished == true) { - return OK; +// No outs. +// Ins. + STRINGDAT *ScsoundPortName; + MYFLT *ichannel; + MYFLT *ikey; + MYFLT *ivelocity; + char status; + char channel; + char key; + char velocity; +// State. + const char *csoundPortName; + jack_port_t *csoundPort; + jack_nframes_t csoundFramesPerTick; + jack_midi_data_t *buffer; + JackoState *jackoState; + int init(CSOUND *csound) { + csound::QueryGlobalPointer(csound, "jackoState", jackoState); + int result = OK; + csoundFramesPerTick = jackoState->csoundFramesPerTick; + csoundPortName = csound->strarg2name( + csound, (char *)0, ScsoundPortName->data, (char *)"", (int)1); + csoundPort = jackoState->midiOutPorts[csoundPortName]; + channel = (char)*ichannel; + key = (char)*ikey; + velocity = (char)*ivelocity; + buffer = jackoState->getMidiOutBuffer(csoundPort); + jack_midi_data_t *data = jack_midi_event_reserve(buffer, 0, 3); + data[0] = (144 + channel); + data[1] = key; + data[2] = velocity; + log(csound, "noteon: %3d %3d %3d\n", data[0], data[1], data[2]); + return result; + } + int noteoff(CSOUND *csound) { + IGN(csound); + if (jackoState->jacko_has_finished == true) { + return OK; + } + int result = OK; + buffer = jackoState->getMidiOutBuffer(csoundPort); + jack_midi_data_t *data = jack_midi_event_reserve(buffer, 0, 3); + data[0] = (128 + channel); + data[1] = key; + data[2] = 0; + log(csound, "noteoff: %3d %3d %3d\n", data[0], data[1], data[2]); + return result; } - int result = OK; - buffer = jackoState->getMidiOutBuffer(csoundPort); - jack_midi_data_t *data = jack_midi_event_reserve(buffer, 0, 3); - data[0] = (128 + channel); - data[1] = key; - data[2] = 0; - log(csound, "noteoff: %3d %3d %3d\n", data[0], data[1], data[2]); - return result; - } }; struct JackoTransport : public OpcodeBase { - // Outs. - // Ins. - MYFLT *kcommand; - MYFLT *Oposition; - // State. - int command; - int priorCommand; - double positionSeconds; - double priorPositionSeconds; - JackoState *jackoState; - int init(CSOUND *csound) { - csound::QueryGlobalPointer(csound, "jackoState", jackoState); - priorCommand = -1; - priorPositionSeconds = 0.0; - return kontrol(csound); - } - int kontrol(CSOUND *csound) { - if (jackoState->jacko_finished == true) { - return OK; +// Outs. +// Ins. + MYFLT *kcommand; + MYFLT *Oposition; +// State. + int command; + int priorCommand; + double positionSeconds; + double priorPositionSeconds; + JackoState *jackoState; + int init(CSOUND *csound) { + csound::QueryGlobalPointer(csound, "jackoState", jackoState); + priorCommand = -1; + priorPositionSeconds = 0.0; + return kontrol(csound); } - int result = OK; - command = int(*kcommand); - positionSeconds = double(*Oposition); - if (command) { - if (command != priorCommand) { - priorCommand = command; - switch (command) { - case 1: - result = jackoState->positionTransport(0.0); - jackoState->startTransport(); - log(csound, "Started Jack transport.\n"); - break; - case 2: - jackoState->stopTransport(); - log(csound, "Stopped Jack transport.\n"); - break; - case 3: - if (positionSeconds != priorPositionSeconds) { - priorPositionSeconds = positionSeconds; - result = jackoState->positionTransport(positionSeconds); - jackoState->startTransport(); - if (result) { - log(csound, "Failed to start Jack transport at %f seconds with" - " result: %d\n", - positionSeconds, result); - } else { - log(csound, "Started Jack transport at %f seconds.\n", - positionSeconds); + int kontrol(CSOUND *csound) { + if (jackoState->jacko_has_finished == true) { + return OK; + } + int result = OK; + command = int(*kcommand); + positionSeconds = double(*Oposition); + if (command) { + if (command != priorCommand) { + priorCommand = command; + switch (command) { + case 1: + result = jackoState->positionTransport(0.0); + jackoState->startTransport(); + log(csound, "Started Jack transport.\n"); + break; + case 2: + jackoState->stopTransport(); + log(csound, "Stopped Jack transport.\n"); + break; + case 3: + if (positionSeconds != priorPositionSeconds) { + priorPositionSeconds = positionSeconds; + result = jackoState->positionTransport(positionSeconds); + jackoState->startTransport(); + if (result) { + log(csound, "Failed to start Jack transport at %f seconds with" + " result: %d\n", + positionSeconds, result); + } else { + log(csound, "Started Jack transport at %f seconds.\n", + positionSeconds); + } + } + break; + }; } - } - break; - }; - } + } + return result; } - return result; - } }; extern "C" { -static OENTRY oentries[] = { - {(char *)"JackoInit", sizeof(JackoInit), 0, 1, (char *)"", (char *)"SS", - (SUBR)&JackoInit::init_, 0, 0}, - {(char *)"JackoInfo", sizeof(JackoInfo), 0, 1, (char *)"", (char *)"", - (SUBR)&JackoInfo::init_, 0, 0}, - {(char *)"JackoFreewheel", sizeof(JackoFreewheel), 0, 1, (char *)"", - (char *)"i", (SUBR)&JackoFreewheel::init_, 0, 0}, - {(char *)"JackoOn", sizeof(JackoOn), 0, 1, (char *)"", (char *)"j", - (SUBR)&JackoOn::init_, 0, 0}, - { - (char *)"JackoAudioInConnect", sizeof(JackoAudioInConnect), 0, 1, - (char *)"", (char *)"SS", (SUBR)&JackoAudioInConnect::init_, 0, 0, - }, - { - (char *)"JackoAudioIn", sizeof(JackoAudioIn), 0, 3, (char *)"a", - (char *)"S", (SUBR)&JackoAudioIn::init_, (SUBR)&JackoAudioIn::audio_, - }, - { - (char *)"JackoAudioOutConnect", sizeof(JackoAudioOutConnect), 0, 1, - (char *)"", (char *)"SS", (SUBR)&JackoAudioOutConnect::init_, 0, 0, - }, - { - (char *)"JackoAudioOut", sizeof(JackoAudioOut), 0, 3, (char *)"", - (char *)"Sa", (SUBR)&JackoAudioOut::init_, - (SUBR)&JackoAudioOut::audio_, - }, - { - (char *)"JackoMidiInConnect", sizeof(JackoMidiInConnect), 0, 1, - (char *)"", (char *)"SS", (SUBR)&JackoMidiInConnect::init_, 0, 0, - }, - { - (char *)"JackoMidiOutConnect", sizeof(JackoMidiOutConnect), 0, 1, - (char *)"", (char *)"SS", (SUBR)&JackoMidiOutConnect::init_, 0, 0, - }, - { - (char *)"JackoMidiOut", sizeof(JackoMidiOut), 0, 3, (char *)"", - (char *)"SkkkO", (SUBR)&JackoMidiOut::init_, - (SUBR)&JackoMidiOut::kontrol_, 0, - }, - {(char *)"JackoNoteOut", sizeof(JackoNoteOut), 0, 3, (char *)"", - (char *)"Siii", (SUBR)&JackoNoteOut::init_, (SUBR)&JackoNoteOut::kontrol_, - 0}, - {(char *)"JackoTransport", sizeof(JackoTransport), 0, 3, (char *)"", - (char *)"kO", // O defaults to 0. - (SUBR)&JackoTransport::init_, (SUBR)&JackoTransport::kontrol_, 0}, - {0, 0, 0, 0, 0, 0, (SUBR)0, (SUBR)0, (SUBR)0}}; + static OENTRY oentries[] = { + { (char *)"JackoInit", sizeof(JackoInit), 0, 1, (char *)"", (char *)"SS", + (SUBR)&JackoInit::init_, 0, 0 + }, + { (char *)"JackoInfo", sizeof(JackoInfo), 0, 1, (char *)"", (char *)"", + (SUBR)&JackoInfo::init_, 0, 0 + }, + { (char *)"JackoFreewheel", sizeof(JackoFreewheel), 0, 1, (char *)"", + (char *)"i", (SUBR)&JackoFreewheel::init_, 0, 0 + }, + { (char *)"JackoOn", sizeof(JackoOn), 0, 1, (char *)"", (char *)"j", + (SUBR)&JackoOn::init_, 0, 0 + }, + { + (char *)"JackoAudioInConnect", sizeof(JackoAudioInConnect), 0, 1, + (char *)"", (char *)"SS", (SUBR)&JackoAudioInConnect::init_, 0, 0, + }, + { + (char *)"JackoAudioIn", sizeof(JackoAudioIn), 0, 3, (char *)"a", + (char *)"S", (SUBR)&JackoAudioIn::init_, (SUBR)&JackoAudioIn::audio_, + }, + { + (char *)"JackoAudioOutConnect", sizeof(JackoAudioOutConnect), 0, 1, + (char *)"", (char *)"SS", (SUBR)&JackoAudioOutConnect::init_, 0, 0, + }, + { + (char *)"JackoAudioOut", sizeof(JackoAudioOut), 0, 3, (char *)"", + (char *)"Sa", (SUBR)&JackoAudioOut::init_, + (SUBR)&JackoAudioOut::audio_, + }, + { + (char *)"JackoMidiInConnect", sizeof(JackoMidiInConnect), 0, 1, + (char *)"", (char *)"SS", (SUBR)&JackoMidiInConnect::init_, 0, 0, + }, + { + (char *)"JackoMidiOutConnect", sizeof(JackoMidiOutConnect), 0, 1, + (char *)"", (char *)"SS", (SUBR)&JackoMidiOutConnect::init_, 0, 0, + }, + { + (char *)"JackoMidiOut", sizeof(JackoMidiOut), 0, 3, (char *)"", + (char *)"SkkkO", (SUBR)&JackoMidiOut::init_, + (SUBR)&JackoMidiOut::kontrol_, 0, + }, + { (char *)"JackoNoteOut", sizeof(JackoNoteOut), 0, 3, (char *)"", + (char *)"Siii", (SUBR)&JackoNoteOut::init_, (SUBR)&JackoNoteOut::kontrol_, + 0 + }, + { (char *)"JackoTransport", sizeof(JackoTransport), 0, 3, (char *)"", + (char *)"kO", // O defaults to 0. + (SUBR)&JackoTransport::init_, (SUBR)&JackoTransport::kontrol_, 0 + }, + {0, 0, 0, 0, 0, 0, (SUBR)0, (SUBR)0, (SUBR)0} + }; -PUBLIC int csoundModuleCreate(CSOUND *csound) { - IGN(csound); - return 0; -} + PUBLIC int csoundModuleCreate(CSOUND *csound) { + IGN(csound); + return 0; + } -PUBLIC int csoundModuleInit(CSOUND *csound) { + PUBLIC int csoundModuleInit(CSOUND *csound) { - OENTRY *ep = (OENTRY *)&(oentries[0]); - int err = 0; - while (ep->opname != 0) { - err |= csound->AppendOpcode(csound, ep->opname, ep->dsblksiz, ep->flags, - ep->thread, ep->outypes, ep->intypes, - (int (*)(CSOUND *, void *))ep->iopadr, - (int (*)(CSOUND *, void *))ep->kopadr, - (int (*)(CSOUND *, void *))ep->aopadr); - ep++; - } - return err; -} + OENTRY *ep = (OENTRY *)&(oentries[0]); + int err = 0; + while (ep->opname != 0) { + err |= csound->AppendOpcode(csound, ep->opname, ep->dsblksiz, ep->flags, + ep->thread, ep->outypes, ep->intypes, + (int (*)(CSOUND *, void *))ep->iopadr, + (int (*)(CSOUND *, void *))ep->kopadr, + (int (*)(CSOUND *, void *))ep->aopadr); + ep++; + } + return err; + } -PUBLIC int csoundModuleDestroy(CSOUND *csound) { - if (csound->GetDebug(csound)) { - csound->Message(csound, "jacko: csoundModuleDestroy(%p)...\n", - csound); - } - int result = OK; - JackoState *jackoState = 0; - csound::QueryGlobalPointer(csound, "jackoState", jackoState); - if (jackoState) { - if (jackoState->jacko_finished == false) { - jackoState->close(); + PUBLIC int csoundModuleDestroy(CSOUND *csound) { + if (csound->GetDebug(csound)) { + csound->Message(csound, "jacko: csoundModuleDestroy(%p)...\n", + csound); + } + int result = OK; + JackoState *jackoState = 0; + csound::QueryGlobalPointer(csound, "jackoState", jackoState); + if (jackoState) { + if (jackoState->jacko_has_finished == false) { + jackoState->close(); + } + delete jackoState; + jackoState = 0; + } + if (csound->GetDebug(csound)) { + csound->Message(csound, "jacko: csoundModuleDestroy(%p).\n", + csound); + } + return result; } - delete jackoState; - jackoState = 0; - } - if (csound->GetDebug(csound)) { - csound->Message(csound, "jacko: csoundModuleDestroy(%p).\n", - csound); - } - return result; -} }