Example #1
0
int main(int argc, char **argv)
{
	int rc;
	int result = EXIT_FAILURE;
	struct device *upnp_renderer;

	rc = process_cmdline(argc, argv);
	if (rc != 0) {
		goto out;
	}

	if (show_version) {
		do_show_version();
		exit(EXIT_SUCCESS);
	}
	if (show_connmgr_scpd) {
		upnp_renderer_dump_connmgr_scpd();
		exit(EXIT_SUCCESS);
	}
	if (show_control_scpd) {
		upnp_renderer_dump_control_scpd();
		exit(EXIT_SUCCESS);
	}
	if (show_transport_scpd) {
		upnp_renderer_dump_transport_scpd();
		exit(EXIT_SUCCESS);
	}

	if (show_outputs) {
		output_dump_modules();
		exit(EXIT_SUCCESS);
	}

	if (pid_file && pid_file[0] != '/') {
		// We need to canonicalize the filename because our
		// cwd will change after becoming a daemon.
		char *buf = (char*) malloc(PATH_MAX);  // will leak. Ok.
		char *result = getcwd(buf, PATH_MAX);
		result = strcat(result, "/");
		pid_file = strcat(result, pid_file);
	}
	if (daemon_mode) {
		daemon(0, 0);  // TODO: check for daemon() in configure.
	}
	if (pid_file) {
		FILE *p = fopen(pid_file, "w+");
		if (p) {
			fprintf(p, "%d\n", getpid());
			fclose(p);
		} else {
			perror("Failed to write pid file");
		}
	}
	if (!g_thread_get_initialized()) {
		g_thread_init(NULL);
	}

	upnp_renderer = upnp_renderer_new(friendly_name, uuid);
	if (upnp_renderer == NULL) {
		goto out;
	}

	if (show_devicedesc) {
		char *buf;
		buf = upnp_get_device_desc(upnp_renderer);
		assert(buf != NULL);
		fputs(buf, stdout);
		exit(EXIT_SUCCESS);
	}

	rc = output_init(output);
	if (rc != 0) {
		fprintf(stderr,"ERROR: Failed to initialize Output subsystem\n");
		goto out;
	}

	struct device_private *device;
	device = upnp_device_init(upnp_renderer, ip_address);
	if (device == NULL) {
		fprintf(stderr,"ERROR: Failed to initialize UPnP device\n");
		goto out;
	}

	upnp_transport_init(device);
	upnp_control_init();

	printf("Ready for rendering..\n");
	output_loop();
	result = EXIT_SUCCESS;

out:
	return result;
}
int main(int argc, char **argv)
{
	int rc;
	struct upnp_device_descriptor *device_desc;

	if (!process_cmdline(argc, argv)) {
		return EXIT_FAILURE;
	}

	if (show_version) {
		do_show_version();
		exit(EXIT_SUCCESS);
	}
	if (show_connmgr_scpd) {
		upnp_renderer_dump_connmgr_scpd();
		exit(EXIT_SUCCESS);
	}
	if (show_control_scpd) {
		upnp_renderer_dump_control_scpd();
		exit(EXIT_SUCCESS);
	}
	if (show_transport_scpd) {
		upnp_renderer_dump_transport_scpd();
		exit(EXIT_SUCCESS);
	}

	if (show_outputs) {
		output_dump_modules();
		exit(EXIT_SUCCESS);
	}

	init_logging(log_file);
	variable_container_init();

	// Now we're going to start threads etc, which means we need
	// to become a daemon before that.

	// We need to open the pid-file now because relative filenames will
	// break if we're becoming a daemon and cwd changes.
	FILE *pid_file_stream = NULL;
	if (pid_file) {
		pid_file_stream = fopen(pid_file, "w");
	}
	if (daemon_mode) {
		daemon(0, 0);  // TODO: check for daemon() in configure.
	}
	if (pid_file_stream) {
		fprintf(pid_file_stream, "%d\n", getpid());
		fclose(pid_file_stream);
	}

#if !GLIB_CHECK_VERSION(2, 32, 0)
	// Only older version of glib require this.
	if (!g_thread_get_initialized()) {
		g_thread_init(NULL);
	}
#endif

	if (!openhome_mode)
		device_desc = upnp_renderer_descriptor(friendly_name, uuid);
	else
		device_desc = oh_source_descriptor(friendly_name, uuid);
	if (device_desc == NULL) {
		return EXIT_FAILURE;
	}

	rc = output_init(output);
	if (rc != 0) {
		Log_error("main",
			  "ERROR: Failed to initialize Output subsystem");
		return EXIT_FAILURE;
	}

	if (openhome_mode && playlist_file != NULL)
		oh_playlist_load(playlist_file);

	struct upnp_device *device;
	if (listen_port != 0 &&
	    (listen_port < 49152 || listen_port > 65535)) {
		// Somewhere obscure internally in libupnp, they clamp the
		// port to be outside of the IANA range, so at least 49152.
		// Instead of surprising the user by ignoring lower port
		// numbers, complain loudly.
		Log_error("main", "Parameter error: --port needs to be in "
			  "range [49152..65535] (but was set to %d)",
			  listen_port);
		return EXIT_FAILURE;
	}
	device = upnp_device_init(device_desc, ip_address, listen_port);
	if (device == NULL) {
		Log_error("main", "ERROR: Failed to initialize UPnP device");
		return EXIT_FAILURE;
	}

	if (!openhome_mode) {
		upnp_transport_init(device);
		upnp_control_init(device);
	} else {
		oh_product_init(device);
		oh_playlist_init(device);
		oh_info_init(device);
		oh_time_init(device);
		oh_volume_init(device);
	}

	if (show_devicedesc) {
		// This can only be run after all services have been
		// initialized.
		char *buf = upnp_create_device_desc(device_desc);
		assert(buf != NULL);
		fputs(buf, stdout);
		exit(EXIT_SUCCESS);
	}

	if (!openhome_mode && Log_info_enabled()) {
		upnp_transport_register_variable_listener(log_variable_change,
							  (void*) "transport");
		upnp_control_register_variable_listener(log_variable_change,
							(void*) "control");
	}

	// Write both to the log (which might be disabled) and console.
	Log_info("main", "Ready for rendering.");
	fprintf(stderr, "Ready for rendering.\n");

	output_loop();

	// We're here, because the loop exited. Probably due to catching
	// a signal.
	Log_info("main", "Exiting.");
	upnp_device_shutdown(device);

	return EXIT_SUCCESS;
}