int Xcparse(char* buf, char* input) { int start_comma, end_comma, txt_start, i, k, input_len; char input_line[512], ccase, ccend; union littlebig { char c1[4]; int i1; float f1; } endian; // make a local copy of the input string as we'll modify some characters during parsing. strcpy(input_line, input); start_comma = 0; input_len = strlen(input_line); // jump to next comma, and replace spaces by 0, prior to comma for (i = 0; i < input_len; i++) { if (input_line[i] == SPACE) input_line[i] = 0; if (input_line[i] == COMMA) { start_comma = i; break; } } // Prepare first command block i = 0; i = Xsprint(buf, i, 's', input_line); if (start_comma) { // Set command (",s|i|f" is present) // look for end of formatters (s,i,f) k = start_comma + 1; while ((k < input_len) && ((input_line[k] == 's') || (input_line[k] == 'i') || (input_line[k] == 'f'))) k++; // Prepare command formatters' block input_line[k] = 0; i = Xsprint(buf, i, 's', input_line+start_comma); // k points to first value of data block (text, int or float) // process formatters (between start_comma and end_comma) to parse blocks start_comma += 1; // skip the formatters' leading comma end_comma = k; // last identified formatter // manage blocks according to formatters while (start_comma < end_comma) { // ignore spaces before new block (text, int or float) k += 1; while ((k < input_len) && (input_line[k] == SPACE)) k++; ccase = input_line[start_comma++]; // ignore white spaces out of quotes (single or double) switch (ccase) { case 's': // change next SPACE char to \0 to mark end of string // if the string must have spaces in it, it should start with " or '; "" can be used // in the string to depict an empty substring (String must start with a ' in that case). // String delimiters must be the same (" or '). txt_start = k; if ((input_line[k] == QUOTE) || (input_line[k] == SQUOTE)) { ccend = input_line[k]; k += 1; txt_start += 1; while ((k < input_len) && (input_line[k] != ccend)) k++; } else { while ((k < input_len) && (input_line[k] != SPACE)) k++; } input_line[k] = 0; i = Xsprint(buf, i, 's', input_line+txt_start); break; case 'i': // read integer and move pointer k to the end of the data just read sscanf(input_line+k, "%d", &endian.i1); i = Xsprint(buf, i, 'i', endian.c1); while ((k < input_len) && (input_line[k] != SPACE)) k++; break; case 'f': // read float and move pointer k to the end of the data just read sscanf(input_line+k, "%f", &endian.f1); i = Xsprint(buf, i, 'f', endian.c1); while ((k < input_len) && (input_line[k] != SPACE)) k++; break; default: break; } } } return i; }
int main(int argc, char **argv) { struct sockaddr_in Xip; struct sockaddr* Xip_addr = (struct sockaddr *)&Xip; int Xfd; // our socket char Xip_str[20], Xport_str[8]; int r_len, s_len, p_status; char r_buf[BSIZE]; char s_buf[BSIZE]; // int xremote_on; char xremote[12] = "/xremote"; // automatic trailing zeroes int l_index; char input_line[LINEMAX + 4]; int input_intch; // addresses limitations in certain C compilers wit getopt() int keep_on, do_keyboard, s_delay, filein; FILE* fdk = NULL; time_t before, now; // fd_set ufds; struct timeval timeout; // #ifdef __WIN32__ WSADATA wsa; int Xip_len = sizeof(Xip); // length of addresses unsigned long mode; #else socklen_t Xip_len = sizeof(Xip); // length of addresses #endif // // Initialize communication with XR server at IP ip and PORT port // Set default values to match your XR desk strcpy (Xip_str, "192.168.0.64"); strcpy (Xport_str, "10024"); // // Manage arguments filein = 0; do_keyboard = 1; s_delay = 10; // Removed "s" option as it's not support by XAir series // while ((input_intch = getopt(argc, argv, "i:d:k:f:s:t:v:h")) != -1) { while ((input_intch = getopt(argc, argv, "i:d:k:f:t:v:h")) != -1) { switch (input_intch) { case 'i': strcpy(Xip_str, optarg ); break; case 'd': sscanf(optarg, "%d", &X32debug); break; case 'f': filein = 1; sscanf(optarg, "%s", input_line); break; case 'k': sscanf(optarg, "%d", &do_keyboard); break; // case 's': // filein = 2; // sscanf(optarg, "%s", input_line); // break; case 't': sscanf(optarg, "%d", &s_delay); break; case 'v': sscanf(optarg, "%d", &X32verbose); break; default: case 'h': printf("usage: XAir_Command [-i X32 console ipv4 address]\n"); printf(" [-d 0/1, [0], debug option]\n"); printf(" [-v 0/1 [1], verbose option]\n"); printf(" [-k 0/1 [1], keyboard mode on]\n"); printf(" [-t int [10], delay between batch commands in ms]\n"); // printf(" [-s file, reads X32node formatted data lines from 'file']\n"); printf(" [-f file, sets batch mode on, getting input data from 'file']\n"); printf(" default IP is 192.168.0.64\n\n"); // printf(" If option -s file is used, the program reads data from the provided file \n"); // printf(" until EOF has been reached, and exits after that.\n\n"); printf(" If option -f file is used, the program runs in batch mode, taking data from\n"); printf(" the provided file until EOF has been reached, or 'exit' or 'kill' entered.\n\n"); printf(" If not killed or no -f option, the program runs in standard mode, taking data\n"); printf(" from the keyboard or <stdin> on linux systems.\n"); printf(" While executing, the following commands can be used:\n"); printf(" '#line of text.....': will print out the input line as a comment line\n"); printf(" 'exit' | 'quit': will quit the current mode\n"); printf(" 'kill': [batch mode only] will exit the progam\n"); printf(" 'time <value>': will change the delay between batch commands to <value>\n"); printf(" 'verbose <on|off>': will change the verbose mode\n"); printf(" 'verbose': will return the current verbose mode\n"); printf(" 'xremote <on|off>': will change the xremote mode\n"); printf(" 'xremote': will return the current xremote mode\n"); printf(" '' (empty line) [standard mode only]: will repeat the last entered command\n\n"); printf(" All other commands are parsed and sent to XR18.\n"); printf(" Typical XR18 command structure:\n"); printf(" <command> [<format> [<data> [<data> [...]]]], where for example:\n"); printf(" command: /info, /status, /ch/00/mix/fader, ...\n"); printf(" format: ',i' ',f' ',s' or a combination: ',siss' ',ffiss' ...\n"); printf(" data: a list of int, float or string types separated by a space char...\n\n"); return(0); break; } } #ifdef __WIN32__ //Initialize winsock if (WSAStartup (MAKEWORD( 2, 2), &wsa) != 0) { printf ("Failed. Error Code : %d", WSAGetLastError()); exit (EXIT_FAILURE); } #endif // // Load the XR18 address we connect to; we're a client to XR18, keep it simple. // Create UDP socket if ((Xfd = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { perror ("failed to create XR18 socket"); exit (EXIT_FAILURE); } // Construct server sockaddr_in structure memset (&Xip, 0, sizeof(Xip)); // Clear struct Xip.sin_family = AF_INET; // Internet/IP Xip.sin_addr.s_addr = inet_addr(Xip_str); // IP address Xip.sin_port = htons(atoi(Xport_str)); // server port/ // // Set receiving from XR18 to non blocking mode // The 500ms timeout is used for delaying the printing of '.' at startup. timeout.tv_sec = 0; timeout.tv_usec = 500000; //Set timeout for non blocking recvfrom(): 500ms FD_ZERO(&ufds); FD_SET(Xfd, &ufds); // make stdin (fd = 0) I/O nonblocking #ifdef __WIN32__ mode = 1; p_status = ioctlsocket(0, FIONBIO, &mode); #else fcntl(0, F_SETFL, fcntl(0, F_GETFL, 0) | O_NONBLOCK); #endif // // All done. Let's send and receive messages // Establish logical connection with XR18 server printf(" XAir_Command - v1.39 - (c)2014-18 Patrick-Gilles Maillot\n\nConnecting to XR18."); // keep_on = 1; xremote_on = X32verbose; // Momentarily save X32verbose X32verbose = 0; s_len = Xsprint(s_buf, 0, 's', "/xinfo"); while (keep_on) { SEND // command /info sent; RPOLL // read data if available if (p_status < 0) { printf("Polling for data failed\n"); return 1; // exit on receive error } else if (p_status > 0) { RECV // We have received data - process it! if (strcmp(r_buf, "/xinfo") == 0) break; // Connected! } // ... else timeout printf("."); fflush(stdout); }
int main(int argc, char **argv) { int i, k, read_status; char l_read[128], c; struct sockaddr_in Xip; int fd; // our socket int recvlen, sendlen; char b_rec[BSIZE], Xip_str[20], Xport_str[8]; char b_snd[BSIZE]; // #ifdef __WIN32__ WSADATA wsa; int Xip_len = sizeof(Xip); // length of addresses #else socklen_t Xip_len = sizeof(Xip); // length of addresses #endif struct timeval timeout; fd_set ufds; // // initialize communication with X32 server at IP ip and PORT port // set a default value for server[]; change to match your X32 desk strcpy (Xip_str, "192.168.0.64"); // port[] = "10023" //change to use a different port strcpy (Xport_str, "10023"); // // Manage arguments recvlen = sendlen = 0; while ((c = getopt(argc, argv, "i:s:n:h")) != (char)-1) { switch (c) { case 'i': strcpy(Xip_str, optarg ); break; case 's': strcpy(b_rec, optarg ); recvlen = 1; break; case 'n': strcpy(b_snd, optarg ); sendlen = 1; break; default: case 'h': printf("usage: X32GetScene [-i X32 console ipv4 address] [-s scene name][-n note\n"); printf(" default IP is 192.168.0.64\n"); printf("reads from <stdin> scene IDs to request to X32\n"); printf("writes to <stdout> scene IDs and parameters in readable format (identical to *.scn)\n\n"); return(0); break; } } #ifdef __WIN32__ //Initialize winsock if (WSAStartup(MAKEWORD(2,2),&wsa) != 0) { printf("Failed. Error Code : %d", WSAGetLastError()); exit(EXIT_FAILURE); } #endif // Load the X32 address we connect to; we're a client to X32, keep it simple. // Open a UDP socket if ((fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { perror("failed to create X32 socket"); return(-1); } // // Construct the server sockaddr_in structure memset(&Xip, 0, sizeof(Xip)); // Clear struct Xip.sin_family = AF_INET; // Internet/IP Xip.sin_addr.s_addr = inet_addr(Xip_str); // IP address Xip.sin_port = htons(atoi(Xport_str)); // server port // // Non blocking mode timeout.tv_sec = 0; timeout.tv_usec = 100000; //Set timeout for non blocking recvfrom(): 100ms // // All done. Let's send and receive messages // Establish logical connection with X32 server // // Print header if (!recvlen) { printf ("Please enter scene name: "); scanf ("%s", b_rec); } if (!sendlen) { printf ("Please enter note data: "); scanf ("%s", b_snd); } printf ("#2.1# \"%s\" \"%s\" %%000000000 1 X32GetScene V1.4 (c)2014 Patrick-Gilles Maillot\n\n", b_rec, b_snd); // Open file to interpret from stdin k = Xsprint (b_snd, 0, 's', "/node"); k = Xsprint (b_snd, k, 's', ",s"); while ((read_status = scanf("%s", l_read)) != EOF) { if (l_read[0] == '/') { sendlen = Xsprint(b_snd, k, 's', l_read + 1 ); if (sendto(fd, b_snd, sendlen, 0, (struct sockaddr *)&Xip, Xip_len) < 0) { perror("coundn't send data with sendto"); return (-1); } FD_ZERO (&ufds); FD_SET (fd, &ufds); i = select(fd+1, &ufds, NULL, NULL, &timeout); if (i > 0) { recvlen = recvfrom(fd, b_rec, BSIZE, 0, (struct sockaddr *)&Xip, &Xip_len); if (recvlen > 0) { i = 0; while((b_rec[i] != '/') && (i < recvlen)) i++; // print reply to stdout (or attached file); comes with trailing \a and no \0 chars printf("%s", b_rec + i); fflush (stdout); // make sure all data is printed out } } } else { // Decide here if we want to do anything with other command (comments for example) // Normal commands parameters should be discarded if (strcmp(l_read, "exit") == 0) break; } } fflush (stdout); // make sure all data is printed out #ifdef __WIN32__ WSACleanup(); #endif return(0); }