--- liblscp/trunk/src/client.c 2004/07/06 20:20:51 180 +++ liblscp/trunk/src/client.c 2005/05/22 11:27:56 562 @@ -2,7 +2,7 @@ // /**************************************************************************** liblscp - LinuxSampler Control Protocol API - Copyright (C) 2004, rncbc aka Rui Nuno Capela. All rights reserved. + Copyright (C) 2004-2005, rncbc aka Rui Nuno Capela. All rights reserved. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -40,13 +40,13 @@ static void _lscp_client_evt_proc ( void *pvClient ) { lscp_client_t *pClient = (lscp_client_t *) pvClient; - + fd_set fds; // File descriptor list for select(). int fd, fdmax; // Maximum file descriptor number. struct timeval tv; // For specifying a timeout value. int iSelect; // Holds select return status. int iTimeout; - + char achBuffer[LSCP_BUFSIZ]; int cchBuffer; const char *pszSeps = ":\r\n"; @@ -111,10 +111,10 @@ } } // Check if select has in error. else if (iSelect < 0) { - lscp_socket_perror("_lscp_client_call: select"); + lscp_socket_perror("_lscp_client_evt_proc: select"); pClient->evt.iState = 0; } - + // Finally, always signal the event. lscp_cond_signal(pClient->cond); } @@ -164,10 +164,10 @@ closesocket(sock); return LSCP_FAILED; } - + // Set our socket agent struct... lscp_socket_agent_init(&(pClient->evt), sock, &addr, cAddr); - + // And finally the service thread... return lscp_socket_agent_start(&(pClient->evt), _lscp_client_evt_proc, pClient, 0); } @@ -198,7 +198,7 @@ // Wait on response. lscp_cond_wait(pClient->cond, pClient->mutex); - + // Update as naively as we can... if (iSubscribe) pClient->events |= event; @@ -396,7 +396,7 @@ // Lock this section up. lscp_mutex_lock(pClient->mutex); - + // Free up all cached members. lscp_channel_info_free(&(pClient->channel_info)); lscp_engine_info_free(&(pClient->engine_info)); @@ -500,16 +500,16 @@ lscp_status_t lscp_client_query ( lscp_client_t *pClient, const char *pszQuery ) { lscp_status_t ret; - + // Lock this section up. lscp_mutex_lock(pClient->mutex); // Just make the now guarded call. ret = lscp_client_call(pClient, pszQuery); - + // Unlock this section down. lscp_mutex_unlock(pClient->mutex); - + return ret; } @@ -553,7 +553,7 @@ /** * Register frontend for receiving event messages: - * SUBSCRIBE CHANNELS | VOICE_COUNT | STREAM_COUNT | BUFFER_FILL + * SUBSCRIBE CHANNEL_COUNT | VOICE_COUNT | STREAM_COUNT | BUFFER_FILL * | CHANNEL_INFO | MISCELLANEOUS * * @param pClient Pointer to client instance structure. @@ -574,10 +574,10 @@ // If applicable, start the alternate connection... if (pClient->events == LSCP_EVENT_NONE) ret = _lscp_client_evt_connect(pClient); - + // Send the subscription commands. - if (ret == LSCP_OK && (events & LSCP_EVENT_CHANNELS)) - ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_CHANNELS); + if (ret == LSCP_OK && (events & LSCP_EVENT_CHANNEL_COUNT)) + ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_CHANNEL_COUNT); if (ret == LSCP_OK && (events & LSCP_EVENT_VOICE_COUNT)) ret = _lscp_client_evt_request(pClient, 1, LSCP_EVENT_VOICE_COUNT); if (ret == LSCP_OK && (events & LSCP_EVENT_STREAM_COUNT)) @@ -598,7 +598,7 @@ /** * Deregister frontend from receiving UDP event messages anymore: - * SUBSCRIBE CHANNELS | VOICE_COUNT | STREAM_COUNT | BUFFER_FILL + * SUBSCRIBE CHANNEL_COUNT | VOICE_COUNT | STREAM_COUNT | BUFFER_FILL * | CHANNEL_INFO | MISCELLANEOUS * * @param pClient Pointer to client instance structure. @@ -617,8 +617,8 @@ lscp_mutex_lock(pClient->mutex); // Send the unsubscription commands. - if (ret == LSCP_OK && (events & LSCP_EVENT_CHANNELS)) - ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_CHANNELS); + if (ret == LSCP_OK && (events & LSCP_EVENT_CHANNEL_COUNT)) + ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_CHANNEL_COUNT); if (ret == LSCP_OK && (events & LSCP_EVENT_VOICE_COUNT)) ret = _lscp_client_evt_request(pClient, 0, LSCP_EVENT_VOICE_COUNT); if (ret == LSCP_OK && (events & LSCP_EVENT_STREAM_COUNT)) @@ -641,6 +641,22 @@ } +/** + * Getting current subscribed events. + * + * @param pClient Pointer to client instance structure. + * + * @returns The current subscrived bit-wise OR'ed event flags. + */ +lscp_event_t lscp_client_get_events ( lscp_client_t *pClient ) +{ + if (pClient == NULL) + return LSCP_EVENT_NONE; + + return pClient->events; +} + + //------------------------------------------------------------------------- // Client command protocol functions. @@ -753,7 +769,7 @@ if (pClient == NULL) return NULL; - + // Lock this section up. lscp_mutex_lock(pClient->mutex); @@ -790,7 +806,7 @@ if (lscp_client_call(pClient, "ADD CHANNEL\r\n") == LSCP_OK) iSamplerChannel = atoi(lscp_client_get_result(pClient)); - + // Unlock this section down. lscp_mutex_unlock(pClient->mutex); @@ -820,15 +836,41 @@ /** - * Getting all available engines: + * Getting all available engines count: * GET AVAILABLE_ENGINES * * @param pClient Pointer to client instance structure. * + * @returns The current total number of sampler engines on success, + * -1 otherwise. + */ +int lscp_get_available_engines ( lscp_client_t *pClient ) +{ + int iAvailableEngines = -1; + + // Lock this section up. + lscp_mutex_lock(pClient->mutex); + + if (lscp_client_call(pClient, "GET AVAILABLE_ENGINES\r\n") == LSCP_OK) + iAvailableEngines = atoi(lscp_client_get_result(pClient)); + + // Unlock this section down. + lscp_mutex_unlock(pClient->mutex); + + return iAvailableEngines; +} + + +/** + * Getting all available engines: + * LIST AVAILABLE_ENGINES + * + * @param pClient Pointer to client instance structure. + * * @returns A NULL terminated array of engine name strings, * or NULL in case of failure. */ -const char **lscp_get_available_engines ( lscp_client_t *pClient ) +const char **lscp_list_available_engines ( lscp_client_t *pClient ) { const char *pszSeps = ","; @@ -840,7 +882,7 @@ pClient->engines = NULL; } - if (lscp_client_call(pClient, "GET AVAILABLE_ENGINES\r\n") == LSCP_OK) + if (lscp_client_call(pClient, "LIST AVAILABLE_ENGINES\r\n") == LSCP_OK) pClient->engines = lscp_szsplit_create(lscp_client_get_result(pClient), pszSeps); // Unlock this section down. @@ -898,7 +940,7 @@ } } else pEngineInfo = NULL; - + // Unlock this section down. lscp_mutex_unlock(pClient->mutex); @@ -931,7 +973,7 @@ // Lock this section up. lscp_mutex_lock(pClient->mutex); - + pChannelInfo = &(pClient->channel_info); lscp_channel_info_reset(pChannelInfo); @@ -973,6 +1015,11 @@ if (pszToken) pChannelInfo->instrument_nr = atoi(lscp_ltrim(pszToken)); } + else if (strcasecmp(pszToken, "INSTRUMENT_NAME") == 0) { + pszToken = lscp_strtok(NULL, pszCrlf, &(pch)); + if (pszToken) + lscp_unquote_dup(&(pChannelInfo->instrument_name), &pszToken); + } else if (strcasecmp(pszToken, "INSTRUMENT_STATUS") == 0) { pszToken = lscp_strtok(NULL, pszCrlf, &(pch)); if (pszToken) @@ -990,8 +1037,13 @@ } else if (strcasecmp(pszToken, "MIDI_INPUT_CHANNEL") == 0) { pszToken = lscp_strtok(NULL, pszCrlf, &(pch)); - if (pszToken) - pChannelInfo->midi_channel = atoi(lscp_ltrim(pszToken)); + if (pszToken) { + pszToken = lscp_ltrim(pszToken); + if (strcasecmp(pszToken, "ALL") == 0) + pChannelInfo->midi_channel = LSCP_MIDI_CHANNEL_ALL; + else + pChannelInfo->midi_channel = atoi(pszToken); + } } else if (strcasecmp(pszToken, "VOLUME") == 0) { pszToken = lscp_strtok(NULL, pszCrlf, &(pch)); @@ -1002,7 +1054,7 @@ } } else pChannelInfo = NULL; - + // Unlock this section up. lscp_mutex_unlock(pClient->mutex); @@ -1195,7 +1247,7 @@ else while (iStream < pClient->iStreamCount) pBufferFill[iStream++].stream_usage = 0; } - + // Unlock this section down. lscp_mutex_unlock(pClient->mutex); @@ -1261,7 +1313,7 @@ if (iSamplerChannel < 0 || iAudioOut < 0 || iAudioIn < 0) return LSCP_FAILED; - sprintf(szQuery, "SET CHANNEL AUDIO_OUTPUT_CHANNELS %d %d %d\r\n", iSamplerChannel, iAudioOut, iAudioIn); + sprintf(szQuery, "SET CHANNEL AUDIO_OUTPUT_CHANNEL %d %d %d\r\n", iSamplerChannel, iAudioOut, iAudioIn); return lscp_client_query(pClient, szQuery); } @@ -1336,8 +1388,8 @@ * * @param pClient Pointer to client instance structure. * @param iSamplerChannel Sampler channel number. - * @param iMidiChannel MIDI channel number to listen (1-16) or - * zero (0) to listen on all channels. + * @param iMidiChannel MIDI channel address number to listen (0-15) or + * LSCP_MIDI_CHANNEL_ALL (16) to listen on all channels. * * @returns LSCP_OK on success, LSCP_FAILED otherwise. */ @@ -1348,10 +1400,10 @@ if (iSamplerChannel < 0 || iMidiChannel < 0 || iMidiChannel > 16) return LSCP_FAILED; - if (iMidiChannel > 0) - sprintf(szQuery, "SET CHANNEL MIDI_INPUT_CHANNEL %d %d\r\n", iSamplerChannel, iMidiChannel); - else + if (iMidiChannel == LSCP_MIDI_CHANNEL_ALL) sprintf(szQuery, "SET CHANNEL MIDI_INPUT_CHANNEL %d ALL\r\n", iSamplerChannel); + else + sprintf(szQuery, "SET CHANNEL MIDI_INPUT_CHANNEL %d %d\r\n", iSamplerChannel, iMidiChannel); return lscp_client_query(pClient, szQuery); } @@ -1401,4 +1453,18 @@ } +/** + * Resetting the sampler: + * RESET + * + * @param pClient Pointer to client instance structure. + * + * @returns LSCP_OK on success, LSCP_FAILED otherwise. + */ +lscp_status_t lscp_reset_sampler ( lscp_client_t *pClient ) +{ + return lscp_client_query(pClient, "RESET\r\n"); +} + + // end of client.c