Example #1
0
int main(int argc, char *argv[])
{
  int autoconnect = 0;
  jack_options_t jack_opt = JackNullOption;
  char *client_name = DEFAULT_CLIENT_NAME;
  char *connect_left = NULL;
  char *connect_right = NULL;
  const char *format_name = NULL;
  int bitrate = DEFAULT_BITRATE;
  int sync_period = DEFAULT_SYNC_PERIOD;
  float sleep_time = 0;
  time_t next_sync = 0;
  int i,opt;

  // Make STDOUT unbuffered
  setbuf(stdout, NULL);

  // Parse Switches
  while ((opt = getopt(argc, argv, "al:r:n:N:O:p:jf:b:Q:d:c:R:L:s:uvqh")) != -1) {
    switch (opt) {
      case 'a':  autoconnect = 1; break;
      case 'l':  connect_left = optarg; break;
      case 'r':  connect_right = optarg; break;
      case 'n':  client_name = optarg; break;
      case 'N':  archive_name = optarg; break;
      case 'O':  originator = strdup(optarg); break;
      case 'p':  archive_period_seconds = atol(optarg); break;
      case 'j':  jack_opt |= JackNoStartServer; break;
      case 'f':  format_name = rotter_str_tolower(optarg); break;
      case 'b':  bitrate = atoi(optarg); break;
      case 'Q':  vbr_quality = atof(optarg); break;
      case 'd':  delete_hours = atoi(optarg); break;
      case 'c':  channels = atoi(optarg); break;
      case 'R':  rb_duration = atof(optarg); break;
      case 'L':  file_layout = optarg; break;
      case 's':  sync_period = atoi(optarg); break;
      case 'u':  utc = 1; break;
      case 'v':  verbose = 1; break;
      case 'q':  quiet = 1; break;
      default:  usage(); break;
    }
  }

  // Validate parameters
  if (quiet && verbose) {
    rotter_error("Can't be quiet and verbose at the same time.");
    usage();
  }

  // Check the number of channels
  if (channels!=1 && channels!=2) {
    rotter_error("Number of channels should be either 1 or 2.");
    usage();
  }

  // Check remaining arguments
    argc -= optind;
    argv += optind;
    if (argc!=1) {
      rotter_error("%s requires a root directory argument.", PACKAGE_NAME);
      usage();
  } else {
    root_directory = argv[0];
    if (root_directory[strlen(root_directory)-1] == '/')
      root_directory[strlen(root_directory)-1] = 0;

    if (rotter_directory_exists(root_directory)) {
      rotter_debug("Root directory: %s", root_directory);
    } else {
      rotter_fatal("Root directory does not exist: %s", root_directory);
      goto cleanup;
    }
  }

  // Search for the selected output format
  if (format_name) {
    for(i=0; format_list[i].name; i++) {
      if (strcmp( format_list[i].name, format_name ) == 0) {
        // Found desired format
        output_format = &format_list[i];
        rotter_debug("User selected [%s] '%s'.",  output_format->name,  output_format->desc);
        break;
      }
    }
    if (output_format==NULL) {
      rotter_fatal("Failed to find format [%s], please check the supported format list.", format_name);
      goto cleanup;
    }
  } else {
    output_format = &format_list[0];
  }

  // No originator defined?
  if (!originator) {
    originator = rotter_get_hostname();
  }

  // Initialise JACK
  if (init_jack( client_name, jack_opt )) {
    rotter_debug("Failed to initialise Jack client.");
    goto cleanup;
  }

  // Create ring buffers
  if (init_ringbuffers()) {
    rotter_debug("Failed to initialise ring buffers.");
    goto cleanup;
  }

  // Create temporary buffer for reading samples into
  if (init_tmpbuffers(output_format->samples_per_frame)) {
    rotter_debug("Failed to initialise temporary buffers.");
    goto cleanup;
  }

  // Initialise encoder
  encoder = output_format->initfunc(output_format, channels, bitrate);
  if (encoder==NULL) {
    rotter_debug("Failed to initialise encoder.");
    goto cleanup;
  }

  // Activate JACK
  if (jack_activate(client)) {
    rotter_fatal("Cannot activate JACK client.");
    goto cleanup;
  }

  // Setup signal handlers
  signal(SIGTERM, rotter_termination_handler);
  signal(SIGINT, rotter_termination_handler);
  signal(SIGHUP, rotter_termination_handler);

  // Auto-connect our input ports ?
  if (autoconnect) autoconnect_jack_ports( client );
  if (connect_left) connect_jack_port( connect_left, inport[0] );
  if (connect_right && channels == 2) connect_jack_port( connect_right, inport[1] );

  // Calculate period to wait when there is no audio to process
  sleep_time = (2.0f * output_format->samples_per_frame / jack_get_sample_rate( client ));
  rotter_debug("Sleep period is %dms.", (int)(sleep_time * 1000));

  while( rotter_run_state == ROTTER_STATE_RUNNING ) {
    time_t now = time(NULL);
    int samples_processed = rotter_process_audio();
    if (samples_processed <= 0) {
      usleep(sleep_time * 1000000);
    }

    // Is it time to sync the encoded audio to disk?
    if (next_sync < now) {
      rotter_sync_to_disk();
      next_sync = now + sync_period;
    }

    deletefiles_cleanup_child();
  }


cleanup:

  // Clean up JACK
  deinit_jack();

  // Free buffers and close files
  deinit_tmpbuffers();
  deinit_ringbuffers();

  // Shut down encoder
  if (encoder)
    encoder->deinit();

  // Free the originator string
  if (originator)
    free(originator);

  // Did something go wrong?
  if (rotter_run_state == ROTTER_STATE_QUITING) {
    return EXIT_SUCCESS;
  } else {
    return EXIT_FAILURE;
  }
}
Example #2
0
// Initialise Jack related stuff
static jack_client_t* init_jack( MastSendTool* tool ) 
{
	const char* client_name = tool->get_tool_name();
	jack_client_t* client = NULL;
	jack_status_t status;
	size_t ringbuffer_size = 0;
	int port_count = tool->get_input_channels();
	int i = 0;


    pthread_mutex_init(&g_ringbuffer_cond_mutex, NULL);
    pthread_cond_init(&g_ringbuffer_cond, NULL);

	// Register with Jack
	if ((client = jack_client_open(client_name, g_client_opt, &status)) == 0) {
		MAST_ERROR("Failed to start jack client: 0x%x", status);
		return NULL;
	} else {
		MAST_INFO( "JACK client registered as '%s'", jack_get_client_name( client ) );
	}

	// Create our input port(s)
	if (port_count==1) {
		if (!(g_jackport[0] = jack_port_register(client, "mono", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0))) {
			MAST_ERROR("Cannot register mono input port");
			return NULL;
		}
	} else {
		if (!(g_jackport[0] = jack_port_register(client, "left", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0))) {
			MAST_ERROR("Cannot register left input port");
			return NULL;
		}
		
		if (!(g_jackport[1] = jack_port_register(client, "right", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0))) {
			MAST_ERROR( "Cannot register left input port");
			return NULL;
		}
	}
	
	// Create ring buffer
	ringbuffer_size = jack_get_sample_rate( client ) * g_rb_duration * port_count * sizeof(int16_t) / 1000;
	MAST_INFO("Duration of the ring buffer is %d ms (%d bytes)", g_rb_duration, (int)ringbuffer_size );
	if (!(g_ringbuffer = jack_ringbuffer_create( ringbuffer_size ))) {
		MAST_ERROR("Cannot create ringbuffer %d", i);
		return NULL;
	}

	// Register callbacks
	jack_on_shutdown(client, shutdown_callback, tool );
	jack_set_buffer_size_callback( client, buffersize_callback, tool);
	jack_set_process_callback(client, process_callback, tool);
	
	// Create conversion buffer
	buffersize_callback( jack_get_buffer_size(client), tool );

	// Activate JACK
	if (jack_activate(client)) MAST_FATAL("Cannot activate JACK client");
	
	/* Auto connect ports ? */
	if (g_do_autoconnect) autoconnect_jack_ports( client, tool->get_input_channels() );
	
	return client;
}
Example #3
0
static int connect_jack_ports(out123_handle *ao
,	jack_handle_t* handle)
{
	debug1("connect_jack_ports with dev=%s", ao->device ? ao->device : "<nil>");
	if(ao->device==NULL || strcmp(ao->device, "auto")==0)
		return autoconnect_jack_ports(ao, handle);
	else
	{
		/* Parse device for a set of ports, comma separated. */
		const char** wishlist; /* Channels and end marker. */
		int wish_channels = 1; /* Numper of entries in wishlist. */
		char *devcopy, *chr;
		int ret;
		int c;
		size_t len;
		len = strlen(ao->device);
		/* We connect as many JACK ports as desired, possibly duplicating. */
		for(chr=ao->device; *chr; ++chr)
			if(*chr == ',')
				++wish_channels;
		debug1("wish_channels: %i", wish_channels);
		wishlist = malloc(sizeof(char*)*(wish_channels+1));
		devcopy = compat_strdup(ao->device);
		if(devcopy == NULL || wishlist == NULL)
		{
			if(devcopy)
				free(devcopy);
			if(wishlist)
				free(wishlist);
			if(!AOQUIET)
				error("OOM");
			return 0;
		}

		for(c=0;c<=wish_channels;++c)
			wishlist[c] = NULL;
		if(len && strcmp(devcopy, "none"))
		{
			size_t i=0;
			wishlist[0] = devcopy;
			for(c=0;c<wish_channels;++c)
			{
				while(devcopy[i] != 0 && devcopy[i] != ',') ++i;
				debug2("devcopy[%"SIZE_P"]=%i", i, devcopy[i]);
				if(devcopy[i] == ',')
				{
					/* Terminate previous port name, assign next one. */
					devcopy[i++] = 0;
					debug2("terminaled wish %i: %s", c, wishlist[c]);
					if(c+1 < wish_channels)
						wishlist[c+1] = devcopy+i;
				}
				else
					break;
			}
		}
		if(wishlist[0] == NULL && !AOQUIET)
			warning("Not connecting up jack ports as requested.");

		ret = real_connect_jack_ports(ao, handle, wishlist);
		free(devcopy);
		free(wishlist);
		return ret;
	}
	return 1;
}