Example #1
0
static void process_download(struct server_attr *attr)
{
	int fd;
	unsigned int length, n;
	char str[BUFSZ];
	char filename[NAME_MAX + 1];


download_next:
	/* Format: | uint file-length | uint file-name-length | file-name */
	length = *((int *)attr->data);

	n = *((int *)(attr->data + sizeof(length)));
	strncpy(filename, (attr->data + sizeof(length) * 2), n);
	*(filename + n) = 0;

	create_download_dir(filename);	/* create directory if necessary */
	


	/* Overwrite exist file */
	fd = open(filename, O_WRONLY | O_CREAT, DEFAULT_DL_FILE_MODE);
	if (fd == -1) {
		err_msg(errno, "Error for open %s", filename);
		return;
	}

	SET_PROGRESS_DOWNLOAD(str, filename, length);
	n = 0;
	while (n < length) {
		recv_response(attr);
		writen(fd, attr->data, attr->resp.len);

		n += attr->resp.len;
		PRINT_PROGRESS(str, length, n);
	}

	printf("\n");
	close(fd);

	/* Confirm does recived the RESP_DATA_FINISH flag */
	recv_response(attr);
	if (attr->resp.code != RESP_DATA_FINISH)
		goto download_next;
}
int main (int argc, char *argv[])
{
	GOptionGroup *options;
	GOptionContext *context;
	GError *err = NULL;
	GdkPixbuf *pixbuf;
	const char *input, *output;
	ThumbApp app;

	context = g_option_context_new ("Thumbnail movies");
	options = gst_init_get_option_group ();
	g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
	g_option_context_add_group (context, options);
	g_option_context_add_group (context, gtk_get_option_group (TRUE));

	if (g_option_context_parse (context, &argc, &argv, &err) == FALSE) {
		g_print ("couldn't parse command-line options: %s\n", err->message);
		g_error_free (err);
		return 1;
	}

#ifdef G_OS_UNIX
	if (time_limit != FALSE) {
		errno = 0;
		if (nice (20) != 20 && errno != 0)
			g_warning ("Couldn't change nice value of process.");
	}
#endif

	if (print_progress) {
		fcntl (fileno (stdout), F_SETFL, O_NONBLOCK);
		setbuf (stdout, NULL);
	}

	if (g_fatal_warnings) {
		GLogLevelFlags fatal_mask;

		fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
		fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;
		g_log_set_always_fatal (fatal_mask);
	}

	if (raw_output == FALSE && output_size == -1)
		output_size = DEFAULT_OUTPUT_SIZE;

	if (filenames == NULL || g_strv_length (filenames) != 2 ||
	    (second_index != -1 && gallery != -1) ||
	    (print_progress == TRUE && verbose == TRUE)) {
		char *help;
		help = g_option_context_get_help (context, FALSE, NULL);
		g_print ("%s", help);
		g_free (help);
		return 1;
	}
	input = filenames[0];
	output = filenames[1];

	PROGRESS_DEBUG("Initialised libraries, about to create video widget");
	PRINT_PROGRESS (2.0);

	app.input = input;
	app.output = output;

	thumb_app_setup_play (&app);
	thumb_app_set_filename (&app);

	PROGRESS_DEBUG("Video widget created");
	PRINT_PROGRESS (6.0);

	if (time_limit != FALSE)
		xplayer_resources_monitor_start (input, 0);

	PROGRESS_DEBUG("About to open video file");

	if (thumb_app_start (&app) == FALSE) {
		g_print ("xplayer-video-thumbnailer couldn't open file '%s'\n", input);
		exit (1);
	}
	thumb_app_set_error_handler (&app);

	/* We don't need covers when we're in gallery mode */
	if (gallery == -1)
		thumb_app_check_for_cover (&app);
	if (thumb_app_get_has_video (&app) == FALSE) {
		PROGRESS_DEBUG ("xplayer-video-thumbnailer couldn't find a video track in '%s'\n", input);
		exit (1);
	}
	thumb_app_set_duration (&app);

	PROGRESS_DEBUG("Opened video file: '%s'", input);
	PRINT_PROGRESS (10.0);

	if (gallery == -1) {
		/* If the user has told us to use a frame at a specific second
		 * into the video, just use that frame no matter how boring it
		 * is */
		if (second_index != -1) {
			assert_duration (&app);
			pixbuf = capture_frame_at_time (&app, second_index * 1000);
		} else {
			pixbuf = capture_interesting_frame (&app);
		}
		PRINT_PROGRESS (90.0);
	} else {
		assert_duration (&app);
		/* We're producing a gallery of screenshots from throughout the file */
		pixbuf = create_gallery (&app);
	}

	/* Cleanup */
	xplayer_resources_monitor_stop ();
	thumb_app_cleanup (&app);
	PRINT_PROGRESS (92.0);

	if (pixbuf == NULL) {
		g_print ("xplayer-video-thumbnailer couldn't get a picture from '%s'\n", input);
		exit (1);
	}

	PROGRESS_DEBUG("Saving captured screenshot");
	save_pixbuf (pixbuf, output, input, output_size, FALSE);
	g_object_unref (pixbuf);
	PRINT_PROGRESS (100.0);

	return 0;
}
static GdkPixbuf *
create_gallery (ThumbApp *app)
{
	GdkPixbuf *screenshot, *pixbuf = NULL;
	cairo_t *cr;
	cairo_surface_t *surface;
	PangoLayout *layout;
	PangoFontDescription *font_desc;
	gint64 stream_length, screenshot_interval, pos;
	guint columns = 3, rows, current_column, current_row, x, y;
	gint screenshot_width = 0, screenshot_height = 0, x_padding = 0, y_padding = 0;
	gfloat scale = 1.0;
	gchar *header_text, *duration_text, *filename;

	/* Calculate how many screenshots we're going to take */
	stream_length = app->duration;

	/* As a default, we have one screenshot per minute of stream,
	 * but adjusted so we don't have any gaps in the resulting gallery. */
	if (gallery == 0) {
		gallery = stream_length / 60000;

		while (gallery % 3 != 0 &&
		       gallery % 4 != 0 &&
		       gallery % 5 != 0) {
			gallery++;
		}
	}

	if (gallery < GALLERY_MIN)
		gallery = GALLERY_MIN;
	if (gallery > GALLERY_MAX)
		gallery = GALLERY_MAX;
	screenshot_interval = stream_length / gallery;

	/* Put a lower bound on the screenshot interval so we can't enter an infinite loop below */
	if (screenshot_interval == 0)
		screenshot_interval = 1;

	PROGRESS_DEBUG ("Producing gallery of %u screenshots, taken at %" G_GINT64_FORMAT " millisecond intervals throughout a %" G_GINT64_FORMAT " millisecond-long stream.",
			gallery, screenshot_interval, stream_length);

	/* Calculate how to arrange the screenshots so we don't get ones orphaned on the last row.
	 * At this point, only deal with arrangements of 3, 4 or 5 columns. */
	y = G_MAXUINT;
	for (x = 3; x <= 5; x++) {
		if (gallery % x == 0 || x - gallery % x < y) {
			y = x - gallery % x;
			columns = x;

			/* Have we found an optimal solution already? */
			if (y == x)
				break;
		}
	}

	rows = ceil ((gfloat) gallery / (gfloat) columns);

	PROGRESS_DEBUG ("Outputting as %u rows and %u columns.", rows, columns);

	/* Take the screenshots and composite them into a pixbuf */
	current_column = current_row = x = y = 0;
	for (pos = screenshot_interval; pos <= stream_length; pos += screenshot_interval) {
		if (pos == stream_length)
			screenshot = capture_frame_at_time (app, pos - 1);
		else
			screenshot = capture_frame_at_time (app, pos);

		if (pixbuf == NULL) {
			screenshot_width = gdk_pixbuf_get_width (screenshot);
			screenshot_height = gdk_pixbuf_get_height (screenshot);

			/* Calculate a scaling factor so that screenshot_width -> output_size */
			scale = (float) output_size / (float) screenshot_width;

			x_padding = x = MAX (output_size * 0.05, 1);
			y_padding = y = MAX (scale * screenshot_height * 0.05, 1);

			PROGRESS_DEBUG ("Scaling each screenshot by %f.", scale);

			/* Create our massive pixbuf */
			pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8,
						 columns * output_size + (columns + 1) * x_padding,
						 (guint) (rows * scale * screenshot_height + (rows + 1) * y_padding));
			gdk_pixbuf_fill (pixbuf, 0x000000ff);

			PROGRESS_DEBUG ("Created output pixbuf (%ux%u).", gdk_pixbuf_get_width (pixbuf), gdk_pixbuf_get_height (pixbuf));
		}

		/* Composite the screenshot into our gallery */
		gdk_pixbuf_composite (screenshot, pixbuf,
				      x, y, output_size, scale * screenshot_height,
				      (gdouble) x, (gdouble) y, scale, scale,
				      GDK_INTERP_BILINEAR, 255);
		g_object_unref (screenshot);

		PROGRESS_DEBUG ("Composited screenshot from %" G_GINT64_FORMAT " milliseconds (address %u) at (%u,%u).",
				pos, GPOINTER_TO_UINT (screenshot), x, y);

		/* We print progress in the range 10% (MIN_PROGRESS) to 50% (MAX_PROGRESS - MIN_PROGRESS) / 2.0 */
		PRINT_PROGRESS (MIN_PROGRESS + (current_row * columns + current_column) * (((MAX_PROGRESS - MIN_PROGRESS) / gallery) / 2.0));

		current_column = (current_column + 1) % columns;
		x += output_size + x_padding;
		if (current_column == 0) {
			x = x_padding;
			y += scale * screenshot_height + y_padding;
			current_row++;
		}
	}

	PROGRESS_DEBUG ("Converting pixbuf to a Cairo surface.");

	/* Load the pixbuf into a Cairo surface and overlay the text. The height is the height of
	 * the gallery plus the necessary height for 3 lines of header (at ~18px each), plus some
	 * extra padding. */
	surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, gdk_pixbuf_get_width (pixbuf),
					      gdk_pixbuf_get_height (pixbuf) + GALLERY_HEADER_HEIGHT + y_padding);
	cr = cairo_create (surface);
	cairo_surface_destroy (surface);

	/* First, copy across the gallery pixbuf */
	gdk_cairo_set_source_pixbuf (cr, pixbuf, 0.0, GALLERY_HEADER_HEIGHT + y_padding);
	cairo_rectangle (cr, 0.0, GALLERY_HEADER_HEIGHT + y_padding, gdk_pixbuf_get_width (pixbuf), gdk_pixbuf_get_height (pixbuf));
	cairo_fill (cr);
	g_object_unref (pixbuf);

	/* Build the header information */
	duration_text = xplayer_time_to_string (stream_length);
	filename = NULL;
	if (strstr (app->input, "://")) {
		char *local;
		local = g_filename_from_uri (app->input, NULL, NULL);
		filename = g_path_get_basename (local);
		g_free (local);
	}
	if (filename == NULL)
		filename = g_path_get_basename (app->input);

	/* Translators: The first string is "Filename" (as translated); the second is an actual filename.
			The third string is "Resolution" (as translated); the fourth and fifth are screenshot height and width, respectively.
			The sixth string is "Duration" (as translated); the seventh is the movie duration in words. */
	header_text = g_markup_printf_escaped (_("<b>%s</b>: %s\n<b>%s</b>: %d\303\227%d\n<b>%s</b>: %s"),
					       _("Filename"),
					       filename,
					       _("Resolution"),
					       screenshot_width,
					       screenshot_height,
					       _("Duration"),
					       duration_text);
	g_free (duration_text);
	g_free (filename);

	PROGRESS_DEBUG ("Writing header text with Pango.");

	/* Write out some header information */
	layout = pango_cairo_create_layout (cr);
	font_desc = pango_font_description_from_string ("Sans 18px");
	pango_layout_set_font_description (layout, font_desc);
	pango_font_description_free (font_desc);

	pango_layout_set_markup (layout, header_text, -1);
	g_free (header_text);

	cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); /* white */
	cairo_move_to (cr, (gdouble) x_padding, (gdouble) y_padding);
	pango_cairo_show_layout (cr, layout);

	/* Go through each screenshot and write its timestamp */
	current_column = current_row = 0;
	x = x_padding + output_size;
	y = y_padding * 2 + GALLERY_HEADER_HEIGHT + scale * screenshot_height;

	font_desc = pango_font_description_from_string ("Sans 10px");
	pango_layout_set_font_description (layout, font_desc);
	pango_font_description_free (font_desc);

	PROGRESS_DEBUG ("Writing screenshot timestamps with Pango.");

	for (pos = screenshot_interval; pos <= stream_length; pos += screenshot_interval) {
		gchar *timestamp_text;
		gint layout_width, layout_height;

		timestamp_text = xplayer_time_to_string (pos);

		pango_layout_set_text (layout, timestamp_text, -1);
		pango_layout_get_pixel_size (layout, &layout_width, &layout_height);

		/* Display the timestamp in the bottom-right corner of the current screenshot */
		cairo_move_to (cr, x - layout_width - 0.02 * output_size, y - layout_height - 0.02 * scale * screenshot_height);

		/* We have to stroke the text so it's visible against screenshots of the same
		 * foreground color. */
		pango_cairo_layout_path (cr, layout);
		cairo_set_source_rgb (cr, 0.0, 0.0, 0.0); /* black */
		cairo_stroke_preserve (cr);
		cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); /* white */
		cairo_fill (cr);

		PROGRESS_DEBUG ("Writing timestamp \"%s\" at (%f,%f).", timestamp_text,
				x - layout_width - 0.02 * output_size,
				y - layout_height - 0.02 * scale * screenshot_height);

		/* We print progress in the range 50% (MAX_PROGRESS - MIN_PROGRESS) / 2.0) to 90% (MAX_PROGRESS) */
		PRINT_PROGRESS (MIN_PROGRESS + (MAX_PROGRESS - MIN_PROGRESS) / 2.0 + (current_row * columns + current_column) * (((MAX_PROGRESS - MIN_PROGRESS) / gallery) / 2.0));

		g_free (timestamp_text);

		current_column = (current_column + 1) % columns;
		x += output_size + x_padding;
		if (current_column == 0) {
			x = x_padding + output_size;
			y += scale * screenshot_height + y_padding;
			current_row++;
		}
	}

	g_object_unref (layout);

	PROGRESS_DEBUG ("Converting Cairo surface back to pixbuf.");

	/* Create a new pixbuf from the Cairo context */
	pixbuf = cairo_surface_to_pixbuf (cairo_get_target (cr));
	cairo_destroy (cr);

	return pixbuf;
}
int main (int argc, char *argv[])
{
	GOptionGroup *options;
	GOptionContext *context;
	GError *err = NULL;
	BaconVideoWidget *bvw;
	GdkPixbuf *pixbuf;
	const char *input, *output;
	callback_data data;

	g_thread_init (NULL);

	context = g_option_context_new ("Thumbnail movies");
	options = bacon_video_widget_get_option_group ();
	g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
	g_option_context_add_group (context, options);
#ifndef THUMB_DEBUG
	g_type_init ();
#else
	g_option_context_add_group (context, gtk_get_option_group (TRUE));
#endif

	if (g_option_context_parse (context, &argc, &argv, &err) == FALSE) {
		g_print ("couldn't parse command-line options: %s\n", err->message);
		g_error_free (err);
		return 1;
	}

#ifdef G_OS_UNIX
	if (time_limit != FALSE) {
		errno = 0;
		if (nice (20) != 20 && errno != 0)
			g_warning ("Couldn't change nice value of process.");
	}
#endif

	if (print_progress) {
		fcntl (fileno (stdout), F_SETFL, O_NONBLOCK);
		setbuf (stdout, NULL);
	}

	if (g_fatal_warnings) {
		GLogLevelFlags fatal_mask;

		fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
		fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;
		g_log_set_always_fatal (fatal_mask);
	}

	if (raw_output == FALSE && output_size == -1)
		output_size = DEFAULT_OUTPUT_SIZE;

	if (filenames == NULL || g_strv_length (filenames) != 2 ||
	    (second_index != -1 && gallery != -1) ||
	    (print_progress == TRUE && verbose == TRUE)) {
		char *help;
		help = g_option_context_get_help (context, FALSE, NULL);
		g_print ("%s", help);
		g_free (help);
		return 1;
	}
	input = filenames[0];
	output = filenames[1];

	PROGRESS_DEBUG("Initialised libraries, about to create video widget");
	PRINT_PROGRESS (2.0);

	bvw = BACON_VIDEO_WIDGET (bacon_video_widget_new (-1, -1, BVW_USE_TYPE_CAPTURE, &err));
	if (err != NULL) {
		g_print ("totem-video-thumbnailer couldn't create the video "
				"widget.\nReason: %s.\n", err->message);
		g_error_free (err);
		exit (1);
	}
	data.input = input;
	data.output = output;
	g_signal_connect (G_OBJECT (bvw), "got-metadata",
			  G_CALLBACK (on_got_metadata_event),
			  &data);

	PROGRESS_DEBUG("Video widget created");
	PRINT_PROGRESS (6.0);

	if (time_limit != FALSE)
		totem_resources_monitor_start (input, 0);

	PROGRESS_DEBUG("About to open video file");

	if (bacon_video_widget_open (bvw, input, NULL, &err) == FALSE) {
		g_print ("totem-video-thumbnailer couldn't open file '%s'\n"
				"Reason: %s.\n",
				input, err->message);
		g_error_free (err);
		exit (1);
	}

	PROGRESS_DEBUG("Opened video file: '%s'", input);
	PRINT_PROGRESS (10.0);

	if (gallery == -1) {
		/* If the user has told us to use a frame at a specific second 
		 * into the video, just use that frame no matter how boring it
		 * is */
		if (second_index != -1)
			pixbuf = capture_frame_at_time (bvw, input, output, second_index);
		else
			pixbuf = capture_interesting_frame (bvw, input, output);
		PRINT_PROGRESS (90.0);
	} else {
		/* We're producing a gallery of screenshots from throughout the file */
		pixbuf = create_gallery (bvw, input, output);
	}

	/* Cleanup */
	bacon_video_widget_close (bvw);
	totem_resources_monitor_stop ();
	gtk_widget_destroy (GTK_WIDGET (bvw));
	PRINT_PROGRESS (92.0);

	if (pixbuf == NULL) {
		g_print ("totem-video-thumbnailer couldn't get a picture from "
					"'%s'\n", input);
		exit (1);
	}

	PROGRESS_DEBUG("Saving captured screenshot");
	save_pixbuf (pixbuf, output, input, output_size, FALSE);
	g_object_unref (pixbuf);
	PRINT_PROGRESS (100.0);

	return 0;
}
Example #5
0
/* Download the file which pointed by "pathname" */
static int transmit(struct server_attr *attr, char *pathname,
		int dir_name_length, int flags)
{
	int fd;
	unsigned int length, n;
	char *p;
	char str[BUFSZ];


	if ((fd = open(pathname, O_RDONLY)) == -1) {
		err_msg(errno, "open");
		return -1;
	}

	debug("upload: %s", pathname);
	debug("Transmit: %s", pathname);

	/* File's length */
	attr->req.len = 0;
	length = lseek(fd, 0, SEEK_END);
	attr->req.code = RESP_UPLOAD;
	memcpy(attr->data, &length, sizeof(length));
	attr->req.len += sizeof(length);

	if (!flags) {
		/* The pathname include filename only. */
		n = strlen(pathname);
		p = pathname;
	} else if (flags == UPLOAD_INCLUDE_DIR_NAME) {
		/* Setting the UPLOAD_INCLUDE_DIR_NAME flag */
		p = brevity_name(pathname, dir_name_length, flags);
		n = strlen(p);
	}
	printf("%s, %d\n", pathname, dir_name_length);

	/* Filename's length */
	memcpy(attr->data + attr->req.len, &n, sizeof(n));
	attr->req.len += sizeof(n);

	/* Filename */
	memcpy(attr->data + attr->req.len, p, n);
	attr->req.len += n;
	send_request(attr);


	SET_PROGRESS_UPLOAD(str, p, length);

	/* Send data to server*/
	n = 0;
	lseek(fd, 0, SEEK_SET);
	while ((attr->req.len = read(fd, attr->data, BUFSZ - 1)) > 0) {
		send_request(attr);
		n += attr->req.len;
		PRINT_PROGRESS(str, length, n);
	}

	if (attr->resp.len == -1) {
		err_msg(errno, "Upload occur error");
		return -1;
	}

	printf("\n");
	close(fd);
	return 0;
}
Example #6
0
int main (int argc, char *argv[])
{
	GOptionGroup *options;
	GOptionContext *context;
	GError *err = NULL;
	GdkPixbuf *pixbuf;
	const char *input, *output;
	ThumbApp app;

	setlocale (LC_ALL, "");
	bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
	bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
	textdomain (GETTEXT_PACKAGE);

	context = g_option_context_new ("Thumbnail movies");
	options = gst_init_get_option_group ();
	g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
	g_option_context_add_group (context, options);

	if (g_option_context_parse (context, &argc, &argv, &err) == FALSE) {
		g_print ("couldn't parse command-line options: %s\n", err->message);
		g_error_free (err);
		return 1;
	}

	fcntl (fileno (stdout), F_SETFL, O_NONBLOCK);
	setbuf (stdout, NULL);

	if (raw_output == FALSE && output_size == -1)
		output_size = DEFAULT_OUTPUT_SIZE;

	if (filenames == NULL || g_strv_length (filenames) != 2 ||
	    (second_index != -1 && gallery != -1)) {
		char *help;
		help = g_option_context_get_help (context, FALSE, NULL);
		g_print ("%s", help);
		g_free (help);
		return 1;
	}
	input = filenames[0];
	output = filenames[1];

	g_debug("Initialised libraries, about to create video widget");
	PRINT_PROGRESS (2.0);

	app.input = input;
	app.output = output;

	thumb_app_setup_play (&app);
	thumb_app_set_filename (&app);

	g_debug("Video widget created");
	PRINT_PROGRESS (6.0);

	g_debug("About to open video file");

	if (thumb_app_start (&app) == FALSE) {
		g_print ("totem-video-thumbnailer couldn't open file '%s'\n", input);
		exit (1);
	}
	thumb_app_set_error_handler (&app);

	if (thumb_app_get_has_video (&app) == FALSE) {
		g_debug ("totem-video-thumbnailer couldn't find a video track in '%s'\n", input);
		exit (1);
	}
	thumb_app_set_duration (&app);

	g_debug("Opened video file: '%s'", input);
	PRINT_PROGRESS (10.0);

	assert_duration (&app);
	/* We're producing a gallery of screenshots from throughout the file */
	pixbuf = create_gallery (&app);

	/* Cleanup */
	thumb_app_cleanup (&app);
	PRINT_PROGRESS (92.0);

	if (pixbuf == NULL) {
		g_print ("totem-video-thumbnailer couldn't get a picture from '%s'\n", input);
		exit (1);
	}

	g_debug("Saving captured screenshot to %s", output);
	save_pixbuf (pixbuf, output, input, output_size, FALSE);
	g_object_unref (pixbuf);
	PRINT_PROGRESS (100.0);

	return 0;
}
Example #7
0
int main(int argc, const char * argv[])
{
	setbuf (stdout, NULL);


#if TARGET_OS_MAC
	{
		thread_extended_policy_data_t		theFixedPolicy;
		theFixedPolicy.timeshare = false;	// set to true for a non-fixed thread
		thread_policy_set(pthread_mach_thread_np(pthread_self()), 
													THREAD_EXTENDED_POLICY, 
													(thread_policy_t)&theFixedPolicy, 
													THREAD_EXTENDED_POLICY_COUNT);

		// We keep a reference to the spawning thread's priority around (initialized in the constructor), 
		// and set the importance of the child thread relative to the spawning thread's priority.
		thread_precedence_policy_data_t		thePrecedencePolicy;
		
		thePrecedencePolicy.importance = 63 - 36;
		thread_policy_set(pthread_mach_thread_np(pthread_self()), 
													THREAD_PRECEDENCE_POLICY, 
													(thread_policy_t)&thePrecedencePolicy, 
													THREAD_PRECEDENCE_POLICY_COUNT);
	}
#endif


// These are the variables that are set up from the input parsing
	char* srcFilePath = NULL;
	char* destFilePath = NULL;
	char* auPresetFile = NULL;
	bool shortMemoryProfile = false;
	OSType manu, subType, type = 0;
	int userSetFrames = -1;
	
	for (int i = 1; i < argc; ++i)
	{
		if (strcmp (argv[i], "-au") == 0) {
            if ( (i + 3) < argc ) {                
                StrToOSType (argv[i + 1], type);
                StrToOSType (argv[i + 2], subType);
                StrToOSType (argv[i + 3], manu);
				i += 3;
			} else {
				printf ("Which Audio Unit:\n%s", usageStr);
				exit(1);
			}
		}
		else if (strcmp (argv[i], "-i") == 0) {
			srcFilePath = const_cast<char*>(argv[++i]);
		}
		else if (strcmp (argv[i], "-o") == 0) {
			destFilePath = const_cast<char*>(argv[++i]);
		}
		else if (strcmp (argv[i], "-p") == 0) {
			auPresetFile = const_cast<char*>(argv[++i]);
		}
		else if (strcmp (argv[i], "-m") == 0) {
			shortMemoryProfile = true;
		}
		else if (strcmp (argv[i], "-f") == 0) {
			sscanf(argv[++i], "%d", &userSetFrames);
		}
		else {
			printf ("%s\n", usageStr);
			exit(1);
		}
	}
	
	if (!type || !srcFilePath) {
		printf ("%s\n", usageStr);
		exit(1);
	}
	if (!destFilePath) {
		if (!shortMemoryProfile) {
			printf ("%s\n", usageStr);
			exit(1);
		}
	}
			// delete pre-existing output file
	if (!shortMemoryProfile) {
		FSRef destFSRef;
		if (FSPathMakeRef((UInt8 *)destFilePath, &destFSRef, NULL) == noErr) {
			// output file exists - delete it
			if (FSDeleteObject(&destFSRef)) {
				printf ("Cannot Delete Output File\n");
				exit(1);
			}
		}
	}
	
	CAComponentDescription desc(type, subType, manu);
	
	CFPropertyListRef presetDict = ReadPresetFromPresetFile(auPresetFile);
	
		// the num of frames to use when processing the file with the Render call
	UInt32 maxFramesToUse = shortMemoryProfile ? 512 : 32768;

		// not set from command line
	if (userSetFrames > 0) {
		maxFramesToUse = userSetFrames; 
	}
		
		// in some settings (for instance a delay with 100% feedback) tail time is essentially infinite
		// so you should safeguard the final OL render stage (post process) which is aimed at pulling the tail through
		// if you want to bypass this completely, just set this to zero.
	Float64 maxTailTimeSecs = 10.;
	
#pragma mark -
#pragma mark __ The driving code
#pragma mark -

	try 
	{
		CAComponent comp(desc);
			
			 // CAAUProcessor's constructor throws... so make sure the component is valid
		if (comp.IsValid() == false) {
			printf ("Can't Find Component\n");
			desc.Print();
			exit(1);
		}
			
		CAAUProcessor processor(comp);
													processor.AU().Print();
		
		CAAudioFile srcFile;
		CAAudioFile destFile; 
		
		srcFile.Open(srcFilePath);

		CAStreamBasicDescription procFormat (srcFile.GetFileDataFormat());
		procFormat.SetCanonical (srcFile.GetFileDataFormat().NumberChannels(), false);

													printf ("Processing Format:\n\t");
													procFormat.Print();
		
		
		if (!shortMemoryProfile) {
			FSRef parentDir;
			CFStringRef filename;
			PosixPathToParentFSRefAndName(destFilePath, parentDir, filename);
			destFile.CreateNew (parentDir, filename, 'AIFF', srcFile.GetFileDataFormat());
			destFile.SetClientFormat (procFormat);
		}
	
		srcFile.SetClientFormat (procFormat);
		
		AUOutputBL outputList(procFormat);

		ReadBuffer* readBuf = NULL;	

#if !CAAF_USE_EXTAUDIOFILE
		UInt64 numInputSamples = srcFile.GetNumberPackets();
#else
		UInt64 numInputSamples = srcFile.GetNumberFrames();
#endif
	
		if (shortMemoryProfile) {
			readBuf = new ReadBuffer;
			readBuf->readData = new AUOutputBL(procFormat);
			readBuf->readFrames = 0;
			UInt32 numFrames = UInt32(procFormat.mSampleRate / 2);
			readBuf->readData->Allocate (numFrames); // half a second of audio data
			readBuf->readData->Prepare(); // half a second of audio data
				
				// read 1/2 second of audio into this read buffer
			srcFile.Read (numFrames, readBuf->readData->ABL());
			
			sInputCallback.inputProc = MemoryInputCallback;
			sInputCallback.inputProcRefCon = readBuf;
			numInputSamples = numFrames;
		}
		else {
			if (desc.IsFConv()) {
				maxFramesToUse = userSetFrames == -1 ? 512 : maxFramesToUse; 
				// some format converter's can call you several times in small granularities
				// so you can't use a large buffer to render or you won't return all of the input data
				// this also lessens the final difference between what you should get and what you do
				// converter units *really* should have a version that are offline AU's to 
				// handle this for you.
				sInputCallback.inputProc = FConvInputCallback;
			} else
				sInputCallback.inputProc = InputCallback;
			
			sInputCallback.inputProcRefCon = &srcFile;
		}
				
		OSStatus result;
		require_noerr (result = processor.EstablishInputCallback (sInputCallback), home);
		require_noerr (result = processor.SetMaxFramesPerRender (maxFramesToUse), home); 
		processor.SetMaxTailTime (maxTailTimeSecs);
		require_noerr (result = processor.Initialize (procFormat, numInputSamples), home);
		if (presetDict) {
			require_noerr (result = processor.SetAUPreset (presetDict), home);
			CFRelease (presetDict);
		}
			// this does ALL of the preflighting.. could be specialise for an OfflineAU type
			// to do this piecemeal and do a progress bar by using the OfflineAUPreflight method
		require_noerr (result = processor.Preflight (), home);
		
		bool isDone; isDone = false;
		bool needsPostProcessing;
		bool isSilence;
		UInt32 numFrames; numFrames = processor.MaxFramesPerRender();

#if CA_AU_PROFILE_TIME
		sReadTime = 0;
		sRenderTime = 0;
#endif
					
PRINT_MARKS();
			// this is the render loop
		while (!isDone) 
		{
											#if CA_AU_PROFILE_TIME 
												UInt64 now = CAHostTimeBase::GetTheCurrentTime(); 
											#endif
			outputList.Prepare(); // have to do this every time...
			require_noerr (result = processor.Render (outputList.ABL(), numFrames, isSilence, &isDone,
											&needsPostProcessing), home);
											#if CA_AU_PROFILE_TIME 
												sRenderTime += (CAHostTimeBase::GetTheCurrentTime() - now);
											#endif

if (!shortMemoryProfile)
	PRINT_PROGRESS(processor.GetOLPercentComplete());
else
	PRINT_PROGRESS(((processor.SampleTime() / numInputSamples) * 100.));
	
			if (numFrames && !shortMemoryProfile)
				destFile.Write (numFrames, outputList.ABL());
		}
			
			// this is the postprocessing if needed
		if (!shortMemoryProfile && needsPostProcessing) 
		{
			isDone = false;
			numFrames = processor.MaxFramesPerRender();
			while (!isDone) {
				outputList.Prepare(); // have to do this every time...
											#if CA_AU_PROFILE_TIME 
												UInt64 now = CAHostTimeBase::GetTheCurrentTime(); 
											#endif
				require_noerr (result = processor.PostProcess (outputList.ABL(), numFrames, 
													isSilence, isDone), home);
											#if CA_AU_PROFILE_TIME 
												sRenderTime += (CAHostTimeBase::GetTheCurrentTime() - now); 
											#endif

PRINT_PROGRESS(processor.GetOLPercentComplete());

				if (numFrames && !shortMemoryProfile)
					destFile.Write (numFrames, outputList.ABL());
			}
		}

printf ("\n");

home:
		if (result) {
			printf ("Exit with bad result:%ld\n", result);
			exit(result);
		}
		
		if (readBuf) {
			delete readBuf->readData;
			delete readBuf;
		}
					
#if CA_AU_PROFILE_TIME
	if (!shortMemoryProfile) {
			// this flushes any remaing data to be written to the disk. 
			// the source file is closed in its destructor of course
		destFile.Close(); 
			// open the file again, to get stats about it for profiling
		destFile.Open(destFilePath);
	}

	SInt64 numWritten;
	if (shortMemoryProfile)
		numWritten = 0;
	else {
#if !CAAF_USE_EXTAUDIOFILE
		numWritten = destFile.GetNumberPackets();
#else
		numWritten = destFile.GetNumberFrames();
#endif
	}

	printf ("Read File Time:%.2f secs for %lld packets (%.1f secs), wrote %lld packets\n", 
						(CAHostTimeBase::ConvertToNanos (sReadTime) / 1.0e9),
						numInputSamples,
						(numInputSamples / procFormat.mSampleRate),
						numWritten);

	if (!shortMemoryProfile) 
	{
#if !CAAF_USE_EXTAUDIOFILE
		UInt64 numOutputSamples = destFile.GetNumberPackets();
#else
		UInt64 numOutputSamples = destFile.GetNumberFrames();
#endif
	
		if (numOutputSamples == numInputSamples) {
			printf ("\tWrote the same number of packets as read\n");
		} else {
			bool expectationMet = !desc.IsOffline(); // we don't have any expectations for offline AU's
			if (processor.LatencySampleCount() || processor.TailSampleCount()) {
				if (numOutputSamples - numInputSamples == processor.TailSampleCount())
					expectationMet = true;
				if (expectationMet)	
					printf ("Correctly wrote \'Read Size + Tail\'. ");
				printf ("AU reports (samples): %ld latency, %ld tail\n", 
										processor.LatencySampleCount(), processor.TailSampleCount());
			}
			if (expectationMet == false) 
			{
				if (numOutputSamples > numInputSamples) {
					printf ("\tWrote %lld packets (%.2f secs) more than read\n", 
								(numOutputSamples - numInputSamples), 
								((numOutputSamples - numInputSamples) / procFormat.mSampleRate));
				} else {
					printf ("\tRead %lld packets (%.2f secs) more than wrote\n", 
								(numInputSamples - numOutputSamples), 
								((numInputSamples - numOutputSamples) / procFormat.mSampleRate));
				}
			}
		}
	}
	
	Float64 renderTimeSecs = CAHostTimeBase::ConvertToNanos (sRenderTime - sReadTime) / 1.0e9;
	printf ("Total Render Time:%.2f secs, using render slice size of %ld frames\n", 
							renderTimeSecs, maxFramesToUse);
	
	Float64 cpuUsage;
	if (shortMemoryProfile)
		cpuUsage = (renderTimeSecs / 0.5) * 100.;
	else
		cpuUsage = (renderTimeSecs / (numInputSamples / procFormat.mSampleRate)) * 100.;
	printf ("CPU Usage for Render Time:%.2f%%\n", cpuUsage);

	CFStringRef str = comp.GetCompName();
	UInt32 compNameLen = CFStringGetLength (str);
	
	CFStringRef presetName = NULL;
	if (auPresetFile) {
		CFPropertyListRef dict;
		if (processor.AU().GetAUPreset (dict) == noErr) {
			presetName = (CFStringRef)CFDictionaryGetValue((CFDictionaryRef)dict, CFSTR("name"));
			CFRelease (dict);
		}
	}

	UInt32 presetLen = presetName ? CFStringGetLength(presetName) : 0;

	char* cstr = (char*)malloc (compNameLen + presetLen + 2 + 1);
	CFStringGetCString (str, cstr, (CFStringGetLength (str) + 1), kCFStringEncodingASCII);
	if (presetName) {
		cstr[compNameLen] = ':';
		cstr[compNameLen+1] = ':';
		CFStringGetCString (presetName, cstr + compNameLen + 2, (CFStringGetLength (presetName) + 1), kCFStringEncodingASCII);
	}
	PerfResult("AudioUnitProcess", EndianU32_NtoB(comp.Desc().componentSubType), cstr, cpuUsage, "%realtime");
	free (cstr);
#endif


	}
	catch (CAXException &e) {
		char buf[256];
		printf("Error: %s (%s)\n", e.mOperation, e.FormatError(buf));
		exit(1);
	}
	catch (...) {
		printf("An unknown error occurred\n");
		exit(1);
	}
			
	return 0;
}
int UnRUU(const char *path_ruu_exe_name, const char *path_out)
{
	PRINT_TITLE("Extracting rom.zip from %s", get_basename(path_ruu_exe_name));

	std::string path_base = get_absolute_cwd();

	// we need to operate in the out folder since unruu only outputs to current
	if (change_dir(path_out))
		return 2;

	int exit_code = 0;
	int res;

	res = run_program("unruu", path_ruu_exe_name, NULL);

	if (res != 0) {
		PRINT_ERROR("UnRUU failed");
		exit_code = 4;
	}

	if (access("rom.zip", F_OK) == 0) {
		// PRINT_INFO("Found rom.zip");
	}
	else if (access("rom_01.zip", F_OK) == 0 && access("rom_02.zip", F_OK) == 0) {
		PRINT_PROGRESS("Found rom_01.zip + rom_02.zip");
		exit_code = 5;
		struct stat stat_file01;
		struct stat stat_file02;
		if (stat("rom_01.zip", &stat_file01) < 0)
			PRINT_ERROR("Couldn't get rom_01.zip filesize!");
		else if (stat("rom_02.zip", &stat_file02) < 0)
			PRINT_ERROR("Couldn't get rom_02.zip filesize!");
		else {
			const char *minor_rom;
			if (stat_file01.st_size > stat_file02.st_size) {
				PRINT_PROGRESS("rom_01.zip is the dominant zip and will be used for further processing");
				rename("rom_01.zip", "rom.zip");
				minor_rom = "rom_02.zip";
			}
			else {
				PRINT_PROGRESS("rom_02.zip is the dominant zip and will be used for further processing");
				rename("rom_02.zip", "rom.zip");
				minor_rom = "rom_01.zip";
			}

			if (access("android-info.txt", F_OK) < 0) {
				PRINT_PROGRESS("Attempting extract of android-info.txt from %s...", minor_rom);
				run_program("unzip", "-n", minor_rom, "android-info.txt", NULL);
			}
			PRINT_PROGRESS("Attempting extract of hboot/hosd from %s...", minor_rom);
			run_program("unzip", "-n", minor_rom, "hboot*", "hosd*", NULL);
			exit_code = 0;
		}
	}
	else {
		PRINT_ERROR("UnRUU failed to produce either rom.zip or rom_01.zip+rom_02.zip aborting!");
		exit_code = 6;
	}

	change_dir(path_base);

	return exit_code;
}