void display_time(){ if (started){ format_seconds(remaining_time, remaining_time_text); text_layer_set_text(&remaining_text_layer, remaining_time_text); }else{ text_layer_set_text(&remaining_text_layer, "--:--"); } }
//========================================================= void print_common_jack_properties() { fprintf(stderr,"sample rate: %d\n",sample_rate); char buf[64]; format_seconds(buf,(float)period_size/(float)sample_rate); fprintf(stderr,"period size: %d samples (%s, %d bytes)\n",period_size, buf,period_size*bytes_per_sample ); }
//================================================================ // /buffer int osc_buffer_handler(const char *path, const char *types, lo_arg **argv, int argc, void *data, void *user_data) { if(shutdown_in_progress==1 || not_yet_ready==1) { return 0; } if(allow_remote_buffer_control==0) { fprintf(stderr,"\nremote buffer control /buffer ii disabled! ignoring.\n"); return 0; } int pre_buffer_periods=fmax(1,argv[0]->i); int max_buffer_periods=fmax(pre_buffer_periods,argv[1]->i); fprintf(stderr,"\n/buffer received pre,max: %d, %d\n",pre_buffer_periods,max_buffer_periods); uint64_t rb_size=max_buffer_periods *output_port_count*bytes_per_sample*period_size; //create new buffer if not equal to current max //the current buffer will be lost if(max_buffer_periods!=max_buffer_size) { char buf[64]; format_seconds(buf,(float)max_buffer_periods*period_size/(float)sample_rate); fprintf(stderr,"new ringbuffer size: %d mc periods (%s, %" PRId64 " bytes, %.2f MB)\n", max_buffer_periods, buf, rb_size, (float)rb_size/1000/1000 ); max_buffer_size=max_buffer_periods; rb=jack_ringbuffer_create(rb_size); // /buffer is experimental, it can segfault } //current size uint64_t can_read_count=jack_ringbuffer_read_space(rb); uint64_t can_read_periods_count=can_read_count/port_count/period_size/bytes_per_sample; if(pre_buffer_periods>can_read_periods_count) { //fill buffer uint64_t fill_periods_count=pre_buffer_periods-can_read_periods_count; fprintf(stderr,"-> FILL %" PRId64 "\n",fill_periods_count); pre_buffer_size=fill_periods_count; pre_buffer_counter=0; process_enabled=0; } else if(pre_buffer_periods<can_read_periods_count) { //do in process() (reader) requested_drop_count+=can_read_periods_count-pre_buffer_periods; fprintf(stderr," -> DROP %" PRId64 "\n",requested_drop_count); } fflush(stderr); return 0; }//end osc_buffer_handler
//================================================================ int main(int argc, char *argv[]) { //jack const char **ports; //jack_options_t options = JackNullOption; jack_status_t status; //options struct was here if(argc-optind<1) { print_header("jack_audio_receive"); 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_header("jack_audio_receive"); print_help(); break; case 'v': print_version(); break; case 'x': print_header("jack_audio_receive"); check_lo_props(1); return 1; case 'o': output_port_count=atoi(optarg); if(output_port_count>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 'y': bytes_per_sample=2; break; case 'n': client_name=optarg; break; case 's': server_name=optarg; jack_opts |= JackServerName; break; case 'b': pre_buffer_size=fmax(1,(uint64_t)atoll(optarg)); break; case 'm': max_buffer_size=fmax(1,(uint64_t)atoll(optarg)); 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; break; case 'a': io_host=optarg; break; case 'c': io_port=optarg; break; case 't': use_tcp=1; remote_tcp_server_port=optarg; break; case '?': //invalid commands /* getopt_long already printed an error message. */ print_header("jack_audio_receive"); 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 if(argc-optind!=1) { print_header("jack_audio_receive"); fprintf(stderr, "Wrong arguments, see --help.\n\n"); exit(1); } localPort=argv[optind]; //for commuication with a gui / other controller / visualizer loio=lo_address_new_with_proto(LO_UDP, io_host, io_port); //if was set to use random port if(atoi(localPort)==0) { //for lo_server_thread_new_with_proto localPort=NULL; } //add osc hooks & start osc server early (~right after cmdline parsing) registerOSCMessagePatterns(localPort); lo_server_thread_start(lo_st); //read back port (in case of random) //could use //int lo_server_thread_get_port(lo_server_thread st) const char *osc_server_url=lo_server_get_url(lo_server_thread_get_server(lo_st)); localPort=lo_url_get_port(osc_server_url); //int lport=lo_server_thread_get_port(lo_st); //notify osc gui if(io_()) { lo_message msgio=lo_message_new(); lo_message_add_float(msgio, version); lo_message_add_float(msgio, format_version); lo_send_message(loio, "/startup", msgio); lo_message_free(msgio); } if(check_lo_props(0)>0) { return 1; } if(use_tcp==1) { lo_proto=LO_TCP; } if(shutup==0) { print_header("jack_audio_receive"); if(output_port_count>max_channel_count) { fprintf(stderr,"/!\\ limiting playback ports to %d, sry\n",max_channel_count); } if(test_mode==1) { fprintf(stderr,"/!\\ limiting number of messages: %" PRId64 "\n",receive_max); } } //check for default jack server env var char *evar=getenv("JACK_DEFAULT_SERVER"); if(evar==NULL || strlen(evar)<1) { #ifndef _WIN unsetenv("JACK_DEFAULT_SERVER"); #endif } else if(server_name==NULL) { //use env var if no server was given with --sname server_name=evar; } if(server_name==NULL || strlen(server_name)<=0) { server_name="default"; } if(client_name==NULL) { client_name="receive"; } if(have_libjack()!=0) { fprintf(stderr,"/!\\ libjack not found (JACK not installed?). this is fatal: jack_audio_receive needs JACK to run.\n"); io_quit("nolibjack"); exit(1); } //initialize time gettimeofday(&tv, NULL); tt_prev.sec=tv.tv_sec; tt_prev.frac=tv.tv_usec; //create an array of input ports ioPortArray=(jack_port_t**) malloc(output_port_count * sizeof(jack_port_t*)); //open a client connection to the JACK server client=jack_client_open(client_name, jack_opts, &status, server_name); if(client==NULL) { fprintf(stderr,"jack_client_open() failed, status = 0x%2.0x\n", status); if(status & JackServerFailed) { fprintf(stderr,"Unable to connect to JACK server.\n"); io_quit("nojack"); } exit(1); } if(use_tcp==1) { if(shutup==0) { fprintf(stderr,"receiving on TCP port: %s\n",localPort); } } else { if(shutup==0) { fprintf(stderr,"receiving on UDP port: %s\n",localPort); } } client_name=jack_get_client_name(client); if(shutup==0) { fprintf(stderr,"started JACK client '%s' on server '%s'\n",client_name,server_name); if(status & JackNameNotUnique) { fprintf(stderr, "/!\\ name '%s' was automatically assigned\n", client_name); } } if(status & JackNameNotUnique) { io_simple("/client_name_changed"); } //print startup info read_jack_properties(); if(shutup==0) { print_common_jack_properties(); fprintf(stderr,"channels (playback): %d\n",output_port_count); fprintf(stderr,"channel offset: %d\n",channel_offset); print_bytes_per_sample(); fprintf(stderr,"multi-channel period size: %d bytes\n", output_port_count*period_size*bytes_per_sample ); char *strat="fill with zero (silence)"; if(zero_on_underflow==0) { strat="re-use last available period"; } fprintf(stderr,"underflow strategy: %s\n",strat); if(rebuffer_on_restart==1) { fprintf(stderr,"rebuffer on sender restart: yes\n"); } else { fprintf(stderr,"rebuffer on sender restart: no\n"); } if(rebuffer_on_underflow==1) { fprintf(stderr,"rebuffer on underflow: yes\n"); } else { fprintf(stderr,"rebuffer on underflow: no\n"); } if(allow_remote_buffer_control==1) { fprintf(stderr,"allow external buffer control: yes\n"); } else { fprintf(stderr,"allow external buffer control: no\n"); } if(close_on_incomp==1) { fprintf(stderr,"shutdown receiver when incompatible data received: yes\n"); } else { fprintf(stderr,"shutdown receiver when incompatible data received: no\n"); } }//end cond. print char buf[64]; format_seconds(buf,(float)pre_buffer_size*period_size/(float)sample_rate); uint64_t rb_size_pre=pre_buffer_size*output_port_count*period_size*bytes_per_sample; if(shutup==0) { fprintf(stderr,"initial buffer size: %" PRId64 " mc periods (%s, %" PRId64 " bytes, %.2f MB)\n", pre_buffer_size, buf, rb_size_pre, (float)rb_size_pre/1000/1000 ); } buf[0]='\0'; //ringbuffer size bytes uint64_t rb_size; //ringbuffer mc periods int max_buffer_mc_periods; //max given as param (user knows best. if pre=max, overflows are likely) if(max_buffer_size>0) { max_buffer_mc_periods=fmax(pre_buffer_size,max_buffer_size); rb_size=max_buffer_mc_periods *output_port_count*period_size*bytes_per_sample; } else //"auto" { //make max buffer 0.5 seconds larger than pre buffer max_buffer_mc_periods=pre_buffer_size+ceil(0.5*(float)sample_rate/period_size); rb_size=max_buffer_mc_periods *output_port_count*period_size*bytes_per_sample; } max_buffer_size=max_buffer_mc_periods; format_seconds(buf,(float)max_buffer_mc_periods*period_size/sample_rate); if(shutup==0) { fprintf(stderr,"allocated buffer size: %" PRId64 " mc periods (%s, %" PRId64 " bytes, %.2f MB)\n", max_buffer_size, buf, rb_size, (float)rb_size/1000/1000 ); } buf[0]='\0'; io_dump_config(); //==================================== //main ringbuffer osc blobs -> jack output rb=jack_ringbuffer_create(rb_size); //helper ringbuffer: used when remote period size < local period size rb_helper=jack_ringbuffer_create(rb_size); if(rb==NULL) { fprintf(stderr,"could not create a ringbuffer with that size.\n"); fprintf(stderr,"try --max <smaller size>.\n"); io_quit("ringbuffer_too_large"); exit(1); } //JACK will call process() for every cycle (given by JACK) //NULL could be config/data struct jack_set_process_callback(client, process, NULL); jack_set_xrun_callback(client, xrun_handler, NULL); //register hook to know when JACK shuts down or the connection //was lost (i.e. client zombified) jack_on_shutdown(client, jack_shutdown_handler, 0); // Register each output port int port; for(port=0; port<output_port_count; port ++) { // Create port name char* portName; if(asprintf(&portName, "output_%d", (port+1)) < 0) { fprintf(stderr,"Could not create portname for port %d", port); io_quit("port_error"); exit(1); } // Register the output port ioPortArray[port]=jack_port_register(client, portName, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); if(ioPortArray[port]==NULL) { fprintf(stderr,"Could not create output port %d\n", (port+1)); io_quit("port_error"); exit(1); } } /* Tell the JACK server that we are ready to roll. Our * process() callback will start running now. */ if(jack_activate(client)) { fprintf(stderr, "cannot activate client"); io_quit("cannot_activate_client"); exit(1); } /* Connect the ports. You can't do this before the client is * activated, because we can't make connections to clients * that aren't running. Note the confusing (but necessary) * orientation of the driver backend ports: playback ports are * "input" to the backend, and capture ports are "output" from * it. */ //prevent to get physical midi ports const char* pat="audio"; ports=jack_get_ports(client, NULL, pat, JackPortIsPhysical|JackPortIsInput); if(ports==NULL) { if(shutup==0) { fprintf(stderr,"no physical playback ports\n"); } //exit(1); } if(autoconnect==1) { fprintf(stderr, "\n"); int j=0; int i; for(i=0;i<output_port_count;i++) { if(ports[i]!=NULL && ioPortArray[j]!=NULL && jack_port_name(ioPortArray[j])!=NULL) { if(!jack_connect(client, jack_port_name(ioPortArray[j]), ports[i])) { if(shutup==0) { fprintf(stderr, "autoconnect: %s -> %s\n", jack_port_name(ioPortArray[j]),ports[i] ); } io_simple_string_double("/autoconnect",jack_port_name(ioPortArray[j]),ports[i]); j++; } else { if(shutup==0) { fprintf(stderr, "autoconnect: failed: %s -> %s\n", jack_port_name(ioPortArray[j]),ports[i] ); } } } else { //no more playback ports break; } }//end for all output ports if(shutup==0) { fprintf(stderr, "\n"); } } free(ports); fflush(stderr); /* 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); if(use_tcp==1) { //10 MB max int desired_max_tcp_size=10000000; lo_server s=lo_server_thread_get_server(lo_st); int ret_set_size=lo_server_max_msg_size(s, desired_max_tcp_size); if(shutup==0) { printf("set tcp max size return: %d\n",ret_set_size); io_simple("/tcp_max_size_xxxx"); } } not_yet_ready=0; io_simple("/start_main_loop"); //run possibly forever until not interrupted by any means while(1) { //possibly clean shutdown without any glitches if(shutdown_in_progress==1) { signal_handler(42); } #ifdef WIN_ Sleep(1000); #else sleep(1); #endif } exit(0); }//end main
void display_timer(Timer *timer, char* display){ format_seconds(timer->seconds, display); text_layer_set_text(timer->text_layer, display); }