Moonlight is a Linux implementation of Microsoft's Silverlight, a Web application framework that provides capabilities similar to Adobe Flash. Moonlight is part of the Mono Project and is free and open-source software.
Moonlight is part of the Mono Project. The Mono Project is an open-source implementation of ECMA standards 334 and 335: the C# Language (pronounced “c-sharp”) and the Common Language Infrastructure (CLI), respectively. Moonlight implements a subset of the CLI and fits it into your Web browser as a plugin. Think of Moonlight as a free-as-in-speech, open-source alternative to Adobe's proprietary Flash platform, which often is neglected in Linux. That's a lot of large words just to say that Moonlight is part of something bigger that brings you one of the most powerful languages and runtimes available for programming pretty much anything.
Before programming anything, I recommend just seeing what Moonlight is capable of doing. Many Linux distributions support Moonlight out of the box. In Ubuntu 10.04, you can install Moonlight by selecting the moonlight-plugin-mozilla from your package manager of choice. Once you do that, visit some Moonlight- or Silverlight-driven Web sites. Silverlight is the name of Microsoft's implementation of Moonlight, which runs on Windows and Mac OS X. Don't let the different name fool you. If it runs in Silverlight, it probably will run in Moonlight too. The 2008 Summer Olympics and 2010 Winter Olympics were broadcast by NBC in the USA using Moonlight on Linux. Here are a few other examples:
The Channel 9 Web site uses a Moonlight player: channel9.msdn.com/posts/NicFill/Microsoft-Contributes-Code-to-the-Linux-Kernel. This particular video talks about Microsoft's contribution to the Linux kernel.
flickrlight uses Moonlight to offer an interesting and beautiful alternate view into Flickr: flickrlight.net.
This Web site has a vector graphic map of the Moscow Metro that can be zoomed and panned: www.kalantyr.ru/metro. It is very fast compared to what a similar HTML and JavaScript solution might be.
Getting started developing with Moonlight is easy. As an example scenario, let's write the “media” portion of a Web site for our band named Fictitious Maximus using Moonlight, and to begin, we need a song to which users can listen.
First, install MonoDevelop in your Linux distribution. In Ubuntu 10.04, you need the monodevelop-moonlight package. Start MonoDevelop (Figure 1), and choose Start a new Solution from the Common Actions section of the Welcome page. If you don't see the Welcome Page, select Welcome Page from the View Menu. From the tree view on the left, expand the C# node if it is not already expanded, and select the Moonlight node. Choose the Moonlight Application template from the center list of templates.
I'm naming this project “FictMaxSL” to go along with the FictMax Web site. In the Name text box of the New Solution window, type FixtMaxSL and click OK. Once the new solution and project are created, expand the FictMaxSL project node from the Solution Panel. If for some reason you don't see a Solution Panel on the left side of your MonoDevelop window, choose Solution from the View menu in MonoDevelop.
The first thing to learn about Moonlight is something called eXtensible Application Markup Language (XAML), shown in Figure 2. XAML is really just a fancy XML object serialization format. The devil in learning XAML is just how fancy it can be. Much of the documentation for XAML is in the Microsoft Silverlight documentation, available at the Silverlight Web site. Luckily for our example here, we don't need to know too much about the details.
Every application needs an entry point, and Moonlight is no different. When a Moonlight application starts, it looks for the object that has been defined as the Entry Point. If you right-click on the FictMaxSL project in Solution Panel and click Options, then click the Moonlight tree node from the left side of the options box, you will see a text box labeled Entry Point. This entry point is compiled into the Moonlight output file called a XAP (pronounced “zap”). A XAP file is roughly the Moonlight equivalent to an Adobe Flash SWF file.
Take a look at the App.xaml file. You can open the file by double-clicking on it in the Solution Panel. Notice there is an Application root node with an x:Class="FictMaxSL.App" attribute and value. This tells the XAML Compiler (yes, XAML gets compiled too) what class you are defining. The XAML compiler generates some C# code in the form of a partial class (a single class spread across multiple files). This code is then compiled along with other generated code and the C# code you write for your application. This means you can write code in another file in the same FictMaxSL.App class to make the resulting class definition for the FictMaxSL.App class. If you open the App.xaml.cs file, you will see the rest of the FictMaxSL.App class. The important thing to note is that the Startup event is wired to the OnStartup event handler, and this sets the RootVisual member of the Application class to be a new Instance of the Page type. Now, look at Page.xaml and Page.xaml.cs to see the code for the Moonlight “Page”. Note that even though this is called a page, it could be only part of a much bigger Web page, or it might not even occupy space on a Web page at all.
The Page.xaml file contains the declaration that your page is a UserControl by starting with a UserControl root node. It then imports some common Moonlight namespaces and finally declares that your page will contain a Grid, and inside that Grid is a TextBlock with text content of “Hello World”. Immediately you can see that XAML is somewhat similar to HTML in that you are declaring the markup of your page using tags and attributes, but also notice that instead of separate tags or CSS for things like font and color, those declarations become part of your objects. The TextBlock tag has attributes for FontSize and ForeGround color. If you are familiar with object-oriented programming, you also can read this as you are creating a new TextBlock object and setting property values on that object. Indeed, the rough C# code equivalent to the TextBlock XAML is:
new TextBlock { FontSize=30; Foreground="White"; };
This is a slight over-simplification of what is really happening, due to the use of something in XAML and Moonlight called Dependency Properties. It turns out that Foreground might be a color, but it might be some other kind of Brush, and so you can assign it using XAML to the string “White”, which automatically is converted into an object typed SolidColorBrush, or you can assign it to some other kind of Brush. You could make a Brush out of an image or a video and use that as the Brush with which you paint your text using TextBlock.
As you go deeper with XAML and Moonlight, you will find that “you could” is a common theme. Nearly everything can be composed with nearly everything else. This is vastly different from HTML with respect to the ability to compose its elements. You can place an image inside a button. You can place a button inside an image. You can place a button inside of that image that contains a button. It is not just images and buttons. The common Content controls include TextBox, Button, RadioButton, CheckBox, HyperlinkButton, Image, ListBox, MediaElement, PasswordBox, ProgressBar, Slider and ToggleButton. For example:
<Button id="buttonWithImage"> Hello <Image src="..."/> </Button>
Another type of control, called a Layout Control, handles the sizing and positioning of controls. Controls are not necessarily presented in the order that they are displayed as HTML documents are rendered. The Grid, StackPanel, ScrollViewer and TabControl are all examples of Layout controls.
For details on all controls and layout, see the Moonlight and Silverlight documentation, or pick up a book on Silverlight. For our example, let's use some of these controls to display information about our band and play some music.
Replace the Grid tag and all of its contents with the following XAML:
<Grid x:Name="LayoutRoot" Background="White" > <TextBlock Margin="8" TextWrapping="Wrap"> <Run Text="Hello, Fictitious Maximus lover."/> <LineBreak/> <LineBreak/> <Run FontSize="16" Text="Welcome to our rad new website."/> <LineBreak/> <Run FontSize="16" Text=""/> <LineBreak/> <Run FontSize="16" Text="We are excited about this sweet ↪new track. check it out."/> <LineBreak/> <Run FontSize="16" Text=""/> </TextBlock> <MediaElement x:Name="player" Height="64" Margin="24,128,256,0" VerticalAlignment="Top" Source="/Air_(Bach).mp3"/> <Button x:Name="start" Height="32" HorizontalAlignment="Left" Margin="80,128,0,0" VerticalAlignment="Top" Width="88" Content="Start"/> <Button x:Name="stop" Height="32" Margin="172,128,0,0" VerticalAlignment="Top" Content="Stop" HorizontalAlignment="Left" Width="104"/> </Grid>
Then, open the Page.xaml.cs file, and replace the body of the Page class with this:
public MainPage() { // Required to initialize variables InitializeComponent(); this.start.Click += HandleStarthandleClick; this.stop.Click += HandleStophandleClick; } void HandleStophandleClick (object sender, RoutedEventArgs e) { player.Pause(); } void HandleStarthandleClick (object sender, RoutedEventArgs e) { player.Play(); }
So far, you have created a TextBlock containing Runs of text and LineBreaks, a MediaElement and two Buttons. In the MediaElement, you have set the x:Name property to “player” and the Source property to “/Air_Bach.mp3” (this is a file I pulled from the Wikipedia Sound List for this example). Add the file to your project by right-clicking on the project in the Solution Panel, and under the Add submenu, select Add Files. Select the file, and if prompted about what to do, choose Copy to copy the file into your project. Next, right-click on the newly added MP3, and select Properties: to display the Properties Panel. From the list in the Properties Panel, set the “Copy To Output Directory” value to “Copy If Newer”. This will ensure that your MP3 file is deployed correctly.
Next, you created two buttons named “start” and “stop”. Then, in the Page.xaml.cs file, you have wired up the Click events for those buttons to event handler methods and call the player.Pause and player.Play methods in those event handlers. This causes clicking the buttons to stop and start the playback of the Media Element.
Now, choose Run from the Run menu, or press F5 in MonoDevelop to run your Moonlight application. MonoDevelop launches Firefox by default and points it to read your project's TestPage.HTML file (Figure 3). This HTML file is a tiny wrapper around the generated XAP file.
Now that you have a functioning Moonlight application in your browser, the sky's the limit. You can dive into more controls and use storyboards to animate your application. Moonlight also is scriptable through the browser via JavaScript. If your Moonlight control does not take up the entire Web page, you can use JavaScript to interact with your HTML and Moonlight controls. The flip side of that is also possible. You can use Moonlight to manipulate the HTML DOM in the hosting Web page. If JQuery or another JavaScript library isn't cutting it for you, or if you aren't comfortable writing a lot of JavaScript, you can write C# and execute it in Moonlight to manipulate your Web page.
The interop between JavaScript and C# is very compelling, and although Web browsers continue to make their JavaScript interpreters faster, C# is compiled to bytecode and then Just-In-Time interpreted to native machine code by Moonlight. This is much faster than interpreted JavaScript. There is a demo comparing JavaScript to C# playing Chess that shows just how far ahead each can look at the Chess board given the same amount of time to make a move (www.silverlight.net/content/samples/sl2/silverlightchess/run/default.html). C# is much faster.
Moonlight version numbers follow Silverlight's version numbers. You can view the Roadmap at www.mono-project.com/MoonlightRoadmap. Coming very soon will be Moonlight 3, which adds some support for 3-D and pixel shaders, application library caching, out-of-browser and off-line support, and pluggable multimedia pipelining and codecs. This means Moonlight won't be just for Web browsers anymore, and Linux desktop applications will be able to be written using Moonlight. The codec support should be of interest to those who love freedom. It means Moonlight will support plugging in Ogg, Theora or other free codecs. Unlike Flash, you will not be limited to flv and h264 or other proprietary and patent-encumbered codecs. Even further down the road, Moonlight plans to support version 4, which includes Webcam and microphone support; more trust for reading off the local filesystem; improved localization, including right-to-left text; desktop notifications, aka Toast; and rendering HTML onto Moonlight control surfaces.
In the Microsoft world, there is a very good design tool called Expression Blend, which lets you visually design your applications. This is somewhat similar to Adobe's Flex Builder. Currently, there is nothing like this for Linux. The developer experience consists of writing XAML by hand. This is probably fine for many, but it can be nice to use a visual tool to get a good-looking design quickly before writing code around it. The Mono team is hard at work creating a designer piece for Moonlight that will plug in to MonoDevelop. However, the time of arrival for this MonoDevelop plugin is currently unknown.
To keep the runtime small, Moonlight and Silverlight do not include a large number of more advanced controls. Instead, developers are expected to build their own controls or include third-party controls in their applications. One very common, open-source third-party control library is the Silverlight Toolkit available at silverlight.codeplex.com, which includes more than just controls. There are controls for various functionalities, appropriately named Accordion, AutoCompleteBox, Calendar, DatePicker, NumericUpDown, Rating, TimePicker, TabControl and TreeView.
Various themes also are included. As you might guess, themes are a way of changing the look and feel of all controls at once. You can apply a theme, and all your buttons, text boxes, combo boxes, radio buttons and so on change their look and feel to that of the theme. Although a larger application might demand its own custom Theme to set itself apart from other applications, it is very common for applications to use one of the predefined themes to obtain a different from normal look and feel.
Various commercial third-party control vendors sell toolkits for Silverlight and, thus, Moonlight. Telerik RadControls for Silverlight, DevExpress DX Experience Silverlight and Syncfusion UI for Silverlight are among the more-popular products aimed at developing business applications. They typically include controls for Reports, Charts, Data Grids, Schedules and Calendars. They also are not free-as-in-speech free or open-source software, although some of them offer free-as-in-beer parts of their controls. At the end of the day, if you are writing software for paying customers and can buy one of these off-the-shelf tools and deliver more value in less time, they are a worthwhile investment.
Moonlight is a very important part of the Linux desktop ecosystem and a pillar in the ever expanding Mono Project. Its future as not just as a browser add-in, but as a full-fledged desktop application development platform means it should be considered carefully by every developer. The rich set of controls, both built in and available from third parties, is as good or better than any other development platform available for Linux today. Thanks to the wonderful MonoDevelop IDE, getting started developing Moonlight applications is very easy. Moonlight is poised to be the premiere development platform for the Linux desktop and the Linux Web browser space.