Posts tagged ‘Mono’

New Roxen Application Launcher for Linux written in Vala

This is not the latest version of Roxen Application Launcher. You'll find the latest version at the download page.

A couple of weeks ago I stumbled upon a fairly new programming language named Vala. I thought it looked promising and since Vala is developed by the GNOME project – with the purpose of making software development for, primarily, GNOME easier – and I’m an avid GNOME user I wanted to look deeper into the world of Vala.

I, and most programmers I believe, work in that way that I need a real and useful project when learning a new programming language. So I thought why not re-writing the Roxen Application Launcher I wrote in C#/Mono a couple of years ago in Vala – which by the way is syntactically very, very similar to C# and Java. I’d gotten tired of always having to fiddle with the C# code with every new version of Mono since something always broke when Mono was updated so a re-write wasn’t going to be totally pointless. The good thing about Vala is that the Vala compiler generates C code and that’s what you compile the program from. Fast code and hopefully more mature and stable libraries that won’t break backwards compatibility with every new release.

What about Vala

So, on I went about it and I think that Vala is a really promising language. It’s still a very young language so some library bindings isn’t behaving exactly as expected and the documentation isn’t directly redundant – although the Vala reference documentation site isn’t half bad. But since Vala pretty much is a wrapper for, or binding to, the underlying C libraries you can find answers to your questions that way. All in all I think Vala has a promising future: Way more simple than C and almost as fast and light on memory (remember the Vala compiler generates C code) and way faster than C#/Mono and free from any Microsoft associations ;) .

What about the Roxen Application Launcher

In this new version I utilize GConf for storing application settings. I also made use of – for the first time – the GNU Build Tools for compilation which also makes it easier to distribute and for others to compile from the sources. This also means that the distributed version compiles from the C sources and not the Vala sources so there’s no need for the Vala compiler to build the program.

Other than that there’s nothing fancy about it. The Vala sources is available at my Github repository.

Roxen Appliction Launcher 0.4.2 19:38, Sun 20 December 2009 :: 374 kB

Screenshots

The screenshots is showing the Swedish translation.

List of downloaded files
Screenshot 1 of the Roxen Application Launcher

Adding support for new file type
Screenshot 2 of the Roxen Application Launcher

The GNOME status icon
Screenshot 3 of the Roxen Application Launcher

Vala – the new programming language for Gnome

This Friday when I read the last issue (in Sweden) of Linux Format there was an article on a new programming language named Vala. The goal for Vala is to provide a modern programming language for, primarily, developing Gnome applications. There is of course Mono, but Vala doesn’t run in a virtual machine but is complied to machine code. But Vala resembles C# syntactically and has borrowed a lot of concepts from C#.

From what I understand Vala code is first translated into plain old C code, and then compiled with the ordinary GCC compiler. The benefit is that you don’t have to get head aches about memory management and so forth.

Vala seems pretty interesting and I downloaded it and compiled it without any difficulties. There are precompiled packages for most Linux distros – it’s available in the Ubuntu repository – but since Vala is new and still under development the distro packages is far behind in version.

There’s also a Vala IDE and plugins for GEdit, Anjuta and Eclipse.

Anyway, just to try Vala out I made a little program – using Val(a)ide – that changes the desktop wallpaper on a per interval basis. Send the program a path to a directory with images and the background will change among those images every *nth minutes.

This program needs libgee which at the moment needs to be added manually.

Compile: valac --pkg gconf-2.0 --pkg gee-1.0 --pkg gio-2.0 main.vala -o wallpaper-iterator

239 lines of Vala
  1. /* main.vala
  2. *
  3. * Copyright (C) 2009 Pontus Östlund <spam@poppa.se>
  4. *
  5. * No license what so ever. Do what ever you like...
  6. *
  7. * Author:
  8. * Pontus Östlund <spam@poppa.se>
  9. */
  10. // GLib isn't really neccessary since it's imported automatically
  11. using GLib, Gee, GConf;
  12. /**
  13. * User defined exception types
  14. */
  15. errordomain IOError {
  16. FILE_NOT_FOUND,
  17. NOT_A_DIRECTORY
  18. }
  19. /**
  20. * Main class
  21. */
  22. public class Main
  23. {
  24. /**
  25. * Used as reference in option parser
  26. */
  27. static int arg_delay;
  28. /**
  29. * Application command line options
  30. */
  31. const OptionEntry[] options = {
  32. { "delay", 'd', 0, OptionArg.INT, ref arg_delay,
  33. "Number of minutes to wait before swapping background", null },
  34. { null }
  35. };
  36. /**
  37. * Main method
  38. *
  39. * @param args
  40. * Command line arguments
  41. */
  42. public static int main (string[] args)
  43. {
  44. try {
  45. var opt = new OptionContext("\"/path/to/wallpapers\"");
  46. opt.set_help_enabled(true);
  47. opt.add_main_entries(options, null);
  48. opt.parse(ref args);
  49. }
  50. catch (GLib.Error e) {
  51. stderr.printf("Error: %s\n", e.message);
  52. stderr.printf("Run '%s --help' to see a full list of available "+
  53. "options\n", args[0]);
  54. return 1;
  55. }
  56. if (args.length < 2) {
  57. stderr.printf("Missing argument!\n");
  58. stderr.printf("Run '%s --help' for usage\n", args[0]);
  59. return 1;
  60. }
  61. // Default time before changing background is 30 minutes
  62. int delay = arg_delay > 0 ? arg_delay*60 : 60*30;
  63. try {
  64. WallpaperIterator bg = new WallpaperIterator(args[1], delay);
  65. bg.run();
  66. bg.stop();
  67. }
  68. catch (IOError e) {
  69. stderr.printf("Error: %s\n", e.message);
  70. return 1;
  71. }
  72. finally {
  73. stderr.printf("Finally block reached!\n");
  74. }
  75. return 0;
  76. }
  77. }
  78. /**
  79. * Class that handles changeing of desktop wallpapers on a per interval way
  80. */
  81. public class WallpaperIterator : GLib.Object
  82. {
  83. /**
  84. * Number of seconds to wait before changeing wallpaper
  85. */
  86. private int delay = 0;
  87. /**
  88. * Current index in the images list
  89. */
  90. private int index = 0;
  91. /**
  92. * List of images to change between
  93. */
  94. private ArrayList<string> files = new ArrayList<string>();
  95. /**
  96. * List of allowed content types
  97. */
  98. private ArrayList<string> allow = new ArrayList<string>();
  99. /**
  100. * GConf client object
  101. */
  102. private GConf.Client gclient = null;
  103. /**
  104. * GConf registry where the background image is set
  105. */
  106. private string gconf_key = "/desktop/gnome/background/picture_filename";
  107. /**
  108. * Background being used when the application is started
  109. */
  110. private string default_bg = null;
  111. /**
  112. * Constructor
  113. *
  114. * @param dir
  115. * The directory to collect wallpapers in
  116. * @param delay
  117. * Time to wait - in seconds - before swapping wallpaper
  118. */
  119. public WallpaperIterator(string dir, int delay)
  120. throws IOError
  121. {
  122. assert(delay > 0);
  123. allow.add("image/jpeg");
  124. allow.add("image/png");
  125. var f = File.new_for_path(dir);
  126. if (!f.query_exists(null))
  127. throw new IOError.FILE_NOT_FOUND(" \"%s\" doesn't exits!".printf(dir));
  128. if (f.query_file_type(0, null) != FileType.DIRECTORY) {
  129. throw new IOError.NOT_A_DIRECTORY(" \"%s\" is not a directory!"
  130. .printf(dir));
  131. }
  132. collect(f.get_path());
  133. if (files.size < 2) {
  134. warning("Not enough images found for this application to be useful!\n");
  135. return;
  136. }
  137. this.delay = delay;
  138. }
  139. /**
  140. * Run the application. Starts a MainLoop
  141. */
  142. public void run()
  143. {
  144. gclient = GConf.Client.get_default();
  145. default_bg = gclient.get_string(gconf_key);
  146. MainLoop loop = new MainLoop(null, false);
  147. var time = new TimeoutSource(delay*1000);
  148. time.set_callback(() => { swap(); });
  149. time.attach(loop.get_context());
  150. loop.run();
  151. }
  152. /**
  153. * Stop the application. Tries to reset the background
  154. */
  155. public void stop()
  156. {
  157. try {
  158. if (default_bg != null)
  159. gclient.set_string(gconf_key, default_bg);
  160. }
  161. catch (GLib.Error e) {
  162. warning("Failed to restore background!\n");
  163. }
  164. }
  165. /**
  166. * Does the actual background swapping
  167. */
  168. private void swap()
  169. {
  170. if (index >= files.size) {
  171. debug("Restart...\n");
  172. index = 0;
  173. }
  174. debug("Callback...%-2d (%s)\n", index, files[index]);
  175. try {
  176. gclient.set_string(gconf_key, files[index]);
  177. }
  178. catch (GLib.Error e) {
  179. warning("Failed to set background: %s\n", e.message);
  180. }
  181. index++;
  182. }
  183. /**
  184. * Collect images
  185. *
  186. * @param path
  187. */
  188. private void collect(string path)
  189. {
  190. try {
  191. var dir = File.new_for_path(path).enumerate_children(
  192. "standard::name,standard::type,standard::content-type",
  193. 0, null
  194. );
  195. FileInfo fi;
  196. string fp;
  197. while ((fi = dir.next_file(null)) != null) {
  198. fp = path + "/" + fi.get_name();
  199. if (fi.get_file_type() == FileType.DIRECTORY)
  200. collect(fp);
  201. else {
  202. if (fi.get_content_type() in allow)
  203. files.add(fp);
  204. else
  205. warning("Skipping \"%s\" due to unallowed content type\n", fp);
  206. }
  207. }
  208. }
  209. catch (GLib.Error e) {
  210. warning("Error: %s\n", e.message);
  211. }
  212. }
  213. }

I think Vala looks promising and I will try it out trying to write a more complex application when I find the time.

Gnome Font Manager

One thing I miss on Linux Gnome is font manager. Not just a font viewer but a proper manager like the old Adobe Type Manager. So I thought: Well, lets create one then! It might be that it already exist some font managers for Linux/Gnome but as always; this will be a good project for learning new stuff so I really don’t care if there are 1000 font managers out there ;)

Font parsing

The first thing to do, and that I have done, is porting my font parser from PLib to C#. That was no major head ache. There are at least to different font classes available in C# Mono (`System.Drawing.Font` and `Pango.Font`) but they don’t give all information about the font that I want.

Worth mentioning is that I heavily used the Mono DataConverter class to unpack the binary strings in the fonts. The unpack() function in PHP is just tremendous and there doesn’t seem to be a native alike in C#. But thanks to Miguel de Icasa’s DataConverter it went quite alright.

Font preview

The next thing to do was figuring out how to create the font previews. And I figured it out ;) First I though of using the console program gnome-thumbnail-font to create the previews but I had to throw that one into the bin since it doesn’t seem to handle multi line text. Since I’ve never used the graphics functions in C# before I came to the conclusion that I had to create the previews all by my self. It was quite easy finding good examples on the net of how to create text images with C#. A couple of hours later that problem was also solved (as you can see in the screen shot below). And man the graphics stuff in C# is fast. The preview images are generated instantly!

Next step

I have a lot left to do before this is a useful program but we’re heading there. One feature I’m planning on implementing is the ability to create your own font sets that you can activate/deactivate.

And I will probably come up with some more stuff to add, but that will be a later head ache!

Screen shot: Gnome Font Manager
Gnome Font Manager