All pastes #1494775 Raw Edit

Something

public text v1 · immutable
#1494775 ·published 2009-07-14 15:19 UTC
rendered paste body
diff --git a/class/System.Windows/Mono/NativeMethods.cs b/class/System.Windows/Mono/NativeMethods.cs
index b8b906a..e95fa66 100644
--- a/class/System.Windows/Mono/NativeMethods.cs
+++ b/class/System.Windows/Mono/NativeMethods.cs
@@ -65,7 +65,7 @@ namespace Mono {
 	internal delegate void ApplyDefaultStyleCallback (IntPtr fwe_ptr, IntPtr type_info_ptr);
 	internal delegate void ApplyStyleCallback (IntPtr fwe_ptr, IntPtr style_ptr);
 	internal delegate void ConvertKeyframeValueCallback (Mono.Kind kind, IntPtr property, IntPtr original, out Value converted);
-	internal delegate IntPtr GetResourceCallback (string name, out int size);
+	internal delegate ManagedStreamCallbacks GetResourceCallback (string name);
 
 	// Used in databinding to interact with managed objects
 	internal delegate Value GetValueCallback ();
diff --git a/class/System.Windows/System.Windows/Application.cs b/class/System.Windows/System.Windows/Application.cs
index 5b0f6ab..124742e 100644
--- a/class/System.Windows/System.Windows/Application.cs
+++ b/class/System.Windows/System.Windows/Application.cs
@@ -387,34 +387,28 @@ namespace System.Windows {
 			return null;
 		}
 
-		internal static IntPtr get_resource_cb_safe (string name, out int size)
+		internal static ManagedStreamCallbacks get_resource_cb_safe (string name)
 		{
 			try {
-				return get_resource_cb (name, out size);
+				return get_resource_cb (name);
 			} catch (Exception ex) {
 				try {
 					Console.WriteLine ("Moonlight: Unhandled exception in Application.get_resource_cb: {0}", ex);
 				} catch {
 				}
 			}
-			size = 0;
-			return new IntPtr ();
+			return new ManagedStreamCallbacks ();
 		}
-		
-		internal static IntPtr get_resource_cb (string name, out int size)
+
+		internal static ManagedStreamCallbacks get_resource_cb (string name)
 		{
-			size = 0;
-			try {
-				StreamResourceInfo info = GetResourceStream (new Uri (name, UriKind.Relative));
+			StreamResourceInfo info = GetResourceStream (new Uri (name, UriKind.Relative));
 
-				if (info == null)
-					return IntPtr.Zero;
-				
-				size = (int) info.Stream.Length;
-				return Helper.StreamToIntPtr (info.Stream);
-			} catch {
-				return IntPtr.Zero;
+			if (info == null) {
+				return new ManagedStreamCallbacks ();
 			}
+
+			return new StreamWrapper (info.Stream).GetCallbacks ();
 		}
 
 		internal static Assembly GetAssembly (string name)
diff --git a/class/System.Windows/System.Windows/ChangeLog b/class/System.Windows/System.Windows/ChangeLog
index 6b1b3d0..27aeded 100644
--- a/class/System.Windows/System.Windows/ChangeLog
+++ b/class/System.Windows/System.Windows/ChangeLog
@@ -1,3 +1,7 @@
+2009-07-14  Stephane Delcroix  <sdelcroix@novell.com>
+
+	* Application.cs: GetResource returns a ManagedStreamCallbacks ptr
+
 2009-07-09  Rolf Bjarne Kvinge  <RKvinge@novell.com>
 
 	* Duration.cs: Subtract != Add.
diff --git a/plugin/cbinding.h b/plugin/cbinding.h
index 10e90a8..9dd5389 100644
--- a/plugin/cbinding.h
+++ b/plugin/cbinding.h
@@ -305,6 +305,7 @@ class Border;
 class BounceEase;
 class BrowserBridge;
 class Brush;
+class Cancellable;
 class Canvas;
 class CircleEase;
 class Clock;
@@ -755,7 +756,7 @@ struct XamlLoaderCallbacks;
 typedef void ( * ApplyDefaultStyleCallback ) ( FrameworkElement * fwe , ManagedTypeInfo * key ) ;
 typedef void ( * ApplyStyleCallback ) ( FrameworkElement * fwe , Style * style ) ;
 typedef void * ( * ConvertKeyframeValueCallback ) ( int kind , DependencyProperty * property , Value * original , Value * converted ) ;
-typedef void * ( * GetResourceCallback ) ( const char * name , int * size ) ;
+typedef ManagedStreamCallbacks ( * GetResourceCallback ) ( const char * name ) ;
 typedef void ( * TickCallHandler ) ( EventObject * object ) ;
 typedef void ( * EventHandler ) ( EventObject * sender , EventArgs * args , gpointer closure ) ;
 typedef void ( * ToggleNotifyHandler ) ( EventObject * sender , bool isLastRef ) ;
diff --git a/src/ChangeLog b/src/ChangeLog
index 0e1b397..74b02b0 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,19 @@
+2009-07-14  Stephane Delcroix  <sdelcroix@novell.com>
+
+	* bitmapimage.h|cpp: drop the downloader references, rely on
+	Application::GetResource () for getting from resource AND downloading. The
+	old downloader mechanism for v1 js callbacks.
+
+2009-07-14  Stephane Delcroix  <sdelcroix@novell.com>
+
+	* application.h|cpp: Application.GetResource () now try to get the resource
+	from the managed callback, then fallback to downloading.
+
+2009-07-14  Stephane Delcroix  <sdelcroix@novell.com>
+
+	* utils.h|cpp: Cancellable class, passed as method argument, allows
+	to abort an async action.
+
 2009-07-13  Jeffrey Stedfast  <fejj@novell.com>
 
 	* fonts.cpp (TextFont::Load): Don't g_strfreev() the families
diff --git a/src/application.cpp b/src/application.cpp
index 4636bd5..ec31a06 100644
--- a/src/application.cpp
+++ b/src/application.cpp
@@ -97,22 +97,152 @@ Application::ConvertKeyframeValue (Type::Kind kind, DependencyProperty *property
 	}
 }
 
-gpointer
-Application::GetResource (const Uri *uri, int *size)
+struct NotifyCtx {
+	gpointer user_data;
+	NotifyFunc notify_cb;
+};
+
+void downloader_abort (gpointer data);
+void downloader_progress_changed (EventObject *sender, EventArgs *calldata, gpointer closure);
+void downloader_complete (EventObject *sender, EventArgs *calldata, gpointer closure);
+void downloader_failed (EventObject *sender, EventArgs *calldata, gpointer closure);
+
+void
+Application::GetResource (const Uri *uri, NotifyFunc notify_cb, WriteFunc write_cb, DownloaderAccessPolicy policy, Cancellable *cancellable, gpointer user_data)
 {
-	if (get_resource_cb && uri) {
+	g_warning ("GetResource");
+	if (!uri) {
+		g_warning ("Passing a null uri to Application::GetResource");
+		return;
+	}
+
+	if (get_resource_cb && uri && !uri->isAbsolute) {
 		char *url = uri->ToString ();
-		gpointer ptr = get_resource_cb (url, size);
+		ManagedStreamCallbacks stream = get_resource_cb (url);
 		g_free (url);
-		
-		return ptr;
+		if (stream.handle) {
+			g_warning ("wo oh oh, got a stream");
+			if (notify_cb) {
+				notify_cb (NotifyStarted, NULL, user_data);
+				notify_cb (NotifySize, stream.Length (stream.handle), user_data);
+			}
+
+			char buffer [1024];
+			if (stream.CanSeek (stream.handle) && stream.Position (stream.handle) != 0)
+				stream.Seek (stream.handle, 0, 0);
+	
+			gint32 nread;
+			do {
+				nread = stream.Read (stream.handle, buffer, 0, 1024);
+				if (write_cb)
+					write_cb (buffer, 0, nread, user_data);
+			} while (nread);
+
+			if (notify_cb)
+				notify_cb (NotifyCompleted, NULL, user_data);
+
+			return;
+		}
+	}	
+
+	//no get_resource_cb or empty stream
+	Downloader *downloader;
+	Surface *surface = Deployment::GetCurrent ()->GetSurface ();
+	if (!(downloader = surface->CreateDownloader ()))
+		return;
+	
+	NotifyCtx *ctx = g_new (NotifyCtx, 1);
+	ctx->user_data = user_data;
+	ctx->notify_cb = notify_cb;
+
+	if (notify_cb) {
+		downloader->AddHandler (Downloader::DownloadProgressChangedEvent, downloader_progress_changed, ctx);
+		downloader->AddHandler (Downloader::DownloadFailedEvent, downloader_failed, ctx);
+		downloader->AddHandler (Downloader::CompletedEvent, downloader_complete, ctx);
 	}
+
+	if (cancellable) {
+		cancellable->SetCancelFuncAndData (downloader_abort, downloader);
+	}
+
+	if (downloader->Completed ()) {
+		if (notify_cb)
+			notify_cb (NotifyCompleted, NULL, user_data);
+	} else {
+		if (!downloader->Started ()) {
+			downloader->Open ("GET", (Uri*)uri, policy);
+			downloader->SetStreamFunctions (write_cb, NULL, user_data);
+			downloader->Send ();
+		}
+	}
+}
+
+void
+downloader_abort (gpointer data)
+{
+	Downloader *dl = (Downloader *) data;
+	dl->Abort ();
+}
+
+void
+downloader_progress_changed (EventObject *sender, EventArgs *calldata, gpointer closure)
+{
+	NotifyCtx *ctx = (NotifyCtx *) closure;
+	Downloader *dl = (Downloader *) sender;
+	ctx->notify_cb (NotifyProgressChanged, (gint64) (100 * dl->GetDownloadProgress ()), ctx->user_data);
+}
+
+void
+downloader_complete (EventObject *sender, EventArgs *calldata, gpointer closure)
+{
+	NotifyCtx *ctx = (NotifyCtx *) closure;
+	ctx->notify_cb (NotifyCompleted, NULL, ctx->user_data);
+	g_free (ctx);
+}
+
+void
+downloader_failed (EventObject *sender, EventArgs *calldata, gpointer closure)
+{
+	NotifyCtx *ctx = (NotifyCtx *) closure;
+	ctx->notify_cb (NotifyFailed, NULL, ctx->user_data);
+	g_free (ctx);
+}
+
+//compatibility function, act like the old get_resource_cb
+gpointer
+Application::GetResourceAsBuffer (const Uri *uri, int *size)
+{
+	gpointer buffer = NULL;
+
+	if (!uri) {
+		g_warning ("Passing a null uri to Application::GetResource");
+		return NULL;
+	}
+
+	if (get_resource_cb && uri && !uri->isAbsolute) {
+		char *url = uri->ToString ();
+		ManagedStreamCallbacks stream = get_resource_cb (url);
+		g_free (url);
+
+		if (stream.handle) {
+
+			*size = stream.Length (stream.handle);
+			if (!size)
+				return NULL;
+
+			buffer = g_new (char, *size);
+
+			if (stream.CanSeek (stream.handle) && stream.Position (stream.handle) != 0)
+				stream.Seek (stream.handle, 0, 0);
 	
-	*size = 0;
+			stream.Read (stream.handle, buffer, 0, *size);
+		}
+	}	
 	
-	return NULL;
+	return buffer;
 }
 
+//FIXME: nuke this!
 char *
 Application::GetResourceAsPath (const Uri *uri)
 {
@@ -160,14 +290,11 @@ Application::GetResourceAsPath (const Uri *uri)
 	g_free (dirname);
 	
 	// now we need to get the resource buffer and dump it to disk
-	url = uri->ToString ();
-	if (!(buf = get_resource_cb (url, &size))) {
+	if (!(buf = GetResourceAsBuffer (uri, &size))) {
 		g_free (path);
-		g_free (url);
 		return NULL;
 	}
 	
-	g_free (url);
 	
 	// create and save the buffer to disk
 	if ((fd = open (path, O_WRONLY | O_CREAT | O_EXCL, 0600)) == -1) {
diff --git a/src/application.h b/src/application.h
index 1e3eb87..dc459a2 100644
--- a/src/application.h
+++ b/src/application.h
@@ -12,9 +12,11 @@
 
 #include <glib.h>
 
+#include "utils.h"
 #include "enums.h"
 #include "control.h"
 #include "dependencyobject.h"
+#include "downloader.h"
 
 /* @CBindingRequisite */
 typedef void (*ApplyDefaultStyleCallback)(FrameworkElement *fwe, ManagedTypeInfo *key);
@@ -23,7 +25,11 @@ typedef void (*ApplyStyleCallback)(FrameworkElement *fwe, Style *style);
 /* @CBindingRequisite */
 typedef void *(*ConvertKeyframeValueCallback)(int kind, DependencyProperty *property, Value *original, Value *converted);
 /* @CBindingRequisite */
-typedef void *(*GetResourceCallback)(const char *name, int *size);
+typedef ManagedStreamCallbacks (*GetResourceCallback)(const char *name);
+
+enum NotifyType {NotifyStarted, NotifySize, NotifyProgressChanged, NotifyCompleted, NotifyFailed};
+typedef void (*NotifyFunc) (NotifyType type, gint64 args, gpointer user_data);
+typedef void (*WriteFunc) (void* buf, gint32 offset, gint32 n, gpointer user_data);
 
 /* @ManagedDependencyProperties=Manual */
 /* @Namespace=None */
@@ -43,7 +49,7 @@ public:
 	
 	void ConvertKeyframeValue (Type::Kind kind, DependencyProperty *property, Value *original, Value *converted);
 	
-	gpointer GetResource (const Uri *uri, int *size);
+	void GetResource (const Uri *uri, NotifyFunc notify_cb, WriteFunc write_cb, DownloaderAccessPolicy policy, Cancellable *cancellable, gpointer user_data);
 	char *GetResourceAsPath (const Uri *uri);
 	
 	/* @GenerateCBinding,GeneratePInvoke */
@@ -61,6 +67,7 @@ protected:
 	virtual ~Application ();
 
 private:
+	gpointer GetResourceAsBuffer (const Uri *uri, int *size);
 	ApplyDefaultStyleCallback apply_default_style_cb;
 	ApplyStyleCallback apply_style_cb;
 	ConvertKeyframeValueCallback convert_keyframe_callback;
diff --git a/src/bitmapimage.cpp b/src/bitmapimage.cpp
index 5734210..ce7f053 100644
--- a/src/bitmapimage.cpp
+++ b/src/bitmapimage.cpp
@@ -145,6 +145,7 @@ BitmapImage::BitmapImage ()
 	loader = NULL;
 	error = NULL;
 	part_name = NULL;
+	get_res_aborter = NULL;
 }
 
 BitmapImage::~BitmapImage ()
@@ -165,7 +166,10 @@ BitmapImage::Dispose ()
 		CleanupDownloader ();
 		downloader->Abort ();
 	}
-	
+
+	if (get_res_aborter)
+		get_res_aborter->Cancel ();
+
 	BitmapSource::Dispose ();
 }
 
@@ -176,36 +180,37 @@ BitmapImage::uri_source_changed_callback (EventObject *user_data)
 	image->UriSourceChanged ();
 }
 
+void resource_notify (NotifyType type, gint64 args, gpointer user_data);
+
 void
 BitmapImage::UriSourceChanged ()
 {
 	Surface *surface = Deployment::GetCurrent ()->GetSurface ();
 	Application *current = Application::GetCurrent ();
 	Uri *uri = GetUriSource ();
-	Downloader *downloader;
-	
-	if (current && uri) {
-		int size = 0;
-		unsigned char *buffer = (unsigned char *) current->GetResource (uri, &size);
-		if (size > 0) {
-			PixbufWrite (buffer, 0, size);
-			PixmapComplete ();
-
-			g_free (buffer);
-			return;
-		}
-	}
 	
 	if (surface == NULL) {
 		SetBitmapData (NULL);
 		return;
 	}
 
-	if (!(downloader = surface->CreateDownloader ()))
-		return;
+	if (current && uri) {
+		get_res_aborter = new Cancellable ();
+		current->GetResource (uri, resource_notify, pixbuf_write, MediaPolicy, get_res_aborter, this);
+	}
+}
 
-	SetDownloader (downloader, uri, NULL);
-	downloader->unref ();
+void
+resource_notify (NotifyType type, gint64 args, gpointer user_data)
+{
+	BitmapImage *media = (BitmapImage *) user_data;
+
+	if (type == NotifyProgressChanged)
+		media->SetProgress ((double)(args)/100.0);
+	else if (type == NotifyFailed)
+		media->DownloaderFailed ();
+	else if (type == NotifyCompleted)
+		media->DownloaderComplete ();
 }
 
 
@@ -222,6 +227,9 @@ BitmapImage::OnPropertyChanged (PropertyChangedEventArgs *args, MoonError *error
 			downloader = NULL;
 		}
 
+		if (get_res_aborter)
+			get_res_aborter->Cancel ();
+
 		if (Uri::IsNullOrEmpty (uri)) {
 			SetBitmapData (NULL);
 		} else {
@@ -304,11 +312,12 @@ BitmapImage::DownloaderProgressChanged ()
 void
 BitmapImage::DownloaderComplete ()
 {
-	CleanupDownloader ();
+	if (downloader)
+		CleanupDownloader ();
 
 	SetProgress (1.0);
 
-	if (loader == NULL) {
+	if (downloader && loader == NULL) {
 		char *filename = downloader->GetDownloadedFilename (part_name);
 
 		if (filename == NULL) {
@@ -344,8 +353,10 @@ BitmapImage::DownloaderComplete ()
 		}
 	}
 
-	downloader->unref ();
-	downloader = NULL;
+	if (downloader) {
+		downloader->unref ();
+		downloader = NULL;
+	}
 
 	PixmapComplete ();
 
@@ -405,10 +416,12 @@ failed:
 void
 BitmapImage::DownloaderFailed ()
 {
-	CleanupDownloader ();
+	if (downloader) {
+		CleanupDownloader ();
 
-	downloader->unref ();
-	downloader = NULL;
+		downloader->unref ();
+		downloader = NULL;
+	}
 
 	Emit (ImageFailedEvent, new ExceptionRoutedEventArgs ());
 }
diff --git a/src/bitmapimage.h b/src/bitmapimage.h
index 75c1dad..a49632d 100644
--- a/src/bitmapimage.h
+++ b/src/bitmapimage.h
@@ -16,6 +16,7 @@
 
 #include <gdk/gdkpixbuf.h>
 
+#include "utils.h"
 #include "dependencyobject.h"
 #include "downloader.h"
 #include "bitmapsource.h"
@@ -27,6 +28,7 @@ class BitmapImage : public BitmapSource {
 	GdkPixbufLoader *loader;
 	GError *error;
 	char *part_name;
+	Cancellable *get_res_aborter;
 
  protected:
 	virtual ~BitmapImage ();
diff --git a/src/cbinding.h b/src/cbinding.h
index ab5fb69..e68876a 100644
--- a/src/cbinding.h
+++ b/src/cbinding.h
@@ -305,6 +305,7 @@ class Border;
 class BounceEase;
 class BrowserBridge;
 class Brush;
+class Cancellable;
 class Canvas;
 class CircleEase;
 class Clock;
@@ -755,7 +756,7 @@ struct XamlLoaderCallbacks;
 typedef void ( * ApplyDefaultStyleCallback ) ( FrameworkElement * fwe , ManagedTypeInfo * key ) ;
 typedef void ( * ApplyStyleCallback ) ( FrameworkElement * fwe , Style * style ) ;
 typedef void * ( * ConvertKeyframeValueCallback ) ( int kind , DependencyProperty * property , Value * original , Value * converted ) ;
-typedef void * ( * GetResourceCallback ) ( const char * name , int * size ) ;
+typedef ManagedStreamCallbacks ( * GetResourceCallback ) ( const char * name ) ;
 typedef void ( * TickCallHandler ) ( EventObject * object ) ;
 typedef void ( * EventHandler ) ( EventObject * sender , EventArgs * args , gpointer closure ) ;
 typedef void ( * ToggleNotifyHandler ) ( EventObject * sender , bool isLastRef ) ;
diff --git a/src/utils.cpp b/src/utils.cpp
index 9301671..87f20a9 100644
--- a/src/utils.cpp
+++ b/src/utils.cpp
@@ -962,4 +962,22 @@ char *parse_rfc_1945_token (char *input, char *c, char **end)
 	return start;
 }
 
+Cancellable::Cancellable ()
+{
+	cancel_cb = NULL;
+	user_data = NULL;
+}
 
+void
+Cancellable::Cancel ()
+{
+	if (cancel_cb)
+		cancel_cb (user_data);
+}
+
+void
+Cancellable::SetCancelFuncAndData (CancelCallback cb, gpointer data)
+{
+	cancel_cb = cb;
+	user_data = data;
+}
diff --git a/src/utils.h b/src/utils.h
index a08e099..6475e71 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -138,4 +138,17 @@ public:
 	ssize_t Read (char *buf, size_t n);
 };
 
+typedef void (*CancelCallback) (gpointer user_data);
+
+class Cancellable {
+ private:
+	CancelCallback cancel_cb;
+	gpointer user_data;
+ public:
+	Cancellable ();
+
+	void Cancel ();
+	void SetCancelFuncAndData (CancelCallback cb, gpointer user_data);
+};
+
 #endif /* __UTILS_H__ */