rendered paste bodydiff --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__ */