/** * read the specified number of bytes from the socket */ int net_read(socket_t s, char *buf, int size) { fd_set readfds; struct timeval tv; int rv; // clear the set FD_ZERO(&readfds); while (1) { FD_SET(s, &readfds); tv.tv_sec = 0; tv.tv_usec = BLOCK_INTERVAL; rv = select(s + 1, &readfds, NULL, NULL, &tv); if (rv == -1) { // an error occured return 0; } else if (rv == 0) { // timeout occured if (0 != dev_events(0)) { s = 0; break; } } else { // ready to read return recv(s, buf, size, 0); } } return 0; }
/** * read a string from a socket until a char from delim str found. */ int net_input(socket_t s, char *buf, int size, const char *delim) { // wait for remote input without eating cpu fd_set readfds; struct timeval tv; char ch; int count = 0; // clear the set FD_ZERO(&readfds); while (1) { tv.tv_sec = 0; tv.tv_usec = BLOCK_INTERVAL; // time is reset in select() call in linux FD_SET(s, &readfds); int rv = select(s + 1, &readfds, NULL, NULL, &tv); if (rv == -1) { return 0; // an error occured } else if (rv == 0) { // timeout occured - check for program break if (0 != dev_events(0)) { return 0; } } else if (FD_ISSET(s, &readfds)) { // ready for reading break; } } FD_ZERO(&readfds); memset(buf, 0, size); while (count < size) { int bytes = net_read(s, &ch, 1); if (bytes <= 0) { return count; // no more data } else { if (ch == 0) { return count; } if (delim) { if ((strchr(delim, ch) != NULL)) { return count; // delimiter found } } if (ch != '\015') { // ignore it buf[count] = ch; count += bytes; // actually ++ } } } return count; }
/** * listen for an incoming connection on the given port and * returns the socket once a connection has been established */ socket_t net_listen(int server_port) { int listener; struct sockaddr_in addr, remoteaddr; socket_t s; fd_set readfds; struct timeval tv; int rv; int yes = 1; // more info about listen sockets: // http://beej.us/guide/bgnet/output/htmlsingle/bgnet.html#acceptman net_init(); listener = socket(PF_INET, SOCK_STREAM, 0); if (listener <= 0) { return listener; } addr.sin_family = AF_INET; addr.sin_port = htons(server_port); // clients connect to this port addr.sin_addr.s_addr = INADDR_ANY; // autoselect IP address // prevent address already in use bind errors if (setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, (const char*)&yes, sizeof(int)) == -1) { return -1; } // set s up to be a server (listening) socket if (bind(listener, (struct sockaddr *)&addr, sizeof(addr)) == -1) { return -1; } if (listen(listener, 1) == -1) { return -1; } // clear the set FD_ZERO(&readfds); while (1) { tv.tv_sec = 0; // block at 1 second intervals tv.tv_usec = 500000; // time is reset in select() call in linux FD_SET(listener, &readfds); rv = select(listener + 1, &readfds, NULL, NULL, &tv); if (rv == -1) { s = 0; break; // an error occured } else if (rv == 0) { // timeout occured - check for program break if (0 != dev_events(0)) { s = 0; break; } } else if (FD_ISSET(listener, &readfds)) { // connection is ready #if defined(_Win32) int remoteaddr_len = sizeof(remoteaddr); #else socklen_t remoteaddr_len = sizeof(remoteaddr); #endif s = accept(listener, (struct sockaddr *)&remoteaddr, &remoteaddr_len); break; } } FD_ZERO(&readfds); net_disconnect(listener); return s; }
void cmd_play() { char *p; var_t var; int n = 0; int calc_time_f = 1; char *str, *s; double TmpL; par_getstr(&var); if (prog_error) { return; } if (strncmp("file://", var.v.p.ptr, FILE_PREFIX_LEN) == 0) { const char *path = var.v.p.ptr + FILE_PREFIX_LEN; if (dev_fexists(path)) { dev_audio(path); } else { err_file_not_found(); } v_free(&var); return; } str = (char *) malloc(var.v.p.length + 1); // copy without spaces p = (char *) var.v.p.ptr; s = str; while (*p) { if (*p > 32) { *s++ = to_upper(*p); } p++; } *s = '\0'; v_free(&var); // run p = str; while (*p) { if (dev_events(0) < 0) { break; } if (calc_time_f) { period = (4.0 / L) * (60000 / T) * TM; duration = M * period; calc_time_f = 0; } switch (*p) { // Volume case 'V': n = 0; while (is_digit(*(p + 1))) { p++; n = (n * 10) + (*p - '0'); } CPLERR((n < 0 || n > 100), "PLAY: V0-100"); vol = n; break; // clear queue case 'Q': dev_clear_sound_queue(); break; // Octaves case '<': if (O > 0) O--; break; case '>': if (O < 6) O++; break; case 'O': O = -1; if (is_digit(*(p + 1))) { p++; O = *p - '0'; } CPLERR((O < 0 || O > 6), "PLAY: O0-6"); break; // Time case 'L': n = 0; while (is_digit(*(p + 1))) { p++; n = (n * 10) + (*p - '0'); } CPLERR((n < 1 || n > 64), "PLAY: L1-64"); L = n; calc_time_f = 1; break; case 'T': n = 0; while (is_digit(*(p + 1))) { p++; n = (n * 10) + (*p - '0'); } CPLERR((n < 45 || n > 255), "PLAY: T32-255"); T = n; calc_time_f = 1; break; case 'M': p++; switch (*p) { case 'S': M = 0.5; break; case 'N': M = 3.0 / 4.0; break; case 'L': M = 1.0; break; case 'F': bg = 0; break; case 'B': bg = 1; break; default: rt_raise("PLAY: M%c UNSUPPORTED", *p); v_free(&var); } calc_time_f = 1; break; // Pause case 'P': n = 0; while (is_digit(*(p + 1))) { p++; n = (n * 10) + (*p - '0'); } if (*(p + 1) == '.') { p++; TM = 1.5; } else { TM = 1.0; } CPLERR((n < 1 || n > 64), "PLAY: P1-64"); period = (4.0 / n) * (60000 / T) * TM; dev_sound(0, period, vol, bg); calc_time_f = 1; break; // Play N case 'N': n = 0; while (is_digit(*(p + 1))) { p++; n = (n * 10) + (*p - '0'); } CPLERR((n < 0 || n > 84), "PLAY: N0-84"); if (n) { // oct = n / 12; // pitch = tones[n - oct * 12] * (1 << oct); pitch = tones[n]; } if (n == 0) dev_sound(0, period, vol, bg); else { dev_sound(pitch, duration, vol, bg); if (duration < period) dev_sound(0, period - duration, vol, bg); } calc_time_f = 1; break; // Play note case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': switch (*p) { case 'A': n = 13; break; case 'B': n = 15; break; case 'C': n = 4; break; case 'D': n = 6; break; case 'E': n = 8; break; case 'F': n = 9; break; case 'G': n = 11; break; } if (*(p + 1) == '-' || *(p + 1) == '+' || *(p + 1) == '#') { p++; if (*p == '-') n--; else n++; } if (is_digit(*(p + 1))) { TmpL = 0; while (is_digit(*(p + 1))) { p++; TmpL = (TmpL * 10) + (*p - '0'); } calc_time_f = 1; } else { TmpL = L; } if (*(p + 1) == '.') { p++; TM = 1.5; } else { TM = 1.0; } period = (4.0 / TmpL) * (60000 / T) * TM; duration = M * period; // pitch = tones[n] * (1 << O); pitch = tones[(n - 4) + O * 12]; dev_sound(pitch, duration, vol, bg); if (duration < period) { dev_sound(0, period - duration, vol, bg); } break; default: rt_raise("PLAY: '%c' UNSUPPORTED", *p); free(str); return; } // next if (*p) { p++; } } free(str); }