// Constructor. qtractorNsmClient::qtractorNsmClient ( const QString& nsm_url, QObject *pParent ) : QObject(pParent), #ifdef CONFIG_LIBLO m_address(NULL), m_thread(NULL), m_server(NULL), #endif m_active(false) { #ifdef CONFIG_LIBLO m_address = lo_address_new_from_url(nsm_url.toUtf8().constData()); const int proto = lo_address_get_protocol(m_address); m_thread = lo_server_thread_new_with_proto(NULL, proto, NULL); if (m_thread) { m_server = lo_server_thread_get_server(m_thread); lo_server_thread_add_method(m_thread, "/error", "sis", osc_nsm_error, this); lo_server_thread_add_method(m_thread, "/reply", "ssss", osc_nsm_reply, this); lo_server_thread_add_method(m_thread, "/nsm/client/open", "sss", osc_nsm_open, this); lo_server_thread_add_method(m_thread, "/nsm/client/save", "", osc_nsm_save, this); lo_server_thread_add_method(m_thread, "/nsm/client/session_is_loaded", "", osc_nsm_loaded, this); lo_server_thread_add_method(m_thread, "/nsm/client/show_optional_gui", "", osc_nsm_show, this); lo_server_thread_add_method(m_thread, "/nsm/client/hide_optional_gui", "", osc_nsm_hide, this); lo_server_thread_start(m_thread); } #endif }
Server::Server() { st = lo_server_thread_new("6340", error); if (st) lo_server_thread_start(st); else { printf("err: starting Server\n"); while(1);} st_tcp = lo_server_thread_new_with_proto("6341", LO_TCP, errorTCP); if (st_tcp) lo_server_thread_start(st_tcp); else { printf("err: starting Server\n"); while(1);} }
void registerOSCMessagePatterns(const char *port) { /* osc server */ //lo_st = lo_server_thread_new(port, error); lo_st = lo_server_thread_new_with_proto(port, lo_proto, error); /* /offer fiiiifh 1) f: audio rx/tx format version 2) i: sample rate 3) i: bytes per sample 4) i: period size 5) i: channel count 6) f: expected network data rate 7) h: send / request counter */ lo_server_thread_add_method(lo_st, "/offer", "fiiiifh", offer_handler, NULL); /* /audio hhtib* 1) h: message number 2) h: xrun counter (sender side, as all the following meta data) 3) t: timetag (seconds since Jan 1st 1900 in the UTC, fraction 1/2^32nds of a second) 4) i: sampling rate 5) b: blob of channel 1 (period size * bytes per sample) bytes long ... ...b: up to n channels */ char typetag_string[1024]; int v=0; for(v=0;v<1024;v++) { typetag_string[v]='\0'; } //char *prefix="hhti"; typetag_string[0]='h'; typetag_string[1]='h'; typetag_string[2]='t'; typetag_string[3]='i'; ///////////////// int data_offset=4; v=0; for(v=0;v<max_channel_count;v++) { typetag_string[data_offset+v]='b'; lo_server_thread_add_method(lo_st, "/audio", typetag_string, audio_handler, NULL); } //the max possible channel count depends on JACK period size, SR, liblo version (fixmax), 16/32 bit, 100/1000 mbit/s network }//end registerocsmessages
Server::Obj::Obj( int port, Proto proto ) { string portStr = boost::lexical_cast< string >( port ); mThread = lo_server_thread_new_with_proto( ( port == PORT_ANY ) ? NULL : portStr.c_str(), proto, errorHandler ); if ( port == PORT_ANY ) mPort = lo_server_thread_get_port( mThread ); else mPort = port; lo_server_thread_start( mThread ); }
Server::Server( int port, Proto proto /* = PROTO_UDP */ ) { string portStr = boost::lexical_cast< string >( port ); mThread = lo_server_thread_new_with_proto( ( port == PORT_ANY ) ? NULL : portStr.c_str(), proto, errorHandler ); if ( port == PORT_ANY ) { mPort = lo_server_thread_get_port( mThread ); } else { mPort = port; } lo_server_thread_start( mThread ); }
int Client::init_thread(const char *nsm_url) { this->nsm_url = nsm_url; lo_address addr = lo_address_new_from_url(nsm_url); int proto = lo_address_get_protocol(addr); lo_address_free(addr); _st = lo_server_thread_new_with_proto(NULL, proto, NULL); _server = lo_server_thread_get_server(_st); if(!_server || !_st) return -1; lo_server_thread_add_method(_st, "/error", "sis", &Client::osc_error, this); lo_server_thread_add_method(_st, "/reply", "ssss", &Client::osc_announce_reply, this); lo_server_thread_add_method(_st, "/nsm/client/open", "sss", &Client::osc_open, this); lo_server_thread_add_method(_st, "/nsm/client/save", "", &Client::osc_save, this); lo_server_thread_add_method(_st, "/nsm/client/session_is_loaded", "", &Client::osc_session_is_loaded, this); lo_server_thread_add_method(_st, NULL, NULL, &Client::osc_broadcast, this); return 0; }
bool announce(const int pid, const char* const executableName) { CARLA_SAFE_ASSERT_RETURN(pid != 0, false); CARLA_SAFE_ASSERT_RETURN(executableName != nullptr && executableName[0] != '\0', false); const char* const NSM_URL(std::getenv("NSM_URL")); if (NSM_URL == nullptr) return false; const lo_address nsmAddress(lo_address_new_from_url(NSM_URL)); CARLA_SAFE_ASSERT_RETURN(nsmAddress != nullptr, false); const int proto = lo_address_get_protocol(nsmAddress); if (fServerThread == nullptr) { // create new OSC server fServerThread = lo_server_thread_new_with_proto(nullptr, proto, _osc_error_handler); CARLA_SAFE_ASSERT_RETURN(fServerThread != nullptr, false); // register message handlers lo_server_thread_add_method(fServerThread, "/error", "sis", _error_handler, this); lo_server_thread_add_method(fServerThread, "/reply", "ssss", _reply_handler, this); lo_server_thread_add_method(fServerThread, "/nsm/client/open", "sss", _open_handler, this); lo_server_thread_add_method(fServerThread, "/nsm/client/save", "", _save_handler, this); lo_server_thread_add_method(fServerThread, "/nsm/client/session_is_loaded", "", _loaded_handler, this); lo_server_thread_add_method(fServerThread, "/nsm/client/show_optional_gui", "", _show_gui_handler, this); lo_server_thread_add_method(fServerThread, "/nsm/client/hide_optional_gui", "", _hide_gui_handler, this); lo_server_thread_add_method(fServerThread, nullptr, nullptr, _broadcast_handler, this); fServer = lo_server_thread_get_server(fServerThread); fServerURL = lo_server_thread_get_url(fServerThread); } const char* appName = std::getenv("CARLA_NSM_NAME"); if (appName == nullptr) appName = "Carla"; lo_send_from(nsmAddress, fServer, LO_TT_IMMEDIATE, "/nsm/server/announce", "sssiii", appName, NSM_CLIENT_FEATURES, executableName, NSM_API_VERSION_MAJOR, NSM_API_VERSION_MINOR, pid); lo_address_free(nsmAddress); return true; }
lo_server_thread lo_server_thread_new(const char *port, lo_err_handler err_h) { return lo_server_thread_new_with_proto(port, LO_DEFAULT, err_h); }
int main (int argc, char *argv[]) { ////////////////////////////////////////////// //will be removed // sample_rate=44100; sample_rate=48000; // period_size=2048; period_size=4096; // period_size=256; //period_size=128; bytes_per_sample=4; //osc const char *listenPort; //command line options parsing //http://www.gnu.org/software/libc/manual/html_node/Using-Getopt.html static struct option long_options[] = { {"help", no_argument, 0, 'h'}, {"version", no_argument, 0, 'v'}, {"loinfo", no_argument, 0, 'x'}, {"out", required_argument, 0, 'o'}, {"offset", required_argument, 0, 'f'}, {"16", no_argument, 0, 'y'}, {"max", required_argument, 0, 'm'},//max (allocate) buffer {"update", required_argument, 0, 'u'},//screen info update every nth cycle {"limit", required_argument, 0, 'l'},//test, stop after n processed {0, 0, 0, 0} }; //print program header if(argc>1 && strcmp(argv[1],"--version")) { print_header("audio_post_send"); } if (argc - optind < 1) { fprintf (stderr, "Missing arguments, see --help.\n\n"); exit(1); } int opt; //do until command line options parsed while (1) { /* getopt_long stores the option index here. */ int option_index = 0; opt = getopt_long (argc, argv, "", long_options, &option_index); /* Detect the end of the options. */ if (opt == -1) { break; } switch (opt) { case 0: /* If this option set a flag, do nothing else now. */ if (long_options[option_index].flag != 0) { break; } case 'h': print_help(); break; case 'v': print_version(); break; case 'x': check_lo_props(1); return 1; case 'o': output_port_count=atoi(optarg); if(output_port_count>max_channel_count) { fprintf(stderr,"*** limiting playback ports to %d, sry\n",max_channel_count); output_port_count=max_channel_count; } port_count=fmin(input_port_count,output_port_count); break; case 'f': channel_offset=atoi(optarg); break; case 'm': //min 1 MB max_buffer_size=fmax(1,(uint64_t)atoll(optarg)*1000*1000); break; case 'u': update_display_every_nth_cycle=fmax(1,(uint64_t)atoll(optarg)); break; case 'l': receive_max=fmax(1,(uint64_t)atoll(optarg)); test_mode=1; fprintf(stderr,"*** limiting number of messages: %" PRId64 "\n",receive_max); break; case '?': //invalid commands /* getopt_long already printed an error message. */ fprintf (stderr, "Wrong arguments, see --help.\n\n"); exit(1); break; default: break; } //end switch op }//end while(1) //remaining non optional parameters listening port, remote host, remote port if(argc-optind != 3) { fprintf (stderr, "Wrong arguments, see --help.\n\n"); exit(1); } if(check_lo_props(0)>0) { return 1; } if(have_libjack()!=0) { fprintf(stderr,"/!\\ libjack not found (JACK not installed?). this is fatal: audio_post_send needs JACK to run.\n"); //io_quit("nolibjack"); exit(1); } listenPort=argv[optind]; //tcp target remote_tcp_host=argv[optind+1]; remote_tcp_port=argv[optind+2]; loa_tcp = lo_address_new_with_proto(LO_TCP, remote_tcp_host, remote_tcp_port); //initialize time gettimeofday(&tv, NULL); tt_prev.sec=tv.tv_sec; tt_prev.frac=tv.tv_usec; //print startup info fprintf(stderr,"listening on UDP port: %s\n",listenPort); //udp/tcp use the same port for now fprintf(stderr,"started TCP server on port: %s\n",listenPort); fprintf(stderr,"channels (forward): %d\n",output_port_count); fprintf(stderr,"channel offset: %d\n",channel_offset); fprintf(stderr, "TCP target: %s:%s\n",remote_tcp_host,remote_tcp_port); fprintf(stderr, "period size (TCP forward): %d samples\n",period_size); fprintf(stderr, "delay between TCP sends: %d ms\n",delay_between_tcp_sends); fprintf(stderr, "delay between TCP retries on broken connection: %d ms\n",delay_between_tcp_retries); //ringbuffer size bytes uint64_t rb_size; //use as given via param --max or: if(max_buffer_size==0) { //default //10 MB . . max_buffer_size=10000000; } // rb_size=max_buffer_size; fprintf(stderr,"allocated buffer size: %" PRId64 " bytes (%.2f MB)\n",max_buffer_size,(float)max_buffer_size/1000/1000); //==================================== //main ringbuffer osc blobs -> jack output rb = rb_new (rb_size); //helper ringbuffer: used when remote period size < local period size rb_helper = rb_new (rb_size); if(rb==NULL) { fprintf(stderr,"could not create a ringbuffer with that size.\n"); fprintf(stderr,"try --max <smaller size>.\n"); exit(1); } /* install a signal handler to properly quits jack client */ #ifndef _WIN signal(SIGQUIT, signal_handler); signal(SIGHUP, signal_handler); #endif signal(SIGTERM, signal_handler); signal(SIGINT, signal_handler); //add osc hooks & start UDP server registerOSCMessagePatterns(listenPort); lo_server_thread_start(lo_st); //start TCP server, for forwarding to final receiver lo_st_tcp = lo_server_thread_new_with_proto(listenPort, LO_TCP, error); lo_server_thread_start(lo_st_tcp); fflush(stderr); /* keep running until the Ctrl+C */ while(1) { //possibly clean shutdown without any glitches if(shutdown_in_progress==1) { signal_handler(42); } //if tcp message could not be sent if(process()<0) { //wait x and update info int i; for(i=0;i<delay_between_tcp_retries;i++) { usleep(1000); print_info(); } } else { //wait y and update info int i; for(i=0;i<delay_between_tcp_sends;i++) { usleep(1000); print_info(); } } } exit (0); }
//================================================================ void registerOSCMessagePatterns(const char *port) { /* osc server */ //lo_st=lo_server_thread_new(port, error); lo_st=lo_server_thread_new_with_proto(port, lo_proto, osc_error_handler); //AUDIO RELATED========================================= /* /offer fiiiifh 1) f: audio rx/tx format version 2) i: sample rate 3) i: bytes per sample 4) i: period size 5) i: channel count 6) f: expected network data rate 7) h: send / request counter */ lo_server_thread_add_method(lo_st, "/offer", "fiiiifh", osc_offer_handler, NULL); /* experimental /buffer ii 1) i: target fill value for available periods in ringbuffer (multi channel) 2) i: max. target buffer size in mc periods drop or add periods this will introduce a hearable click on drops or pause playback for rebuffering depending on the current buffer fill */ lo_server_thread_add_method(lo_st, "/buffer", "ii", osc_buffer_handler, NULL); /* /audio hhtib* 1) h: message number 2) h: xrun counter (sender side, as all the following meta data) 3) t: timetag (seconds since Jan 1st 1900 in the UTC, fraction 1/2^32nds of a second) 4) i: sampling rate 5) b: blob of channel 1 (period size * bytes per sample) bytes long ... ...b: up to n channels */ char typetag_string[1024]; int v=0; for(v=0;v<1024;v++) { typetag_string[v]='\0'; } //char *prefix="hhti"; typetag_string[0]='h'; typetag_string[1]='h'; typetag_string[2]='t'; typetag_string[3]='i'; ///////////////// int data_offset=4; //the max possible channel count depends on JACK period size, SR, liblo version (fixmax), 16/32 bit, 100/1000 mbit/s network /* //support 1-n blobs / channels per message lo_server_thread_add_method(lo_st, "/audio", "hhtib", audio_handler, NULL); lo_server_thread_add_method(lo_st, "/audio", "hhtibb", audio_handler, NULL); .. */ v=0; for(v=0;v<max_channel_count;v++) { typetag_string[data_offset+v]='b'; lo_server_thread_add_method(lo_st, "/audio", typetag_string, osc_audio_handler, NULL); } //GUI I/O, CONTROL RELATED============================== /* /quit close / release resources and shutdown program */ lo_server_thread_add_method(lo_st, "/quit", "", osc_quit_handler, NULL); }//end registerocsmessages
int main (int argc, char **argv) { lo_server_thread serv = NULL; FILE *file = NULL; int c; while ( (c = getopt (argc, argv, "i:o:")) != -1) switch (c) { case 'i': { int proto = lo_url_get_protocol_id (optarg); if (proto == -1) fprintf (stderr, "protocol not supported\n"); char *port = lo_url_get_port (optarg); serv = lo_server_thread_new_with_proto (port, proto, _error); free (port); break; } case 'o': { if (!strcmp (optarg, "-")) file = stdout; else file = fopen (optarg, "wb"); break; } case '?': if ( (optopt == 'i') || (optopt == 'o') ) fprintf (stderr, "Option `-%c' requires an argument.\n", optopt); else if (isprint (optopt)) fprintf (stderr, "Unknown option `-%c'.\n", optopt); else fprintf (stderr, "Unknown option character `\\x%x'.\n", optopt); return 1; default: return (1); } if (!serv || !file) { fprintf (stderr, "usage: %s -i PROTOCOL://HOST:PORT -o FILE|-\n\n", argv[0]); return (1); } lo_server *_serv = lo_server_thread_get_server (serv); lo_server_add_bundle_handlers (_serv, _bundle_start_handler, _bundle_end_handler, file); lo_server_enable_queue (_serv, 0, 1); lo_server_thread_add_method (serv, NULL, NULL, _msg_handler, file); lo_server_thread_start (serv); signal (SIGHUP, _quit); signal (SIGQUIT, _quit); signal (SIGTERM, _quit); signal (SIGINT, _quit); while (!done) nanosleep (&_10mu, NULL); fprintf (stderr, "cleaning up\n"); lo_server_thread_stop (serv); lo_server_thread_free (serv); if (file != stdout) fclose (file); return 0; }