2009-10-05 Chris Toshok <toshok@ximian.com>
[moon.git] / tools / mopen / mopen1.cpp
blob7d15fe1ecba95a9ab8205e783f160c2bb6f0d855
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 //
3 // mopen1.cpp: Moonlight Open Application
4 //
5 // Opens a XAML file
6 //
7 // Author:
8 // Rolf Bjarne Kvinge (RKvinge@novell.com)
9 //
11 // See LICENSE file in the Moonlight distribution for licensing details
13 // TODO:
14 // Implement everything mopen implements
17 #ifdef HAVE_CONFIG_H
18 #include <config.h>
19 #endif
21 #include <gtk/gtk.h>
22 #include <stdlib.h>
23 #include <unistd.h>
24 #include <fcntl.h>
25 #include <errno.h>
27 #include "downloader.h"
28 #include "runtime.h"
29 #include "xaml.h"
30 #include "canvas.h"
31 #include "window-gtk.h"
32 #include "frameworkelement.h"
33 #include "asf.h"
34 #include "pipeline.h"
36 static bool
37 get_video_size (const char *filename, int *width, int *height)
39 MediaResult tmp;
40 FileSource *src = NULL;
41 ASFParser *parser = NULL;
42 bool result = false;
43 const asf_stream_properties* stream_properties;
44 const asf_video_stream_data* video_data;
45 const BITMAPINFOHEADER* bmp;
47 src = new FileSource (NULL, filename);
48 if (!MEDIA_SUCCEEDED (tmp = src->Initialize ())) {
49 fprintf (stderr, "mopen1: Error while opening the file %s\n", filename);
50 goto cleanup;
53 parser = new ASFParser (src, NULL);
54 if (!MEDIA_SUCCEEDED (tmp = parser->ReadHeader ())) {
55 fprintf (stderr, "mopen1: Error while reading asf header in file %s\n", filename);
56 goto cleanup;
59 for (int i = 0; i <= 127; i++) {
60 if (!parser->IsValidStream (i))
61 continue;
63 stream_properties = parser->GetStream (i);
65 if (!stream_properties->is_video ())
66 continue;
68 video_data = stream_properties->get_video_data ();
70 if (!video_data)
71 continue;
73 bmp = video_data->get_bitmap_info_header ();
74 if (!bmp)
75 continue;
78 *width = bmp->image_width;
79 *height = bmp->image_height;
80 result = true;
81 goto cleanup;
84 cleanup:
85 if (parser)
86 parser->unref ();
87 if (src)
88 src->unref ();
89 return result;
92 static void
93 Help (void)
95 printf ("Usage is: mopen1 [args] [file.xaml]\n\n"
96 "Arguments are:\n"
97 " --media <filename> Automatically creates some xaml with a MediaElement whose source is set to the filename\n"
98 " This is also automatically assumed if 1 filename is passed and the extension is either\n"
99 " wmv, wma, vc1, asf or mp3.\n"
100 " --timeout T Time, in seconds, before closing the window\n"
103 TODO:
104 " --desklet Remove window decoration for desklets use\n" +
105 " --fixed Disable window resizing\n" +
106 " --geometry WxH Overrides the geometry to be W x H pixels\n" +
107 " --host NAME Specifies that this file should be loaded in host NAME\n" +
108 " --parseonly Only parse (don't display) the XAML input\n" +
109 " --story N1[,Nx] Plays the storyboard name N1, N2, .. Nx when the clicked\n" +
110 " -s,--stories Automatically prepare to play all stories on click\n" +
111 " --sync Make the gdk connection synchronous\n" +
112 " --transparent Transparent toplevel\n" +
117 class FileDownloadState {
118 public:
119 FileDownloadState (Downloader *dl) : uri(NULL), downloader(dl) { }
121 virtual ~FileDownloadState () { Close (); }
122 size_t size;
123 char *uri;
125 void Abort () { Close (); }
126 char* GetResponseText (char *fname, char* PartName) { return NULL; } // XXX
127 void Open (const char *verb, const char *uri)
129 int fd = open (uri, O_RDONLY);
130 if (fd == -1) {
131 const char *msg = g_strerror (errno);
132 printf ("downloader failed to open %s: %s\n", uri, msg);
133 downloader->NotifyFailed (msg);
134 return;
137 struct stat sb;
138 fstat (fd, &sb);
139 close (fd);
140 this->uri = g_strdup (uri);
141 size = sb.st_size;
142 downloader->NotifySize (size);
145 void Send () {
146 if (uri != NULL)
147 downloader->NotifyFinished (uri);
150 void Close ()
152 g_free (uri);
153 uri = NULL;
155 private:
156 Downloader *downloader;
159 static gpointer
160 downloader_create_state (Downloader *dl)
162 return new FileDownloadState (dl);
165 static void
166 downloader_destroy_state (gpointer data)
168 delete ((FileDownloadState*)data);
171 static void
172 downloader_open (gpointer state, const char *verb, const char *uri, bool streaming, bool disable_cache)
174 ((FileDownloadState*)state)->Open (verb, uri);
177 static void
178 downloader_send (gpointer state)
180 ((FileDownloadState*)state)->Send ();
183 static void
184 downloader_abort (gpointer state)
186 ((FileDownloadState*)state)->Abort ();
189 static void
190 downloader_header (gpointer state, const char *header, const char *value)
192 g_assert_not_reached ();
195 static void
196 downloader_body (gpointer state, void *body, guint32 length)
198 g_assert_not_reached ();
201 static void
202 *downloader_request (const char *method, const char *uri, gpointer context)
204 g_assert_not_reached ();
207 static gboolean
208 delete_event (GtkWidget *widget, GdkEvent *e, gpointer data)
210 gtk_main_quit ();
211 return 1;
215 static int LoadXaml (const char* file)
217 int result = 0;
219 runtime_init_desktop();
221 char* dir = g_path_get_dirname (file);
222 chdir (dir);
223 g_free (dir);
224 // printf ("nopen: %s\n", strerror (errno));
226 file = g_basename (file);
228 Downloader::SetFunctions (downloader_create_state,
229 downloader_destroy_state,
230 downloader_open,
231 downloader_send,
232 downloader_abort,
233 downloader_header,
234 downloader_body,
235 downloader_request,
236 NULL,
237 NULL);
239 Type::Kind et;
241 MoonWindowGtk *moon_window = new MoonWindowGtk (false, 300, 300);
242 Surface* surface = new Surface (moon_window);
243 XamlLoader* loader = new XamlLoader (file, NULL, surface);
244 DependencyObject* dob = loader->CreateDependencyObjectFromFile (file, FALSE, &et);
246 delete loader;
248 if (dob == NULL) {
249 printf ("nopen::LoadXaml ('%s'): Could not create xaml from the file.\n", file);
250 result = 1;
251 } else if (dob->Is (Type::CANVAS)) {
253 Canvas* ui = (Canvas*) dob;
254 surface->Attach ((Canvas*) ui);
255 ui->unref ();
257 int width = ui->GetWidth ();
258 int height = ui->GetHeight ();
260 if (width < 100)
261 width = 100;
262 if (height < 100)
263 height = 100;
265 surface->Resize (width, height);
267 GtkWidget *window;
269 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
270 gtk_widget_set_app_paintable (window, TRUE);
272 gtk_signal_connect (GTK_OBJECT (window), "delete-event", G_CALLBACK (delete_event), surface);
273 gtk_container_add (GTK_CONTAINER(window), moon_window->GetWidget ());
275 gtk_widget_set_usize (window, width, height);
277 gtk_widget_show_all (window);
279 gtk_main ();
281 } else {
282 printf ("nopen::LoadXaml ('%s'): didn't get an uielement from the xaml.\n", file);
283 result = 1;
286 surface->Zombify ();
287 surface->unref ();
289 runtime_shutdown ();
291 printf ("Shutting down...\n");
293 return result;
296 gboolean
297 QuitTimeout (gpointer data)
299 gtk_main_quit ();
300 return false;
305 main (int argc, char *argv [])
307 int result = 0;
308 const char *media_extensions [] = { ".wmv", ".wma", ".vc1", ".asf", ".mp3", NULL };
309 const char *media_filename = NULL;
310 const char *filename = NULL;
311 const char *tmpfile = NULL;
312 int media_width = 0;
313 int media_height = 0;
314 int timeout = 0;
316 // quick out if no arguments are provided
317 if (argc == 0) {
318 Help ();
319 return 1;
322 gtk_init (&argc, &argv);
323 g_thread_init (NULL);
324 gdk_threads_init ();
327 for (int i = 1; i < argc; i++) {
328 if (!strcmp (argv [i], "--media")) {
329 if (i + 1 >= argc) {
330 Help ();
331 return 1;
333 media_filename = argv [++i];
334 } else if (!strcmp (argv [i], "--timeout")) {
335 if (i + 1 >= argc) {
336 Help ();
337 return 1;
339 timeout = atoi (argv [++i]);
340 } else {
341 if (filename != NULL) {
342 Help ();
343 return 1;
345 filename = argv [i];
346 for (int j = 0; media_extensions [j] != NULL && media_filename == NULL; j++) {
347 if (g_str_has_suffix (filename, media_extensions [j]))
348 media_filename = filename;
353 if (media_filename) {
354 char *xaml;
356 tmpfile = "mopen1.default.xaml";
358 if (!get_video_size (media_filename, &media_width, &media_height)) {
359 fprintf (stdout, "mopen1: Could not get video size, using 400x300.\n");
360 media_width = 400;
361 media_height = 300;
364 xaml = g_strdup_printf (
365 "<Canvas xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml' Width='%i' Height='%i'>\n"
366 " <MediaElement x:Name='TestVideo' Width='%i' Height='%i' Source='%s'/>\n"
367 "</Canvas>\n", media_width, media_height, media_width, media_height, media_filename);
369 if (!g_file_set_contents (tmpfile, xaml, -1, NULL)) {
370 fprintf (stderr, "mopen1: Error while writing temporary file.\n");
371 return 1;
374 g_free (xaml);
375 filename = tmpfile;
379 if (timeout > 0) {
380 g_timeout_add (timeout * 1000, QuitTimeout, NULL);
384 result = LoadXaml (filename);
386 if (tmpfile)
387 unlink (tmpfile);
390 return result;