/[svn]/liblscp/trunk/src/client.c
ViewVC logotype

Diff of /liblscp/trunk/src/client.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1697 by schoenebeck, Sat Feb 16 19:31:32 2008 UTC revision 1806 by schoenebeck, Thu Dec 11 01:28:42 2008 UTC
# Line 20  Line 20 
20    
21  *****************************************************************************/  *****************************************************************************/
22    
23    #include <locale.h>
24  #include "common.h"  #include "common.h"
25    
26  // Default timeout value (in milliseconds).  // Default timeout value (in milliseconds).
# Line 35  static lscp_status_t    _lscp_client_evt Line 36  static lscp_status_t    _lscp_client_evt
36    
37    
38  //-------------------------------------------------------------------------  //-------------------------------------------------------------------------
39    // General helper functions.
40    
41    struct _locale_t {
42            char numeric[32];
43            char ctype[32];
44    };
45    
46    // we need to ensure a constant locale setting e.g. for parsing
47    // floating point numbers with atof(), as the floating point separator
48    // character varies by the invidual locale settings
49    static void _save_and_set_c_locale(struct _locale_t* locale)
50    {
51            strncpy(locale->numeric, setlocale(LC_NUMERIC, NULL), 32);
52            strncpy(locale->ctype, setlocale(LC_CTYPE, NULL), 32);
53            setlocale(LC_NUMERIC, "C");
54            setlocale(LC_CTYPE, "C");
55    }
56    
57    // restore the original locale setting as nothing happened
58    static void _restore_locale(struct _locale_t* locale)
59    {
60            setlocale(LC_NUMERIC, locale->numeric);
61            setlocale(LC_CTYPE, locale->ctype);
62    }
63    
64    // seems the standard atof() function doesnt care much about locale
65    // runtime modifications, so we use this workaround
66    static float _atof(const char* txt) {
67            float f;
68            sscanf(txt, "%f", &f); // yeah, you're a good boy sscanf()
69            return f;
70    }
71    
72    
73    //-------------------------------------------------------------------------
74  // Event service (datagram oriented).  // Event service (datagram oriented).
75    
76  static void _lscp_client_evt_proc ( void *pvClient )  static void _lscp_client_evt_proc ( void *pvClient )
# Line 1111  lscp_channel_info_t *lscp_get_channel_in Line 1147  lscp_channel_info_t *lscp_get_channel_in
1147          const char *pszCrlf = "\r\n";          const char *pszCrlf = "\r\n";
1148          char *pszToken;          char *pszToken;
1149          char *pch;          char *pch;
1150            struct _locale_t locale;
1151    
1152          if (pClient == NULL)          if (pClient == NULL)
1153                  return NULL;                  return NULL;
# Line 1123  lscp_channel_info_t *lscp_get_channel_in Line 1160  lscp_channel_info_t *lscp_get_channel_in
1160          pChannelInfo = &(pClient->channel_info);          pChannelInfo = &(pClient->channel_info);
1161          lscp_channel_info_reset(pChannelInfo);          lscp_channel_info_reset(pChannelInfo);
1162    
1163            _save_and_set_c_locale(&locale);
1164    
1165          sprintf(szQuery, "GET CHANNEL INFO %d\r\n", iSamplerChannel);          sprintf(szQuery, "GET CHANNEL INFO %d\r\n", iSamplerChannel);
1166          if (lscp_client_call(pClient, szQuery, 1) == LSCP_OK) {          if (lscp_client_call(pClient, szQuery, 1) == LSCP_OK) {
1167                  pszResult = lscp_client_get_result(pClient);                  pszResult = lscp_client_get_result(pClient);
# Line 1207  lscp_channel_info_t *lscp_get_channel_in Line 1246  lscp_channel_info_t *lscp_get_channel_in
1246                          else if (strcasecmp(pszToken, "VOLUME") == 0) {                          else if (strcasecmp(pszToken, "VOLUME") == 0) {
1247                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
1248                                  if (pszToken)                                  if (pszToken)
1249                                          pChannelInfo->volume = (float) atof(lscp_ltrim(pszToken));                                          pChannelInfo->volume = _atof(lscp_ltrim(pszToken));
1250                          }                          }
1251                          else if (strcasecmp(pszToken, "MUTE") == 0) {                          else if (strcasecmp(pszToken, "MUTE") == 0) {
1252                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
# Line 1224  lscp_channel_info_t *lscp_get_channel_in Line 1263  lscp_channel_info_t *lscp_get_channel_in
1263          }          }
1264          else pChannelInfo = NULL;          else pChannelInfo = NULL;
1265    
1266            _restore_locale(&locale);
1267    
1268          // Unlock this section up.          // Unlock this section up.
1269          lscp_mutex_unlock(pClient->mutex);          lscp_mutex_unlock(pClient->mutex);
1270    
# Line 1638  lscp_status_t lscp_set_channel_midi_map Line 1679  lscp_status_t lscp_set_channel_midi_map
1679  lscp_status_t lscp_set_channel_volume ( lscp_client_t *pClient, int iSamplerChannel, float fVolume )  lscp_status_t lscp_set_channel_volume ( lscp_client_t *pClient, int iSamplerChannel, float fVolume )
1680  {  {
1681          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1682            struct _locale_t locale;
1683    
1684          if (iSamplerChannel < 0 || fVolume < 0.0f)          if (iSamplerChannel < 0 || fVolume < 0.0f)
1685                  return LSCP_FAILED;                  return LSCP_FAILED;
1686    
1687            _save_and_set_c_locale(&locale);
1688          sprintf(szQuery, "SET CHANNEL VOLUME %d %g\r\n", iSamplerChannel, fVolume);          sprintf(szQuery, "SET CHANNEL VOLUME %d %g\r\n", iSamplerChannel, fVolume);
1689            _restore_locale(&locale);
1690    
1691          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1692  }  }
1693    
# Line 1726  lscp_status_t lscp_reset_channel ( lscp_ Line 1771  lscp_status_t lscp_reset_channel ( lscp_
1771   */   */
1772  lscp_status_t lscp_reset_sampler ( lscp_client_t *pClient )  lscp_status_t lscp_reset_sampler ( lscp_client_t *pClient )
1773  {  {
1774          // Do actual whole sampler reset...          // Do actual whole sampler reset...
1775          return lscp_client_query(pClient, "RESET\r\n");          return lscp_client_query(pClient, "RESET\r\n");
1776  }  }
1777    
# Line 1859  int lscp_get_total_voice_count_max ( lsc Line 1904  int lscp_get_total_voice_count_max ( lsc
1904  float lscp_get_volume ( lscp_client_t *pClient )  float lscp_get_volume ( lscp_client_t *pClient )
1905  {  {
1906          float fVolume = 0.0f;          float fVolume = 0.0f;
1907            struct _locale_t locale;
1908    
1909          if (pClient == NULL)          if (pClient == NULL)
1910                  return 0.0f;                  return 0.0f;
# Line 1866  float lscp_get_volume ( lscp_client_t *p Line 1912  float lscp_get_volume ( lscp_client_t *p
1912          // Lock this section up.          // Lock this section up.
1913          lscp_mutex_lock(pClient->mutex);          lscp_mutex_lock(pClient->mutex);
1914    
1915            _save_and_set_c_locale(&locale);
1916    
1917          if (lscp_client_call(pClient, "GET VOLUME\r\n", 0) == LSCP_OK)          if (lscp_client_call(pClient, "GET VOLUME\r\n", 0) == LSCP_OK)
1918                  fVolume = (float) atof(lscp_client_get_result(pClient));                  fVolume = _atof(lscp_client_get_result(pClient));
1919    
1920            _restore_locale(&locale);
1921    
1922          // Unlock this section down.          // Unlock this section down.
1923          lscp_mutex_unlock(pClient->mutex);          lscp_mutex_unlock(pClient->mutex);
# Line 1890  float lscp_get_volume ( lscp_client_t *p Line 1940  float lscp_get_volume ( lscp_client_t *p
1940  lscp_status_t lscp_set_volume ( lscp_client_t *pClient, float fVolume )  lscp_status_t lscp_set_volume ( lscp_client_t *pClient, float fVolume )
1941  {  {
1942          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
1943            struct _locale_t locale;
1944    
1945          if (fVolume < 0.0f)          if (fVolume < 0.0f)
1946                  return LSCP_FAILED;                  return LSCP_FAILED;
1947    
1948            _save_and_set_c_locale(&locale);
1949          sprintf(szQuery, "SET VOLUME %g\r\n", fVolume);          sprintf(szQuery, "SET VOLUME %g\r\n", fVolume);
1950            _restore_locale(&locale);
1951    
1952          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
1953  }  }
1954    
1955    /**
1956     *  Get global voice limit setting:
1957     *  @code
1958     *  GET VOICES
1959     *  @endcode
1960     *  This value reflects the maximum amount of voices a sampler engine
1961     *  processes simultaniously before voice stealing kicks in.
1962     *
1963     *  @param pClient  Pointer to client instance structure.
1964     *
1965     *  @returns The current global maximum amount of voices limit or a
1966     *           negative value on error (e.g. if sampler doesn't support
1967     *           this command).
1968     */
1969    int lscp_get_voices(lscp_client_t *pClient)
1970    {
1971            int iVoices = -1;
1972    
1973            if (pClient == NULL)
1974                    return -1;
1975    
1976            // Lock this section up.
1977            lscp_mutex_lock(pClient->mutex);
1978    
1979            if (lscp_client_call(pClient, "GET VOICES\r\n", 0) == LSCP_OK)
1980                    iVoices = atoi(lscp_client_get_result(pClient));
1981    
1982            // Unlock this section down.
1983            lscp_mutex_unlock(pClient->mutex);
1984    
1985            return iVoices;
1986    }
1987    
1988    /**
1989     *  Setting global voice limit setting:
1990     *  @code
1991     *  SET VOICES <max-voices>
1992     *  @endcode
1993     *  This value reflects the maximum amount of voices a sampler engine
1994     *  processes simultaniously before voice stealing kicks in. Note that
1995     *  this value will be passed to all sampler engine instances, that is
1996     *  the total amount of maximum voices on the running system is thus
1997     *  @param iMaxVoices multiplied with the current amount of sampler
1998     *  engine instances.
1999     *
2000     *  @param pClient     Pointer to client instance structure.
2001     *  @param iMaxVoices  Global voice limit setting as integer value larger
2002     *                     or equal to 1.
2003     *
2004     *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2005     */
2006    lscp_status_t lscp_set_voices(lscp_client_t *pClient, int iMaxVoices)
2007    {
2008            char szQuery[LSCP_BUFSIZ];
2009    
2010            if (iMaxVoices < 1)
2011                    return LSCP_FAILED;
2012    
2013            sprintf(szQuery, "SET VOICES %d\r\n", iMaxVoices);
2014            return lscp_client_query(pClient, szQuery);
2015    }
2016    
2017    /**
2018     *  Get global disk streams limit setting:
2019     *  @code
2020     *  GET STREAMS
2021     *  @endcode
2022     *  This value reflects the maximum amount of disk streams a sampler
2023     *  engine processes simultaniously.
2024     *
2025     *  @param pClient  Pointer to client instance structure.
2026     *
2027     *  @returns The current global maximum amount of disk streams limit
2028     *           or a negative value on error (e.g. if sampler doesn't
2029     *           support this command).
2030     */
2031    int lscp_get_streams(lscp_client_t *pClient)
2032    {
2033            int iStreams = -1;
2034    
2035            if (pClient == NULL)
2036                    return -1;
2037    
2038            // Lock this section up.
2039            lscp_mutex_lock(pClient->mutex);
2040    
2041            if (lscp_client_call(pClient, "GET STREAMS\r\n", 0) == LSCP_OK)
2042                    iStreams = atoi(lscp_client_get_result(pClient));
2043    
2044            // Unlock this section down.
2045            lscp_mutex_unlock(pClient->mutex);
2046    
2047            return iStreams;
2048    }
2049    
2050    /**
2051     *  Setting global disk streams limit setting:
2052     *  @code
2053     *  SET STREAMS <max-streams>
2054     *  @endcode
2055     *  This value reflects the maximum amount of dist streams a sampler
2056     *  engine instance processes simultaniously. Note that this value will
2057     *  be passed to all sampler engine instances, that is the total amount
2058     *  of maximum disk streams on the running system is thus
2059     *  @param iMaxStreams multiplied with the current amount of sampler
2060     *  engine instances.
2061     *
2062     *  @param pClient      Pointer to client instance structure.
2063     *  @param iMaxStreams  Global streams limit setting as positive integer
2064     *                      value (larger or equal to 0).
2065     *
2066     *  @returns LSCP_OK on success, LSCP_FAILED otherwise.
2067     */
2068    lscp_status_t lscp_set_streams(lscp_client_t *pClient, int iMaxStreams)
2069    {
2070            char szQuery[LSCP_BUFSIZ];
2071    
2072            if (iMaxStreams < 0)
2073                    return LSCP_FAILED;
2074    
2075            sprintf(szQuery, "SET STREAMS %d\r\n", iMaxStreams);
2076            return lscp_client_query(pClient, szQuery);
2077    }
2078    
2079  /**  /**
2080   *  Add an effect send to a sampler channel:   *  Add an effect send to a sampler channel:
# Line 1926  int lscp_create_fxsend ( lscp_client_t * Line 2103  int lscp_create_fxsend ( lscp_client_t *
2103          lscp_mutex_lock(pClient->mutex);          lscp_mutex_lock(pClient->mutex);
2104    
2105          sprintf(szQuery, "CREATE FX_SEND %d %d", iSamplerChannel, iMidiController);          sprintf(szQuery, "CREATE FX_SEND %d %d", iSamplerChannel, iMidiController);
2106            
2107          if (pszFxName)          if (pszFxName)
2108                  sprintf(szQuery + strlen(szQuery), " '%s'", pszFxName);                  sprintf(szQuery + strlen(szQuery), " '%s'", pszFxName);
2109    
# Line 2058  lscp_fxsend_info_t *lscp_get_fxsend_info Line 2235  lscp_fxsend_info_t *lscp_get_fxsend_info
2235          const char *pszCrlf = "\r\n";          const char *pszCrlf = "\r\n";
2236          char *pszToken;          char *pszToken;
2237          char *pch;          char *pch;
2238            struct _locale_t locale;
2239    
2240          if (pClient == NULL)          if (pClient == NULL)
2241                  return NULL;                  return NULL;
# Line 2067  lscp_fxsend_info_t *lscp_get_fxsend_info Line 2245  lscp_fxsend_info_t *lscp_get_fxsend_info
2245          // Lock this section up.          // Lock this section up.
2246          lscp_mutex_lock(pClient->mutex);          lscp_mutex_lock(pClient->mutex);
2247    
2248            _save_and_set_c_locale(&locale);
2249    
2250          pFxSendInfo = &(pClient->fxsend_info);          pFxSendInfo = &(pClient->fxsend_info);
2251          lscp_fxsend_info_reset(pFxSendInfo);          lscp_fxsend_info_reset(pFxSendInfo);
2252    
# Line 2096  lscp_fxsend_info_t *lscp_get_fxsend_info Line 2276  lscp_fxsend_info_t *lscp_get_fxsend_info
2276                          else if (strcasecmp(pszToken, "LEVEL") == 0) {                          else if (strcasecmp(pszToken, "LEVEL") == 0) {
2277                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
2278                                  if (pszToken)                                  if (pszToken)
2279                                          pFxSendInfo->level = (float) atof(lscp_ltrim(pszToken));                                          pFxSendInfo->level = _atof(lscp_ltrim(pszToken));
2280                          }                          }
2281                          pszToken = lscp_strtok(NULL, pszSeps, &(pch));                          pszToken = lscp_strtok(NULL, pszSeps, &(pch));
2282                  }                  }
2283          }          }
2284          else pFxSendInfo = NULL;          else pFxSendInfo = NULL;
2285    
2286            _restore_locale(&locale);
2287    
2288          // Unlock this section up.          // Unlock this section up.
2289          lscp_mutex_unlock(pClient->mutex);          lscp_mutex_unlock(pClient->mutex);
2290    
# Line 2196  lscp_status_t lscp_set_fxsend_midi_contr Line 2378  lscp_status_t lscp_set_fxsend_midi_contr
2378  lscp_status_t lscp_set_fxsend_level ( lscp_client_t *pClient, int iSamplerChannel, int iFxSend, float fLevel )  lscp_status_t lscp_set_fxsend_level ( lscp_client_t *pClient, int iSamplerChannel, int iFxSend, float fLevel )
2379  {  {
2380          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
2381            struct _locale_t locale;
2382    
2383          if (iSamplerChannel < 0 || iFxSend < 0 || fLevel < 0.0f)          if (iSamplerChannel < 0 || iFxSend < 0 || fLevel < 0.0f)
2384                  return LSCP_FAILED;                  return LSCP_FAILED;
2385    
2386            _save_and_set_c_locale(&locale);
2387          sprintf(szQuery, "SET FX_SEND LEVEL %d %d %f\r\n", iSamplerChannel, iFxSend, fLevel);          sprintf(szQuery, "SET FX_SEND LEVEL %d %d %f\r\n", iSamplerChannel, iFxSend, fLevel);
2388            _restore_locale(&locale);
2389    
2390          return lscp_client_query(pClient, szQuery);          return lscp_client_query(pClient, szQuery);
2391  }  }
2392    
# Line 2227  int lscp_add_midi_instrument_map ( lscp_ Line 2413  int lscp_add_midi_instrument_map ( lscp_
2413          lscp_mutex_lock(pClient->mutex);          lscp_mutex_lock(pClient->mutex);
2414    
2415          strcpy(szQuery, "ADD MIDI_INSTRUMENT_MAP");          strcpy(szQuery, "ADD MIDI_INSTRUMENT_MAP");
2416            
2417          if (pszMapName)          if (pszMapName)
2418                  sprintf(szQuery + strlen(szQuery), " '%s'", pszMapName);                  sprintf(szQuery + strlen(szQuery), " '%s'", pszMapName);
2419    
# Line 2353  const char *lscp_get_midi_instrument_map Line 2539  const char *lscp_get_midi_instrument_map
2539    
2540          // Lock this section up.          // Lock this section up.
2541          lscp_mutex_lock(pClient->mutex);          lscp_mutex_lock(pClient->mutex);
2542            
2543          if (pClient->midi_map_name) {          if (pClient->midi_map_name) {
2544                  free(pClient->midi_map_name);                  free(pClient->midi_map_name);
2545                  pClient->midi_map_name = NULL;                  pClient->midi_map_name = NULL;
# Line 2417  lscp_status_t lscp_set_midi_instrument_m Line 2603  lscp_status_t lscp_set_midi_instrument_m
2603   *  @param pszFileName      Instrument file name.   *  @param pszFileName      Instrument file name.
2604   *  @param iInstrIndex      Instrument index number.   *  @param iInstrIndex      Instrument index number.
2605   *  @param fVolume          Reflects the master volume of the instrument as   *  @param fVolume          Reflects the master volume of the instrument as
2606   *                          a positive floating point number, where a value   *                          a positive floating point number, where a value
2607   *                          less than 1.0 for attenuation, and greater than   *                          less than 1.0 for attenuation, and greater than
2608   *                          1.0 for amplification.   *                          1.0 for amplification.
2609   *  @param load_mode        Instrument load life-time strategy, either   *  @param load_mode        Instrument load life-time strategy, either
# Line 2432  lscp_status_t lscp_set_midi_instrument_m Line 2618  lscp_status_t lscp_set_midi_instrument_m
2618  lscp_status_t lscp_map_midi_instrument ( lscp_client_t *pClient, lscp_midi_instrument_t *pMidiInstr, const char *pszEngineName, const char *pszFileName, int iInstrIndex, float fVolume, lscp_load_mode_t load_mode, const char *pszName )  lscp_status_t lscp_map_midi_instrument ( lscp_client_t *pClient, lscp_midi_instrument_t *pMidiInstr, const char *pszEngineName, const char *pszFileName, int iInstrIndex, float fVolume, lscp_load_mode_t load_mode, const char *pszName )
2619  {  {
2620          char szQuery[LSCP_BUFSIZ];          char szQuery[LSCP_BUFSIZ];
2621            struct _locale_t locale;
2622    
2623          if (pMidiInstr->map < 0)          if (pMidiInstr->map < 0)
2624                  return LSCP_FAILED;                  return LSCP_FAILED;
# Line 2445  lscp_status_t lscp_map_midi_instrument ( Line 2632  lscp_status_t lscp_map_midi_instrument (
2632          if (fVolume < 0.0f)          if (fVolume < 0.0f)
2633                  fVolume = 1.0f;                  fVolume = 1.0f;
2634    
2635            _save_and_set_c_locale(&locale);
2636          sprintf(szQuery, "MAP MIDI_INSTRUMENT %d %d %d %s '%s' %d %g",          sprintf(szQuery, "MAP MIDI_INSTRUMENT %d %d %d %s '%s' %d %g",
2637                  pMidiInstr->map, pMidiInstr->bank, pMidiInstr->prog,                  pMidiInstr->map, pMidiInstr->bank, pMidiInstr->prog,
2638                  pszEngineName, pszFileName, iInstrIndex, fVolume);                  pszEngineName, pszFileName, iInstrIndex, fVolume);
2639            _restore_locale(&locale);
2640    
2641          switch (load_mode) {          switch (load_mode) {
2642          case LSCP_LOAD_PERSISTENT:          case LSCP_LOAD_PERSISTENT:
# Line 2604  lscp_midi_instrument_info_t *lscp_get_mi Line 2793  lscp_midi_instrument_info_t *lscp_get_mi
2793          const char *pszCrlf = "\r\n";          const char *pszCrlf = "\r\n";
2794          char *pszToken;          char *pszToken;
2795          char *pch;          char *pch;
2796            struct _locale_t locale;
2797    
2798          if (pClient == NULL)          if (pClient == NULL)
2799                  return NULL;                  return NULL;
# Line 2616  lscp_midi_instrument_info_t *lscp_get_mi Line 2806  lscp_midi_instrument_info_t *lscp_get_mi
2806    
2807          // Lock this section up.          // Lock this section up.
2808          lscp_mutex_lock(pClient->mutex);          lscp_mutex_lock(pClient->mutex);
2809            
2810            _save_and_set_c_locale(&locale);
2811    
2812          pInstrInfo = &(pClient->midi_instrument_info);          pInstrInfo = &(pClient->midi_instrument_info);
2813          lscp_midi_instrument_info_reset(pInstrInfo);          lscp_midi_instrument_info_reset(pInstrInfo);
2814    
# Line 2670  lscp_midi_instrument_info_t *lscp_get_mi Line 2862  lscp_midi_instrument_info_t *lscp_get_mi
2862                          else if (strcasecmp(pszToken, "VOLUME") == 0) {                          else if (strcasecmp(pszToken, "VOLUME") == 0) {
2863                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));                                  pszToken = lscp_strtok(NULL, pszCrlf, &(pch));
2864                                  if (pszToken)                                  if (pszToken)
2865                                          pInstrInfo->volume = (float) atof(lscp_ltrim(pszToken));                                          pInstrInfo->volume = _atof(lscp_ltrim(pszToken));
2866                          }                          }
2867                          pszToken = lscp_strtok(NULL, pszSeps, &(pch));                          pszToken = lscp_strtok(NULL, pszSeps, &(pch));
2868                  }                  }
2869          }          }
2870          else pInstrInfo = NULL;          else pInstrInfo = NULL;
2871    
2872            _restore_locale(&locale);
2873    
2874          // Unlock this section down.          // Unlock this section down.
2875          lscp_mutex_unlock(pClient->mutex);          lscp_mutex_unlock(pClient->mutex);
2876    

Legend:
Removed from v.1697  
changed lines
  Added in v.1806

  ViewVC Help
Powered by ViewVC