Source

gnome-record-screen / GNOME-Record-Screen / src / Utils.cs

Full commit
/**
 * Utils.cs
 *
 * :copyright: 2008 mitsuhiko.
 * :license: BSD
 */

using System;
using System.IO;
using System.Text;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Linq;

using Gtk;
using Mono.Unix;

namespace Gnome.RecordScreen {
	
	/**
	 * Baseclass for all configuration pane widgets.
	 */
	public class ConfigurationPane : Gtk.Bin {
		
	}
	
	public interface IGstObject {
		
		bool IsAvailable { get; }
		string GstKey { get; }
	}
	
	public interface IEncoder : IGstObject {
	}
	
	public class Utils {
		private static VideoEncoder[] availableVideoEncoders;
		private static string[] mpegFormats = new string[] {
			"Generic MPEG1",
			"Standard VCD",
			"User VCD",
			"Generic Mpeg",
			"Standard SVCD",
			"User SVCD",
			"VCD stills sequences",
			"SVCD stills sequences",
			"DVD MPEG-2 for author",
			"DVD MPEG-2"
		};
		
		/**
		 * Shows an error message as dialog.
		 */
		public static void ShowError (string title, string message, Gtk.Window parent)
		{
			Gtk.Dialog dialog = new Gtk.MessageDialog (parent, DialogFlags.Modal,
			                                           MessageType.Error,
			                                           ButtonsType.Ok, message);
			dialog.Title = title;
			dialog.Run ();
			dialog.Destroy ();
		}
		
		public static void ShowError (string title, string message)
		{
			ShowError (title, message, null);
		}
		
		/**
		 * Makes sure the rectangle is divisble by two which is required
		 * for some codecs such as H.284.  If the rectangle is too small,
		 * a RectangleTooSmallException() is raised.
		 * 
		 * This function returns a copy of the rectangle if it had to
		 * modify it.
		 */
		public static Gdk.Rectangle RemodelRectangle (Gdk.Rectangle rect)
		{
			int width = rect.Width;
			int height = rect.Height;
			
			if (width % 2 == 1)
				width--;
			if (height % 2 == 1)
				height--;

			if (height < 32 || width < 32)
				throw new RectangleTooSmallException ();
			
			if (width == rect.Width && height == rect.Height)
				return rect;
			
			return new Gdk.Rectangle (rect.X, rect.Y, width, height);
		}
		
		/**
		 * Adds the current date to the filename.
		 */
		public static string AddDateToFilename (string filename)
		{
			DateTime now = DateTime.Now;
			string text = String.Format(" ({0}-{1}-{2})",
			                            now.Year, now.Month, now.Day);			
			return AddToFilename (filename, text);
		}
		
		/**
		 * Add something to a filename.
		 */
		public static string AddToFilename (string filename, string text)
		{
			string extension = "";
			List<string> parts = new List<string> (filename.Split ('.'));
			if (parts.Count > 1) {
				extension = "." + parts[parts.Count - 1];
				parts.RemoveAt(parts.Count - 1);
				filename = String.Join(".", parts.ToArray ());
			}
			return filename + text + extension;
		}
		
		/**
		 * Find all the files in a directory that start with the
		 * given prefix.
		 */
		public static string[] FindPrefixedFiles (string path, string prefix)
		{
			string real_prefix = Path.Combine (path, prefix);
			List<string> found = new List<string> ();
			foreach (string filename in Directory.GetFiles (path))
				if (filename.StartsWith (real_prefix))
					found.Add (Path.Combine (path, filename));
			return found.ToArray ();
		}
		
		public static string[] FindPrefixedFiles (string filename)
		{
			return FindPrefixedFiles (Path.GetDirectoryName (filename),
			                          Path.GetFileName (filename));
		}
		
		/**
		 * Inserts a number into the string where the pound signs are.
		 */
		public static string AddFormatedNumber (string template, int number)
		{
			string pattern = "";
			int length = 0;
			int first_pos = template.IndexOf ('#');
			if (first_pos < 0)
				throw new ArgumentException ("No pound signs in string.");

			for (int i = first_pos; i < template.Length; i++) {
				if (template[i] == '#') {
					length++;
					pattern += "0";
				}
			}
			
			return (template.Substring (0, first_pos) +
			        number.ToString (pattern) +
			        template.Substring (first_pos + length));
		}
		
		/**
		 * Sets the process title for process monitors
		 */
		public static void SetProcessName (string name)
		{
			if (name.IndexOf ('\0') >= 0)
				throw new ArgumentException ("null-bytes in name not allowed");
			try {
				if (prctl (15, Encoding.UTF8.GetBytes (name + "\0"),
				           IntPtr.Zero, IntPtr.Zero, IntPtr.Zero) != 0)
					throw new ApplicationException ("Error setting process name: " +
					                                Mono.Unix.Native.Stdlib.GetLastError ());
			}
			catch (EntryPointNotFoundException) {
				setproctitle (Encoding.UTF8.GetBytes ("%s\0"),
				              Encoding.UTF8.GetBytes (name + "\0"));
			}
		}
		
		/**
		 * List of supported MPEG formats.
		 */
		public static string[] MpegFormats {
			get { return mpegFormats; }
		}		
		
		/**
		 * A list of available video encoders.
		 */
		public static VideoEncoder[] AvailableVideoEncoders {
			get {
				if (availableVideoEncoders == null)
					availableVideoEncoders = (new VideoEncoder[] {
						VideoEncoder.H264,
						VideoEncoder.Theora,
						VideoEncoder.Mpeg,
						VideoEncoder.Png
					}).Where(x => x.IsAvailable).ToArray ();
				return availableVideoEncoders;
			}
		}
		
#region Low-Level Functions
		
		[DllImport ("libc")] // Linux
		private static extern int prctl (int option, byte [] arg2, IntPtr arg3,
		                                 IntPtr arg4, IntPtr arg5);

		[DllImport ("libc")] // BSD
		private static extern void setproctitle (byte [] fmt, byte [] str_arg);

#endregion
	}
}