mistelix r7 - in trunk: . extensions extensions/Effects extensions/Effects/RotateImage po src src/core src/datamodel src/dialogs src/widgets
- From: jmas svn gnome org
- To: svn-commits-list gnome org
- Subject: mistelix r7 - in trunk: . extensions extensions/Effects extensions/Effects/RotateImage po src src/core src/datamodel src/dialogs src/widgets
- Date: Wed, 25 Mar 2009 20:26:34 +0000 (UTC)
Author: jmas
Date: Wed Mar 25 20:26:34 2009
New Revision: 7
URL: http://svn.gnome.org/viewvc/mistelix?rev=7&view=rev
Log:
Better preview & initial effect support
Added:
trunk/extensions/Effects/
trunk/extensions/Effects/Makefile.am
trunk/extensions/Effects/RotateImage/
trunk/extensions/Effects/RotateImage/Makefile.am
trunk/extensions/Effects/RotateImage/RotateImage.addin.xml
trunk/extensions/Effects/RotateImage/RotateImage.cs
trunk/src/core/EffectManager.cs
trunk/src/core/NoneEffect.cs
trunk/src/datamodel/IEffect.cs
trunk/src/widgets/DataImageSurface.cs
Modified:
trunk/ChangeLog
trunk/configure.in
trunk/extensions/Makefile.am
trunk/po/POTFILES.in
trunk/src/Makefile.am
trunk/src/core/DvdMenu.cs
trunk/src/core/SlideImage.cs
trunk/src/core/SlideShow.cs
trunk/src/datamodel/SlideShowProjectElement.cs
trunk/src/dialogs/AddSlideDialog.cs
trunk/src/mistelix.addin.xml
trunk/src/mistelix.cs
trunk/src/widgets/FileView.cs
trunk/src/widgets/GtkMenu.cs
trunk/src/widgets/ImagesFileView.cs
trunk/src/widgets/PixbufImageSurface.cs
trunk/src/widgets/SlideShowImageView.cs
Modified: trunk/configure.in
==============================================================================
--- trunk/configure.in (original)
+++ trunk/configure.in Wed Mar 25 20:26:34 2009
@@ -133,4 +133,6 @@
extensions/SlideTransitions/Makefile
extensions/SlideTransitions/Fade/Makefile
extensions/SlideTransitions/OpaqueLines/Makefile
+extensions/Effects/Makefile
+extensions/Effects/RotateImage/Makefile
])
Added: trunk/extensions/Effects/Makefile.am
==============================================================================
--- (empty file)
+++ trunk/extensions/Effects/Makefile.am Wed Mar 25 20:26:34 2009
@@ -0,0 +1,2 @@
+SUBDIRS = \
+ RotateImage
Added: trunk/extensions/Effects/RotateImage/Makefile.am
==============================================================================
--- (empty file)
+++ trunk/extensions/Effects/RotateImage/Makefile.am Wed Mar 25 20:26:34 2009
@@ -0,0 +1,39 @@
+PLUGIN_NAME = RotateImage
+
+PLUGIN_MANIFEST = $(PLUGIN_NAME).addin.xml
+
+PLUGIN_ASSEMBLY = $(PLUGIN_NAME).dll
+
+PLUGIN_SOURCES = \
+ $(srcdir)/RotateImage.cs
+
+REFS = \
+ -r:$(top_builddir)/src/mistelix.exe
+
+PKGS = \
+ -pkg:gtk-sharp-2.0
+
+RESOURCES = \
+ -resource:$(srcdir)/$(PLUGIN_MANIFEST)
+
+all: $(PLUGIN_ASSEMBLY)
+
+mpack: $(PLUGIN_ASSEMBLY)
+ mautil p $(PLUGIN_ASSEMBLY)
+
+$(PLUGIN_ASSEMBLY): $(PLUGIN_SOURCES) $(PLUGIN_MANIFEST)
+ $(CSC) -target:library -out:$@ $(CSC_DEFINES) $(PLUGIN_SOURCES) $(REFS) $(PKGS) $(ASSEMBLIES) $(RESOURCES)
+
+plugindir = $(pkglibdir)/extensions
+
+plugin_DATA = \
+ $(PLUGIN_ASSEMBLY)
+
+EXTRA_DIST = \
+ $(PLUGIN_SOURCES) \
+ $(PLUGIN_MANIFEST)
+
+CLEANFILES = \
+ $(PLUGIN_ASSEMBLY) \
+ $(PLUGIN_ASSEMBLY).mdb \
+ *.mpack
Added: trunk/extensions/Effects/RotateImage/RotateImage.addin.xml
==============================================================================
--- (empty file)
+++ trunk/extensions/Effects/RotateImage/RotateImage.addin.xml Wed Mar 25 20:26:34 2009
@@ -0,0 +1,17 @@
+<Addin namespace="Mistelix"
+ version="0.10"
+ name="Fade"
+ description="Rotate images"
+ author="Jordi Mas"
+ url=""
+ defaultEnabled="true"
+ category="Effects">
+
+ <Dependencies>
+ <Addin id="Mistelix" version="0.10"/>
+ </Dependencies>
+
+ <Extension path="/Mistelix/Effects">
+ <Effects type="Mistelix.Effects.RotateImage" />
+ </Extension>
+</Addin>
Added: trunk/extensions/Effects/RotateImage/RotateImage.cs
==============================================================================
--- (empty file)
+++ trunk/extensions/Effects/RotateImage/RotateImage.cs Wed Mar 25 20:26:34 2009
@@ -0,0 +1,55 @@
+//
+// Copyright (C) 2008 Jordi Mas i Hernandez, jmas softcatala org
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+
+using Mistelix.DataModel;
+using Mistelix.Effects;
+
+namespace Mistelix.Effects
+{
+ public class RotateImage: IEffect
+ {
+ public string DisplayName {
+ get { return ("Rotate image"); }
+ }
+
+ public string Name {
+ get { return ("rotate image"); }
+ }
+
+ public SlideImage ApplyEffect (SlideImage org)
+ {
+ SlideImage image;
+
+ image = new SlideImage ();
+ image.CopyProperties (org);
+ image.Pixels = new byte [org.stride * org.height];
+
+ for (int i = 0; i < org.stride * org.height; i++)
+ image.Pixels[i] = (byte) ((double) org.Pixels[i] * 0.5);
+
+ return image;
+ }
+ }
+}
Modified: trunk/extensions/Makefile.am
==============================================================================
--- trunk/extensions/Makefile.am (original)
+++ trunk/extensions/Makefile.am Wed Mar 25 20:26:34 2009
@@ -1,5 +1,6 @@
SUBDIRS = \
- SlideTransitions
+ SlideTransitions \
+ Effects
addinsdir = $(pkglibdir)
addins_DATA = mistelix.global.addins
Modified: trunk/po/POTFILES.in
==============================================================================
--- trunk/po/POTFILES.in (original)
+++ trunk/po/POTFILES.in Wed Mar 25 20:26:34 2009
@@ -3,6 +3,7 @@
src/core/Dependencies.cs
src/core/DvdProjectBuilder.cs
src/core/MistelixLib.cs
+src/core/NoneEffect.cs
src/core/NoneTransition.cs
src/core/TheoraProjectBuilder.cs
src/core/ThumbnailSizeManager.cs
Modified: trunk/src/Makefile.am
==============================================================================
--- trunk/src/Makefile.am (original)
+++ trunk/src/Makefile.am Wed Mar 25 20:26:34 2009
@@ -63,7 +63,11 @@
$(srcdir)/dialogs/AboutDialog.cs \
$(srcdir)/core/Dependencies.cs \
$(srcdir)/dialogs/CheckDependenciesDialog.cs \
- $(srcdir)/datamodel/ObservableList.cs
+ $(srcdir)/datamodel/ObservableList.cs \
+ $(srcdir)/datamodel/IEffect.cs \
+ $(srcdir)/core/EffectManager.cs \
+ $(srcdir)/core/NoneEffect.cs \
+ $(srcdir)/widgets/DataImageSurface.cs
ASSEMBLIES = \
$(MISTELIX_LIBS) \
Modified: trunk/src/core/DvdMenu.cs
==============================================================================
--- trunk/src/core/DvdMenu.cs (original)
+++ trunk/src/core/DvdMenu.cs Wed Mar 25 20:26:34 2009
@@ -66,6 +66,8 @@
public string GenerateMPEG (/*, ProgressEventHandler progress*/)
{
SlideShow sw;
+
+ Logger.Debug ("DvdMenu.GenerateMPEG");
Save (project.FileToFullPath (Defines.MAIN_MENU_FILE_PNG));
Added: trunk/src/core/EffectManager.cs
==============================================================================
--- (empty file)
+++ trunk/src/core/EffectManager.cs Wed Mar 25 20:26:34 2009
@@ -0,0 +1,76 @@
+//
+// Copyright (C) 2009 Jordi Mas i Hernandez, jmas softcatala org
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using Mono.Addins;
+using Mistelix.Effects;
+
+namespace Mistelix.Core
+{
+ // Manages all the available effects
+ public static class EffectManager
+ {
+ static None none;
+ static EffectManager ()
+ {
+ }
+
+ static public IEffect None {
+ get {
+ if (none == null)
+ none = new None ();
+
+ return none;
+ }
+ }
+
+ // Get default none transition + the ones provides by pluggins
+ static public IEffect[] List {
+ get {
+ IEffect[] effects;
+ int pos = 0;
+ ExtensionNodeList addins = AddinManager.GetExtensionNodes ("/Mistelix/Effects");
+ effects = new IEffect [addins.Count + 1];
+
+ effects[pos++] = new None ();
+
+ foreach (TypeExtensionNode node in addins) {
+ effects[pos++] = (IEffect) node.CreateInstance ();
+ }
+
+ return effects;
+ }
+ }
+
+ static public IEffect FromName (string val)
+ {
+ foreach (IEffect effect in List)
+ {
+ if (effect.Name.Equals (val))
+ return effect;
+ }
+ Logger.Debug (String.Format ("EffectManager.FromName -> effect {0} not found", val));
+ return None;
+ }
+ }
+}
Added: trunk/src/core/NoneEffect.cs
==============================================================================
--- (empty file)
+++ trunk/src/core/NoneEffect.cs Wed Mar 25 20:26:34 2009
@@ -0,0 +1,48 @@
+//
+// Copyright (C) 2009 Jordi Mas i Hernandez, jmas softcatala org
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using Mistelix.DataModel;
+using Mono.Unix;
+
+// Default built-in transition
+namespace Mistelix.Effects
+{
+ // This transition does nothing
+ public class None: IEffect
+ {
+ public string DisplayName {
+ get { return (Catalog.GetString ("<None>")); }
+ }
+
+ public string Name {
+ get { return ("none"); }
+ }
+
+ public SlideImage ApplyEffect (SlideImage slideimage)
+ {
+ return null;
+ }
+ }
+}
+
Modified: trunk/src/core/SlideImage.cs
==============================================================================
--- trunk/src/core/SlideImage.cs (original)
+++ trunk/src/core/SlideImage.cs Wed Mar 25 20:26:34 2009
@@ -29,9 +29,11 @@
using System.Xml.Serialization;
using Gdk;
using Pango;
+using Cairo;
using Mistelix.Core;
using Mistelix.Widgets;
+using Mistelix.Effects;
namespace Mistelix.DataModel
{
@@ -40,33 +42,40 @@
//
public class SlideImage : SlideShowProjectElement.Image
{
- [XmlIgnoreAttribute] public int width, height, stride, channels = 3;
+ [XmlIgnoreAttribute] public int width, height, stride, channels = 3, requested_channels = 3;
[XmlIgnoreAttribute] public bool alpha = false;
[XmlIgnoreAttribute] byte[] pixels = null;
[XmlIgnoreAttribute] Project project;
+ [XmlIgnoreAttribute] int offset_x, offset_y, w, h;
public SlideImage ()
{
- transition = 2; // Transition from slide to slide (effect duration)
- time = Mistelix.Preferences.GetIntValue (Preferences.DefaultDurationKey);
- effect = Mistelix.Preferences.GetStringValue (Preferences.DefaultTransitionKey);
- position = (TextPosition) Mistelix.Preferences.GetIntValue (Preferences.DefaultTextPositionKey);
+ TransitionTime = 2; // Transition from slide to slide (effect duration). Hardcoded default
+ ShowTime = Mistelix.Preferences.GetIntValue (Preferences.DefaultDurationKey);
+ Transition = Mistelix.Preferences.GetStringValue (Preferences.DefaultTransitionKey);
+ Position = (TextPosition) Mistelix.Preferences.GetIntValue (Preferences.DefaultTextPositionKey);
}
public SlideImage (string image) : this ()
{
+ if (name == null)
+ throw new ArgumentNullException ("image name cannot be null");
+
this.image = image;
}
- public SlideImage (string image, string title, int time, string effect) : this ()
+ public SlideImage (string image, string title, int time, string transition) : this ()
{
- if (effect == null)
+ if (transition == null)
throw new ArgumentNullException ("effect cannot be null");
+
+ if (image == null)
+ throw new ArgumentNullException ("image name cannot be null");
this.image = image;
- this.title = title;
- this.time = time;
- this.effect = effect;
+ Title = title;
+ ShowTime = time;
+ Transition = transition;
}
// Used only for previewing the transition effect
@@ -82,41 +91,12 @@
alpha = true;
pixels = img.Data;
}
-
- // mistelixvideosrc expects images in 24 bits (3 channels)
- public void FromImage (PixbufImageSurface img)
- {
- if (img.Format != Cairo.Format.Argb32 && img.Format != Cairo.Format.Rgb24)
- throw new InvalidOperationException (String.Format ("SlideImage.FromCairo: unsupported format {0}", img.Format));
-
- width = img.Width;
- height = img.Height;
- stride = img.Width * 3;
- channels = 3;
- alpha = false;
- pixels = img.Get24bitsPixBuf ();
- }
-
- void LoadPixBuffer (Gdk.Pixbuf buf)
- {
- int len;
-
- width = buf.Width;
- height = buf.Height;
- stride = buf.Rowstride;
- channels = buf.NChannels;
- alpha = buf.HasAlpha;
- len = stride * height;
-
- pixels = new byte [len];
- Marshal.Copy (buf.Pixels, pixels, 0, len);
- }
[System.Xml.Serialization.XmlIgnoreAttribute]
public byte[] Pixels {
get {
if (pixels == null)
- LoadImageFromFile ();
+ LoadAndScaleImage ();
return pixels;
}
@@ -130,6 +110,19 @@
set { project = value; }
}
+ public void CopyProperties (SlideImage src)
+ {
+ // TODO: Missing SlideImage properties
+ width = src.width;
+ height = src.height;
+ stride = src.stride;
+ alpha = src.alpha;
+ channels = src.channels;
+ Effects = src.Effects;
+
+ image = src.image;
+ }
+
// The list of images for a slideshow is kept on a list
// When generating the slideshow the pixels are allocated, however they are only
// needed during the slideshow generation. Releasing the pixels helps to GC
@@ -139,6 +132,34 @@
pixels = null;
}
+
+ public DataImageSurface GetThumbnail (int width, int height)
+ {
+ SlideImage slide = new SlideImage ();
+ slide.CopyProperties (this);
+ slide.requested_channels = 4;
+ slide.LoadAndScaleImage (width, height);
+ //slide.ProcessImage ();
+ slide.ProcessEffects ();
+
+ return new DataImageSurface (DataImageSurface.Allocate (slide.Pixels),
+ Cairo.Format.ARGB32, slide.width, slide.height, slide.stride);
+ }
+
+ // mistelixvideosrc expects images in 24 bits (3 channels)
+ void FromImage (DataImageSurface img)
+ {
+ if (img.Format != Cairo.Format.Argb32 && img.Format != Cairo.Format.Rgb24)
+ throw new InvalidOperationException (String.Format ("SlideImage.FromCairo: unsupported format {0}", img.Format));
+
+ width = img.Width;
+ height = img.Height;
+ stride = img.Width * 3;
+ channels = 3;
+ alpha = false;
+ pixels = img.Get24bitsPixBuf ();
+ }
+
void DrawImageLegend (Cairo.Context cr, string title, int x, int y, int width, int height)
{
const int marginx = 50; // Distance of the coloured box from the x margins (in safe area)
@@ -167,7 +188,7 @@
box_w = w;
box_h = y + h + textoffset_y * 2;
- switch (position) {
+ switch (Position) {
case TextPosition.Top:
box_y = marginy;
break;
@@ -189,23 +210,29 @@
}
}
- void LoadImageFromFile ()
+ void LoadAndScaleImage ()
{
- if (time == 0)
- time = 3;
-
if (project == null)
throw new InvalidOperationException (String.Format ("SlideImage.CreateImage: need project defined (image {0})", image));
+ LoadAndScaleImage (project.Details.Width, project.Details.Height);
+ ProcessEffects ();
+ }
+
+ //
+ // Loads the image from disk and scales it to certain size
+ // It is used to generate the final images and thumbnails
+ //
+ void LoadAndScaleImage (int width, int height)
+ {
if (image == null)
throw new InvalidOperationException (String.Format ("SlideImage.CreateImage: no filename defined for image"));
- Logger.Debug ("SlideImage.CreateImage {0}", image);
+ Logger.Debug ("SlideImage.CreateImage {0}", image, width, height);
- int max_w = project.Details.Width; // max target width
- int max_h = project.Details.Height; // max target height
+ int max_w = width; // max target width
+ int max_h = height; // max target height
double target_ratio = (double) max_w / (double) max_h; // aspect ratio target
- int offset_x, offset_y, w, h;
double scale, original_ratio, corrected_ratio;
Gdk.Pixbuf raw_image, processed_image;
@@ -251,30 +278,101 @@
else
offset_y = 0;
- raw_image.Scale (processed_image, offset_x, offset_y, w, h, offset_x, offset_y, (double) w / (double) raw_image.Width, (double)h /(double) raw_image.Height, InterpType.Hyper);
+ raw_image.Scale (processed_image, offset_x, offset_y, w, h, offset_x, offset_y,
+ (double) w / (double) raw_image.Width, (double)h /(double) raw_image.Height, InterpType.Hyper);
- if (title != string.Empty) {
- PixbufImageSurface pix = new PixbufImageSurface (processed_image);
- Cairo.Context gr = new Cairo.Context (pix);
- DrawImageLegend (gr, title, offset_x, offset_y, w, h);
- FromImage (pix);
- ((IDisposable)gr).Dispose ();
- ((IDisposable)pix).Dispose ();
- } else
- LoadPixBuffer (processed_image);
+ LoadPixBuffer (processed_image);
raw_image.Dispose ();
processed_image.Dispose ();
}
- public void CopyProperties (SlideImage src)
+ void ProcessImage ()
{
- // TODO: Missing SlideImage properties
- width = src.width;
- height = src.height;
- stride = src.stride;
- alpha = src.alpha;
- channels = src.channels;
+ Logger.Debug ("SlideImage.ProcessImage {0}", image);
+
+ if (Title == null)
+ return;
+
+ if (Title == string.Empty)
+ throw new Exception ("Not expecting an empty.string here");
+
+ Logger.Debug ("SlideImage.ProcessImage {0}", image);
+
+ DataImageSurface pix = new DataImageSurface (DataImageSurface.Allocate (Pixels), Cairo.Format.Argb32, width, height, stride);
+ Cairo.Context gr = new Cairo.Context (pix);
+ DrawImageLegend (gr, Title, offset_x, offset_y, w, h);
+ FromImage (pix);
+ ((IDisposable)gr).Dispose ();
+ ((IDisposable)pix).Dispose ();
+ }
+
+ public void ProcessEffects ()
+ {
+ IEffect effect;
+ SlideImage processed, previous;
+
+ if (Effects == null)
+ return;
+
+ previous = processed = this;
+
+ foreach (string name in Effects)
+ {
+ Logger.Debug ("SlideImage.ProcessEffects -> effect {0}", name);
+ effect = EffectManager.FromName (name);
+ previous = processed;
+ processed = effect.ApplyEffect (processed);
+ previous.ReleasePixels ();
+ }
+
+ CopyProperties (processed);
+ Pixels = processed.Pixels;
+ }
+
+ void LoadPixBuffer (Gdk.Pixbuf buf)
+ {
+ int len;
+
+ width = buf.Width;
+ height = buf.Height;
+ stride = buf.Rowstride;
+ alpha = buf.HasAlpha;
+
+ if (requested_channels == buf.NChannels) {
+ channels = buf.NChannels;
+ len = stride * height;
+ pixels = new byte [len];
+ Marshal.Copy (buf.Pixels, pixels, 0, len);
+ return;
+ }
+
+ if (requested_channels == 4 && buf.NChannels == 3) {
+ int src;
+ byte [] source;
+
+ src = 0;
+ channels = buf.NChannels;
+ stride = 4 * width;
+ len = stride * height;
+ source = new byte [channels * height * width];
+ Marshal.Copy (buf.Pixels, source, 0, channels * height * width);
+
+ pixels = new byte [len];
+
+ for (int trg = 0; trg < len; trg = trg + 4) {
+ pixels [trg] = source [src + 2];
+ pixels [trg + 1] = source [src + 1];
+ pixels [trg + 2] = source [src + 0];
+ pixels [trg + 3] = 0xff;
+ src += 3;
+ }
+ return;
+ }
+
+ throw new InvalidOperationException (
+ String.Format ("Could not process SlideImage.LoadPixBuffer requested channels {0} image {1}",
+ requested_channels, buf.NChannels));
}
}
}
Modified: trunk/src/core/SlideShow.cs
==============================================================================
--- trunk/src/core/SlideShow.cs (original)
+++ trunk/src/core/SlideShow.cs Wed Mar 25 20:26:34 2009
@@ -49,12 +49,12 @@
for (int i = 0; i < images.Count - 1; i++)
{
- total_frames += (frames_sec * images[i].time) + (images[i].transition * frames_sec);
+ total_frames += (frames_sec * images[i].ShowTime) + (images[i].TransitionTime * frames_sec);
((SlideImage) images[i]).Project = project;
}
((SlideImage) images[images.Count - 1]).Project = project;
- total_frames += frames_sec * images[images.Count - 1].time;
+ total_frames += frames_sec * images[images.Count - 1].ShowTime;
args.Total = images.Count;
Logger.Debug ("SlideShow.GenerateMPEG -> Generating MPEG for " + images.Count + " images " + "total frames " + total_frames + " at " + filename);
@@ -85,14 +85,13 @@
progress (this, args);
}
- Logger.Debug ("SlideShow.GenerateMPEG ->Send Fixed image {0}, time {1} (frames)", i, (uint) (frames_sec * images[i].time));
-
- transition = TransitionManager.FromName (images[i].effect);
- lib.SlideShowAddImageFixed (((SlideImage)images[i]), (uint) (frames_sec * images[i].time));
+ Logger.Debug ("SlideShow.GenerateMPEG ->Send Fixed image {0}, time {1} (frames)", i, (uint) (frames_sec * images[i].ShowTime));
+ transition = TransitionManager.FromName (images[i].Transition);
+ lib.SlideShowAddImageFixed (((SlideImage)images[i]), (uint) (frames_sec * images[i].ShowTime));
// Transition between two images
- Logger.Debug ("SlideShow.GenerateMPEG ->Generate transition for frames_sec {0} and time {1}", frames_sec, images[i].transition);
- images_transition = transition.Effect (((SlideImage)images[i]), ((SlideImage)images[i + 1]), frames_sec, images[i].transition);
+ Logger.Debug ("SlideShow.GenerateMPEG ->Generate transition for frames_sec {0} and time {1}", frames_sec, images[i].TransitionTime);
+ images_transition = transition.Effect (((SlideImage)images[i]), ((SlideImage)images[i + 1]), frames_sec, images[i].TransitionTime);
for (int j = 0; j < images_transition.Length; j++) {
Logger.Debug (" Sending subimage {0}", j);
lib.SlideShowAddImage (images_transition [j]);
@@ -100,8 +99,8 @@
((SlideImage) images[i]).ReleasePixels ();
}
- Logger.Debug ("SlideShow.GenerateMPEG ->Send Fixed image time {0} (frames)", (uint) (frames_sec * images[images.Count -1].time));
- lib.SlideShowAddImageFixed (((SlideImage)images[images.Count - 1]), (uint) (frames_sec * images[images.Count -1].time));
+ Logger.Debug ("SlideShow.GenerateMPEG ->Send Fixed image time {0} (frames)", (uint) (frames_sec * images[images.Count -1].ShowTime));
+ lib.SlideShowAddImageFixed (((SlideImage)images[images.Count - 1]), (uint) (frames_sec * images[images.Count -1].ShowTime));
if (progress != null) {
args.Progress = args.Progress + 1;
Added: trunk/src/datamodel/IEffect.cs
==============================================================================
--- (empty file)
+++ trunk/src/datamodel/IEffect.cs Wed Mar 25 20:26:34 2009
@@ -0,0 +1,45 @@
+//
+// Copyright (C) 2009 Jordi Mas i Hernandez, jmas softcatala org
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using Mistelix.DataModel;
+
+namespace Mistelix.Effects
+{
+ //
+ // Interface that defines an effect to apply to an image
+ //
+ public interface IEffect
+ {
+ SlideImage ApplyEffect (SlideImage slideimage);
+
+ string DisplayName {
+ get;
+ }
+
+ string Name {
+ get;
+ }
+ }
+}
+
Modified: trunk/src/datamodel/SlideShowProjectElement.cs
==============================================================================
--- trunk/src/datamodel/SlideShowProjectElement.cs (original)
+++ trunk/src/datamodel/SlideShowProjectElement.cs Wed Mar 25 20:26:34 2009
@@ -30,6 +30,7 @@
using Gdk;
using Mistelix.Core;
+using Mistelix.Effects;
namespace Mistelix.DataModel
{
@@ -84,15 +85,63 @@
public abstract class Image : ProjectElement
{
public string image;
- public string title;
- public int transition ; // Transition from slide to slide (effect duration)
- public int time; // Time that the image is shown
- public string effect; // Transition effect
+ string title;
+ int transition_time;
+ int shown_time;
+ string transition;
+ TextPosition position;
+ List <string> effects;
+
+ // Text description
+ //[XmlElementAttribute ("effects")]
+ public List <string> Effects {
+ get { return effects;}
+ set { effects = value;}
+ }
+
+ // Text description
+ [XmlElementAttribute ("title")]
+ public string Title {
+ get { return title;}
+ set { title = value;}
+ }
+
+ // Transition type
+ [XmlElementAttribute ("transition")]
+ public string Transition {
+ get { return transition;}
+ set { transition = value;}
+ }
+
+ // Time that the image is statically shown
+ [XmlElementAttribute ("show_time")]
+ public int ShowTime {
+ get { return shown_time;}
+ set { shown_time = value;}
+ }
+
+ // Transition from slide to slide (effect duration)
+ [XmlIgnoreAttribute]
+ public int TransitionTime {
+ get { return transition_time;}
+ set { transition_time = value;}
+ }
- [XmlElementAttribute (DataType="int")]
- public TextPosition position;
+ [XmlElementAttribute ("position", DataType="int")]
+ public TextPosition Position {
+ get { return position;}
+ set { position = value;}
+ }
protected Image () {}
+
+ public void AddEffect (string effect)
+ {
+ if (effects == null)
+ effects = new List <string> ();
+
+ effects.Add (effect);
+ }
}
}
}
Modified: trunk/src/dialogs/AddSlideDialog.cs
==============================================================================
--- trunk/src/dialogs/AddSlideDialog.cs (original)
+++ trunk/src/dialogs/AddSlideDialog.cs Wed Mar 25 20:26:34 2009
@@ -53,7 +53,6 @@
ListStore transitions_combo, textposition_store;
SlideImage selected_image;
SlideShow slide;
- Dictionary <string, Gdk.Pixbuf> thumbnail_cache;
TransitionPreview drawing_area;
bool edit_mode;
@@ -77,7 +76,6 @@
image_view.ChangeEvent = new ShowImageSelectionEventHandler (OnChangeImage);
image_view.UpdatedElements = new ShowImageUpdatedElementsEventHandler (OnUpdatedImages);
scrolled_images.Add (image_view);
- thumbnail_cache = new Dictionary <string, Gdk.Pixbuf> ();
up_button.Clicked += new EventHandler (OnButtonUp);
down_button.Clicked += new EventHandler (OnButtonDown);
@@ -86,8 +84,6 @@
new DirectoryView (vbox_dir, new ChangeDirectoryEventHandler (OnDirectoryChanged),
Mistelix.Preferences.GetStringValue (Preferences.ImagesDirectoryKey));
- file_view.Cache = thumbnail_cache;
- image_view.Cache = thumbnail_cache;
scrolledwin_files.Add (file_view);
drawing_area = new TransitionPreview ();
@@ -201,7 +197,7 @@
{
model.GetIter (out iter, path);
image = (SlideImage) model.GetValue (iter, SlideShowImageView.COL_OBJECT);
- image.time = spinner.ValueAsInt;
+ image.ShowTime = spinner.ValueAsInt;
}
}
@@ -225,15 +221,15 @@
TreeIter iter;
TreeModel model;
SlideImage image;
- string effect;
+ string transition;
TreeSelection selection;
TreePath[] paths;
if (!combo.GetActiveIter (out iter))
return;
- // Establish new effect on the selected items
- effect = (string) combo.Model.GetValue (iter, (int) ColumnsCombo.Column_Data);
+ // Establish new transition on the selected items
+ transition = (string) combo.Model.GetValue (iter, (int) ColumnsCombo.Column_Data);
selection = (image_view as TreeView).Selection;
paths = selection.GetSelectedRows (out model);
@@ -241,10 +237,10 @@
{
model.GetIter (out iter, path);
image = (SlideImage) model.GetValue (iter, SlideShowImageView.COL_OBJECT);
- image.effect = effect;
+ image.Transition = transition;
}
- drawing_area.UpdateTransitionType (effect);
+ drawing_area.UpdateTransitionType (transition);
}
void OnTextPositionComboChanged (object sender, EventArgs args)
@@ -271,7 +267,7 @@
{
model.GetIter (out iter, path);
image = (SlideImage) model.GetValue (iter, SlideShowImageView.COL_OBJECT);
- image.position = position;
+ image.Position = position;
}
}
@@ -280,7 +276,7 @@
{
bool more;
TreeIter iter;
- string effect;
+ string transition;
Logger.Debug ("AddSlideDialog.OnChangeImage. Images {0}", args.images.Length);
@@ -290,15 +286,15 @@
selected_image = args.images [0]; // Take the first since all of them will be the same
ImageControlsSensitive (true);
- duration_spin.Value = selected_image.time;
+ duration_spin.Value = selected_image.ShowTime;
drawing_area.UpdateTransitionType (string.Empty);
- // Transition effect for this image
+ // Transition for this image
more = transitions_combo.GetIterFirst (out iter);
while (more)
{
- effect = (string) transitions_combo.GetValue (iter, (int) ColumnsCombo.Column_Data);
- if (selected_image.effect.Equals (effect)) {
+ transition = (string) transitions_combo.GetValue (iter, (int) ColumnsCombo.Column_Data);
+ if (selected_image.Transition.Equals (transition)) {
transition_combo.SetActiveIter (iter);
break;
}
@@ -308,13 +304,13 @@
if (more == false)
SetTransisitionToNone ();
- // Text position effect for this image
+ // Text position for this image
TextPosition position;
more = textposition_store.GetIterFirst (out iter);
while (more)
{
position = (TextPosition) textposition_store.GetValue (iter, (int) ColumnsCombo.Column_Data);
- if (selected_image.position == position) {
+ if (selected_image.Position == position) {
textposition_combo.SetActiveIter (iter);
return;
}
@@ -339,11 +335,9 @@
public override void FreeResources ()
{
- Dialog.Destroy ();
file_view.Dispose ();
-
- foreach (KeyValuePair <string, Gdk.Pixbuf> kvp in thumbnail_cache)
- kvp.Value.Dispose ();
+ image_view.Dispose ();
+ Dialog.Destroy ();
}
void LoadTextPositionsIntoCombo ()
@@ -375,7 +369,7 @@
gr.MoveTo (10, 45);
gr.SetFontSize (50);
- // Translators: Used as an example of how a transition effect looks like, transitioning from 'A' to 'B'
+ // Translators: Used as an example of how a transition looks like, transitioning from 'A' to 'B'
gr.ShowText (Catalog.GetString ("A"));
gr.Stroke ();
((IDisposable)gr).Dispose ();
@@ -385,7 +379,7 @@
gr.MoveTo (10, 45);
gr.SetFontSize (50);
- // Translators: Used as an example of how a transition effect looks like, transitioning from 'A' to 'B'
+ // Translators: Used as an example of how a transition looks like, transitioning from 'A' to 'B'
gr.ShowText (Catalog.GetString ("B"));
gr.Stroke ();
((IDisposable)gr).Dispose ();
Modified: trunk/src/mistelix.addin.xml
==============================================================================
--- trunk/src/mistelix.addin.xml (original)
+++ trunk/src/mistelix.addin.xml Wed Mar 25 20:26:34 2009
@@ -7,6 +7,10 @@
<ExtensionPoint path="/Mistelix/SlideTransitions">
<ExtensionNode name="SlideTransitions" objectType="Mistelix.Transitions.ITransition" />
</ExtensionPoint>
+
+ <ExtensionPoint path="/Mistelix/Effects">
+ <ExtensionNode name="Effects" objectType="Mistelix.Effects.IEffect" />
+ </ExtensionPoint>
</Addin>
Modified: trunk/src/mistelix.cs
==============================================================================
--- trunk/src/mistelix.cs (original)
+++ trunk/src/mistelix.cs Wed Mar 25 20:26:34 2009
@@ -96,6 +96,10 @@
Logger.Info ("Extension:" + node.CreateInstance ());
}
+ foreach (TypeExtensionNode node in AddinManager.GetExtensionNodes ("/Mistelix/Effects")) {
+ Logger.Info ("Extension:" + node.CreateInstance ());
+ }
+
if (String.Compare (Environment.GetEnvironmentVariable ("MISTELIX_DEBUG"), "true", false) == 0) {
debugging = true;
} else {
Added: trunk/src/widgets/DataImageSurface.cs
==============================================================================
--- (empty file)
+++ trunk/src/widgets/DataImageSurface.cs Wed Mar 25 20:26:34 2009
@@ -0,0 +1,117 @@
+//
+// Copyright (C) 2008 Aaron Bockover, abockover novell com
+// Copyright (C) 2008 Jordi Mas i Hernandez, jmas softcatala org
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Runtime.InteropServices;
+
+using Cairo;
+
+namespace Mistelix.Widgets
+{
+ public class DataImageSurface : ImageSurface, IDisposable
+ {
+ delegate void cairo_destroy_func_t (IntPtr userdata);
+ static int user_data_key = 0;
+ static cairo_destroy_func_t destroy_func;
+ protected IntPtr data;
+ protected bool is_le = BitConverter.IsLittleEndian;
+
+ static void DestroyPixelData (IntPtr data)
+ {
+ Marshal.FreeHGlobal (data);
+ }
+
+ static DataImageSurface ()
+ {
+ destroy_func = new cairo_destroy_func_t (DestroyPixelData);
+ }
+
+ static public IntPtr Allocate (byte [] pixels)
+ {
+ IntPtr ptr = Marshal.AllocHGlobal (pixels.Length);
+ Marshal.Copy (pixels, 0, ptr, pixels.Length);
+ return ptr;
+ }
+
+ public DataImageSurface (IntPtr data, Cairo.Format format, int width, int height, int stride) : base (data, format, width, height, width * 4)
+ {
+ this.data = data;
+ SetDestroyFunc ();
+ }
+
+ // Converts from Cairo 32-bits to GTK 24 bits (3 channels)
+ public byte[] Get24bitsPixBuf ()
+ {
+ int pos_cairo = 0;
+ int pos_gdk = 0;
+ byte [] cairo_pixels;
+ byte [] pixels;
+ int width, height;
+ const int channels = 3;
+
+ width = Width;
+ height = Height;
+ pixels = new byte [height * Width * channels];
+ cairo_pixels = Data;
+
+ for (int h = 0; h < height; h++)
+ {
+ for (int i = 0; i < width; i++)
+ {
+ if (is_le) {
+ pixels[pos_gdk + 2] = cairo_pixels[pos_cairo + 0];
+ pixels[pos_gdk + 1] = cairo_pixels[pos_cairo + 1];
+ pixels[pos_gdk + 0] = cairo_pixels[pos_cairo + 2];
+ } else {
+ pixels[pos_gdk + 0] = cairo_pixels[pos_cairo + 1];
+ pixels[pos_gdk + 1] = cairo_pixels[pos_cairo + 2];
+ pixels[pos_gdk + 2] = cairo_pixels[pos_cairo + 3];
+ }
+
+ pos_gdk += channels;
+ pos_cairo += 4;
+ }
+ }
+ return pixels;
+ }
+
+
+ [DllImport ("libcairo.so.2")]
+ static extern Cairo.Status cairo_surface_set_user_data (IntPtr surface, ref int key, IntPtr userdata, cairo_destroy_func_t destroy);
+
+ void SetDestroyFunc ()
+ {
+ try {
+ Cairo.Status status = cairo_surface_set_user_data (Handle, ref user_data_key, data, destroy_func);
+ if (status != Cairo.Status.Success) {
+ throw new ApplicationException (String.Format (
+ "cairo_surface_set_user_data returned {0}", status));
+ }
+ } catch (Exception e) {
+ Console.Error.WriteLine (e);
+ }
+ }
+ }
+}
+
Modified: trunk/src/widgets/FileView.cs
==============================================================================
--- trunk/src/widgets/FileView.cs (original)
+++ trunk/src/widgets/FileView.cs Wed Mar 25 20:26:34 2009
@@ -56,7 +56,6 @@
protected int thumbnail_height;
protected int thumbnail_width;
- protected Dictionary <string, Gdk.Pixbuf> thumbnail_cache;
protected FileView ()
{
@@ -79,10 +78,6 @@
Dispose (false);
}
- public Dictionary <string, Gdk.Pixbuf> Cache {
- set { thumbnail_cache = value; }
- }
-
public List <string> SelectedFiles {
get {
List <string> files = new List <string> ();
@@ -140,15 +135,6 @@
if (thumbnailing != null)
thumbnailing.Dispose ();
- if (thumbnail_cache != null) {
- lock (thumbnail_cache) {
- foreach (KeyValuePair <string, Gdk.Pixbuf> kvp in thumbnail_cache)
- kvp.Value.Dispose ();
-
- thumbnail_cache.Clear ();
- }
- }
-
thumbnailing = new BackgroundWorker ();
thumbnailing.DoWork += new DoWorkEventHandler (DoWork);
Modified: trunk/src/widgets/GtkMenu.cs
==============================================================================
--- trunk/src/widgets/GtkMenu.cs (original)
+++ trunk/src/widgets/GtkMenu.cs Wed Mar 25 20:26:34 2009
@@ -33,7 +33,7 @@
{
}
- public void AddItem (string label, EventHandler ev)
+ public Gtk.MenuItem AddItem (string label, EventHandler ev)
{
Gtk.MenuItem item = new Gtk.MenuItem (label);
Append (item);
@@ -42,6 +42,15 @@
item.Activated += ev;
item.Show ();
+
+ return item;
+ }
+
+ public void AddSeparator ()
+ {
+ Gtk.SeparatorMenuItem item = new Gtk.SeparatorMenuItem ();
+ Append (item);
+ item.Show ();
}
public void Popup (ButtonPressEventArgs args)
Modified: trunk/src/widgets/ImagesFileView.cs
==============================================================================
--- trunk/src/widgets/ImagesFileView.cs (original)
+++ trunk/src/widgets/ImagesFileView.cs Wed Mar 25 20:26:34 2009
@@ -133,10 +133,6 @@
Application.Invoke (delegate {
store.SetValue (iter, 2, scaled);
} );
-
- lock (thumbnail_cache) {
- thumbnail_cache[file] = scaled;
- }
im.Dispose ();
return false;
Modified: trunk/src/widgets/PixbufImageSurface.cs
==============================================================================
--- trunk/src/widgets/PixbufImageSurface.cs (original)
+++ trunk/src/widgets/PixbufImageSurface.cs Wed Mar 25 20:26:34 2009
@@ -29,26 +29,13 @@
namespace Mistelix.Widgets
{
- public class PixbufImageSurface : ImageSurface, IDisposable
- {
- private delegate void cairo_destroy_func_t (IntPtr userdata);
-
- private static bool is_le = BitConverter.IsLittleEndian;
- private static int user_data_key = 0;
- private static cairo_destroy_func_t destroy_func;
-
+ public class PixbufImageSurface : DataImageSurface, IDisposable
+ {
private static void DestroyPixelData (IntPtr data)
{
Marshal.FreeHGlobal (data);
}
- static PixbufImageSurface ()
- {
- destroy_func = new cairo_destroy_func_t (DestroyPixelData);
- }
-
- private IntPtr data;
-
public PixbufImageSurface (Gdk.Pixbuf pixbuf) : this (pixbuf, false)
{
}
@@ -70,49 +57,12 @@
this.data = data;
CreateSurface (width, height, channels, rowstride, pixels);
- SetDestroyFunc ();
if (pixbuf != null && pixbuf.Handle != IntPtr.Zero) {
pixbuf.Dispose ();
}
}
- // Converts from Cairo 32-bits to GTK 24 bits (3 channels)
- public byte[] Get24bitsPixBuf ()
- {
- bool is_le = BitConverter.IsLittleEndian;
- int pos_cairo = 0;
- int pos_gdk = 0;
- byte [] cairo_pixels;
- byte [] pixels;
- int width, height;
- const int channels = 3;
-
- width = Width;
- height = Height;
- pixels = new byte [height * Width * channels];
- cairo_pixels = Data;
-
- for (int h = 0; h < height; h++)
- {
- for (int i = 0; i < width; i++)
- {
- if (is_le) {
- pixels[pos_gdk + 2] = cairo_pixels[pos_cairo + 0];
- pixels[pos_gdk + 1] = cairo_pixels[pos_cairo + 1];
- pixels[pos_gdk + 0] = cairo_pixels[pos_cairo + 2];
- } else {
- pixels[pos_gdk + 0] = cairo_pixels[pos_cairo + 1];
- pixels[pos_gdk + 1] = cairo_pixels[pos_cairo + 2];
- pixels[pos_gdk + 2] = cairo_pixels[pos_cairo + 3];
- }
-
- pos_gdk += channels;
- pos_cairo += 4;
- }
- }
- return pixels;
- }
private unsafe void CreateSurface (int width, int height, int channels, int gdk_rowstride, IntPtr pixels)
{
@@ -177,23 +127,6 @@
cr.Paint ();
cr.Restore ();
}
-
- [DllImport ("libcairo.so.2")]
- private static extern Cairo.Status cairo_surface_set_user_data (IntPtr surface,
- ref int key, IntPtr userdata, cairo_destroy_func_t destroy);
-
- private void SetDestroyFunc ()
- {
- try {
- Status status = cairo_surface_set_user_data (Handle, ref user_data_key, data, destroy_func);
- if (status != Status.Success) {
- throw new ApplicationException (String.Format (
- "cairo_surface_set_user_data returned {0}", status));
- }
- } catch (Exception e) {
- Console.Error.WriteLine (e);
- }
- }
}
}
Modified: trunk/src/widgets/SlideShowImageView.cs
==============================================================================
--- trunk/src/widgets/SlideShowImageView.cs (original)
+++ trunk/src/widgets/SlideShowImageView.cs Wed Mar 25 20:26:34 2009
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2008 Jordi Mas i Hernandez, jmas softcatala org
+// Copyright (C) 2008-2009 Jordi Mas i Hernandez, jmas softcatala org
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
@@ -30,9 +30,11 @@
using Gdk;
using Cairo;
using Mono.Unix;
+using Mono.Addins;
using Mistelix.DataModel;
using Mistelix.Core;
+using Mistelix.Effects;
namespace Mistelix.Widgets
{
@@ -50,6 +52,56 @@
public delegate void ShowImageUpdatedElementsEventHandler (object sender, EventArgs e);
+ // Renders a Cairo Image into a tree Cell
+ public class CellRendererCairoImage : CellRenderer
+ {
+ int width, height;
+ Cairo.ImageSurface surface, default_surface;
+ Gtk.TreeIter iter;
+ SlideShowImageView parent;
+
+ public CellRendererCairoImage (int width, int height, Cairo.ImageSurface default_surface, SlideShowImageView parent)
+ {
+ this.width = width;
+ this.height = height;
+ this.default_surface = default_surface;
+ this.parent = parent;
+ }
+
+ public Gtk.TreeIter Iter {
+ get { return iter; }
+ set { iter = value; }
+ }
+
+ public override void GetSize (Widget widget, ref Gdk.Rectangle cell_area, out int x_offset, out int y_offset, out int w, out int h)
+ {
+ x_offset = 0;
+ y_offset = 0;
+ w = width + ((int) Xpad) * 2;
+ h = height + ((int) Ypad) * 2;
+ }
+
+ protected override void Render (Gdk.Drawable window, Widget widget, Gdk.Rectangle background, Gdk.Rectangle cell, Gdk.Rectangle expose, CellRendererState flags)
+ {
+ Cairo.Context cr = Gdk.CairoHelper.Create (window);
+ //Console.WriteLine ("Render {0}", DateTime.Now);
+
+ SlideImage image = (SlideImage) parent.store.GetValue (iter, SlideShowImageView.COL_OBJECT);
+ string filename = image.image;
+
+ surface = (DataImageSurface) parent.store.GetValue (iter, SlideShowImageView.COL_CAIROIMAGE);
+
+ if (surface == null) {
+ parent.RequestThumbnail (iter);
+ }
+
+ cr.Rectangle (cell.X, cell.Y, cell.Width, cell.Height);
+ cr.SetSourceSurface (surface != null ? surface : default_surface, cell.X, cell.Y);
+ cr.Paint ();
+ (cr as System.IDisposable).Dispose ();
+ }
+ }
+
//
// Displays the images selected by the user when creating a slideshow. Drop target.
//
@@ -63,32 +115,36 @@
Date_Descending
}
- ListStore store;
+ public ListStore store; // todo: property
Gtk.Image image;
BackgroundWorker thumbnailing;
- Pixbuf def_image;
int cnt = 1;
bool paint_control = false;
readonly int thumbnail_height;
readonly int thumbnail_width;
readonly string notitle;
- Dictionary <string, Gdk.Pixbuf> thumbnail_cache;
ImageSortType sort_type;
+ IEffect[] effects;
+ Cairo.ImageSurface def_image;
public const int COL_INDEX = 0;
- public const int COL_PIXBUF = 1;
+ public const int COL_CAIROIMAGE = 1;
public const int COL_DESCRIPTION = 2;
public const int COL_OBJECT = 3;
+ public const string EFFECT = "effect";
static TargetEntry [] tag_dest_target_table = new TargetEntry [] {
new TargetEntry ("application/x-mistelix-img", 0, (uint) 2)};
public ShowImageSelectionEventHandler ChangeEvent;
public ShowImageUpdatedElementsEventHandler UpdatedElements;
+ DateTime start_time = DateTime.Now;
+ List <Gtk.TreeIter> iters_list;
public SlideShowImageView ()
{
Model = store = CreateStore ();
+ iters_list = new List <Gtk.TreeIter> ();
notitle = Catalog.GetString ("<No title>");
@@ -103,11 +159,12 @@
DragAction.Copy | DragAction.Move );
CursorChanged += OnCursorChanged;
- def_image = Gtk.IconTheme.Default.LoadIcon ("gtk-new", thumbnail_width, (Gtk.IconLookupFlags) 0);
thumbnailing = new BackgroundWorker ();
thumbnailing.DoWork += new DoWorkEventHandler (DoWork);
ButtonPressEvent += new ButtonPressEventHandler (OnButtonPressed);
KeyPressEvent += OnKeyPressed;
+
+ CreateDefaultImage ();
}
~SlideShowImageView ()
@@ -115,10 +172,6 @@
Dispose (false);
}
- public Dictionary <string, Gdk.Pixbuf> Cache {
- set { thumbnail_cache = value; }
- }
-
public override void Dispose ()
{
Dispose (true);
@@ -130,13 +183,16 @@
Logger.Debug ("SlideShowImageView.Disposing");
store.Foreach (delegate (TreeModel model, TreePath path, TreeIter iter)
{
- Gdk.Pixbuf im = (Gdk.Pixbuf) store.GetValue (iter, COL_PIXBUF);
- im.Dispose ();
+ DataImageSurface image = (DataImageSurface) store.GetValue (iter, COL_CAIROIMAGE);
+
+ if (image != null)
+ image.Dispose ();
return false;
});
-
+ Logger.Debug ("SlideShowImageView.Disposed");
thumbnailing.Dispose ();
+ def_image.Dispose ();
}
public ListStore ListStore {
@@ -151,13 +207,15 @@
foreach (SlideShow.Image image in slideshow.images)
{
FileInfo fi = new FileInfo (image.image);
- store.AppendValues (cnt.ToString (), def_image,
- image.title == null ? notitle : image.title,
+ store.AppendValues (cnt.ToString (), null,
+ image.Title == null ? notitle : image.Title,
image);
cnt++;
}
- thumbnailing.RunWorkerAsync (store);
+ if (thumbnailing.IsBusy == false)
+ thumbnailing.RunWorkerAsync (store);
+
UpdateButtonSensitivity ();
}
@@ -168,7 +226,10 @@
title_cell.Edited += OnDescriptionCellEdited;
AppendColumn (Catalog.GetString ("#"), new CellRendererText (), "text", COL_INDEX);
- AppendColumn (Catalog.GetString ("Image"), new CellRendererPixbuf (), "pixbuf", COL_PIXBUF);
+ AppendColumn (Catalog.GetString ("Image"),
+ new CellRendererCairoImage (thumbnail_width, thumbnail_height, def_image, this),
+ new TreeCellDataFunc (SetTreeIter));
+
AppendColumn (Catalog.GetString ("Description"), title_cell, "text", COL_DESCRIPTION);
}
@@ -183,15 +244,31 @@
if (String.Compare (notitle, args.NewText) != 0)
{
if (args.NewText.Length == 0) { // Title has been clean up
- image.title = null;
+ image.Title = null;
store.SetValue (iter, COL_DESCRIPTION, notitle);
}
else {
- image.title = args.NewText;
- store.SetValue (iter, COL_DESCRIPTION, image.title);
+ image.Title = args.NewText;
+ store.SetValue (iter, COL_DESCRIPTION, image.Title);
}
}
}
+
+ // Sets the Iter element to paint into the CellRendererCairoImage (shared by all cells)
+ void SetTreeIter (Gtk.TreeViewColumn tree_column, Gtk.CellRenderer c, Gtk.TreeModel tree_model, Gtk.TreeIter iter)
+ {
+ ((CellRendererCairoImage)c).Iter = iter;
+ }
+
+ public void RequestThumbnail (Gtk.TreeIter iter)
+ {
+ lock (iters_list) {
+ iters_list.Add (iter);
+ }
+
+ if (thumbnailing.IsBusy == false)
+ thumbnailing.RunWorkerAsync (store);
+ }
void HandleTargetDragDrop (object sender, DragDropArgs args)
{
@@ -221,14 +298,16 @@
args.RetVal = true;
UpdateButtonSensitivity ();
Gtk.Drag.Finish (args.Context, true, false, args.Time);
- thumbnailing.RunWorkerAsync (store);
+
+ if (thumbnailing.IsBusy == false)
+ thumbnailing.RunWorkerAsync (store);
}
// Adds a new dropped file into the view
void LoadFile (string file)
{
FileInfo fi = new FileInfo (file);
- store.AppendValues (cnt.ToString (), def_image, notitle,
+ store.AppendValues (cnt.ToString (), null, notitle,
new SlideImage (fi.FullName));
cnt++;
}
@@ -241,7 +320,7 @@
ListStore CreateStore ()
{
// Image number, image pixbuf, object
- return new ListStore (typeof (string), typeof (Gdk.Pixbuf), typeof (string), typeof (SlideImage));
+ return new ListStore (typeof (string), typeof (DataImageSurface), typeof (string), typeof (SlideImage));
}
protected override void OnSizeAllocated (Gdk.Rectangle allocation)
@@ -297,43 +376,37 @@
ChangeEvent (this, new ShowImageSelectionEventArgs (images));
}
- // TODO: Only new dragged elements should be loaded
- public void DoWork (object sender, DoWorkEventArgs e)
- {
+ void DoWork (object sender, DoWorkEventArgs e)
+ {
Logger.Debug ("SlideShowImageView.Dowork start");
- ListStore store = (ListStore) e.Argument;
-
- store.Foreach (delegate (TreeModel model, TreePath path, TreeIter iter)
- {
+
+ while (true) {
+
+ Gtk.TreeIter iter;
+
+ lock (iters_list) {
+ if (iters_list.Count == 0)
+ break;
+
+ iter = iters_list [0];
+ iters_list.RemoveAt (0);
+ }
+
SlideImage image = (SlideImage) store.GetValue (iter, COL_OBJECT);
string filename = image.image;
- Gdk.Pixbuf scaled;
+ DataImageSurface prev_image;
+ DataImageSurface cairo_image;
- try {
- lock (thumbnail_cache) {
- scaled = thumbnail_cache [filename];
- }
- }
- catch {
- scaled = null;
- }
+ prev_image = (DataImageSurface) store.GetValue (iter, COL_CAIROIMAGE);
- if (scaled == null) {
- Logger.Debug ("file->{0}", filename);
- Gdk.Pixbuf im = new Gdk.Pixbuf (filename);
- int max = Math.Max (im.Width, im.Height);
- scaled = im.ScaleSimple (thumbnail_width * im.Width / max, thumbnail_height * im.Height / max, InterpType.Nearest);
- im.Dispose ();
+ if (prev_image != null) {
+ continue;
}
+ cairo_image = image.GetThumbnail (thumbnail_width, thumbnail_height);
+ Application.Invoke (delegate { store.SetValue (iter, COL_CAIROIMAGE, cairo_image); });
+ }
- Application.Invoke (delegate {
- store.SetValue (iter, COL_PIXBUF, scaled);
- } );
-
- return false;
- });
-
- Logger.Debug ("SlideShowImageView.Dowork end");
+ Logger.Debug ("SlideShowImageView.Dowork end");
}
public void MoveUpSelectedElements ()
@@ -410,16 +483,35 @@
void OnButtonPressed (object o, ButtonPressEventArgs args)
{
GtkMenu menu;
+ ExtensionNodeList nodelist;
if (args.Event.Button != 3)
return;
menu = new GtkMenu ();
+ nodelist = AddinManager.GetExtensionNodes ("/Mistelix/Effects");
+ if (nodelist.Count > 0) {
+
+ effects = new IEffect [nodelist.Count];
+ int pos = 0;
+ foreach (TypeExtensionNode node in nodelist) {
+ IEffect effect = (IEffect) node.CreateInstance ();
+
+ MenuItem item = menu.AddItem (effect.DisplayName, OnEffect);
+ item.SetData (EFFECT, new IntPtr (pos));
+ effects [pos] = effect;
+ pos++;
+ }
+
+ menu.AddSeparator ();
+ }
+
menu.AddItem (Catalog.GetString ("Sort by filename (Ascending)"), OnSortAscendingbyName);
menu.AddItem (Catalog.GetString ("Sort by filename (Descending)"), OnSortDescendingbyName);
menu.AddItem (Catalog.GetString ("Sort by date on disc (Ascending)"), OnSortAscendingbyDate);
menu.AddItem (Catalog.GetString ("Sort by date on disc (Descending)"), OnSortDescendingbyDate);
+ menu.AddSeparator ();
menu.AddItem (Catalog.GetString ("Remove selected images"), OnRemoveSelectedImage);
menu.AddItem (Catalog.GetString ("Remove all images"), OnRemoveImages);
@@ -516,5 +608,62 @@
OnRemoveSelectedImage (sender, EventArgs.Empty);
}
}
+
+ void OnEffect (object obj, EventArgs e)
+ {
+ TreeIter iter;
+ TreePath[] paths;
+ IEffect effect;
+ SlideImage image, effect_image;
+ DataImageSurface cairo_image, prev_image;
+
+ paths = Selection.GetSelectedRows ();
+
+ if (paths.Length == 0)
+ return;
+
+ int pos = (int) ((MenuItem) obj).GetData (EFFECT);
+ effect = effects [pos];
+
+ Logger.Debug ("OnEffect {0} {1}", paths.Length, effect.Name);
+
+ for (int i = 0; i < paths.Length; i++)
+ {
+ store.GetIter (out iter, paths[i]);
+ prev_image = (DataImageSurface) store.GetValue (iter, COL_CAIROIMAGE);
+ image = (SlideImage) store.GetValue (iter, COL_OBJECT);
+ image.AddEffect (effect.Name);
+
+ cairo_image = image.GetThumbnail (thumbnail_width, thumbnail_height);
+ store.SetValue (iter, COL_CAIROIMAGE, cairo_image);
+
+ if (prev_image != null)
+ prev_image.Dispose ();
+ }
+ }
+
+ // Create the image indicating that there is no preview available yet
+ void CreateDefaultImage ()
+ {
+ Cairo.Context cr;
+ int box_width, box_height;
+ const int min_xpad = 10;
+
+ def_image = new Cairo.ImageSurface (Format.Argb32, thumbnail_width, thumbnail_height);
+ cr = new Cairo.Context (def_image);
+
+ using (Pango.Layout layout = Pango.CairoHelper.CreateLayout (cr))
+ {
+ layout.FontDescription = Pango.FontDescription.FromString ("sans 8");
+ layout.SetMarkup (Catalog.GetString ("No preview available"));
+ layout.Alignment = Pango.Alignment.Center;
+ layout.SingleParagraphMode = false;
+ layout.Width = (int) ((thumbnail_width - min_xpad * 2) * Pango.Scale.PangoScale);
+ layout.GetPixelSize (out box_width, out box_height);
+ cr.MoveTo (min_xpad, (thumbnail_height - box_height) / 2);
+ Pango.CairoHelper.ShowLayout (cr, layout);
+ }
+ ((IDisposable)cr).Dispose ();
+ }
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]