git-svn-id: http://subversion.jackaudio.org/jack/jack2/branches/libjacknet@3402 0c269be4-1314-0410-8aa9-9f06e86f4224tags/1.9.8
| @@ -23,6 +23,19 @@ Michael Voigt | |||||
| Jackdmp changes log | Jackdmp changes log | ||||
| --------------------------- | --------------------------- | ||||
| 2009-03-05 Stephane Letz <letz@grame.fr> | |||||
| * Support for BIG_ENDIAN machines in NetJack2 for transport data. | |||||
| * Add auto_connect parameter in netmanager and netadapter. | |||||
| 2009-03-03 Stephane Letz <letz@grame.fr> | |||||
| * More robust profiling tools when clients come and go. | |||||
| 2009-03-01 Stephane Letz <letz@grame.fr> | |||||
| * Raise default port number to 1024. | |||||
| 2009-02-27 Stephane Letz <letz@grame.fr> | 2009-02-27 Stephane Letz <letz@grame.fr> | ||||
| * Improve generated gnuplot files for adapting code. | * Improve generated gnuplot files for adapting code. | ||||
| @@ -69,6 +69,24 @@ namespace Jack | |||||
| } | } | ||||
| //JackAudioAdapter ********************************************************* | //JackAudioAdapter ********************************************************* | ||||
| JackAudioAdapter::JackAudioAdapter (jack_client_t* jack_client, JackAudioAdapterInterface* audio_io, const JSList* params, bool system) | |||||
| :fJackClient(jack_client), fAudioAdapter(audio_io) | |||||
| { | |||||
| const JSList* node; | |||||
| const jack_driver_param_t* param; | |||||
| fAutoConnect = false; | |||||
| for (node = params; node; node = jack_slist_next(node)) { | |||||
| param = (const jack_driver_param_t*) node->data; | |||||
| switch (param->character) { | |||||
| case 'c': | |||||
| fAutoConnect = param->value.i; | |||||
| break; | |||||
| } | |||||
| } | |||||
| } | |||||
| JackAudioAdapter::~JackAudioAdapter() | JackAudioAdapter::~JackAudioAdapter() | ||||
| { | { | ||||
| // When called, Close has already been used for the client, thus ports are already unregistered. | // When called, Close has already been used for the client, thus ports are already unregistered. | ||||
| @@ -87,6 +105,27 @@ namespace Jack | |||||
| delete[] fCapturePortList; | delete[] fCapturePortList; | ||||
| delete[] fPlaybackPortList; | delete[] fPlaybackPortList; | ||||
| } | } | ||||
| void JackAudioAdapter::ConnectPorts() | |||||
| { | |||||
| const char **ports; | |||||
| ports = jack_get_ports(fJackClient, NULL, NULL, JackPortIsPhysical | JackPortIsInput); | |||||
| if (ports != NULL) { | |||||
| for (int i = 0; i < fAudioAdapter->GetInputs() && ports[i]; i++) { | |||||
| jack_connect(fJackClient,jack_port_name(fCapturePortList[i]), ports[i]); | |||||
| } | |||||
| free(ports); | |||||
| } | |||||
| ports = jack_get_ports(fJackClient, NULL, NULL, JackPortIsPhysical | JackPortIsOutput); | |||||
| if (ports != NULL) { | |||||
| for (int i = 0; i < fAudioAdapter->GetOutputs() && ports[i]; i++) { | |||||
| jack_connect(fJackClient, ports[i], jack_port_name(fPlaybackPortList[i])); | |||||
| } | |||||
| free(ports); | |||||
| } | |||||
| } | |||||
| void JackAudioAdapter::Reset() | void JackAudioAdapter::Reset() | ||||
| { | { | ||||
| @@ -126,6 +165,9 @@ namespace Jack | |||||
| goto fail; | goto fail; | ||||
| if ( jack_activate ( fJackClient ) < 0 ) | if ( jack_activate ( fJackClient ) < 0 ) | ||||
| goto fail; | goto fail; | ||||
| if (fAutoConnect) | |||||
| ConnectPorts(); | |||||
| // Ring buffer are now allocated.. | // Ring buffer are now allocated.. | ||||
| return fAudioAdapter->Open(); | return fAudioAdapter->Open(); | ||||
| @@ -21,6 +21,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
| #define __JackAudioAdapter__ | #define __JackAudioAdapter__ | ||||
| #include "JackAudioAdapterInterface.h" | #include "JackAudioAdapterInterface.h" | ||||
| #include "driver_interface.h" | |||||
| namespace Jack | namespace Jack | ||||
| { | { | ||||
| @@ -42,15 +43,15 @@ namespace Jack | |||||
| jack_client_t* fJackClient; | jack_client_t* fJackClient; | ||||
| JackAudioAdapterInterface* fAudioAdapter; | JackAudioAdapterInterface* fAudioAdapter; | ||||
| bool fAutoConnect; | |||||
| void FreePorts(); | void FreePorts(); | ||||
| void ConnectPorts(); | |||||
| void Reset(); | void Reset(); | ||||
| public: | public: | ||||
| JackAudioAdapter ( jack_client_t* jack_client, JackAudioAdapterInterface* audio_io ) : | |||||
| fJackClient ( jack_client ), fAudioAdapter ( audio_io ) | |||||
| {} | |||||
| JackAudioAdapter(jack_client_t* jack_client, JackAudioAdapterInterface* audio_io, const JSList* params = NULL, bool system = false); | |||||
| ~JackAudioAdapter(); | ~JackAudioAdapter(); | ||||
| int Open(); | int Open(); | ||||
| @@ -34,7 +34,7 @@ | |||||
| #define JACK_CLIENT_NAME_SIZE 64 | #define JACK_CLIENT_NAME_SIZE 64 | ||||
| #ifndef PORT_NUM | #ifndef PORT_NUM | ||||
| #define PORT_NUM 512 | |||||
| #define PORT_NUM 1024 | |||||
| #endif | #endif | ||||
| #define DRIVER_PORT_NUM 256 | #define DRIVER_PORT_NUM 256 | ||||
| @@ -26,7 +26,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||||
| namespace Jack | namespace Jack | ||||
| { | { | ||||
| JackEngineProfiling::JackEngineProfiling():fAudioCycle(0) | |||||
| JackEngineProfiling::JackEngineProfiling():fAudioCycle(0),fMeasuredClient(0) | |||||
| { | { | ||||
| jack_info("Engine profiling activated, beware %ld MBytes are needed to record profiling points...", sizeof(fProfileTable) / (1024 * 1024)); | jack_info("Engine profiling activated, beware %ld MBytes are needed to record profiling points...", sizeof(fProfileTable) / (1024 * 1024)); | ||||
| @@ -36,66 +36,59 @@ JackEngineProfiling::JackEngineProfiling():fAudioCycle(0) | |||||
| JackEngineProfiling::~JackEngineProfiling() | JackEngineProfiling::~JackEngineProfiling() | ||||
| { | { | ||||
| // Window monitoring | |||||
| int max_client = 0; | |||||
| char buffer[1024]; | |||||
| char* nameTable[CLIENT_NUM]; | |||||
| FILE* file = fopen("JackEngineProfiling.log", "w"); | FILE* file = fopen("JackEngineProfiling.log", "w"); | ||||
| char buffer[1024]; | |||||
| jack_info("Write server and clients timing data..."); | jack_info("Write server and clients timing data..."); | ||||
| if (file == NULL) { | if (file == NULL) { | ||||
| jack_error("JackEngineProfiling::Save cannot open JackEngineProfiling.log file"); | jack_error("JackEngineProfiling::Save cannot open JackEngineProfiling.log file"); | ||||
| } else { | } else { | ||||
| // For each measured point | |||||
| for (int i = 2; i < TIME_POINTS; i++) { | for (int i = 2; i < TIME_POINTS; i++) { | ||||
| bool header = true; | |||||
| bool printed = false; | |||||
| int count = 0; | |||||
| for (int j = REAL_REFNUM; j < CLIENT_NUM; j++) { | |||||
| if (fProfileTable[i].fClientTable[j].fRefNum > 0) { | |||||
| long d1 = long(fProfileTable[i - 1].fCurCycleBegin - fProfileTable[i - 2].fCurCycleBegin); | |||||
| long d2 = long(fProfileTable[i].fPrevCycleEnd - fProfileTable[i - 1].fCurCycleBegin); | |||||
| if (d1 > 0 && fProfileTable[i].fClientTable[j].fStatus != NotTriggered) { // Valid cycle | |||||
| count++; | |||||
| nameTable[count] = fNameTable[fProfileTable[i].fClientTable[j].fRefNum]; | |||||
| // driver delta and end cycle | |||||
| if (header) { | |||||
| fprintf(file, "%ld \t %ld \t", d1, d2); | |||||
| header = false; | |||||
| } | |||||
| long d5 = long(fProfileTable[i].fClientTable[j].fSignaledAt - fProfileTable[i - 1].fCurCycleBegin); | |||||
| long d6 = long(fProfileTable[i].fClientTable[j].fAwakeAt - fProfileTable[i - 1].fCurCycleBegin); | |||||
| long d7 = long(fProfileTable[i].fClientTable[j].fFinishedAt - fProfileTable[i - 1].fCurCycleBegin); | |||||
| // ref, signal, start, end, scheduling, duration, status | |||||
| fprintf(file, "%d \t %ld \t %ld \t %ld \t %ld \t %ld \t %d \t", | |||||
| fProfileTable[i].fClientTable[j].fRefNum, | |||||
| ((d5 > 0) ? d5 : 0), | |||||
| ((d6 > 0) ? d6 : 0), | |||||
| ((d7 > 0) ? d7 : 0), | |||||
| ((d6 > 0 && d5 > 0) ? (d6 - d5) : 0), | |||||
| ((d7 > 0 && d6 > 0) ? (d7 - d6) : 0), | |||||
| fProfileTable[i].fClientTable[j].fStatus); | |||||
| printed = true; | |||||
| } | |||||
| } | |||||
| max_client = (count > max_client) ? count : max_client; | |||||
| } | |||||
| if (printed) { | |||||
| fprintf(file, "\n"); | |||||
| } else if (fProfileTable[i].fAudioCycle > 0) { // Driver timing only | |||||
| long d1 = long(fProfileTable[i].fCurCycleBegin - fProfileTable[i - 1].fCurCycleBegin); | |||||
| long d2 = long(fProfileTable[i].fPrevCycleEnd - fProfileTable[i - 1].fCurCycleBegin); | |||||
| if (d1 > 0) { // Valid cycle | |||||
| fprintf(file, "%ld \t %ld \n", d1, d2); | |||||
| // Driver timing values | |||||
| long d1 = long(fProfileTable[i].fCurCycleBegin - fProfileTable[i - 1].fCurCycleBegin); | |||||
| long d2 = long(fProfileTable[i].fPrevCycleEnd - fProfileTable[i - 1].fCurCycleBegin); | |||||
| if (d1 <= 0 || fProfileTable[i].fAudioCycle <= 0) | |||||
| continue; // Skip non valid cycles | |||||
| // Print driver delta and end cycle | |||||
| fprintf(file, "%ld \t %ld \t", d1, d2); | |||||
| // For each measured client | |||||
| for (unsigned int j = 0; j < fMeasuredClient; j++) { | |||||
| int ref = fIntervalTable[j].fRefNum; | |||||
| // Is valid client cycle | |||||
| if (fProfileTable[i].fClientTable[ref].fStatus != NotTriggered) { | |||||
| long d5 = long(fProfileTable[i].fClientTable[ref].fSignaledAt - fProfileTable[i - 1].fCurCycleBegin); | |||||
| long d6 = long(fProfileTable[i].fClientTable[ref].fAwakeAt - fProfileTable[i - 1].fCurCycleBegin); | |||||
| long d7 = long(fProfileTable[i].fClientTable[ref].fFinishedAt - fProfileTable[i - 1].fCurCycleBegin); | |||||
| // Print ref, signal, start, end, scheduling, duration, status | |||||
| fprintf(file, "%d \t %ld \t %ld \t %ld \t %ld \t %ld \t %d \t", | |||||
| ref, | |||||
| ((d5 > 0) ? d5 : 0), | |||||
| ((d6 > 0) ? d6 : 0), | |||||
| ((d7 > 0) ? d7 : 0), | |||||
| ((d6 > 0 && d5 > 0) ? (d6 - d5) : 0), | |||||
| ((d7 > 0 && d6 > 0) ? (d7 - d6) : 0), | |||||
| fProfileTable[i].fClientTable[ref].fStatus); | |||||
| } else { // Print tabs | |||||
| fprintf(file, "\t \t \t \t \t \t \t"); | |||||
| } | } | ||||
| } | } | ||||
| // Terminate line | |||||
| fprintf(file, "\n"); | |||||
| } | } | ||||
| fclose(file); | |||||
| } | } | ||||
| // Driver period | // Driver period | ||||
| file = fopen("Timing1.plot", "w"); | file = fopen("Timing1.plot", "w"); | ||||
| @@ -145,9 +138,9 @@ JackEngineProfiling::~JackEngineProfiling() | |||||
| fclose(file); | fclose(file); | ||||
| } | } | ||||
| // Clients end date | // Clients end date | ||||
| if (max_client > 0) { | |||||
| if (fMeasuredClient > 0) { | |||||
| file = fopen("Timing3.plot", "w"); | file = fopen("Timing3.plot", "w"); | ||||
| if (file == NULL) { | if (file == NULL) { | ||||
| jack_error("JackEngineProfiling::Save cannot open Timing3.log file"); | jack_error("JackEngineProfiling::Save cannot open Timing3.log file"); | ||||
| @@ -158,21 +151,20 @@ JackEngineProfiling::~JackEngineProfiling() | |||||
| fprintf(file, "set title \"Clients end date\"\n"); | fprintf(file, "set title \"Clients end date\"\n"); | ||||
| fprintf(file, "set xlabel \"audio cycles\"\n"); | fprintf(file, "set xlabel \"audio cycles\"\n"); | ||||
| fprintf(file, "set ylabel \"usec\"\n"); | fprintf(file, "set ylabel \"usec\"\n"); | ||||
| fprintf(file, "plot "); | fprintf(file, "plot "); | ||||
| for (int i = 0; i < max_client; i++) { | |||||
| for (unsigned int i = 0; i < fMeasuredClient; i++) { | |||||
| if (i == 0) { | if (i == 0) { | ||||
| if ((i + 1) == max_client) { | |||||
| if (i + 1 == fMeasuredClient) { // Last client | |||||
| sprintf(buffer, "\"JackEngineProfiling.log\" using 1 title \"Audio period\" with lines,\"JackEngineProfiling.log\" using %d title \"%s\" with lines", | sprintf(buffer, "\"JackEngineProfiling.log\" using 1 title \"Audio period\" with lines,\"JackEngineProfiling.log\" using %d title \"%s\" with lines", | ||||
| ((i + 1) * 7) - 1 , nameTable[(i + 1)]); | |||||
| ((i + 1) * 7) - 1 , fIntervalTable[i].fName); | |||||
| } else { | } else { | ||||
| sprintf(buffer, "\"JackEngineProfiling.log\" using 1 title \"Audio period\" with lines,\"JackEngineProfiling.log\" using %d title \"%s\" with lines,", | sprintf(buffer, "\"JackEngineProfiling.log\" using 1 title \"Audio period\" with lines,\"JackEngineProfiling.log\" using %d title \"%s\" with lines,", | ||||
| ((i + 1) * 7) - 1 , nameTable[(i + 1)]); | |||||
| ((i + 1) * 7) - 1 , fIntervalTable[i].fName); | |||||
| } | } | ||||
| } else if ((i + 1) == max_client) { // Last client | |||||
| sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines", ((i + 1) * 7) - 1 , nameTable[(i + 1)]); | |||||
| } else if (i + 1 == fMeasuredClient) { // Last client | |||||
| sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines", ((i + 1) * 7) - 1 , fIntervalTable[i].fName); | |||||
| } else { | } else { | ||||
| sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines,", ((i + 1) * 7) - 1, nameTable[(i + 1)]); | |||||
| sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines,", ((i + 1) * 7) - 1, fIntervalTable[i].fName); | |||||
| } | } | ||||
| fprintf(file, buffer); | fprintf(file, buffer); | ||||
| } | } | ||||
| @@ -187,28 +179,29 @@ JackEngineProfiling::~JackEngineProfiling() | |||||
| fprintf(file, "set xlabel \"audio cycles\"\n"); | fprintf(file, "set xlabel \"audio cycles\"\n"); | ||||
| fprintf(file, "set ylabel \"usec\"\n"); | fprintf(file, "set ylabel \"usec\"\n"); | ||||
| fprintf(file, "plot "); | fprintf(file, "plot "); | ||||
| for (int i = 0; i < max_client; i++) { | |||||
| for (unsigned int i = 0; i < fMeasuredClient; i++) { | |||||
| if (i == 0) { | if (i == 0) { | ||||
| if ((i + 1) == max_client) { | |||||
| if ((i + 1) == fMeasuredClient) { // Last client | |||||
| sprintf(buffer, "\"JackEngineProfiling.log\" using 1 title \"Audio period\" with lines,\"JackEngineProfiling.log\" using %d title \"%s\" with lines", | sprintf(buffer, "\"JackEngineProfiling.log\" using 1 title \"Audio period\" with lines,\"JackEngineProfiling.log\" using %d title \"%s\" with lines", | ||||
| ((i + 1) * 7) - 1 , nameTable[(i + 1)]); | |||||
| ((i + 1) * 7) - 1 , fIntervalTable[i].fName); | |||||
| } else { | } else { | ||||
| sprintf(buffer, "\"JackEngineProfiling.log\" using 1 title \"Audio period\" with lines,\"JackEngineProfiling.log\" using %d title \"%s\" with lines,", | sprintf(buffer, "\"JackEngineProfiling.log\" using 1 title \"Audio period\" with lines,\"JackEngineProfiling.log\" using %d title \"%s\" with lines,", | ||||
| ((i + 1) * 7) - 1 , nameTable[(i + 1)]); | |||||
| ((i + 1) * 7) - 1 , fIntervalTable[i].fName); | |||||
| } | } | ||||
| } else if ((i + 1) == max_client) { // Last client | |||||
| sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines", ((i + 1) * 7) - 1 , nameTable[(i + 1)]); | |||||
| } else if ((i + 1) == fMeasuredClient) { // Last client | |||||
| sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines", ((i + 1) * 7) - 1 , fIntervalTable[i].fName); | |||||
| } else { | } else { | ||||
| sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines,", ((i + 1) * 7) - 1, nameTable[(i + 1)]); | |||||
| sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines,", ((i + 1) * 7) - 1, fIntervalTable[i].fName); | |||||
| } | } | ||||
| fprintf(file, buffer); | fprintf(file, buffer); | ||||
| } | } | ||||
| fclose(file); | fclose(file); | ||||
| } | } | ||||
| } | } | ||||
| // Clients scheduling | // Clients scheduling | ||||
| if (max_client > 0) { | |||||
| if (fMeasuredClient > 0) { | |||||
| file = fopen("Timing4.plot", "w"); | file = fopen("Timing4.plot", "w"); | ||||
| if (file == NULL) { | if (file == NULL) { | ||||
| @@ -221,11 +214,11 @@ JackEngineProfiling::~JackEngineProfiling() | |||||
| fprintf(file, "set xlabel \"audio cycles\"\n"); | fprintf(file, "set xlabel \"audio cycles\"\n"); | ||||
| fprintf(file, "set ylabel \"usec\"\n"); | fprintf(file, "set ylabel \"usec\"\n"); | ||||
| fprintf(file, "plot "); | fprintf(file, "plot "); | ||||
| for (int i = 0; i < max_client; i++) { | |||||
| if ((i + 1) == max_client) // Last client | |||||
| sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines", ((i + 1) * 7), nameTable[(i + 1)]); | |||||
| for (unsigned int i = 0; i < fMeasuredClient; i++) { | |||||
| if ((i + 1) == fMeasuredClient) // Last client | |||||
| sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines", ((i + 1) * 7), fIntervalTable[i].fName); | |||||
| else | else | ||||
| sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines,", ((i + 1) * 7), nameTable[(i + 1)]); | |||||
| sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines,", ((i + 1) * 7), fIntervalTable[i].fName); | |||||
| fprintf(file, buffer); | fprintf(file, buffer); | ||||
| } | } | ||||
| @@ -239,11 +232,11 @@ JackEngineProfiling::~JackEngineProfiling() | |||||
| fprintf(file, "set xlabel \"audio cycles\"\n"); | fprintf(file, "set xlabel \"audio cycles\"\n"); | ||||
| fprintf(file, "set ylabel \"usec\"\n"); | fprintf(file, "set ylabel \"usec\"\n"); | ||||
| fprintf(file, "plot "); | fprintf(file, "plot "); | ||||
| for (int i = 0; i < max_client; i++) { | |||||
| if ((i + 1) == max_client) // Last client | |||||
| sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines", ((i + 1) * 7), nameTable[(i + 1)]); | |||||
| for (unsigned int i = 0; i < fMeasuredClient; i++) { | |||||
| if ((i + 1) == fMeasuredClient) // Last client | |||||
| sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines", ((i + 1) * 7), fIntervalTable[i].fName); | |||||
| else | else | ||||
| sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines,", ((i + 1) * 7), nameTable[(i + 1)]); | |||||
| sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines,", ((i + 1) * 7), fIntervalTable[i].fName); | |||||
| fprintf(file, buffer); | fprintf(file, buffer); | ||||
| } | } | ||||
| fclose(file); | fclose(file); | ||||
| @@ -251,7 +244,7 @@ JackEngineProfiling::~JackEngineProfiling() | |||||
| } | } | ||||
| // Clients duration | // Clients duration | ||||
| if (max_client > 0) { | |||||
| if (fMeasuredClient > 0) { | |||||
| file = fopen("Timing5.plot", "w"); | file = fopen("Timing5.plot", "w"); | ||||
| if (file == NULL) { | if (file == NULL) { | ||||
| @@ -264,11 +257,11 @@ JackEngineProfiling::~JackEngineProfiling() | |||||
| fprintf(file, "set xlabel \"audio cycles\"\n"); | fprintf(file, "set xlabel \"audio cycles\"\n"); | ||||
| fprintf(file, "set ylabel \"usec\"\n"); | fprintf(file, "set ylabel \"usec\"\n"); | ||||
| fprintf(file, "plot "); | fprintf(file, "plot "); | ||||
| for (int i = 0; i < max_client; i++) { | |||||
| if ((i + 1) == max_client) // Last client | |||||
| sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines", ((i + 1) * 7) + 1, nameTable[(i + 1)]); | |||||
| for (unsigned int i = 0; i < fMeasuredClient; i++) { | |||||
| if ((i + 1) == fMeasuredClient) // Last client | |||||
| sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines", ((i + 1) * 7) + 1, fIntervalTable[i].fName); | |||||
| else | else | ||||
| sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines,", ((i + 1) * 7) + 1, nameTable[(i + 1)]); | |||||
| sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines,", ((i + 1) * 7) + 1, fIntervalTable[i].fName); | |||||
| fprintf(file, buffer); | fprintf(file, buffer); | ||||
| } | } | ||||
| @@ -282,11 +275,11 @@ JackEngineProfiling::~JackEngineProfiling() | |||||
| fprintf(file, "set xlabel \"audio cycles\"\n"); | fprintf(file, "set xlabel \"audio cycles\"\n"); | ||||
| fprintf(file, "set ylabel \"usec\"\n"); | fprintf(file, "set ylabel \"usec\"\n"); | ||||
| fprintf(file, "plot "); | fprintf(file, "plot "); | ||||
| for (int i = 0; i < max_client; i++) { | |||||
| if ((i + 1) == max_client) // Last client | |||||
| sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines", ((i + 1) * 7) + 1, nameTable[(i + 1)]); | |||||
| for (unsigned int i = 0; i < fMeasuredClient; i++) { | |||||
| if ((i + 1) == fMeasuredClient) // Last client | |||||
| sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines", ((i + 1) * 7) + 1, fIntervalTable[i].fName); | |||||
| else | else | ||||
| sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines,", ((i + 1) * 7) + 1, nameTable[(i + 1)]); | |||||
| sprintf(buffer, "\"JackEngineProfiling.log\" using %d title \"%s\" with lines,", ((i + 1) * 7) + 1, fIntervalTable[i].fName); | |||||
| fprintf(file, buffer); | fprintf(file, buffer); | ||||
| } | } | ||||
| fclose(file); | fclose(file); | ||||
| @@ -294,6 +287,17 @@ JackEngineProfiling::~JackEngineProfiling() | |||||
| } | } | ||||
| } | } | ||||
| bool JackEngineProfiling::CheckClient(const char* name, int cur_point) | |||||
| { | |||||
| for (int i = 0; i < MEASURED_CLIENTS; i++) { | |||||
| if (strcmp(fIntervalTable[i].fName, name) == 0) { | |||||
| fIntervalTable[i].fEndInterval = cur_point; | |||||
| return true; | |||||
| } | |||||
| } | |||||
| return false; | |||||
| } | |||||
| void JackEngineProfiling::Profile(JackClientInterface** table, | void JackEngineProfiling::Profile(JackClientInterface** table, | ||||
| JackGraphManager* manager, | JackGraphManager* manager, | ||||
| jack_time_t period_usecs, | jack_time_t period_usecs, | ||||
| @@ -311,8 +315,16 @@ void JackEngineProfiling::Profile(JackClientInterface** table, | |||||
| for (int i = REAL_REFNUM; i < CLIENT_NUM; i++) { | for (int i = REAL_REFNUM; i < CLIENT_NUM; i++) { | ||||
| JackClientInterface* client = table[i]; | JackClientInterface* client = table[i]; | ||||
| JackClientTiming* timing = manager->GetClientTiming(i); | JackClientTiming* timing = manager->GetClientTiming(i); | ||||
| if (client && client->GetClientControl()->fActive) { | |||||
| strcpy(fNameTable[i], client->GetClientControl()->fName); | |||||
| if (client && client->GetClientControl()->fActive && client->GetClientControl()->fCallback[kRealTimeCallback]) { | |||||
| if (!CheckClient(client->GetClientControl()->fName, fAudioCycle)) { | |||||
| // Keep new measured client | |||||
| fIntervalTable[fMeasuredClient].fRefNum = i; | |||||
| strcpy(fIntervalTable[fMeasuredClient].fName, client->GetClientControl()->fName); | |||||
| fIntervalTable[fMeasuredClient].fBeginInterval = fAudioCycle; | |||||
| fIntervalTable[fMeasuredClient].fEndInterval = fAudioCycle; | |||||
| fMeasuredClient++; | |||||
| } | |||||
| fProfileTable[fAudioCycle].fClientTable[i].fRefNum = i; | fProfileTable[fAudioCycle].fClientTable[i].fRefNum = i; | ||||
| fProfileTable[fAudioCycle].fClientTable[i].fSignaledAt = timing->fSignaledAt; | fProfileTable[fAudioCycle].fClientTable[i].fSignaledAt = timing->fSignaledAt; | ||||
| fProfileTable[fAudioCycle].fClientTable[i].fAwakeAt = timing->fAwakeAt; | fProfileTable[fAudioCycle].fClientTable[i].fAwakeAt = timing->fAwakeAt; | ||||
| @@ -31,6 +31,7 @@ namespace Jack | |||||
| #define TIME_POINTS 250000 | #define TIME_POINTS 250000 | ||||
| #define FAILURE_TIME_POINTS 10000 | #define FAILURE_TIME_POINTS 10000 | ||||
| #define FAILURE_WINDOW 10 | #define FAILURE_WINDOW 10 | ||||
| #define MEASURED_CLIENTS 32 | |||||
| /*! | /*! | ||||
| \brief Timing stucture for a client. | \brief Timing stucture for a client. | ||||
| @@ -43,6 +44,32 @@ struct JackTimingMeasureClient | |||||
| jack_time_t fAwakeAt; | jack_time_t fAwakeAt; | ||||
| jack_time_t fFinishedAt; | jack_time_t fFinishedAt; | ||||
| jack_client_state_t fStatus; | jack_client_state_t fStatus; | ||||
| JackTimingMeasureClient() | |||||
| :fRefNum(-1), | |||||
| fSignaledAt(0), | |||||
| fAwakeAt(0), | |||||
| fFinishedAt(0), | |||||
| fStatus((jack_client_state_t)0) | |||||
| {} | |||||
| }; | |||||
| /*! | |||||
| \brief Timing interval in the global table for a given client | |||||
| */ | |||||
| struct JackTimingClientInterval | |||||
| { | |||||
| int fRefNum; | |||||
| char fName[JACK_CLIENT_NAME_SIZE + 1]; | |||||
| int fBeginInterval; | |||||
| int fEndInterval; | |||||
| JackTimingClientInterval() | |||||
| :fRefNum(-1), | |||||
| fBeginInterval(-1), | |||||
| fEndInterval(-1) | |||||
| {} | |||||
| }; | }; | ||||
| /*! | /*! | ||||
| @@ -56,6 +83,13 @@ struct JackTimingMeasure | |||||
| jack_time_t fCurCycleBegin; | jack_time_t fCurCycleBegin; | ||||
| jack_time_t fPrevCycleEnd; | jack_time_t fPrevCycleEnd; | ||||
| JackTimingMeasureClient fClientTable[CLIENT_NUM]; | JackTimingMeasureClient fClientTable[CLIENT_NUM]; | ||||
| JackTimingMeasure() | |||||
| :fAudioCycle(0), | |||||
| fPeriodUsecs(0), | |||||
| fCurCycleBegin(0), | |||||
| fPrevCycleEnd(0) | |||||
| {} | |||||
| }; | }; | ||||
| /*! | /*! | ||||
| @@ -71,9 +105,13 @@ class SERVER_EXPORT JackEngineProfiling | |||||
| private: | private: | ||||
| JackTimingMeasure fProfileTable[TIME_POINTS]; | JackTimingMeasure fProfileTable[TIME_POINTS]; | ||||
| char fNameTable[CLIENT_NUM][JACK_CLIENT_NAME_SIZE + 1]; | |||||
| JackTimingClientInterval fIntervalTable[MEASURED_CLIENTS]; | |||||
| unsigned int fAudioCycle; | unsigned int fAudioCycle; | ||||
| unsigned int fMeasuredClient; | |||||
| bool CheckClient(const char* name, int cur_point); | |||||
| public: | public: | ||||
| JackEngineProfiling(); | JackEngineProfiling(); | ||||
| @@ -354,9 +354,8 @@ struct JackNetExtMaster : public JackNetMasterInterface { | |||||
| if (SyncRecv() == SOCKET_ERROR) | if (SyncRecv() == SOCKET_ERROR) | ||||
| return 0; | return 0; | ||||
| if (DecodeSyncPacket() < 0) | |||||
| return 0; | |||||
| DecodeSyncPacket(); | |||||
| return DataRecv(); | return DataRecv(); | ||||
| } | } | ||||
| @@ -373,9 +372,8 @@ struct JackNetExtMaster : public JackNetMasterInterface { | |||||
| fNetMidiCaptureBuffer->SetBuffer(port_index, ((JackMidiBuffer**)midi_output_buffer)[port_index]); | fNetMidiCaptureBuffer->SetBuffer(port_index, ((JackMidiBuffer**)midi_output_buffer)[port_index]); | ||||
| } | } | ||||
| if (EncodeSyncPacket() < 0) | |||||
| return 0; | |||||
| EncodeSyncPacket(); | |||||
| if (SyncSend() == SOCKET_ERROR) | if (SyncSend() == SOCKET_ERROR) | ||||
| return SOCKET_ERROR; | return SOCKET_ERROR; | ||||
| @@ -383,15 +381,11 @@ struct JackNetExtMaster : public JackNetMasterInterface { | |||||
| } | } | ||||
| // Transport | // Transport | ||||
| int EncodeTransportData() | |||||
| { | |||||
| return 0; | |||||
| } | |||||
| void EncodeTransportData() | |||||
| {} | |||||
| int DecodeTransportData() | |||||
| { | |||||
| return 0; | |||||
| } | |||||
| void DecodeTransportData() | |||||
| {} | |||||
| }; | }; | ||||
| @@ -574,15 +568,11 @@ struct JackNetExtSlave : public JackNetSlaveInterface, public JackRunnableInterf | |||||
| } | } | ||||
| // Transport | // Transport | ||||
| int EncodeTransportData() | |||||
| { | |||||
| return 0; | |||||
| } | |||||
| void EncodeTransportData() | |||||
| {} | |||||
| int DecodeTransportData() | |||||
| { | |||||
| return 0; | |||||
| } | |||||
| void DecodeTransportData() | |||||
| {} | |||||
| bool Init() | bool Init() | ||||
| { | { | ||||
| @@ -624,17 +614,15 @@ struct JackNetExtSlave : public JackNetSlaveInterface, public JackRunnableInterf | |||||
| if (SyncRecv() == SOCKET_ERROR) | if (SyncRecv() == SOCKET_ERROR) | ||||
| return 0; | return 0; | ||||
| if (DecodeSyncPacket() < 0) | |||||
| return 0; | |||||
| DecodeSyncPacket(); | |||||
| return DataRecv(); | return DataRecv(); | ||||
| } | } | ||||
| int Write() | int Write() | ||||
| { | { | ||||
| if (EncodeSyncPacket() < 0) | |||||
| return 0; | |||||
| EncodeSyncPacket(); | |||||
| if (SyncSend() == SOCKET_ERROR) | if (SyncSend() == SOCKET_ERROR) | ||||
| return SOCKET_ERROR; | return SOCKET_ERROR; | ||||
| @@ -260,7 +260,7 @@ namespace Jack | |||||
| } | } | ||||
| //transport--------------------------------------------------------------------------- | //transport--------------------------------------------------------------------------- | ||||
| int JackNetAdapter::DecodeTransportData() | |||||
| void JackNetAdapter::DecodeTransportData() | |||||
| { | { | ||||
| //TODO : we need here to get the actual timebase master to eventually release it from its duty (see JackNetDriver) | //TODO : we need here to get the actual timebase master to eventually release it from its duty (see JackNetDriver) | ||||
| @@ -288,11 +288,9 @@ namespace Jack | |||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| return 0; | |||||
| } | } | ||||
| int JackNetAdapter::EncodeTransportData() | |||||
| void JackNetAdapter::EncodeTransportData() | |||||
| { | { | ||||
| //is there a timebase master change ? | //is there a timebase master change ? | ||||
| int refnum = -1; | int refnum = -1; | ||||
| @@ -326,8 +324,6 @@ namespace Jack | |||||
| if ( fReturnTransportData.fNewState ) | if ( fReturnTransportData.fNewState ) | ||||
| jack_info ( "Sending transport state '%s'.", GetTransportState ( fReturnTransportData.fState ) ); | jack_info ( "Sending transport state '%s'.", GetTransportState ( fReturnTransportData.fState ) ); | ||||
| fLastTransportState = fReturnTransportData.fState; | fLastTransportState = fReturnTransportData.fState; | ||||
| return 0; | |||||
| } | } | ||||
| //read/write operations--------------------------------------------------------------- | //read/write operations--------------------------------------------------------------- | ||||
| @@ -338,17 +334,14 @@ namespace Jack | |||||
| if ( SyncRecv() == SOCKET_ERROR ) | if ( SyncRecv() == SOCKET_ERROR ) | ||||
| return 0; | return 0; | ||||
| if ( DecodeSyncPacket() < 0 ) | |||||
| return 0; | |||||
| DecodeSyncPacket(); | |||||
| return DataRecv(); | return DataRecv(); | ||||
| } | } | ||||
| int JackNetAdapter::Write() | int JackNetAdapter::Write() | ||||
| { | { | ||||
| if ( EncodeSyncPacket() < 0 ) | |||||
| return 0; | |||||
| EncodeSyncPacket(); | |||||
| if ( SyncSend() == SOCKET_ERROR ) | if ( SyncSend() == SOCKET_ERROR ) | ||||
| return SOCKET_ERROR; | return SOCKET_ERROR; | ||||
| @@ -358,48 +351,21 @@ namespace Jack | |||||
| //process----------------------------------------------------------------------------- | //process----------------------------------------------------------------------------- | ||||
| int JackNetAdapter::Process() | int JackNetAdapter::Process() | ||||
| { | { | ||||
| bool failure = false; | |||||
| int port_index; | |||||
| //read data from the network | //read data from the network | ||||
| //in case of fatal network error, stop the process | //in case of fatal network error, stop the process | ||||
| if ( Read() == SOCKET_ERROR ) | |||||
| if (Read() == SOCKET_ERROR) | |||||
| return SOCKET_ERROR; | return SOCKET_ERROR; | ||||
| //get the resample factor, | |||||
| jack_time_t time1, time2; | |||||
| ResampleFactor ( time1, time2 ); | |||||
| //resample input data, | |||||
| for ( port_index = 0; port_index < fCaptureChannels; port_index++ ) | |||||
| { | |||||
| fCaptureRingBuffer[port_index]->SetRatio ( time1, time2 ); | |||||
| if ( fCaptureRingBuffer[port_index]->WriteResample ( fSoftCaptureBuffer[port_index], fAdaptedBufferSize ) < fAdaptedBufferSize ) | |||||
| failure = true; | |||||
| } | |||||
| //and output data, | |||||
| for ( port_index = 0; port_index < fPlaybackChannels; port_index++ ) | |||||
| { | |||||
| fPlaybackRingBuffer[port_index]->SetRatio ( time2, time1 ); | |||||
| if ( fPlaybackRingBuffer[port_index]->ReadResample ( fSoftPlaybackBuffer[port_index], fAdaptedBufferSize ) < fAdaptedBufferSize ) | |||||
| failure = true; | |||||
| } | |||||
| PushAndPull(fSoftCaptureBuffer, fSoftPlaybackBuffer, fAdaptedBufferSize); | |||||
| //then write data to network | //then write data to network | ||||
| //in case of failure, stop process | //in case of failure, stop process | ||||
| if ( Write() == SOCKET_ERROR ) | |||||
| if (Write() == SOCKET_ERROR) | |||||
| return SOCKET_ERROR; | return SOCKET_ERROR; | ||||
| //if there was any ringbuffer failure during resampling, reset | |||||
| if ( failure ) | |||||
| { | |||||
| jack_error ( "JackNetAdapter::Execute ringbuffer failure...reset." ); | |||||
| ResetRingBuffers(); | |||||
| } | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| } // namespace Jack | } // namespace Jack | ||||
| //loader------------------------------------------------------------------------------ | //loader------------------------------------------------------------------------------ | ||||
| @@ -420,7 +386,7 @@ extern "C" | |||||
| strcpy(desc->name, "netadapter"); // size MUST be less then JACK_DRIVER_NAME_MAX + 1 | strcpy(desc->name, "netadapter"); // size MUST be less then JACK_DRIVER_NAME_MAX + 1 | ||||
| strcpy(desc->desc, "netjack net <==> audio backend adapter"); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1 | strcpy(desc->desc, "netjack net <==> audio backend adapter"); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1 | ||||
| desc->nparams = 9; | |||||
| desc->nparams = 10; | |||||
| desc->params = ( jack_driver_param_desc_t* ) calloc ( desc->nparams, sizeof ( jack_driver_param_desc_t ) ); | desc->params = ( jack_driver_param_desc_t* ) calloc ( desc->nparams, sizeof ( jack_driver_param_desc_t ) ); | ||||
| int i = 0; | int i = 0; | ||||
| @@ -494,6 +460,14 @@ extern "C" | |||||
| desc->params[i].value.ui = 0; | desc->params[i].value.ui = 0; | ||||
| strcpy(desc->params[i].short_desc, "Resample algorithm quality (0 - 4)"); | strcpy(desc->params[i].short_desc, "Resample algorithm quality (0 - 4)"); | ||||
| strcpy(desc->params[i].long_desc, desc->params[i].short_desc); | strcpy(desc->params[i].long_desc, desc->params[i].short_desc); | ||||
| i++; | |||||
| strcpy ( desc->params[i].name, "auto_connect" ); | |||||
| desc->params[i].character = 'c'; | |||||
| desc->params[i].type = JackDriverParamBool; | |||||
| desc->params[i].value.i = false; | |||||
| strcpy ( desc->params[i].short_desc, "Auto connect netmaster to system ports" ); | |||||
| strcpy ( desc->params[i].long_desc, desc->params[i].short_desc ); | |||||
| return desc; | return desc; | ||||
| } | } | ||||
| @@ -508,7 +482,7 @@ extern "C" | |||||
| try { | try { | ||||
| adapter = new Jack::JackAudioAdapter ( jack_client, new Jack::JackNetAdapter ( jack_client, buffer_size, sample_rate, params ) ); | |||||
| adapter = new Jack::JackAudioAdapter(jack_client, new Jack::JackNetAdapter(jack_client, buffer_size, sample_rate, params), params, false); | |||||
| assert ( adapter ); | assert ( adapter ); | ||||
| if ( adapter->Open() == 0 ) | if ( adapter->Open() == 0 ) | ||||
| @@ -48,8 +48,8 @@ namespace Jack | |||||
| JackThread fThread; | JackThread fThread; | ||||
| //transport | //transport | ||||
| int EncodeTransportData(); | |||||
| int DecodeTransportData(); | |||||
| void EncodeTransportData(); | |||||
| void DecodeTransportData(); | |||||
| public: | public: | ||||
| @@ -381,7 +381,7 @@ namespace Jack | |||||
| } | } | ||||
| //transport--------------------------------------------------------------------------- | //transport--------------------------------------------------------------------------- | ||||
| int JackNetDriver::DecodeTransportData() | |||||
| void JackNetDriver::DecodeTransportData() | |||||
| { | { | ||||
| //is there a new timebase master on the net master ? | //is there a new timebase master on the net master ? | ||||
| // - release timebase master only if it's a non-conditional request | // - release timebase master only if it's a non-conditional request | ||||
| @@ -397,9 +397,10 @@ namespace Jack | |||||
| jack_info ( "The NetMaster is now the new timebase master." ); | jack_info ( "The NetMaster is now the new timebase master." ); | ||||
| } | } | ||||
| //is there a tranport state change to handle ? | |||||
| //is there a transport state change to handle ? | |||||
| if ( fSendTransportData.fNewState && ( fSendTransportData.fState != fEngineControl->fTransport.GetState() ) ) | if ( fSendTransportData.fNewState && ( fSendTransportData.fState != fEngineControl->fTransport.GetState() ) ) | ||||
| { | { | ||||
| switch ( fSendTransportData.fState ) | switch ( fSendTransportData.fState ) | ||||
| { | { | ||||
| case JackTransportStopped : | case JackTransportStopped : | ||||
| @@ -419,11 +420,9 @@ namespace Jack | |||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| return 0; | |||||
| } | } | ||||
| int JackNetDriver::EncodeTransportData() | |||||
| void JackNetDriver::EncodeTransportData() | |||||
| { | { | ||||
| //is there a timebase master change ? | //is there a timebase master change ? | ||||
| int refnum; | int refnum; | ||||
| @@ -457,8 +456,6 @@ namespace Jack | |||||
| if ( fReturnTransportData.fNewState ) | if ( fReturnTransportData.fNewState ) | ||||
| jack_info ( "Sending '%s'.", GetTransportState ( fReturnTransportData.fState ) ); | jack_info ( "Sending '%s'.", GetTransportState ( fReturnTransportData.fState ) ); | ||||
| fLastTransportState = fReturnTransportData.fState; | fLastTransportState = fReturnTransportData.fState; | ||||
| return 0; | |||||
| } | } | ||||
| //driver processes-------------------------------------------------------------------- | //driver processes-------------------------------------------------------------------- | ||||
| @@ -486,9 +483,8 @@ namespace Jack | |||||
| //decode sync | //decode sync | ||||
| //if there is an error, don't return -1, it will skip Write() and the network error probably won't be identified | //if there is an error, don't return -1, it will skip Write() and the network error probably won't be identified | ||||
| if ( DecodeSyncPacket() < 0 ) | |||||
| return 0; | |||||
| DecodeSyncPacket(); | |||||
| #ifdef JACK_MONITOR | #ifdef JACK_MONITOR | ||||
| fNetTimeMon->Add ( ( ( float ) ( GetMicroSeconds() - JackDriver::fBeginDateUst ) / ( float ) fEngineControl->fPeriodUsecs ) * 100.f ); | fNetTimeMon->Add ( ( ( float ) ( GetMicroSeconds() - JackDriver::fBeginDateUst ) / ( float ) fEngineControl->fPeriodUsecs ) * 100.f ); | ||||
| #endif | #endif | ||||
| @@ -519,9 +515,8 @@ namespace Jack | |||||
| #endif | #endif | ||||
| //sync | //sync | ||||
| if ( EncodeSyncPacket() < 0 ) | |||||
| return 0; | |||||
| EncodeSyncPacket(); | |||||
| //send sync | //send sync | ||||
| if ( SyncSend() == SOCKET_ERROR ) | if ( SyncSend() == SOCKET_ERROR ) | ||||
| return SOCKET_ERROR; | return SOCKET_ERROR; | ||||
| @@ -57,8 +57,8 @@ namespace Jack | |||||
| int FreePorts(); | int FreePorts(); | ||||
| //transport | //transport | ||||
| int EncodeTransportData(); | |||||
| int DecodeTransportData(); | |||||
| void EncodeTransportData(); | |||||
| void DecodeTransportData(); | |||||
| JackMidiBuffer* GetMidiInputBuffer ( int port_index ); | JackMidiBuffer* GetMidiInputBuffer ( int port_index ); | ||||
| JackMidiBuffer* GetMidiOutputBuffer ( int port_index ); | JackMidiBuffer* GetMidiOutputBuffer ( int port_index ); | ||||
| @@ -565,39 +565,35 @@ namespace Jack | |||||
| return rx_bytes; | return rx_bytes; | ||||
| } | } | ||||
| int JackNetMasterInterface::EncodeSyncPacket() | |||||
| void JackNetMasterInterface::EncodeSyncPacket() | |||||
| { | { | ||||
| //this method contains every step of sync packet informations coding | //this method contains every step of sync packet informations coding | ||||
| //first of all, reset sync packet | //first of all, reset sync packet | ||||
| memset ( fTxData, 0, fPayloadSize ); | memset ( fTxData, 0, fPayloadSize ); | ||||
| //then, first step : transport | //then, first step : transport | ||||
| if ( fParams.fTransportSync ) | |||||
| { | |||||
| if ( EncodeTransportData() < 0 ) | |||||
| return -1; | |||||
| if (fParams.fTransportSync) { | |||||
| EncodeTransportData(); | |||||
| TransportDataHToN( &fSendTransportData, &fSendTransportData); | |||||
| //copy to TxBuffer | //copy to TxBuffer | ||||
| memcpy ( fTxData, &fSendTransportData, sizeof ( net_transport_data_t ) ); | memcpy ( fTxData, &fSendTransportData, sizeof ( net_transport_data_t ) ); | ||||
| } | } | ||||
| //then others (freewheel etc.) | //then others (freewheel etc.) | ||||
| //... | //... | ||||
| return 0; | |||||
| } | } | ||||
| int JackNetMasterInterface::DecodeSyncPacket() | |||||
| void JackNetMasterInterface::DecodeSyncPacket() | |||||
| { | { | ||||
| //this method contains every step of sync packet informations decoding process | //this method contains every step of sync packet informations decoding process | ||||
| //first : transport | //first : transport | ||||
| if ( fParams.fTransportSync ) | |||||
| { | |||||
| if (fParams.fTransportSync) { | |||||
| //copy received transport data to transport data structure | //copy received transport data to transport data structure | ||||
| memcpy ( &fReturnTransportData, fRxData, sizeof ( net_transport_data_t ) ); | memcpy ( &fReturnTransportData, fRxData, sizeof ( net_transport_data_t ) ); | ||||
| if ( DecodeTransportData() < 0 ) | |||||
| return -1; | |||||
| TransportDataNToH( &fReturnTransportData, &fReturnTransportData); | |||||
| DecodeTransportData(); | |||||
| } | } | ||||
| //then others | //then others | ||||
| //... | //... | ||||
| return 0; | |||||
| } | } | ||||
| // JackNetSlaveInterface ************************************************************************************************ | // JackNetSlaveInterface ************************************************************************************************ | ||||
| @@ -955,38 +951,34 @@ namespace Jack | |||||
| } | } | ||||
| //network sync------------------------------------------------------------------------ | //network sync------------------------------------------------------------------------ | ||||
| int JackNetSlaveInterface::DecodeSyncPacket() | |||||
| { | |||||
| //this method contains every step of sync packet informations decoding process | |||||
| //first : transport | |||||
| if ( fParams.fTransportSync ) | |||||
| { | |||||
| //copy received transport data to transport data structure | |||||
| memcpy ( &fSendTransportData, fRxData, sizeof ( net_transport_data_t ) ); | |||||
| if ( DecodeTransportData() < 0 ) | |||||
| return -1; | |||||
| } | |||||
| //then others | |||||
| //... | |||||
| return 0; | |||||
| } | |||||
| int JackNetSlaveInterface::EncodeSyncPacket() | |||||
| void JackNetSlaveInterface::EncodeSyncPacket() | |||||
| { | { | ||||
| //this method contains every step of sync packet informations coding | //this method contains every step of sync packet informations coding | ||||
| //first of all, reset sync packet | //first of all, reset sync packet | ||||
| memset ( fTxData, 0, fPayloadSize ); | memset ( fTxData, 0, fPayloadSize ); | ||||
| //then first step : transport | //then first step : transport | ||||
| if ( fParams.fTransportSync ) | |||||
| { | |||||
| if ( EncodeTransportData() < 0 ) | |||||
| return -1; | |||||
| if (fParams.fTransportSync) { | |||||
| EncodeTransportData(); | |||||
| TransportDataHToN( &fReturnTransportData, &fReturnTransportData); | |||||
| //copy to TxBuffer | //copy to TxBuffer | ||||
| memcpy ( fTxData, &fReturnTransportData, sizeof ( net_transport_data_t ) ); | memcpy ( fTxData, &fReturnTransportData, sizeof ( net_transport_data_t ) ); | ||||
| } | } | ||||
| //then others | //then others | ||||
| //... | //... | ||||
| return 0; | |||||
| } | |||||
| void JackNetSlaveInterface::DecodeSyncPacket() | |||||
| { | |||||
| //this method contains every step of sync packet informations decoding process | |||||
| //first : transport | |||||
| if (fParams.fTransportSync) { | |||||
| //copy received transport data to transport data structure | |||||
| memcpy ( &fSendTransportData, fRxData, sizeof ( net_transport_data_t ) ); | |||||
| TransportDataNToH( &fSendTransportData, &fSendTransportData); | |||||
| DecodeTransportData(); | |||||
| } | |||||
| //then others | |||||
| //... | |||||
| } | } | ||||
| } | } | ||||
| @@ -73,12 +73,12 @@ namespace Jack | |||||
| virtual bool Init() = 0; | virtual bool Init() = 0; | ||||
| //transport | //transport | ||||
| virtual int EncodeTransportData() = 0; | |||||
| virtual int DecodeTransportData() = 0; | |||||
| virtual void EncodeTransportData() = 0; | |||||
| virtual void DecodeTransportData() = 0; | |||||
| //sync packet | //sync packet | ||||
| virtual int EncodeSyncPacket() = 0; | |||||
| virtual int DecodeSyncPacket() = 0; | |||||
| virtual void EncodeSyncPacket() = 0; | |||||
| virtual void DecodeSyncPacket() = 0; | |||||
| virtual int SyncRecv() = 0; | virtual int SyncRecv() = 0; | ||||
| virtual int SyncSend() = 0; | virtual int SyncSend() = 0; | ||||
| @@ -119,8 +119,8 @@ namespace Jack | |||||
| int DataSend(); | int DataSend(); | ||||
| //sync packet | //sync packet | ||||
| int EncodeSyncPacket(); | |||||
| int DecodeSyncPacket(); | |||||
| void EncodeSyncPacket(); | |||||
| void DecodeSyncPacket(); | |||||
| int Send ( size_t size, int flags ); | int Send ( size_t size, int flags ); | ||||
| int Recv ( size_t size, int flags ); | int Recv ( size_t size, int flags ); | ||||
| @@ -163,8 +163,8 @@ namespace Jack | |||||
| int DataSend(); | int DataSend(); | ||||
| //sync packet | //sync packet | ||||
| int EncodeSyncPacket(); | |||||
| int DecodeSyncPacket(); | |||||
| void EncodeSyncPacket(); | |||||
| void DecodeSyncPacket(); | |||||
| int Recv ( size_t size, int flags ); | int Recv ( size_t size, int flags ); | ||||
| int Send ( size_t size, int flags ); | int Send ( size_t size, int flags ); | ||||
| @@ -26,7 +26,7 @@ namespace Jack | |||||
| { | { | ||||
| //JackNetMaster****************************************************************************************************** | //JackNetMaster****************************************************************************************************** | ||||
| JackNetMaster::JackNetMaster ( JackNetSocket& socket, session_params_t& params, const char* multicast_ip ) | |||||
| JackNetMaster::JackNetMaster ( JackNetSocket& socket, session_params_t& params, const char* multicast_ip) | |||||
| : JackNetMasterInterface ( params, socket, multicast_ip ) | : JackNetMasterInterface ( params, socket, multicast_ip ) | ||||
| { | { | ||||
| jack_log ( "JackNetMaster::JackNetMaster" ); | jack_log ( "JackNetMaster::JackNetMaster" ); | ||||
| @@ -107,7 +107,7 @@ namespace Jack | |||||
| #endif | #endif | ||||
| } | } | ||||
| //init-------------------------------------------------------------------------------- | //init-------------------------------------------------------------------------------- | ||||
| bool JackNetMaster::Init() | |||||
| bool JackNetMaster::Init(bool auto_connect) | |||||
| { | { | ||||
| //network init | //network init | ||||
| if ( !JackNetMasterInterface::Init() ) | if ( !JackNetMasterInterface::Init() ) | ||||
| @@ -141,9 +141,10 @@ namespace Jack | |||||
| jack_error ( "Can't activate jack client." ); | jack_error ( "Can't activate jack client." ); | ||||
| goto fail; | goto fail; | ||||
| } | } | ||||
| if (auto_connect) | |||||
| ConnectPorts(); | |||||
| jack_info ( "New NetMaster started." ); | jack_info ( "New NetMaster started." ); | ||||
| return true; | return true; | ||||
| fail: | fail: | ||||
| @@ -156,27 +157,26 @@ namespace Jack | |||||
| //jack ports-------------------------------------------------------------------------- | //jack ports-------------------------------------------------------------------------- | ||||
| int JackNetMaster::AllocPorts() | int JackNetMaster::AllocPorts() | ||||
| { | { | ||||
| jack_log ( "JackNetMaster::AllocPorts" ); | |||||
| uint i; | uint i; | ||||
| char name[24]; | char name[24]; | ||||
| jack_nframes_t port_latency = jack_get_buffer_size ( fJackClient ); | jack_nframes_t port_latency = jack_get_buffer_size ( fJackClient ); | ||||
| unsigned long port_flags; | |||||
| jack_log ( "JackNetMaster::AllocPorts" ); | |||||
| //audio | //audio | ||||
| port_flags = JackPortIsInput | JackPortIsPhysical | JackPortIsTerminal; | |||||
| for ( i = 0; i < fParams.fSendAudioChannels; i++ ) | for ( i = 0; i < fParams.fSendAudioChannels; i++ ) | ||||
| { | { | ||||
| sprintf ( name, "to_slave_%d", i+1 ); | sprintf ( name, "to_slave_%d", i+1 ); | ||||
| if ( ( fAudioCapturePorts[i] = jack_port_register ( fJackClient, name, JACK_DEFAULT_AUDIO_TYPE, port_flags, 0 ) ) == NULL ) | |||||
| if ( ( fAudioCapturePorts[i] = jack_port_register ( fJackClient, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput | JackPortIsTerminal, 0 ) ) == NULL ) | |||||
| return -1; | return -1; | ||||
| //port latency | //port latency | ||||
| jack_port_set_latency ( fAudioCapturePorts[i], 0 ); | jack_port_set_latency ( fAudioCapturePorts[i], 0 ); | ||||
| } | } | ||||
| port_flags = JackPortIsOutput | JackPortIsPhysical | JackPortIsTerminal; | |||||
| for ( i = 0; i < fParams.fReturnAudioChannels; i++ ) | for ( i = 0; i < fParams.fReturnAudioChannels; i++ ) | ||||
| { | { | ||||
| sprintf ( name, "from_slave_%d", i+1 ); | sprintf ( name, "from_slave_%d", i+1 ); | ||||
| if ( ( fAudioPlaybackPorts[i] = jack_port_register ( fJackClient, name, JACK_DEFAULT_AUDIO_TYPE, port_flags, 0 ) ) == NULL ) | |||||
| if ( ( fAudioPlaybackPorts[i] = jack_port_register ( fJackClient, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput | JackPortIsTerminal, 0 ) ) == NULL ) | |||||
| return -1; | return -1; | ||||
| //port latency | //port latency | ||||
| switch ( fParams.fNetworkMode ) | switch ( fParams.fNetworkMode ) | ||||
| @@ -192,21 +192,21 @@ namespace Jack | |||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| //midi | //midi | ||||
| port_flags = JackPortIsInput | JackPortIsPhysical | JackPortIsTerminal; | |||||
| for ( i = 0; i < fParams.fSendMidiChannels; i++ ) | for ( i = 0; i < fParams.fSendMidiChannels; i++ ) | ||||
| { | { | ||||
| sprintf ( name, "midi_to_slave_%d", i+1 ); | sprintf ( name, "midi_to_slave_%d", i+1 ); | ||||
| if ( ( fMidiCapturePorts[i] = jack_port_register ( fJackClient, name, JACK_DEFAULT_MIDI_TYPE, port_flags, 0 ) ) == NULL ) | |||||
| if ( ( fMidiCapturePorts[i] = jack_port_register ( fJackClient, name, JACK_DEFAULT_MIDI_TYPE, JackPortIsInput | JackPortIsTerminal, 0 ) ) == NULL ) | |||||
| return -1; | return -1; | ||||
| //port latency | //port latency | ||||
| jack_port_set_latency ( fMidiCapturePorts[i], 0 ); | jack_port_set_latency ( fMidiCapturePorts[i], 0 ); | ||||
| } | } | ||||
| port_flags = JackPortIsOutput | JackPortIsPhysical | JackPortIsTerminal; | |||||
| for ( i = 0; i < fParams.fReturnMidiChannels; i++ ) | for ( i = 0; i < fParams.fReturnMidiChannels; i++ ) | ||||
| { | { | ||||
| sprintf ( name, "midi_from_slave_%d", i+1 ); | sprintf ( name, "midi_from_slave_%d", i+1 ); | ||||
| if ( ( fMidiPlaybackPorts[i] = jack_port_register ( fJackClient, name, JACK_DEFAULT_MIDI_TYPE, port_flags, 0 ) ) == NULL ) | |||||
| if ( ( fMidiPlaybackPorts[i] = jack_port_register ( fJackClient, name, JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput | JackPortIsTerminal, 0 ) ) == NULL ) | |||||
| return -1; | return -1; | ||||
| //port latency | //port latency | ||||
| switch ( fParams.fNetworkMode ) | switch ( fParams.fNetworkMode ) | ||||
| @@ -224,6 +224,27 @@ namespace Jack | |||||
| } | } | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| void JackNetMaster::ConnectPorts() | |||||
| { | |||||
| const char **ports; | |||||
| ports = jack_get_ports(fJackClient, NULL, NULL, JackPortIsPhysical | JackPortIsOutput); | |||||
| if (ports != NULL) { | |||||
| for (unsigned int i = 0; i < fParams.fSendAudioChannels && ports[i]; i++) { | |||||
| jack_connect(fJackClient, ports[i], jack_port_name(fAudioCapturePorts[i])); | |||||
| } | |||||
| free(ports); | |||||
| } | |||||
| ports = jack_get_ports(fJackClient, NULL, NULL, JackPortIsPhysical | JackPortIsInput); | |||||
| if (ports != NULL) { | |||||
| for (unsigned int i = 0; i < fParams.fReturnAudioChannels && ports[i]; i++) { | |||||
| jack_connect(fJackClient, jack_port_name(fAudioPlaybackPorts[i]), ports[i]); | |||||
| } | |||||
| free(ports); | |||||
| } | |||||
| } | |||||
| void JackNetMaster::FreePorts() | void JackNetMaster::FreePorts() | ||||
| { | { | ||||
| @@ -245,7 +266,7 @@ namespace Jack | |||||
| } | } | ||||
| //transport--------------------------------------------------------------------------- | //transport--------------------------------------------------------------------------- | ||||
| int JackNetMaster::EncodeTransportData() | |||||
| void JackNetMaster::EncodeTransportData() | |||||
| { | { | ||||
| //is there a new timebase master ? | //is there a new timebase master ? | ||||
| //TODO : check if any timebase callback has been called (and if it's conditional or not) and set correct value... | //TODO : check if any timebase callback has been called (and if it's conditional or not) and set correct value... | ||||
| @@ -260,11 +281,9 @@ namespace Jack | |||||
| if ( fSendTransportData.fNewState ) | if ( fSendTransportData.fNewState ) | ||||
| jack_info ( "Sending '%s' to '%s'.", GetTransportState ( fSendTransportData.fState ), fParams.fName ); | jack_info ( "Sending '%s' to '%s'.", GetTransportState ( fSendTransportData.fState ), fParams.fName ); | ||||
| fLastTransportState = fSendTransportData.fState; | fLastTransportState = fSendTransportData.fState; | ||||
| } | |||||
| return 0; | |||||
| } | |||||
| int JackNetMaster::DecodeTransportData() | |||||
| void JackNetMaster::DecodeTransportData() | |||||
| { | { | ||||
| //is there timebase master change ? | //is there timebase master change ? | ||||
| if ( fReturnTransportData.fTimebaseMaster != NO_CHANGE ) | if ( fReturnTransportData.fTimebaseMaster != NO_CHANGE ) | ||||
| @@ -322,7 +341,6 @@ namespace Jack | |||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| return 0; | |||||
| } | } | ||||
| void JackNetMaster::SetTimebaseCallback ( jack_transport_state_t state, jack_nframes_t nframes, jack_position_t* pos, int new_pos, void* arg ) | void JackNetMaster::SetTimebaseCallback ( jack_transport_state_t state, jack_nframes_t nframes, jack_position_t* pos, int new_pos, void* arg ) | ||||
| @@ -385,9 +403,8 @@ namespace Jack | |||||
| if (IsSynched()) { // only send if connection is "synched" | if (IsSynched()) { // only send if connection is "synched" | ||||
| //encode the first packet | //encode the first packet | ||||
| if ( EncodeSyncPacket() < 0 ) | |||||
| return 0; | |||||
| EncodeSyncPacket(); | |||||
| //send sync | //send sync | ||||
| if ( SyncSend() == SOCKET_ERROR ) | if ( SyncSend() == SOCKET_ERROR ) | ||||
| return SOCKET_ERROR; | return SOCKET_ERROR; | ||||
| @@ -418,9 +435,8 @@ namespace Jack | |||||
| #endif | #endif | ||||
| //decode sync | //decode sync | ||||
| if ( DecodeSyncPacket() < 0 ) | |||||
| return 0; | |||||
| DecodeSyncPacket(); | |||||
| //receive data | //receive data | ||||
| res = DataRecv(); | res = DataRecv(); | ||||
| if ( ( res == 0 ) || ( res == SOCKET_ERROR ) ) | if ( ( res == 0 ) || ( res == SOCKET_ERROR ) ) | ||||
| @@ -444,6 +460,7 @@ namespace Jack | |||||
| fSocket.SetPort ( DEFAULT_PORT ); | fSocket.SetPort ( DEFAULT_PORT ); | ||||
| fGlobalID = 0; | fGlobalID = 0; | ||||
| fRunning = true; | fRunning = true; | ||||
| fAutoConnect = false; | |||||
| const JSList* node; | const JSList* node; | ||||
| const jack_driver_param_t* param; | const jack_driver_param_t* param; | ||||
| @@ -458,8 +475,14 @@ namespace Jack | |||||
| else | else | ||||
| jack_error("Can't use multicast address %s, using default %s", param->value.ui, DEFAULT_MULTICAST_IP); | jack_error("Can't use multicast address %s, using default %s", param->value.ui, DEFAULT_MULTICAST_IP); | ||||
| break; | break; | ||||
| case 'p': | case 'p': | ||||
| fSocket.SetPort ( param->value.ui ); | fSocket.SetPort ( param->value.ui ); | ||||
| break; | |||||
| case 'c': | |||||
| fAutoConnect = param->value.i; | |||||
| break; | |||||
| } | } | ||||
| } | } | ||||
| @@ -618,8 +641,8 @@ namespace Jack | |||||
| SetSlaveName ( params ); | SetSlaveName ( params ); | ||||
| //create a new master and add it to the list | //create a new master and add it to the list | ||||
| JackNetMaster* master = new JackNetMaster ( fSocket, params, fMulticastIP ); | |||||
| if ( master->Init() ) | |||||
| JackNetMaster* master = new JackNetMaster(fSocket, params, fMulticastIP); | |||||
| if ( master->Init(fAutoConnect) ) | |||||
| { | { | ||||
| fMasterList.push_back ( master ); | fMasterList.push_back ( master ); | ||||
| return master; | return master; | ||||
| @@ -679,7 +702,7 @@ extern "C" | |||||
| strcpy ( desc->name, "netmanager" ); // size MUST be less then JACK_DRIVER_NAME_MAX + 1 | strcpy ( desc->name, "netmanager" ); // size MUST be less then JACK_DRIVER_NAME_MAX + 1 | ||||
| strcpy ( desc->desc, "netjack multi-cast master component" ); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1 | strcpy ( desc->desc, "netjack multi-cast master component" ); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1 | ||||
| desc->nparams = 2; | |||||
| desc->nparams = 3; | |||||
| desc->params = ( jack_driver_param_desc_t* ) calloc ( desc->nparams, sizeof ( jack_driver_param_desc_t ) ); | desc->params = ( jack_driver_param_desc_t* ) calloc ( desc->nparams, sizeof ( jack_driver_param_desc_t ) ); | ||||
| int i = 0; | int i = 0; | ||||
| @@ -697,6 +720,14 @@ extern "C" | |||||
| desc->params[i].value.i = DEFAULT_PORT; | desc->params[i].value.i = DEFAULT_PORT; | ||||
| strcpy ( desc->params[i].short_desc, "UDP port" ); | strcpy ( desc->params[i].short_desc, "UDP port" ); | ||||
| strcpy ( desc->params[i].long_desc, desc->params[i].short_desc ); | strcpy ( desc->params[i].long_desc, desc->params[i].short_desc ); | ||||
| i++; | |||||
| strcpy ( desc->params[i].name, "auto_connect" ); | |||||
| desc->params[i].character = 'c'; | |||||
| desc->params[i].type = JackDriverParamBool; | |||||
| desc->params[i].value.i = false; | |||||
| strcpy ( desc->params[i].short_desc, "Auto connect netmaster to system ports" ); | |||||
| strcpy ( desc->params[i].long_desc, desc->params[i].short_desc ); | |||||
| return desc; | return desc; | ||||
| } | } | ||||
| @@ -53,29 +53,28 @@ namespace Jack | |||||
| //sync and transport | //sync and transport | ||||
| int fLastTransportState; | int fLastTransportState; | ||||
| net_transport_data_t fSendTransportData; | |||||
| net_transport_data_t fReturnTransportData; | |||||
| //monitoring | //monitoring | ||||
| #ifdef JACK_MONITOR | #ifdef JACK_MONITOR | ||||
| jack_time_t fPeriodUsecs; | jack_time_t fPeriodUsecs; | ||||
| JackGnuPlotMonitor<float>* fNetTimeMon; | JackGnuPlotMonitor<float>* fNetTimeMon; | ||||
| #endif | #endif | ||||
| bool Init(); | |||||
| bool Init(bool auto_connect); | |||||
| int AllocPorts(); | int AllocPorts(); | ||||
| void FreePorts(); | void FreePorts(); | ||||
| void Exit(); | void Exit(); | ||||
| //transport | //transport | ||||
| int EncodeTransportData(); | |||||
| int DecodeTransportData(); | |||||
| void EncodeTransportData(); | |||||
| void DecodeTransportData(); | |||||
| int Process(); | int Process(); | ||||
| void TimebaseCallback ( jack_position_t* pos ); | void TimebaseCallback ( jack_position_t* pos ); | ||||
| void ConnectPorts(); | |||||
| public: | public: | ||||
| JackNetMaster ( JackNetSocket& socket, session_params_t& params, const char* multicast_ip ); | |||||
| JackNetMaster ( JackNetSocket& socket, session_params_t& params, const char* multicast_ip); | |||||
| ~JackNetMaster (); | ~JackNetMaster (); | ||||
| bool IsSlaveReadyToRoll(); | bool IsSlaveReadyToRoll(); | ||||
| @@ -103,6 +102,7 @@ namespace Jack | |||||
| master_list_t fMasterList; | master_list_t fMasterList; | ||||
| uint32_t fGlobalID; | uint32_t fGlobalID; | ||||
| bool fRunning; | bool fRunning; | ||||
| bool fAutoConnect; | |||||
| void Run(); | void Run(); | ||||
| JackNetMaster* MasterInit ( session_params_t& params ); | JackNetMaster* MasterInit ( session_params_t& params ); | ||||
| @@ -112,7 +112,7 @@ namespace Jack | |||||
| int SyncCallback ( jack_transport_state_t state, jack_position_t* pos ); | int SyncCallback ( jack_transport_state_t state, jack_position_t* pos ); | ||||
| public: | public: | ||||
| JackNetMasterManager ( jack_client_t* jack_client, const JSList* params ); | |||||
| JackNetMasterManager ( jack_client_t* jack_client, const JSList* params); | |||||
| ~JackNetMasterManager(); | ~JackNetMasterManager(); | ||||
| }; | }; | ||||
| } | } | ||||
| @@ -377,6 +377,15 @@ namespace Jack | |||||
| jack_info ( "**********************************************" ); | jack_info ( "**********************************************" ); | ||||
| } | } | ||||
| SERVER_EXPORT void NetTransportDataDisplay ( net_transport_data_t* data ) | |||||
| { | |||||
| jack_info ( "********************Network Transport********************" ); | |||||
| jack_info ( "Transport new state : %u", data->fNewState ); | |||||
| jack_info ( "Transport timebase master : %u", data->fTimebaseMaster ); | |||||
| jack_info ( "Transport cycle state : %u", data->fState ); | |||||
| jack_info ( "**********************************************" ); | |||||
| } | |||||
| SERVER_EXPORT void MidiBufferHToN ( JackMidiBuffer* src_buffer, JackMidiBuffer* dst_buffer ) | SERVER_EXPORT void MidiBufferHToN ( JackMidiBuffer* src_buffer, JackMidiBuffer* dst_buffer ) | ||||
| { | { | ||||
| dst_buffer->magic = htonl(src_buffer->magic); | dst_buffer->magic = htonl(src_buffer->magic); | ||||
| @@ -398,6 +407,56 @@ namespace Jack | |||||
| dst_buffer->lost_events = ntohl(src_buffer->lost_events); | dst_buffer->lost_events = ntohl(src_buffer->lost_events); | ||||
| dst_buffer->mix_index = ntohl(src_buffer->mix_index); | dst_buffer->mix_index = ntohl(src_buffer->mix_index); | ||||
| } | } | ||||
| SERVER_EXPORT void TransportDataHToN ( net_transport_data_t* src_params, net_transport_data_t* dst_params ) | |||||
| { | |||||
| dst_params->fNewState = htonl(src_params->fNewState); | |||||
| dst_params->fTimebaseMaster = htonl(src_params->fTimebaseMaster); | |||||
| dst_params->fState = htonl(src_params->fState); | |||||
| dst_params->fPosition.unique_1 = htonll(src_params->fPosition.unique_1); | |||||
| dst_params->fPosition.usecs = htonl(src_params->fPosition.usecs); | |||||
| dst_params->fPosition.frame_rate = htonl(src_params->fPosition.frame_rate); | |||||
| dst_params->fPosition.frame = htonl(src_params->fPosition.frame); | |||||
| dst_params->fPosition.bar = htonl(src_params->fPosition.bar); | |||||
| dst_params->fPosition.beat = htonl(src_params->fPosition.beat); | |||||
| dst_params->fPosition.tick = htonl(src_params->fPosition.tick); | |||||
| dst_params->fPosition.bar_start_tick = htonll((uint64_t)src_params->fPosition.bar_start_tick); | |||||
| dst_params->fPosition.beats_per_bar = htonl(src_params->fPosition.beats_per_bar); | |||||
| dst_params->fPosition.beat_type = htonl(src_params->fPosition.beat_type); | |||||
| dst_params->fPosition.ticks_per_beat = htonll((uint64_t)src_params->fPosition.ticks_per_beat); | |||||
| dst_params->fPosition.beats_per_minute = htonll((uint64_t)src_params->fPosition.beats_per_minute); | |||||
| dst_params->fPosition.frame_time = htonll((uint64_t)src_params->fPosition.frame_time); | |||||
| dst_params->fPosition.next_time = htonll((uint64_t)src_params->fPosition.next_time); | |||||
| dst_params->fPosition.bbt_offset = htonl(src_params->fPosition.bbt_offset); | |||||
| dst_params->fPosition.audio_frames_per_video_frame = htonl(src_params->fPosition.audio_frames_per_video_frame); | |||||
| dst_params->fPosition.video_offset = htonl(src_params->fPosition.video_offset); | |||||
| dst_params->fPosition.unique_2 = htonll(src_params->fPosition.unique_2); | |||||
| } | |||||
| SERVER_EXPORT void TransportDataNToH ( net_transport_data_t* src_params, net_transport_data_t* dst_params ) | |||||
| { | |||||
| dst_params->fNewState = ntohl(src_params->fNewState); | |||||
| dst_params->fTimebaseMaster = ntohl(src_params->fTimebaseMaster); | |||||
| dst_params->fState = ntohl(src_params->fState); | |||||
| dst_params->fPosition.unique_1 = ntohll(src_params->fPosition.unique_1); | |||||
| dst_params->fPosition.usecs = ntohl(src_params->fPosition.usecs); | |||||
| dst_params->fPosition.frame_rate = ntohl(src_params->fPosition.frame_rate); | |||||
| dst_params->fPosition.frame = ntohl(src_params->fPosition.frame); | |||||
| dst_params->fPosition.bar = ntohl(src_params->fPosition.bar); | |||||
| dst_params->fPosition.beat = ntohl(src_params->fPosition.beat); | |||||
| dst_params->fPosition.tick = ntohl(src_params->fPosition.tick); | |||||
| dst_params->fPosition.bar_start_tick = ntohll((uint64_t)src_params->fPosition.bar_start_tick); | |||||
| dst_params->fPosition.beats_per_bar = ntohl(src_params->fPosition.beats_per_bar); | |||||
| dst_params->fPosition.beat_type = ntohl(src_params->fPosition.beat_type); | |||||
| dst_params->fPosition.ticks_per_beat = ntohll((uint64_t)src_params->fPosition.ticks_per_beat); | |||||
| dst_params->fPosition.beats_per_minute = ntohll((uint64_t)src_params->fPosition.beats_per_minute); | |||||
| dst_params->fPosition.frame_time = ntohll((uint64_t)src_params->fPosition.frame_time); | |||||
| dst_params->fPosition.next_time = ntohll((uint64_t)src_params->fPosition.next_time); | |||||
| dst_params->fPosition.bbt_offset = ntohl(src_params->fPosition.bbt_offset); | |||||
| dst_params->fPosition.audio_frames_per_video_frame = ntohl(src_params->fPosition.audio_frames_per_video_frame); | |||||
| dst_params->fPosition.video_offset = ntohl(src_params->fPosition.video_offset); | |||||
| dst_params->fPosition.unique_2 = ntohll(src_params->fPosition.unique_2); | |||||
| } | |||||
| // Utility ******************************************************************************************************* | // Utility ******************************************************************************************************* | ||||
| @@ -29,6 +29,16 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
| using namespace std; | using namespace std; | ||||
| #ifndef htonll | |||||
| #ifdef __BIG_ENDIAN__ | |||||
| #define htonll(x) (x) | |||||
| #define ntohll(x) (x) | |||||
| #else | |||||
| #define htonll(x) ((((uint64_t)htonl(x)) << 32) + htonl(x >> 32)) | |||||
| #define ntohll(x) ((((uint64_t)ntohl(x)) << 32) + ntohl(x >> 32)) | |||||
| #endif | |||||
| #endif | |||||
| namespace Jack | namespace Jack | ||||
| { | { | ||||
| typedef struct _session_params session_params_t; | typedef struct _session_params session_params_t; | ||||
| @@ -282,6 +292,8 @@ namespace Jack | |||||
| SERVER_EXPORT void PacketHeaderNToH ( packet_header_t* src_header, packet_header_t* dst_header ); | SERVER_EXPORT void PacketHeaderNToH ( packet_header_t* src_header, packet_header_t* dst_header ); | ||||
| SERVER_EXPORT void MidiBufferHToN ( JackMidiBuffer* src_buffer, JackMidiBuffer* dst_buffer ); | SERVER_EXPORT void MidiBufferHToN ( JackMidiBuffer* src_buffer, JackMidiBuffer* dst_buffer ); | ||||
| SERVER_EXPORT void MidiBufferNToH ( JackMidiBuffer* src_buffer, JackMidiBuffer* dst_buffer ); | SERVER_EXPORT void MidiBufferNToH ( JackMidiBuffer* src_buffer, JackMidiBuffer* dst_buffer ); | ||||
| SERVER_EXPORT void TransportDataHToN ( net_transport_data_t* src_params, net_transport_data_t* dst_params ); | |||||
| SERVER_EXPORT void TransportDataNToH ( net_transport_data_t* src_params, net_transport_data_t* dst_params ); | |||||
| //display session parameters | //display session parameters | ||||
| SERVER_EXPORT void SessionParamsDisplay ( session_params_t* params ); | SERVER_EXPORT void SessionParamsDisplay ( session_params_t* params ); | ||||
| //display packet header | //display packet header | ||||
| @@ -292,4 +304,5 @@ namespace Jack | |||||
| SERVER_EXPORT int SetPacketType ( session_params_t* params, sync_packet_type_t packet_type ); | SERVER_EXPORT int SetPacketType ( session_params_t* params, sync_packet_type_t packet_type ); | ||||
| //transport utility | //transport utility | ||||
| SERVER_EXPORT const char* GetTransportState ( int transport_state ); | SERVER_EXPORT const char* GetTransportState ( int transport_state ); | ||||
| SERVER_EXPORT void NetTransportDataDisplay ( net_transport_data_t* data ); | |||||
| } | } | ||||
| @@ -218,7 +218,7 @@ extern "C" | |||||
| strcpy(desc->params[i].name, "cpu-load"); | strcpy(desc->params[i].name, "cpu-load"); | ||||
| desc->params[i].character = 'c'; | desc->params[i].character = 'c'; | ||||
| desc->params[i].type = JackDriverParamBool; | desc->params[i].type = JackDriverParamBool; | ||||
| desc->params[i].value.i = TRUE; | |||||
| desc->params[i].value.i = FALSE; | |||||
| strcpy(desc->params[i].short_desc, "Show DSP CPU load"); | strcpy(desc->params[i].short_desc, "Show DSP CPU load"); | ||||
| strcpy(desc->params[i].long_desc, desc->params[i].short_desc); | strcpy(desc->params[i].long_desc, desc->params[i].short_desc); | ||||
| @@ -226,7 +226,7 @@ extern "C" | |||||
| strcpy(desc->params[i].name, "driver-period"); | strcpy(desc->params[i].name, "driver-period"); | ||||
| desc->params[i].character = 'p'; | desc->params[i].character = 'p'; | ||||
| desc->params[i].type = JackDriverParamBool; | desc->params[i].type = JackDriverParamBool; | ||||
| desc->params[i].value.i = TRUE; | |||||
| desc->params[i].value.i = FALSE; | |||||
| strcpy(desc->params[i].short_desc, "Show driver period"); | strcpy(desc->params[i].short_desc, "Show driver period"); | ||||
| strcpy(desc->params[i].long_desc, desc->params[i].short_desc); | strcpy(desc->params[i].long_desc, desc->params[i].short_desc); | ||||
| @@ -234,7 +234,7 @@ extern "C" | |||||
| strcpy(desc->params[i].name, "driver-end-time"); | strcpy(desc->params[i].name, "driver-end-time"); | ||||
| desc->params[i].character = 'e'; | desc->params[i].character = 'e'; | ||||
| desc->params[i].type = JackDriverParamBool; | desc->params[i].type = JackDriverParamBool; | ||||
| desc->params[i].value.i = TRUE; | |||||
| desc->params[i].value.i = FALSE; | |||||
| strcpy(desc->params[i].short_desc, "Show driver end time"); | strcpy(desc->params[i].short_desc, "Show driver end time"); | ||||
| strcpy(desc->params[i].long_desc, desc->params[i].short_desc); | strcpy(desc->params[i].long_desc, desc->params[i].short_desc); | ||||
| @@ -223,34 +223,7 @@ void JackOSSDriver::DisplayDeviceInfo() | |||||
| if (cap & DSP_CAP_BIND) jack_info(" DSP_CAP_BIND"); | if (cap & DSP_CAP_BIND) jack_info(" DSP_CAP_BIND"); | ||||
| } | } | ||||
| } | } | ||||
| /* | |||||
| TODO | |||||
| ai_in.dev = fInFD; | |||||
| jack_log("JackOSSDriver::DisplayDeviceInfo input fInFD = %d", ai_in.dev); | |||||
| if (ioctl(fInFD, SNDCTL_AUDIOINFO, &ai_in) != -1) { | |||||
| jack_info("Using audio engine %d = %s for input", ai_in.dev, ai_in.name); | |||||
| if (ai_in.iformats & AFMT_S24_NE) | |||||
| jack_info("Available input format : AFMT_S24_NE"); | |||||
| if (ai_in.iformats & AFMT_S16_NE) | |||||
| jack_info("Available input format : AFMT_S16_NE"); | |||||
| if (ai_in.iformats & AFMT_S32_NE) | |||||
| jack_info("Available input format : AFMT_S32_NE"); | |||||
| } | |||||
| ai_out.dev = fOutFD; | |||||
| jack_log("JackOSSDriver::DisplayDeviceInfo output fOutFD = %d", ai_out.dev); | |||||
| if (ioctl(fOutFD, SNDCTL_AUDIOINFO, &ai_out) != -1) { | |||||
| jack_info("Using audio engine %d = %s for output", ai_out.dev, ai_out.name); | |||||
| if (ai_out.oformats & AFMT_S24_NE) | |||||
| jack_info("Available output format : AFMT_S24_NE"); | |||||
| if (ai_out.oformats & AFMT_S16_NE) | |||||
| jack_info("Available output format : AFMT_S16_NE"); | |||||
| if (ai_out.oformats & AFMT_S32_NE) | |||||
| jack_info("Available output format : AFMT_S32_NE"); | |||||
| } | |||||
| */ | |||||
| if (ai_in.rate_source != ai_out.rate_source) { | if (ai_in.rate_source != ai_out.rate_source) { | ||||
| jack_info("Warning : input and output are not necessarily driven by the same clock!"); | jack_info("Warning : input and output are not necessarily driven by the same clock!"); | ||||
| } | } | ||||
| @@ -541,7 +514,7 @@ int JackOSSDriver::OpenAux() | |||||
| // In duplex mode, check that input and output use the same buffer size | // In duplex mode, check that input and output use the same buffer size | ||||
| /* | /* | ||||
| // 10/02/09 : desactivated for now, needs more check (only needed when *same* device is used for input and output ??) | |||||
| 10/02/09 : desactivated for now, needs more check (only needed when *same* device is used for input and output ??) | |||||
| if ((fRWMode & kRead) && (fRWMode & kWrite) && (fInputBufferSize != fOutputBufferSize)) { | if ((fRWMode & kRead) && (fRWMode & kWrite) && (fInputBufferSize != fOutputBufferSize)) { | ||||
| jack_error("JackOSSDriver::OpenAux input and output buffer size are not the same!!"); | jack_error("JackOSSDriver::OpenAux input and output buffer size are not the same!!"); | ||||
| @@ -583,32 +556,6 @@ int JackOSSDriver::Read() | |||||
| } | } | ||||
| ssize_t count; | ssize_t count; | ||||
| /* | |||||
| // Maybe necessary to write an empty output buffer first time : see http://manuals.opensound.com/developer/fulldup.c.html | |||||
| if (fFirstCycle) { | |||||
| fFirstCycle = false; | |||||
| memset(fOutputBuffer, 0, fOutputBufferSize); | |||||
| // Prefill ouput buffer | |||||
| for (int i = 0; i < fNperiods; i++) { | |||||
| count = ::write(fOutFD, fOutputBuffer, fOutputBufferSize); | |||||
| if (count < fOutputBufferSize) { | |||||
| jack_error("JackOSSDriver::Write error bytes written = %ld", count); | |||||
| return -1; | |||||
| } | |||||
| } | |||||
| int delay; | |||||
| if (ioctl(fOutFD, SNDCTL_DSP_GETODELAY, &delay) == -1) { | |||||
| jack_error("JackOSSDriver::Write error get out delay : %s@%i, errno = %d", __FILE__, __LINE__, errno); | |||||
| return -1; | |||||
| } | |||||
| delay /= fSampleSize * fPlaybackChannels; | |||||
| jack_info("JackOSSDriver::Write output latency frames = %ld", delay); | |||||
| } | |||||
| */ | |||||
| #ifdef JACK_MONITOR | #ifdef JACK_MONITOR | ||||
| gCycleTable.fTable[gCycleCount].fBeforeRead = GetMicroSeconds(); | gCycleTable.fTable[gCycleCount].fBeforeRead = GetMicroSeconds(); | ||||
| @@ -1,5 +1,5 @@ | |||||
| ------------------------------- | ------------------------------- | ||||
| Jackmp on windows | |||||
| Jackmp on Windows | |||||
| ------------------------------- | ------------------------------- | ||||
| This folder contains all the windows specific sources. | This folder contains all the windows specific sources. | ||||
| @@ -34,11 +34,11 @@ You can make a small installer ('setup.exe') with CreateInstallFree, a little fr | |||||
| A binary version of qjackctl is also included. | A binary version of qjackctl is also included. | ||||
| ------------------------------- | ------------------------------- | ||||
| Running Jack on windows | |||||
| Running Jack on Windows | |||||
| ------------------------------- | ------------------------------- | ||||
| You can use two drivers : PortAudio and NetDriver. | You can use two drivers : PortAudio and NetDriver. | ||||
| The PortAudio backend allow the use of many soundcards, using ASIO or WMME drivers (any ASIO driver can be seen by PortAudio). | |||||
| The PortAudio backend allow the use of many soundcards, using ASIO, DirectSound or WMME drivers (any ASIO driver can be seen by PortAudio). | |||||
| The NetDriver allow you to use NetJack2 on windows. Thus you can easily exchange midi and audio streams bitween computers (Linux, MacOSX or Windows). | The NetDriver allow you to use NetJack2 on windows. Thus you can easily exchange midi and audio streams bitween computers (Linux, MacOSX or Windows). | ||||
| In both cases, you have to use the minimalist : | In both cases, you have to use the minimalist : | ||||
| 'jackd -R -d ...' | 'jackd -R -d ...' | ||||
| @@ -46,7 +46,11 @@ In both cases, you have to use the minimalist : | |||||
| 'jackd -R -S -d portaudio -l' | 'jackd -R -S -d portaudio -l' | ||||
| Other options still stay the same. | Other options still stay the same. | ||||
| You can also pick a binary of Qjackctl, but this is still in development. | |||||
| You can also pick a binary of Qjackctl, but this is still in development. | |||||
| ------------------------------- | |||||
| Running Jack on windows | |||||
| ------------------------------- | |||||
| More information at : 'http://www.grame.fr/~letz/jackdmp.html'. | More information at : 'http://www.grame.fr/~letz/jackdmp.html'. | ||||
| @@ -66,8 +66,8 @@ | |||||
| <_><src>..\Release\bin\jack_metro.exe</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></> | <_><src>..\Release\bin\jack_metro.exe</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></> | ||||
| <_><src>..\Release\bin\jack_unload.exe</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></> | <_><src>..\Release\bin\jack_unload.exe</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></> | ||||
| <_><src>..\Release\bin\jackd.exe</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></> | <_><src>..\Release\bin\jackd.exe</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></> | ||||
| <_><src>..\Release\bin\libjack.dll</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></> | |||||
| <_><src>..\Release\bin\libjackserver.dll</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></> | |||||
| <_><src>..\Release\bin\libjack.dll</><dest>sys</><custom></><ifexist>overnewer</><recurs>0</></> | |||||
| <_><src>..\Release\bin\libjackserver.dll</><dest>sys</><custom></><ifexist>overnewer</><recurs>0</></> | |||||
| <_><src>..\Release\bin\libsamplerate-0.dll</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></> | <_><src>..\Release\bin\libsamplerate-0.dll</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></> | ||||
| <_><src>..\Release\bin\portaudio_x86.dll</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></> | <_><src>..\Release\bin\portaudio_x86.dll</><dest>inst</><custom></><ifexist>overnewer</><recurs>0</></> | ||||
| <_><src>..\Release\bin\jack\jack_net.dll</><dest>inst</><custom>jack</><ifexist>overnewer</><recurs>0</></> | <_><src>..\Release\bin\jack\jack_net.dll</><dest>inst</><custom>jack</><ifexist>overnewer</><recurs>0</></> | ||||
| @@ -28,7 +28,7 @@ It is compiled from the latest CVS version which is using QT4 framework. To uses | |||||
| - quit qjackctl.exe and start is again, it should now launch the jack server. Quitting the qjackctl.exe will now close the jack server. | - quit qjackctl.exe and start is again, it should now launch the jack server. Quitting the qjackctl.exe will now close the jack server. | ||||
| Starting the jack server with another audio device installed on the machine (like an ASIO card) can now be done directly in qjackctl. | Starting the jack server with another audio device installed on the machine (like an ASIO card) can now be done directly in qjackctl. | ||||
| A ">" button at the right of the interface button allows to list the name of all available devices, driven either by "MME", "Direct Sound", or "ASIO". | |||||
| A ">" button at the right of the interface button allows to list the name of all available devices, driven either by "MME", "DirectSound", or "ASIO". | |||||
| Alternatively using the following command allows to display the names of available devices: | Alternatively using the following command allows to display the names of available devices: | ||||
| - jackd -d portaudio -l to display the entire list of available audio devices. (jackd -d portaudio -h will display all portaudio driver features) | - jackd -d portaudio -l to display the entire list of available audio devices. (jackd -d portaudio -h will display all portaudio driver features) | ||||
| @@ -65,9 +65,9 @@ def set_options(opt): | |||||
| opt.add_option('--doxygen', action='store_true', default=False, help='Enable build of doxygen documentation') | opt.add_option('--doxygen', action='store_true', default=False, help='Enable build of doxygen documentation') | ||||
| opt.add_option('--profile', action='store_true', default=False, help='Build with engine profiling') | opt.add_option('--profile', action='store_true', default=False, help='Build with engine profiling') | ||||
| opt.add_option('--clients', default=64, type="int", dest="clients", help='Maximum number of JACK clients') | opt.add_option('--clients', default=64, type="int", dest="clients", help='Maximum number of JACK clients') | ||||
| opt.add_option('--ports', default=512, type="int", dest="ports", help='Maximum number of ports') | |||||
| opt.add_option('--ports', default=1024, type="int", dest="ports", help='Maximum number of ports') | |||||
| opt.add_option('--clients', default=64, type="int", dest="clients", help='Maximum number of JACK clients') | opt.add_option('--clients', default=64, type="int", dest="clients", help='Maximum number of JACK clients') | ||||
| opt.add_option('--ports', default=512, type="int", dest="ports", help='Maximum number of ports') | |||||
| opt.add_option('--ports', default=1024, type="int", dest="ports", help='Maximum number of ports') | |||||
| opt.sub_options('dbus') | opt.sub_options('dbus') | ||||
| def configure(conf): | def configure(conf): | ||||