Vala – the new programming language for Gnome

Published 25 October, 2009 in Linux , Programming - 0 Comments

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.