/[svn]/liblscp/trunk/examples/example_server.c
ViewVC logotype

Diff of /liblscp/trunk/examples/example_server.c

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

revision 105 by capela, Fri Jun 4 14:48:59 2004 UTC revision 963 by capela, Sun Dec 3 18:30:04 2006 UTC
# Line 1  Line 1 
1  // example_server.c  // example_server.c
2  //  //
3  /****************************************************************************  /****************************************************************************
4     Copyright (C) 2004, rncbc aka Rui Nuno Capela. All rights reserved.     liblscp - LinuxSampler Control Protocol API
5       Copyright (C) 2004-2006, rncbc aka Rui Nuno Capela. All rights reserved.
6    
7     This program is free software; you can redistribute it and/or     This program is free software; you can redistribute it and/or
8     modify it under the terms of the GNU General Public License     modify it under the terms of the GNU General Public License
# Line 13  Line 14 
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15     GNU General Public License for more details.     GNU General Public License for more details.
16    
17     You should have received a copy of the GNU General Public License     You should have received a copy of the GNU General Public License along
18     along with this program; if not, write to the Free Software     with this program; if not, write to the Free Software Foundation, Inc.,
19     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20    
21  *****************************************************************************/  *****************************************************************************/
22    
# Line 34  static WSADATA _wsaData; Line 35  static WSADATA _wsaData;
35    
36  lscp_status_t server_callback ( lscp_connect_t *pConnect, const char *pchBuffer, int cchBuffer, void *pvData )  lscp_status_t server_callback ( lscp_connect_t *pConnect, const char *pchBuffer, int cchBuffer, void *pvData )
37  {  {
38      lscp_status_t ret = LSCP_OK;          lscp_status_t ret = LSCP_OK;
39      lscp_parser_t tok;          lscp_parser_t tok;
40      const char *pszResult = NULL;          const char *pszResult = NULL;
41      char szTemp[256];          char szTemp[4096];
42      static int iChannel = 0;          int i;
43            static int iSamplerChannel = 0;
44      if (pchBuffer == NULL) {          static int iAudioDevice = 0;
45          fprintf(stderr, "server_callback: addr=%s port=%d: ",          static int iMidiDevice  = 0;
46              inet_ntoa(pConnect->client.addr.sin_addr),          static int iMidiInstruments = 0;
47              htons(pConnect->client.addr.sin_port));  
48          switch (cchBuffer) {          if (pchBuffer == NULL) {
49            case LSCP_CONNECT_OPEN:                  fprintf(stderr, "server_callback: addr=%s port=%d: ",
50              fprintf(stderr, "New client connection.\n");                          inet_ntoa(pConnect->client.addr.sin_addr),
51              break;                          htons(pConnect->client.addr.sin_port));
52            case LSCP_CONNECT_CLOSE:                  switch (cchBuffer) {
53              fprintf(stderr, "Connection closed.\n");                  case LSCP_CONNECT_OPEN:
54              break;                          fprintf(stderr, "New client connection.\n");
55          }                          break;
56          return ret;                  case LSCP_CONNECT_CLOSE:
57      }                          fprintf(stderr, "Connection closed.\n");
58                            break;
59      lscp_socket_trace("server_callback", &(pConnect->client.addr), pchBuffer, cchBuffer);                  }
60                    return ret;
61      lscp_parser_init(&tok, pchBuffer, cchBuffer);          }
62    
63      if (lscp_parser_test(&tok, "GET")) {          lscp_socket_trace("server_callback", &(pConnect->client.addr), pchBuffer, cchBuffer);
64          if (lscp_parser_test(&tok, "CHANNEL")) {  
65              if (lscp_parser_test(&tok, "INFO")) {          lscp_parser_init(&tok, pchBuffer, cchBuffer);
66                  // Getting sampler channel informations:  
67                  // GET CHANNEL INFO <sampler-channel>          if (lscp_parser_test(&tok, "GET")) {
68                  pszResult = "ENGINE_NAME: DummyEngine\r\n"                  if (lscp_parser_test(&tok, "CHANNEL")) {
69                              "INSTRUMENT_FILE: DummyInstrument.gig\r\n"                          if (lscp_parser_test(&tok, "INFO")) {
70                              "INSTRUMENT_NR: 0\r\n"                                  // Getting sampler channel informations:
71                              "AUDIO_OUTPUT_DEVICE: 0\r\n"                                  // GET CHANNEL INFO <sampler-channel>
72                              "AUDIO_OUTPUT_CHANNELS: 2\r\n"                                  pszResult = "ENGINE_NAME: DummyEngine\r\n"
73                              "AUDIO_OUTPUT_ROUTING: 0,1\r\n"                                                          "INSTRUMENT_FILE: DummyInstrument.gig\r\n"
74                              "MIDI_INPUT_DEVICE: 0\r\n"                                                          "INSTRUMENT_NR: 0\r\n"
75                              "MIDI_INPUT_PORT: 0\r\n"                                                          "INSTRUMENT_NAME: Dummy Instrument\r\n"
76                              "MIDI_INPUT_CHANNEL: ALL\r\n"                                                          "INSTRUMENT_STATUS: 100\r\n"
77                              "VOLUME: 0.5\r\n";                                                          "AUDIO_OUTPUT_DEVICE: 0\r\n"
78              }                                                          "AUDIO_OUTPUT_CHANNELS: 2\r\n"
79              else if (lscp_parser_test(&tok, "VOICE_COUNT")) {                                                          "AUDIO_OUTPUT_ROUTING: 0,1\r\n"
80                  // Current number of active voices:                                                          "MIDI_INPUT_DEVICE: 0\r\n"
81                  // GET CHANNEL VOICE_COUNT <sampler-channel>                                                          "MIDI_INPUT_PORT: 0\r\n"
82                  sprintf(szTemp, "%d", rand() % 100);                                                          "MIDI_INPUT_CHANNEL: ALL\r\n"
83                  pszResult = szTemp;                                                          "VOLUME: 0.5\r\n"
84              }                                                          "MUTE: FALSE\r\n"
85              else if (lscp_parser_test(&tok, "STREAM_COUNT")) {                                                          "SOLO: TRUE\r\n"
86                  // Current number of active disk streams:                                                          ".\r\n";
87                  // GET CHANNEL STREAM_COUNT <sampler-channel>                          }
88                  pszResult = "3\r\n";                          else if (lscp_parser_test(&tok, "VOICE_COUNT")) {
89              }                                  // Current number of active voices:
90              else if (lscp_parser_test(&tok, "BUFFER_FILL")) {                                  // GET CHANNEL VOICE_COUNT <sampler-channel>
91                  if (lscp_parser_test(&tok, "BYTES")) {                                  sprintf(szTemp, "%d\r\n", rand() % 100);
92                      // Current fill state of disk stream buffers:                                  pszResult = szTemp;
93                      // GET CHANNEL BUFFER_FILL BYTES <sampler-channel>                          }
94                      sprintf(szTemp, "[1]%d,[2]%d,[3]%d\r\n", rand(), rand(), rand());                          else if (lscp_parser_test(&tok, "STREAM_COUNT")) {
95                      pszResult = szTemp;                                  // Current number of active disk streams:
96                  }                                  // GET CHANNEL STREAM_COUNT <sampler-channel>
97                  else if (lscp_parser_test(&tok, "PERCENTAGE")) {                                  pszResult = "3\r\n";
98                      // Current fill state of disk stream buffers:                          }
99                      // GET CHANNEL BUFFER_FILL PERCENTAGE <sampler-channel>                          else if (lscp_parser_test(&tok, "BUFFER_FILL")) {
100                      sprintf(szTemp, "[1]%d%%,[2]%d%%,[3]%d%%\r\n", rand() % 100, rand() % 100, rand() % 100);                                  if (lscp_parser_test(&tok, "BYTES")) {
101                      pszResult = szTemp;                                          // Current fill state of disk stream buffers:
102                  }                                          // GET CHANNEL BUFFER_FILL BYTES <sampler-channel>
103                  else ret = LSCP_FAILED;                                          sprintf(szTemp, "[1]%d,[2]%d,[3]%d\r\n", rand(), rand(), rand());
104              }                                          pszResult = szTemp;
105              else if (lscp_parser_test(&tok, "AUDIO_OUTPUT_TYPE")) {                                  }
106                  // Getting audio output type:                                  else if (lscp_parser_test(&tok, "PERCENTAGE")) {
107                  // GET CHANNEL AUDIO_OUTPUT_TYPE <sampler-channel>                                          // Current fill state of disk stream buffers:
108                  // (unspecified as of draft 04)                                          // GET CHANNEL BUFFER_FILL PERCENTAGE <sampler-channel>
109              }                                          sprintf(szTemp, "[1]%d%%,[2]%d%%,[3]%d%%\r\n", rand() % 100, rand() % 100, rand() % 100);
110              else if (lscp_parser_test(&tok, "AUDIO_OUTPUT_CHANNEL")) {                                          pszResult = szTemp;
111                  // Getting audio output channel:                                  }
112                  // GET CHANNEL AUDIO_OUTPUT_CHANNEL <sampler-channel>                                  else ret = LSCP_FAILED;
113                  // (unspecified as of draft 04)                          }
114              }                          else ret = LSCP_FAILED;
115              else ret = LSCP_FAILED;                  }
116          }                  else if (lscp_parser_test(&tok, "CHANNELS")) {
117          else if (lscp_parser_test(&tok, "CHANNELS")) {                          // Current number of sampler channels:
118              // Current number of sampler channels:                          // GET CHANNELS
119              // GET CHANNELS                          sprintf(szTemp, "%d\r\n", iSamplerChannel);
120              sprintf(szTemp, "%d", iChannel);                          pszResult = szTemp;
121              pszResult = szTemp;                  }
122          }                  else if (lscp_parser_test(&tok, "AVAILABLE_AUDIO_OUTPUT_DRIVERS")) {
123          else if (lscp_parser_test(&tok, "AVAILABLE_AUDIO_OUTPUT_DRIVERS")) {                          // Getting all available audio output driver count.
124              // Getting all available audio output drivers.                          // GET AVAILABLE_AUDIO_OUTPUT_DRIVERS
125              // GET AVAILABLE_AUDIO_OUTPUT_DRIVERS                          pszResult = "2\r\n";
126              pszResult = "ALSA,JACK\r\n";                  }
127          }                  else if (lscp_parser_test(&tok, "AVAILABLE_MIDI_INPUT_DRIVERS")) {
128          else if (lscp_parser_test(&tok, "AVAILABLE_MIDI_INPUT_DRIVERS")) {                          // Getting all available MIDI input driver count.
129              // Getting all available MIDI input drivers.                          // GET AVAILABLE_MIDI_INPUT_DRIVERS
130              // GET AVAILABLE_MIDI_INPUT_DRIVERS                          pszResult = "1\r\n";
131              pszResult = "ALSA\r\n";                  }
132          }                  else if (lscp_parser_test2(&tok, "AUDIO_OUTPUT_DRIVER", "INFO")) {
133          else if (lscp_parser_test2(&tok, "AUDIO_OUTPUT_DRIVER", "INFO")) {                          // Getting informations about a specific audio output driver.
134              // Getting informations about a specific audio output driver.                          // GET AUDIO_OUTPUT_DRIVER INFO <audio-output-type>
135              // GET AUDIO_OUTPUT_DRIVER INFO <audio-output-type>                          if (lscp_parser_test(&tok, "Alsa")) {
136              if (lscp_parser_test(&tok, "ALSA")) {                                  pszResult = "DESCRIPTION: 'ALSA PCM'\r\n"
137                  pszResult = "DESCRIPTION: 'ALSA PCM'\r\n"                                                          "VERSION: '1.0'\r\n"
138                              "VERSION: '1.0'\r\n"                                                          "PARAMETERS: channels,samplerate,active\r\n"
139                              "PARAMETERS: CHANNELS,SAMPLERATE,ACTIVE,CARD\r\n";                                                          ".\r\n";
140              }                          }
141              else if (lscp_parser_test(&tok, "JACK")) {                          else if (lscp_parser_test(&tok, "Jack")) {
142                  pszResult = "DESCRIPTION: Jack Audio Connection Kit\r\n"                                  pszResult = "DESCRIPTION: JACK Audio Connection Kit\r\n"
143                              "VERSION: 0.98.1\r\n"                                                          "VERSION: 0.98.1\r\n"
144                              "PARAMETERS: CHANNELS,SAMPLERATE,ACTIVE\r\n";                                                          "PARAMETERS: channels,samplerate,active\r\n"
145              }                                                          ".\r\n";
146              else ret = LSCP_FAILED;                          }
147          }                          else ret = LSCP_FAILED;
148          else if (lscp_parser_test2(&tok, "MIDI_INPUT_DRIVER", "INFO")) {                  }
149              // Getting informations about a specific MIDI input driver.                  else if (lscp_parser_test2(&tok, "MIDI_INPUT_DRIVER", "INFO")) {
150              // GET MIDI_INPUT_DRIVER INFO <midi-input-type>                          // Getting informations about a specific MIDI input driver.
151              if (lscp_parser_test(&tok, "ALSA")) {                          // GET MIDI_INPUT_DRIVER INFO <midi-input-type>
152                  pszResult = "DESCRIPTION: ALSA Sequencer\r\n"                          if (lscp_parser_test(&tok, "Alsa")) {
153                              "VERSION: 1.0\r\n"                                  pszResult = "DESCRIPTION: ALSA Sequencer\r\n"
154                              "PARAMETERS: PORTS,ACTIVE\r\n";                                                          "VERSION: 1.0\r\n"
155              }                                                          "PARAMETERS: ports,active\r\n"
156              else ret = LSCP_FAILED;                                                          ".\r\n";
157          }                          }
158          else if (lscp_parser_test(&tok, "AVAILABLE_ENGINES")) {                          else ret = LSCP_FAILED;
159              // Getting all available engines:                  }
160              // GET AVAILABLE_ENGINES                  else if (lscp_parser_test2(&tok, "AUDIO_OUTPUT_DRIVER_PARAMETER", "INFO")) {
161              pszResult = "Engine1,Engine2,Engine3\r\n";                          // Getting informations about a specific audio output driver parameter.
162          }                          // GET AUDIO_OUTPUT_DRIVER_PARAMETER INFO <audio-output-type> <param>
163          else if (lscp_parser_test2(&tok, "ENGINE", "INFO")) {                          if (lscp_parser_test(&tok, "Alsa")) {
164              // Getting information about an engine.                                  if (lscp_parser_test(&tok, "active")) {
165              // GET ENGINE INFO <engine-name>                                          pszResult = "DESCRIPTION: 'ALSA PCM active state'\r\n"
166              pszResult = "DESCRIPTION: DummyEngine\r\n"                                                                  "TYPE: BOOL\r\n"
167                          "VERSION: 1.0\r\n";                                                                  "MANDATORY: TRUE\r\n"
168          }                                                                  "FIX: TRUE\r\n"
169          else ret = LSCP_FAILED;                                                                  "MULTIPLICITY: FALSE\r\n"
170      }                                                                  "DEPENDS: channels,samplerate,card\r\n"
171      else if (lscp_parser_test(&tok, "SET")) {                                                                  "DEFAULT: TRUE\r\n"
172          if (lscp_parser_test(&tok, "CHANNEL")) {                                                                  "RANGE_MIN: FALSE\r\n"
173              if (lscp_parser_test(&tok, "VOLUME")) {                                                                  "RANGE_MAX: TRUE\r\n"
174                  // Setting channel volume:                                                                  "POSSIBILITIES: FALSE,TRUE\r\n"
175                  // SET CHANNEL VOLUME <sampler-channel> <volume>                                                                  ".\r\n";
176              }                                  }
177              else if (lscp_parser_test(&tok, "AUDIO_OUTPUT_TYPE")) {                                  else if (lscp_parser_test(&tok, "channels")) {
178                  // Setting audio output type:                                          pszResult = "DESCRIPTION: 'Number of ALSA PCM channels'\r\n"
179                  // SET CHANNEL AUDIO_OUTPUT_TYPE <sampler-channel> <audio-output-type>                                                                  "TYPE: INT\r\n"
180              }                                                                  "MANDATORY: TRUE\r\n"
181              else if (lscp_parser_test(&tok, "AUDIO_OUTPUT_CHANNEL")) {                                                                  "FIX: TRUE\r\n"
182                  // Setting audio output channel:                                                                  "MULTIPLICITY: FALSE\r\n"
183                  // SET CHANNEL AUDIO_OUTPUT_CHANNEL <sampler-channel> <audio-channel>                                                                  "DEFAULT: 2\r\n"
184              }                                                                  ".\r\n";
185              else if (lscp_parser_test(&tok, "MIDI_INPUT_TYPE")) {                                  }
186                  // Setting MIDI input type:                                  else if (lscp_parser_test(&tok, "samplerate")) {
187                  // SET CHANNEL MIDI_INPUT_TYPE <sampler-channel> <midi-input-type>                                          pszResult = "DESCRIPTION: 'ALSA PCM sample rate'\r\n"
188              }                                                                  "TYPE: INT\r\n"
189              else if (lscp_parser_test(&tok, "MIDI_INPUT_PORT")) {                                                                  "MANDATORY: TRUE\r\n"
190                  // Setting MIDI input port:                                                                  "FIX: TRUE\r\n"
191                  // SET CHANNEL MIDI_INPUT_PORT <sampler-channel> <midi-input-port>                                                                  "MULTIPLICITY: TRUE\r\n"
192              }                                                                  "DEFAULT: 44100\r\n"
193              else if (lscp_parser_test(&tok, "MIDI_INPUT_CHANNEL")) {                                                                  "POSSIBILITIES: 44100,48000,96000\r\n"
194                  // Setting MIDI input channel:                                                                  ".\r\n";
195                  // SET CHANNEL MIDI_INPUT_CHANNEL <sampler-channel> <midi-input-chan>                                  }
196              }                                  else ret = LSCP_FAILED;
197              else ret = LSCP_FAILED;                          }
198          }                          else if (lscp_parser_test(&tok, "Jack")) {
199          else ret = LSCP_FAILED;                                  if (lscp_parser_test(&tok, "active")) {
200      }                                          pszResult = "DESCRIPTION: 'JACK active state'\r\n"
201      else if (lscp_parser_test(&tok, "LOAD")) {                                                                  "TYPE: BOOL\r\n"
202          if (lscp_parser_test(&tok, "ENGINE")) {                                                                  "MANDATORY: TRUE\r\n"
203              // Loading a sampler engine:                                                                  "FIX: TRUE\r\n"
204              // LOAD ENGINE <engine-name> <sampler-channel>                                                                  "MULTIPLICITY: FALSE\r\n"
205          }                                                                  "DEPENDS: channels,samplerate\r\n"
206          else if (lscp_parser_test(&tok, "INSTRUMENT")) {                                                                  "DEFAULT: TRUE\r\n"
207              // Loading an instrument:                                                                  "RANGE_MIN: FALSE\r\n"
208              // LOAD INSTRUMENT <filename> <instr-index> <sampler-channel>                                                                  "RANGE_MAX: TRUE\r\n"
209          }                                                                  "POSSIBILITIES: FALSE,TRUE\r\n"
210          else ret = LSCP_FAILED;                                                                  ".\r\n";
211      }                                  }
212      else if (lscp_parser_test2(&tok, "ADD", "CHANNEL")) {                                  else if (lscp_parser_test(&tok, "channels")) {
213          // Adding a new sampler channel:                                          pszResult = "DESCRIPTION: 'Number of JACK audio channels'\r\n"
214          // ADD CHANNEL                                                                  "TYPE: INT\r\n"
215          sprintf(szTemp, "OK[%d]", iChannel++);                                                                  "MANDATORY: TRUE\r\n"
216          pszResult = szTemp;                                                                  "FIX: TRUE\r\n"
217      }                                                                  "MULTIPLICITY: FALSE\r\n"
218      else if (lscp_parser_test2(&tok, "REMOVE", "CHANNEL")) {                                                                  "DEFAULT: 2\r\n"
219          // Removing a sampler channel:                                                                  ".\r\n";
220          // REMOVE CHANNEL <sampler-channel>                                  }
221      }                                  else if (lscp_parser_test(&tok, "samplerate")) {
222      else if (lscp_parser_test2(&tok, "RESET", "CHANNEL")) {                                          pszResult = "DESCRIPTION: 'JACK sample rate'\r\n"
223          // Resetting a sampler channel:                                                                  "TYPE: INT\r\n"
224          // RESET CHANNEL <sampler-channel>                                                                  "MANDATORY: TRUE\r\n"
225      }                                                                  "FIX: TRUE\r\n"
226      else if (lscp_parser_test2(&tok, "SUBSCRIBE", "NOTIFICATION")) {                                                                  "MULTIPLICITY: TRUE\r\n"
227          // Register frontend for receiving UDP event messages:                                                                  "DEFAULT: 44100\r\n"
228          // SUBSCRIBE NOTIFICATION <udp-port>                                                                  "POSSIBILITIES: 44100,48000,96000\r\n"
229          ret = lscp_server_subscribe(pConnect, lscp_parser_nextint(&tok));                                                                  ".\r\n";
230      }                                  }
231      else if (lscp_parser_test2(&tok, "UNSUBSCRIBE", "NOTIFICATION")) {                                  else ret = LSCP_FAILED;
232          // Deregister frontend for not receiving UDP event messages anymore:                          }
233          // UNSUBSCRIBE NOTIFICATION <session-id>                          else ret = LSCP_FAILED;
234          ret = lscp_server_unsubscribe(pConnect, lscp_parser_next(&tok));                  }
235      }                  else if (lscp_parser_test2(&tok, "MIDI_INPUT_DRIVER_PARAMETER", "INFO")) {
236      else if (lscp_parser_test(&tok, "QUIT")) {                          // Getting informations about a specific MIDI input driver parameter.
237          // Close client connection:                          // GET MIDI_INPUT_DRIVER_PARAMETER INFO <midi-input-type> <param>
238          // QUIT                          if (lscp_parser_test(&tok, "Alsa")) {
239          lscp_parser_free(&tok);                                  if (lscp_parser_test(&tok, "active")) {
240          return LSCP_FAILED; // Disconnect.                                          pszResult = "DESCRIPTION: 'ALSA Sequencer device active state'\r\n"
241      }                                                                  "TYPE: BOOL\r\n"
242      else ret = LSCP_FAILED;                                                                  "MANDATORY: TRUE\r\n"
243                                                                    "FIX: TRUE\r\n"
244                                                                    "MULTIPLICITY: FALSE\r\n"
245                                                                    "DEPENDS: channels,ports\r\n"
246                                                                    "DEFAULT: TRUE\r\n"
247                                                                    "RANGE_MIN: FALSE\r\n"
248                                                                    "RANGE_MAX: TRUE\r\n"
249                                                                    "POSSIBILITIES: FALSE,TRUE\r\n"
250                                                                    ".\r\n";
251                                    }
252                                    else if (lscp_parser_test(&tok, "ports")) {
253                                            pszResult = "DESCRIPTION: 'Number of ALSA Sequencer ports'\r\n"
254                                                                    "TYPE: INT\r\n"
255                                                                    "MANDATORY: FALSE\r\n"
256                                                                    "FIX: FALSE\r\n"
257                                                                    "MULTIPLICITY: FALSE\r\n"
258                                                                    "DEFAULT: 1\r\n"
259                                                                    "RANGE_MIN: 1\r\n"
260                                                                    "RANGE_MAX: 4\r\n"
261                                                                    ".\r\n";
262                                    }
263                                    else ret = LSCP_FAILED;
264                            }
265                            else ret = LSCP_FAILED;
266                    }
267                    else if (lscp_parser_test2(&tok, "AUDIO_OUTPUT_DEVICE", "INFO")) {
268                            // Getting informations about a specific audio output device.
269                            // GET AUDIO_OUTPUT_DEVICE INFO <audio-device-id>
270                            if (lscp_parser_nextint(&tok) < iAudioDevice) {
271                                    pszResult = "driver: Alsa\r\n"
272                                                            "active: TRUE\r\n"
273                                                            "channels: 2\r\n"
274                                                            "samplerate: 44100\r\n"
275                                                            ".\r\n";
276                            }
277                            else ret = LSCP_FAILED;
278                    }
279                    else if (lscp_parser_test2(&tok, "MIDI_INPUT_DEVICE", "INFO")) {
280                            // Getting informations about a specific MIDI input device.
281                            // GET MIDI_INPUT_DEVICE INFO <midi-device-id>
282                            if (lscp_parser_nextint(&tok) < iMidiDevice) {
283                                    pszResult = "driver: Alsa\r\n"
284                                                            "active: TRUE\r\n"
285                                                            "channels: 16\r\n"
286                                                            "ports: 1\r\n"
287                                                            ".\r\n";
288                            }
289                            else ret = LSCP_FAILED;
290                    }
291                    else if (lscp_parser_test2(&tok, "AUDIO_OUTPUT_CHANNEL", "INFO")) {
292                            // Getting informations about an audio channel.
293                            // GET AUDIO_OUTPUT_CHANNEL INFO <audio-device-id> <audio-channel>
294                            if (lscp_parser_nextint(&tok) < iAudioDevice) {
295                                    pszResult = "name: DummyMonitor\r\n"
296                                                            "is_mix_channel: FALSE\r\n"
297                                                            "mix_channel_destination: 0\r\n"
298                                                            ".\r\n";
299                            }
300                            else ret = LSCP_FAILED;
301                    }
302                    else if (lscp_parser_test2(&tok, "MIDI_INPUT_PORT", "INFO")) {
303                            // Getting informations about a MIDI port.
304                            // GET MIDI_INPUT_PORT INFO <midi-device-id> <midi-port>
305                            if (lscp_parser_nextint(&tok) < iMidiDevice) {
306                                    pszResult = "name: DummyKeyboard\r\n"
307                                                            "alsa_seq_bindings: '64:0'\r\n"
308                                                            ".\r\n";
309                            }
310                            else ret = LSCP_FAILED;
311                    }
312                    else if (lscp_parser_test2(&tok, "AUDIO_OUTPUT_CHANNEL_PARAMETER", "INFO")) {
313                            // Getting informations about specific audio channel parameter.
314                            // GET AUDIO_OUTPUT_CHANNEL_PARAMETER INFO <audio-device-id> <audio-channel> <param>
315                            if (lscp_parser_nextint(&tok) < iAudioDevice) {
316                                    lscp_parser_nextint(&tok);
317                                    if (lscp_parser_test(&tok, "is_mix_channel")) {
318                                            pszResult = "DESCRIPTION: 'Whether this is an audio mix channel'\r\n"
319                                                                    "TYPE: BOOL\r\n"
320                                                                    "MANDATORY: TRUE\r\n"
321                                                                    "FIX: FALSE\r\n"
322                                                                    "MULTIPLICITY: FALSE\r\n"
323                                                                    "POSSIBILITIES: FALSE,TRUE\r\n"
324                                                                    ".\r\n";
325                                    }
326                                    else if (lscp_parser_test(&tok, "mix_channel_destination")) {
327                                            pszResult = "DESCRIPTION: 'Audio mix channel destination'\r\n"
328                                                                    "TYPE: INT\r\n"
329                                                                    "MANDATORY: TRUE\r\n"
330                                                                    "FIX: FALSE\r\n"
331                                                                    "MULTIPLICITY: TRUE\r\n"
332                                                                    "POSSIBILITIES: 0,1\r\n"
333                                                                    ".\r\n";
334                                    }
335                                    else ret = LSCP_FAILED;
336                            }
337                            else ret = LSCP_FAILED;
338                    }
339                    else if (lscp_parser_test2(&tok, "MIDI_INPUT_PORT_PARAMETER", "INFO")) {
340                            // Getting informations about specific MIDI port parameter.
341                            // GET MIDI_INPUT_PORT_PARAMETER INFO <midi-device-id> <midi-port> <param>
342                            if (lscp_parser_nextint(&tok) < iMidiDevice) {
343                                    lscp_parser_nextint(&tok);
344                                    if (lscp_parser_test(&tok, "alsa_seq_bindings")) {
345                                            pszResult = "DESCRIPTION: 'Alsa sequencer port bindings'\r\n"
346                                                                    "TYPE: STRING\r\n"
347                                                                    "MANDATORY: TRUE\r\n"
348                                                                    "FIX: FALSE\r\n"
349                                                                    "MULTIPLICITY: TRUE\r\n"
350                                                                    "POSSIBILITIES: '64:0','68:0','68:1'\r\n"
351                                                                    ".\r\n";
352                                    }
353                                    else ret = LSCP_FAILED;
354                            }
355                            else ret = LSCP_FAILED;
356                    }
357                    else if (lscp_parser_test(&tok, "AUDIO_OUTPUT_DEVICES")) {
358                            // Getting all created audio output device count.
359                            // GET AUDIO_OUTPUT_DEVICES
360                            sprintf(szTemp, "%d\r\n", iAudioDevice);
361                            pszResult = szTemp;
362                    }
363                    else if (lscp_parser_test(&tok, "MIDI_INPUT_DEVICES")) {
364                            // Getting all created MID input device count.
365                            // GET MIDI_INPUT_DEVICES
366                            sprintf(szTemp, "%d\r\n", iMidiDevice);
367                            pszResult = szTemp;
368                    }
369                    else if (lscp_parser_test(&tok, "AVAILABLE_ENGINES")) {
370                            // Getting all available engine count:
371                            // GET AVAILABLE_ENGINES
372                            pszResult = "3\r\n";
373                    }
374                    else if (lscp_parser_test2(&tok, "SERVER", "INFO")) {
375                            // Getting information about the server.
376                            // GET SERVER INFO
377                            sprintf(szTemp, "DESCRIPTION: example_server (%s) %s\r\n"
378                                    "VERSION: %s\r\n.\r\n", lscp_server_package(),
379                                    lscp_server_build(), lscp_server_version());
380                            pszResult = szTemp;
381                    }
382                    else if (lscp_parser_test2(&tok, "ENGINE", "INFO")) {
383                            // Getting information about an engine.
384                            // GET ENGINE INFO <engine-name>
385                            if (lscp_parser_test(&tok, "GigEngine")) {
386                                    pszResult = "DESCRIPTION: GigaSampler Engine\r\n"
387                                                            "VERSION: 0.3\r\n"
388                                                            ".\r\n";
389                            }
390                            else if (lscp_parser_test(&tok, "DLSEngine")) {
391                                    pszResult = "DESCRIPTION: 'DLS Generic Engine'\r\n"
392                                                            "VERSION: 0.2\r\n"
393                                                            ".\r\n";
394                            }
395                            else if (lscp_parser_test(&tok, "AkaiEngine")) {
396                                    pszResult = "DESCRIPTION: Akai Sampler Engine\r\n"
397                                                            "VERSION: 0.1\r\n"
398                                                            ".\r\n";
399                            }
400                            else ret = LSCP_FAILED;
401                    }
402                    else if (lscp_parser_test(&tok, "TOTAL_VOICE_COUNT")) {
403                            // Current number of active voices:
404                            // GET TOTAL_VOICE_COUNT
405                            sprintf(szTemp, "%d\r\n", rand() % 100);
406                            pszResult = szTemp;
407                    }
408                    else if (lscp_parser_test(&tok, "TOTAL_VOICE_COUNT_MAX")) {
409                            // Maximum amount of active voices:
410                            // GET TOTAL_VOICE_COUNT_MAX
411                            sprintf(szTemp, "%d\r\n", rand() % 100);
412                            pszResult = szTemp;
413                    }
414                    else if (lscp_parser_test(&tok, "MIDI_INSTRUMENTS")) {
415                            // Get the total count of MIDI instrument map entries:
416                            // GET MIDI_INSTRUMENTS
417                            sprintf(szTemp, "%d\r\n", iMidiInstruments);
418                            pszResult = szTemp;
419                    }
420                    if (lscp_parser_test2(&tok, "MIDI_INSTRUMENT", "INFO")) {
421                            // Getting information about a MIDI instrument map entry:
422                            // GET MIDI_INSTRUMENT INFO <midi-bank-msb> <midi-bank-lsb> <midi-prog>
423                            pszResult = "NAME: DummyName\r\n"
424                                                    "ENGINE_NAME: DummyEngine\r\n"
425                                                    "INSTRUMENT_FILE: DummyInstrument.gig\r\n"
426                                                    "INSTRUMENT_NR: 0\r\n"
427                                                    "INSTRUMENT_NAME: Dummy Instrument\r\n"
428                                                    "LOAD_MODE: ON_DEMAND\r\n"
429                                                    "VOLUME: 0.5\r\n"
430                                                    ".\r\n";
431                    }
432                    else ret = LSCP_FAILED;
433            }
434            else if (lscp_parser_test(&tok, "LIST")) {
435                    if (lscp_parser_test(&tok, "CHANNELS")) {
436                            // Getting all created sampler channel list.
437                            // LIST CHANNELS
438                            for (i = 0; i < iSamplerChannel && strlen(szTemp) < sizeof(szTemp) - 8; i++) {
439                                    if (i > 0)
440                                            strcat(szTemp, ",");
441                                    sprintf(szTemp + strlen(szTemp), "%d", i);
442                            }
443                            strcat(szTemp, "\r\n");
444                            pszResult = szTemp;
445                    }
446                    else if (lscp_parser_test(&tok, "AVAILABLE_ENGINES")) {
447                            // Getting all available engines:
448                            // LIST AVAILABLE_ENGINES
449                            pszResult = "GigEngine,DLSEngine,AkaiEngine\r\n";
450                    }
451                    else if (lscp_parser_test(&tok, "AVAILABLE_AUDIO_OUTPUT_DRIVERS")) {
452                            // Getting all available audio output drivers.
453                            // LIST AVAILABLE_AUDIO_OUTPUT_DRIVERS
454                            pszResult = "ALSA,JACK\r\n";
455                    }
456                    else if (lscp_parser_test(&tok, "AVAILABLE_MIDI_INPUT_DRIVERS")) {
457                            // Getting all available MIDI input drivers.
458                            // LIST AVAILABLE_MIDI_INPUT_DRIVERS
459                            pszResult = "ALSA\r\n";
460                    }
461                    else if (lscp_parser_test(&tok, "AUDIO_OUTPUT_DEVICES")) {
462                            // Getting all created audio output device list.
463                            // LIST AUDIO_OUTPUT_DEVICES
464                            for (i = 0; i < iAudioDevice && strlen(szTemp) < sizeof(szTemp) - 8; i++) {
465                                    if (i > 0)
466                                            strcat(szTemp, ",");
467                                    sprintf(szTemp + strlen(szTemp), "%d", i);
468                            }
469                            strcat(szTemp, "\r\n");
470                            pszResult = szTemp;
471                    }
472                    else if (lscp_parser_test(&tok, "MIDI_INPUT_DEVICES")) {
473                            // Getting all created MID input device list.
474                            // LIST MIDI_INPUT_DEVICES
475                            for (i = 0; i < iMidiDevice && strlen(szTemp) < sizeof(szTemp) - 8; i++) {
476                                    if (i > 0)
477                                            strcat(szTemp, ",");
478                                    sprintf(szTemp + strlen(szTemp), "%d", i);
479                            }
480                            strcat(szTemp, "\r\n");
481                            pszResult = szTemp;
482                    }
483                    else if (lscp_parser_test(&tok, "MIDI_INSTRUMENTS")) {
484                            // Getting indeces of all MIDI instrument map entries:
485                            // LIST MIDI_INSTRUMENTS
486                            for (i = 0; i < iMidiInstruments && strlen(szTemp) < sizeof(szTemp) - 16; i++) {
487                                    if (i > 0)
488                                            strcat(szTemp, ",");
489                                    sprintf(szTemp + strlen(szTemp), "{0,%d,%d}", i / 128, i % 128);
490                            }
491                            strcat(szTemp, "\r\n");
492                            pszResult = szTemp;
493                    }
494                    else ret = LSCP_FAILED;
495            }
496            else if (lscp_parser_test(&tok, "SET")) {
497                    if (lscp_parser_test(&tok, "CHANNEL")) {
498                            if (lscp_parser_test(&tok, "VOLUME")) {
499                                    // Setting channel volume:
500                                    // SET CHANNEL VOLUME <sampler-channel> <volume>
501                            }
502                            else if (lscp_parser_test(&tok, "MUTE")) {
503                                    // Muting a sampler channel:
504                                    // SET CHANNEL MUTE <sampler-channel> <mute>
505                            }
506                            else if (lscp_parser_test(&tok, "SOLO")) {
507                                    // Soloing a sampler channel:
508                                    // SET CHANNEL SOLO <sampler-channel> <solo>
509                            }
510                            else if (lscp_parser_test(&tok, "AUDIO_OUTPUT_TYPE")) {
511                                    // Setting audio output type:
512                                    // SET CHANNEL AUDIO_OUTPUT_TYPE <sampler-channel> <audio-output-type>
513                            }
514                            else if (lscp_parser_test(&tok, "AUDIO_OUTPUT_DEVICE")) {
515                                    // Setting audio output device:
516                                    // SET CHANNEL AUDIO_OUTPUT_DEVICE <sampler-channel> <device-id>
517                            }
518                            else if (lscp_parser_test(&tok, "AUDIO_OUTPUT_CHANNEL")) {
519                                    // Setting audio output channel:
520                                    // SET CHANNEL AUDIO_OUTPUT_CHANNEL <sampler-channel> <audio-in> <audio-out>
521                            }
522                            else if (lscp_parser_test(&tok, "MIDI_INPUT_TYPE")) {
523                                    // Setting MIDI input type:
524                                    // SET CHANNEL MIDI_INPUT_TYPE <sampler-channel> <midi-input-type>
525                            }
526                            else if (lscp_parser_test(&tok, "MIDI_INPUT_DEVICE")) {
527                                    // Setting MIDI input device:
528                                    // SET CHANNEL MIDI_INPUT_DEVICE <sampler-channel> <device-id>
529                            }
530                            else if (lscp_parser_test(&tok, "MIDI_INPUT_PORT")) {
531                                    // Setting MIDI input port:
532                                    // SET CHANNEL MIDI_INPUT_PORT <sampler-channel> <midi-input-port>
533                            }
534                            else if (lscp_parser_test(&tok, "MIDI_INPUT_CHANNEL")) {
535                                    // Setting MIDI input channel:
536                                    // SET CHANNEL MIDI_INPUT_CHANNEL <sampler-channel> <midi-input-chan>
537                            }
538                            else ret = LSCP_FAILED;
539                    }
540                    else ret = LSCP_FAILED;
541            }
542            else if (lscp_parser_test(&tok, "LOAD")) {
543                    if (lscp_parser_test(&tok, "ENGINE")) {
544                            // Loading a sampler engine:
545                            // LOAD ENGINE <engine-name> <sampler-channel>
546                    }
547                    else if (lscp_parser_test(&tok, "INSTRUMENT")) {
548                            // Loading an instrument:
549                            // LOAD INSTRUMENT [NON_MODAL] <filename> <instr-index> <sampler-channel>
550                    }
551                    else ret = LSCP_FAILED;
552            }
553            else if (lscp_parser_test2(&tok, "ADD", "CHANNEL")) {
554                    // Adding a new sampler channel:
555                    // ADD CHANNEL
556                    if (iSamplerChannel < 16) {
557                            sprintf(szTemp, "OK[%d]\r\n", iSamplerChannel++);
558                            pszResult = szTemp;
559                    } else {
560                            iSamplerChannel = 0;
561                            ret = LSCP_FAILED;
562                    }
563            }
564            else if (lscp_parser_test2(&tok, "REMOVE", "CHANNEL")) {
565                    // Removing a sampler channel:
566                    // REMOVE CHANNEL <sampler-channel>
567                    if (lscp_parser_nextint(&tok) < iSamplerChannel)
568                            iSamplerChannel--;
569                    else
570                            ret = LSCP_FAILED;
571            }
572            else if (lscp_parser_test(&tok, "RESET")) {
573                    if (lscp_parser_test(&tok, "CHANNEL")) {
574                            // Resetting a sampler channel:
575                            // RESET CHANNEL <sampler-channel>
576                            if (lscp_parser_nextint(&tok) > iSamplerChannel)
577                                    ret = LSCP_FAILED;
578                    } else {
579                            // Reset sampler:
580                            // RESET
581                            iSamplerChannel = 0;
582                            iAudioDevice = 0;
583                            iMidiDevice = 0;
584                    }
585            }
586            else if (lscp_parser_test(&tok, "CREATE")) {
587                    if (lscp_parser_test(&tok, "AUDIO_OUTPUT_DEVICE")) {
588                            // Creating an audio output device.
589                            // CREATE AUDIO_OUTPUT_DEVICE <audio-output-driver> [<params>]
590                            if (iAudioDevice < 8) {
591                                    sprintf(szTemp, "OK[%d]\r\n", iAudioDevice++);
592                                    pszResult = szTemp;
593                            } else {
594                                    iAudioDevice = 0;
595                                    ret = LSCP_FAILED;
596                            }
597                    }
598                    else if (lscp_parser_test(&tok, "MIDI_INPUT_DEVICE")) {
599                            // Creating an MIDI input device.
600                            // CREATE MIDI_INPUT_DEVICE <midi-input-driver> [<params>]
601                            if (iMidiDevice < 8) {
602                                    sprintf(szTemp, "OK[%d]\r\n", iMidiDevice++);
603                                    pszResult = szTemp;
604                            } else {
605                                    iMidiDevice = 0;
606                                    ret = LSCP_FAILED;
607                            }
608                    }
609                    else ret = LSCP_FAILED;
610            }
611            else if (lscp_parser_test(&tok, "DESTROY")) {
612                    if (lscp_parser_test(&tok, "AUDIO_OUTPUT_DEVICE")) {
613                            // Destroying an audio output device.
614                            // DESTROY AUDIO_OUTPUT_DEVICE <audio-device-id>
615                            if (lscp_parser_nextint(&tok) < iAudioDevice)
616                                    iAudioDevice--;
617                            else
618                                    ret = LSCP_FAILED;
619                    }
620                    else if (lscp_parser_test(&tok, "MIDI_INPUT_DEVICE")) {
621                            // Destroying an MIDI intput device.
622                            // DESTROY MIDI_INPUT_DEVICE <midi-device-id>
623                            if (lscp_parser_nextint(&tok) < iMidiDevice)
624                                    iMidiDevice--;
625                            else
626                                    ret = LSCP_FAILED;
627                    }
628                    else ret = LSCP_FAILED;
629            }
630            else if (lscp_parser_test2(&tok, "MAP", "MIDI_INSTRUMENT")) {
631                    // Create or replace a MIDI instrumnet map entry:
632                    // MAP MIDI_INSTRUMENT <midi-bank-msb> <midi-bank-lsb> <midi-prog>
633                    // <engine-name> <filename> <instr-index> <volume> <load-mode> [<name>]
634                    iMidiInstruments++;
635            }
636            else if (lscp_parser_test2(&tok, "UNMAP", "MIDI_INSTRUMENT")) {
637                    // Remove an entry from the MIDI instrument map:
638                    // UNMAP MIDI_INSTRUMENT <midi-bank-msb> <midi-bank-lsb> <midi-prog>
639                    if (iMidiInstruments > 0)
640                            iMidiInstruments--;
641                    else
642                            ret = LSCP_FAILED;
643            }
644            else if (lscp_parser_test2(&tok, "CLEAR", "MIDI_INSTRUMENTS")) {
645                    // Clear the MIDI instrumnet map:
646                    // CLEAR MIDI_INSTRUMENTS
647            }
648            else if (lscp_parser_test(&tok, "SUBSCRIBE")) {
649                    // Register frontend for receiving event notification messages:
650                    // SUBSCRIBE <event>
651                    ret = lscp_server_subscribe(pConnect, lscp_event_from_text(lscp_parser_next(&tok)));
652            }
653            else if (lscp_parser_test(&tok, "UNSUBSCRIBE")) {
654                    // Deregister frontend for not receiving event notification messages anymore:
655                    // UNSUBSCRIBE <event>
656                    ret = lscp_server_unsubscribe(pConnect, lscp_event_from_text(lscp_parser_next(&tok)));
657            }
658            else if (lscp_parser_test(&tok, "QUIT")) {
659                    // Close client connection:
660                    // QUIT
661                    lscp_parser_free(&tok);
662                    return LSCP_FAILED; // Disconnect.
663            }
664            else ret = LSCP_FAILED;
665    
666      lscp_parser_free(&tok);          lscp_parser_free(&tok);
667    
668      if (pszResult == NULL)          if (pszResult == NULL)
669          pszResult = (ret == LSCP_OK ? "OK\r\n" : "ERR:1:Failed\r\n");                  pszResult = (ret == LSCP_OK ? "OK\r\n" : "ERR:1:Failed\r\n");
670    
671      fprintf(stderr, "> %s", pszResult);          fprintf(stderr, "> %s", pszResult);
672    
673      return lscp_server_result(pConnect, pszResult, strlen(pszResult));          return lscp_server_result(pConnect, pszResult, strlen(pszResult));
674  }  }
675    
676  ////////////////////////////////////////////////////////////////////////  ////////////////////////////////////////////////////////////////////////
677    
678    
679  void server_usage (void)  void server_usage (void)
680  {  {
681      printf("\n  %s %s (Build: %s)\n", lscp_server_package(), lscp_server_version(), lscp_server_build());          printf("\n  %s %s (Build: %s)\n", lscp_server_package(), lscp_server_version(), lscp_server_build());
682    
683      fputs("\n  Available server commands: help, exit, quit, list", stdout);          fputs("\n  Available server commands: help, exit, quit, list", stdout);
684      fputs("\n  (all else are broadcast verbatim to subscribers)\n\n", stdout);          fputs("\n  (all else are broadcast verbatim to subscribers)\n\n", stdout);
685  }  }
686    
687  void server_prompt (void)  void server_prompt (void)
688  {  {
689      fputs("lscp_server> ", stdout);          fputs("lscp_server> ", stdout);
690  }  }
691    
692  int main (int argc, char *argv[] )  int main (int argc, char *argv[] )
693  {  {
694      lscp_server_t *pServer;          lscp_server_t *pServer;
695      char szLine[200];          char szLine[200];
696      int cchLine;          int cchLine;
697      lscp_connect_t *p;          lscp_connect_t *p;
698    
699  #if defined(WIN32)  #if defined(WIN32)
700      if (WSAStartup(MAKEWORD(1, 1), &_wsaData) != 0) {          if (WSAStartup(MAKEWORD(1, 1), &_wsaData) != 0) {
701          fprintf(stderr, "lscp_server: WSAStartup failed.\n");                  fprintf(stderr, "lscp_server: WSAStartup failed.\n");
702          return -1;                  return -1;
703      }          }
704  #endif  #endif
705    
706      srand(time(NULL));          srand(time(NULL));
707    
708      pServer = lscp_server_create(SERVER_PORT, server_callback, NULL);          pServer = lscp_server_create(SERVER_PORT, server_callback, NULL);
709      if (pServer == NULL)          if (pServer == NULL)
710          return -1;                  return -1;
711    
712      server_usage();          server_usage();
713      server_prompt();          server_prompt();
714    
715      while (fgets(szLine, sizeof(szLine), stdin)) {          while (fgets(szLine, sizeof(szLine), stdin)) {
716    
717          cchLine = strlen(szLine);                  cchLine = strlen(szLine);
718          while (cchLine > 0 && (szLine[cchLine - 1] == '\n' || szLine[cchLine - 1] == '\r'))                  while (cchLine > 0 && (szLine[cchLine - 1] == '\n' || szLine[cchLine - 1] == '\r'))
719              cchLine--;                          cchLine--;
720          szLine[cchLine] = '\0';                  szLine[cchLine] = '\0';
721    
722          if (strcmp(szLine, "exit") == 0 || strcmp(szLine, "quit") == 0)                  if (strcmp(szLine, "exit") == 0 || strcmp(szLine, "quit") == 0)
723              break;                          break;
724          else                  else
725          if (strcmp(szLine, "list") == 0) {                  if (strcmp(szLine, "list") == 0) {
726              for (p = pServer->connects.first; p; p = p->next) {                          for (p = pServer->connects.first; p; p = p->next) {
727                  printf("client: sock=%d addr=%s tcp.port=%d udp.port=%d ping=%d sessid=%s.\n",                                  printf("client: sock=%d addr=%s port=%d events=0x%04x.\n",
728                      p->client.sock,                                          p->client.sock,
729                      inet_ntoa(p->client.addr.sin_addr),                                          inet_ntoa(p->client.addr.sin_addr),
730                      ntohs(p->client.addr.sin_port),                                          ntohs(p->client.addr.sin_port),
731                      p->port,                                          (int) p->events
732                      p->ping,                                  );
733                      p->sessid                          }
734                  );                  }
735              }                  else
736          }                  if (cchLine > 0 && strcmp(szLine, "help") != 0)
737          else                          lscp_server_broadcast(pServer, LSCP_EVENT_MISCELLANEOUS, szLine, strlen(szLine));
738          if (cchLine > 0 && strcmp(szLine, "help") != 0)                  else
739              lscp_server_broadcast(pServer, szLine, strlen(szLine));                          server_usage();
         else  
             server_usage();  
740    
741          server_prompt();                  server_prompt();
742      }          }
743    
744      lscp_server_destroy(pServer);          lscp_server_destroy(pServer);
745    
746  #if defined(WIN32)  #if defined(WIN32)
747      WSACleanup();          WSACleanup();
748  #endif  #endif
749    
750      return 0;          return 0;
751  }  }
752    
753  // end of example_server.c  // end of example_server.c

Legend:
Removed from v.105  
changed lines
  Added in v.963

  ViewVC Help
Powered by ViewVC