[longomatch] Add support for external videos and images in playlists
- From: Andoni Morales Alastruey <amorales src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [longomatch] Add support for external videos and images in playlists
- Date: Tue, 11 Nov 2014 17:58:00 +0000 (UTC)
commit 423e9a6c7c81e205f1765f48befd40836acb68cd
Author: Andoni Morales Alastruey <ylatuya gmail com>
Date: Wed Nov 5 21:44:06 2014 +0100
Add support for external videos and images in playlists
LongoMatch.Core/Interfaces/IPlaylistElement.cs | 5 +
LongoMatch.Core/LongoMatch.Core.csproj | 1 +
LongoMatch.Core/Makefile.am | 1 +
LongoMatch.Core/Store/Playlists/PlaylistDrawing.cs | 3 +-
LongoMatch.Core/Store/Playlists/PlaylistImage.cs | 4 +
.../Store/Playlists/PlaylistPlayElement.cs | 7 ++
LongoMatch.Core/Store/Playlists/PlaylistVideo.cs | 64 ++++++++++++
LongoMatch.Drawing/PlayslistCellRenderer.cs | 5 +
LongoMatch.Drawing/Widgets/Blackboard.cs | 14 ++-
LongoMatch.GUI.Multimedia/Gui/PlayerBin.cs | 105 ++++++++++++++++----
LongoMatch.GUI.Multimedia/gtk-gui/objects.xml | 1 -
LongoMatch.GUI/Gui/TreeView/PlayListTreeView.cs | 54 ++++++++++-
LongoMatch.Services/Services/PlaylistManager.cs | 4 +-
.../Services/RenderingJobsManager.cs | 11 ++-
14 files changed, 248 insertions(+), 31 deletions(-)
---
diff --git a/LongoMatch.Core/Interfaces/IPlaylistElement.cs b/LongoMatch.Core/Interfaces/IPlaylistElement.cs
index cc6c079..127c741 100644
--- a/LongoMatch.Core/Interfaces/IPlaylistElement.cs
+++ b/LongoMatch.Core/Interfaces/IPlaylistElement.cs
@@ -16,6 +16,7 @@
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
//
using LongoMatch.Core.Common;
+using LongoMatch.Core.Store;
namespace LongoMatch.Core.Interfaces
{
@@ -33,5 +34,9 @@ namespace LongoMatch.Core.Interfaces
get;
set;
}
+
+ Time Duration {
+ get;
+ }
}
}
diff --git a/LongoMatch.Core/LongoMatch.Core.csproj b/LongoMatch.Core/LongoMatch.Core.csproj
index 7481e1e..5974cea 100644
--- a/LongoMatch.Core/LongoMatch.Core.csproj
+++ b/LongoMatch.Core/LongoMatch.Core.csproj
@@ -131,6 +131,7 @@
<Compile Include="Store\MediaFileSet.cs" />
<Compile Include="Common\Hotkeys.cs" />
<Compile Include="Common\Keyboard.cs" />
+ <Compile Include="Store\Playlists\PlaylistVideo.cs" />
</ItemGroup>
<ItemGroup>
<Folder Include="Common\" />
diff --git a/LongoMatch.Core/Makefile.am b/LongoMatch.Core/Makefile.am
index a7dad10..8563ed9 100644
--- a/LongoMatch.Core/Makefile.am
+++ b/LongoMatch.Core/Makefile.am
@@ -92,6 +92,7 @@ SOURCES = Common/Area.cs \
Store/Playlists/PlaylistDrawing.cs \
Store/Playlists/PlaylistImage.cs \
Store/Playlists/PlaylistPlayElement.cs \
+ Store/Playlists/PlaylistVideo.cs \
Store/Point.cs \
Store/Project.cs \
Store/ProjectDescription.cs \
diff --git a/LongoMatch.Core/Store/Playlists/PlaylistDrawing.cs
b/LongoMatch.Core/Store/Playlists/PlaylistDrawing.cs
index 8b17a2f..302044c 100644
--- a/LongoMatch.Core/Store/Playlists/PlaylistDrawing.cs
+++ b/LongoMatch.Core/Store/Playlists/PlaylistDrawing.cs
@@ -18,6 +18,7 @@
using System;
using LongoMatch.Core.Interfaces;
using LongoMatch.Core.Common;
+using Newtonsoft.Json;
namespace LongoMatch.Core.Store.Playlists
{
@@ -29,11 +30,11 @@ namespace LongoMatch.Core.Store.Playlists
Drawing = drawing;
}
+ [JsonIgnore]
public bool Selected {
get;
set;
}
-
public int Width {
get;
diff --git a/LongoMatch.Core/Store/Playlists/PlaylistImage.cs
b/LongoMatch.Core/Store/Playlists/PlaylistImage.cs
index 9ca89e6..cfbc17e 100644
--- a/LongoMatch.Core/Store/Playlists/PlaylistImage.cs
+++ b/LongoMatch.Core/Store/Playlists/PlaylistImage.cs
@@ -18,6 +18,7 @@
using System;
using LongoMatch.Core.Common;
using LongoMatch.Core.Interfaces;
+using Newtonsoft.Json;
#if HAVE_GTK
using SImage = Gdk.Pixbuf;
@@ -31,6 +32,8 @@ namespace LongoMatch.Core.Store.Playlists
public PlaylistImage (Image image, Time duration)
{
Image = image;
+ Miniature = image.Scale (Constants.MAX_THUMBNAIL_SIZE,
+ Constants.MAX_THUMBNAIL_SIZE);
Duration = duration;
}
@@ -39,6 +42,7 @@ namespace LongoMatch.Core.Store.Playlists
set;
}
+ [JsonIgnore]
public bool Selected {
get;
set;
diff --git a/LongoMatch.Core/Store/Playlists/PlaylistPlayElement.cs
b/LongoMatch.Core/Store/Playlists/PlaylistPlayElement.cs
index 7637e77..0d78fb3 100644
--- a/LongoMatch.Core/Store/Playlists/PlaylistPlayElement.cs
+++ b/LongoMatch.Core/Store/Playlists/PlaylistPlayElement.cs
@@ -41,11 +41,18 @@ namespace LongoMatch.Core.Store.Playlists
set;
}
+ [JsonIgnore]
public bool Selected {
get;
set;
}
+ public Time Duration {
+ get {
+ return Play.Duration;
+ }
+ }
+
public string Title {
get;
set;
diff --git a/LongoMatch.Core/Store/Playlists/PlaylistVideo.cs
b/LongoMatch.Core/Store/Playlists/PlaylistVideo.cs
new file mode 100644
index 0000000..6b39d3e
--- /dev/null
+++ b/LongoMatch.Core/Store/Playlists/PlaylistVideo.cs
@@ -0,0 +1,64 @@
+//
+// Copyright (C) 2014 Andoni Morales Alastruey
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+using System;
+using System.IO;
+using LongoMatch.Core.Interfaces;
+using LongoMatch.Core.Common;
+using Newtonsoft.Json;
+
+namespace LongoMatch.Core.Store.Playlists
+{
+ [Serializable]
+ public class PlaylistVideo: IPlaylistElement
+ {
+ public PlaylistVideo (MediaFile file)
+ {
+ File = file;
+ }
+
+ public MediaFile File {
+ get;
+ set;
+ }
+
+ public string Description {
+ get {
+ return Path.GetFileName (File.FilePath);
+ }
+ }
+
+ public Image Miniature {
+ get {
+ return File.Preview;
+ }
+ }
+
+ [JsonIgnore]
+ public bool Selected {
+ get;
+ set;
+ }
+
+ public Time Duration {
+ get {
+ return File.Duration;
+ }
+ }
+ }
+}
+
diff --git a/LongoMatch.Drawing/PlayslistCellRenderer.cs b/LongoMatch.Drawing/PlayslistCellRenderer.cs
index 0f5ca15..32f9df3 100644
--- a/LongoMatch.Drawing/PlayslistCellRenderer.cs
+++ b/LongoMatch.Drawing/PlayslistCellRenderer.cs
@@ -23,6 +23,7 @@ using LongoMatch.Core.Store.Playlists;
using System.IO;
using System.Collections.Generic;
using LongoMatch.Drawing.CanvasObjects;
+using LongoMatch.Core.Interfaces;
namespace LongoMatch.Drawing
{
@@ -270,6 +271,10 @@ namespace LongoMatch.Drawing
PlaylistPlayElement p = item as PlaylistPlayElement;
RenderPlay (p.Play.EventType.Color, p.Miniature, null, p.Selected,
p.Description, count, isExpanded, tk,
context, backgroundArea, cellArea, state);
+ } else if (item is IPlaylistElement) {
+ IPlaylistElement p = item as IPlaylistElement;
+ RenderPlay (Config.Style.PaletteActive, p.Miniature, null, p.Selected,
p.Description,
+ count, isExpanded, tk, context, backgroundArea, cellArea, state);
} else {
Log.Error ("No renderer for type " + item.GetType ());
}
diff --git a/LongoMatch.Drawing/Widgets/Blackboard.cs b/LongoMatch.Drawing/Widgets/Blackboard.cs
index 57bb62e..2b73ef6 100644
--- a/LongoMatch.Drawing/Widgets/Blackboard.cs
+++ b/LongoMatch.Drawing/Widgets/Blackboard.cs
@@ -62,14 +62,18 @@ namespace LongoMatch.Drawing.Widgets
set {
Clear (false);
drawing = value;
- foreach (IBlackboardObject d in value.Drawables) {
- Add (d);
- }
if (backbuffer != null) {
backbuffer.Dispose ();
}
- backbuffer = tk.CreateSurface (Background.Width, Background.Height,
- drawing.Freehand);
+ if (drawing != null) {
+ foreach (IBlackboardObject d in drawing.Drawables) {
+ Add (d);
+ }
+ backbuffer = tk.CreateSurface (Background.Width, Background.Height,
+ drawing.Freehand);
+ } else {
+ backbuffer = tk.CreateSurface (Background.Width, Background.Height);
+ }
Accuracy = Background.Width / 100;
}
}
diff --git a/LongoMatch.GUI.Multimedia/Gui/PlayerBin.cs b/LongoMatch.GUI.Multimedia/Gui/PlayerBin.cs
index 6d20cad..183cd2e 100644
--- a/LongoMatch.GUI.Multimedia/Gui/PlayerBin.cs
+++ b/LongoMatch.GUI.Multimedia/Gui/PlayerBin.cs
@@ -56,11 +56,12 @@ namespace LongoMatch.Gui
const int THUMBNAIL_MAX_WIDTH = 100;
const int SCALE_FPS = 25;
+ const int TIMEOUT_MS = 20;
IPlayer player;
TimelineEvent loadedPlay;
IPlaylistElement loadedPlaylistElement;
Playlist loadedPlaylist;
- Time length, lastTime;
+ Time length, lastTime, imageLoadedTS;
bool seeking, IsPlayingPrevState, muted, emitRateScale, readyToSeek;
bool ignoreTick, stillimageLoaded, delayedOpen;
MediaFileSet fileSet;
@@ -220,18 +221,26 @@ namespace LongoMatch.Gui
public void Play ()
{
- DrawingsVisible = false;
- player.Play ();
+ if (ImageLoaded) {
+ ReconfigureTimeout (TIMEOUT_MS);
+ } else {
+ DrawingsVisible = false;
+ player.Play ();
+ }
}
public void Pause ()
{
- player.Pause ();
+ if (ImageLoaded) {
+ ReconfigureTimeout (0);
+ } else {
+ player.Pause ();
+ }
}
public void TogglePlay ()
{
- if (player.Playing)
+ if ((ImageLoaded && timeout != 0) || player.Playing)
Pause ();
else
Play ();
@@ -267,10 +276,12 @@ namespace LongoMatch.Gui
PlaylistPlayElement ple = element as PlaylistPlayElement;
TimelineEvent play = ple.Play;
LoadSegment (ple.FileSet, play.Start, play.Stop, play.Start, true, play.Rate);
+ } else if (element is PlaylistVideo) {
+ LoadVideo (element as PlaylistVideo);
} else if (element is PlaylistImage) {
- //LoadStillImage (element as PlaylistImage);
+ LoadStillImage (element as PlaylistImage);
} else if (element is PlaylistDrawing) {
- //LoadFrameDrawing (element as PlaylistDrawing);
+ LoadFrameDrawing (element as PlaylistDrawing);
}
}
@@ -301,6 +312,9 @@ namespace LongoMatch.Gui
public void Seek (Time time, bool accurate)
{
+ if (ImageLoaded) {
+ return;
+ }
DrawingsVisible = false;
player.Seek (time + activeFile.Offset, accurate);
OnTick ();
@@ -308,6 +322,9 @@ namespace LongoMatch.Gui
public void SeekToNextFrame ()
{
+ if (ImageLoaded) {
+ return;
+ }
DrawingsVisible = false;
if (CurrentTime < segment.Stop) {
player.SeekToNextFrame ();
@@ -317,6 +334,9 @@ namespace LongoMatch.Gui
public void SeekToPreviousFrame ()
{
+ if (ImageLoaded) {
+ return;
+ }
DrawingsVisible = false;
if (CurrentTime > segment.Start) {
seeker.Seek (SeekType.StepDown);
@@ -325,25 +345,35 @@ namespace LongoMatch.Gui
public void StepForward ()
{
+ if (ImageLoaded) {
+ return;
+ }
DrawingsVisible = false;
Jump ((int)jumpspinbutton.Value);
}
public void StepBackward ()
{
+ if (ImageLoaded) {
+ return;
+ }
DrawingsVisible = false;
Jump (-(int)jumpspinbutton.Value);
}
public void FramerateUp ()
{
- DrawingsVisible = false;
+ if (!ImageLoaded) {
+ DrawingsVisible = false;
+ }
vscale1.Adjustment.Value += vscale1.Adjustment.StepIncrement;
}
public void FramerateDown ()
{
- DrawingsVisible = false;
+ if (!ImageLoaded) {
+ DrawingsVisible = false;
+ }
vscale1.Adjustment.Value -= vscale1.Adjustment.StepIncrement;
}
@@ -356,7 +386,6 @@ namespace LongoMatch.Gui
SetScaleValue (SCALE_FPS);
//timescale.Sensitive = true;
loadedPlay = null;
- ImageLoaded = false;
}
public void SetSensitive ()
@@ -379,7 +408,7 @@ namespace LongoMatch.Gui
}
}
- void Open (MediaFileSet fileSet, bool seek, bool force=false)
+ void Open (MediaFileSet fileSet, bool seek, bool force=false, bool play=false)
{
ResetGui ();
CloseSegment ();
@@ -401,6 +430,9 @@ namespace LongoMatch.Gui
Seek (new Time (0), true);
}
}
+ if (play) {
+ player.Play ();
+ }
detachbutton.Sensitive = true;
}
@@ -424,6 +456,11 @@ namespace LongoMatch.Gui
bool ImageLoaded {
set {
stillimageLoaded = value;
+ if (stillimageLoaded) {
+ player.Pause();
+ imageLoadedTS = new Time (0);
+ ReconfigureTimeout (TIMEOUT_MS);
+ }
drawbutton.Sensitive = !stillimageLoaded;
playbutton.Sensitive = !stillimageLoaded;
pausebutton.Sensitive = !stillimageLoaded;
@@ -492,16 +529,28 @@ namespace LongoMatch.Gui
videowindow.Visible = false;
}
- void LoadStillImage (Image image)
+ void LoadStillImage (PlaylistImage image)
{
+ loadedPlaylistElement = image;
+ CloseSegment ();
ImageLoaded = true;
- LoadImage (image, null);
+ LoadImage (image.Image, null);
}
- void LoadFrameDrawing (FrameDrawing drawing)
+ void LoadFrameDrawing (PlaylistDrawing drawing)
{
+ loadedPlaylistElement = drawing;
+ CloseSegment ();
ImageLoaded = true;
- LoadImage (null, drawing);
+ LoadImage (null, drawing.Drawing);
+ }
+
+ void LoadVideo (PlaylistVideo video)
+ {
+ loadedPlaylistElement = video;
+ MediaFileSet fileSet = new MediaFileSet ();
+ fileSet.SetAngle (MediaFileAngle.Angle1, video.File);
+ Open (fileSet, false, true, true);
}
void LoadPlayDrawing (FrameDrawing drawing)
@@ -590,11 +639,13 @@ namespace LongoMatch.Gui
void DoStateChanged (bool playing)
{
if (playing) {
- ReconfigureTimeout (20);
+ ReconfigureTimeout (TIMEOUT_MS);
playbutton.Hide ();
pausebutton.Show ();
} else {
- ReconfigureTimeout (0);
+ if (!ImageLoaded) {
+ ReconfigureTimeout (0);
+ }
playbutton.Show ();
pausebutton.Hide ();
}
@@ -650,6 +701,18 @@ namespace LongoMatch.Gui
return true;
}
+ if (ImageLoaded) {
+ slength = loadedPlaylistElement.Duration.ToMSecondsString (true);
+ timelabel.Text = imageLoadedTS.ToMSecondsString (true) + "/" + slength;
+ timescale.Value = (double)imageLoadedTS.MSeconds /
loadedPlaylistElement.Duration.MSeconds;
+ if (imageLoadedTS >= loadedPlaylistElement.Duration) {
+ Config.EventsBroker.EmitNextPlaylistElement (loadedPlaylist);
+ } else {
+ imageLoadedTS.MSeconds += TIMEOUT_MS;
+ }
+ return true;
+ }
+
currentTime = CurrentTime;
if (SegmentLoaded) {
Time dur, ct;
@@ -767,8 +830,12 @@ namespace LongoMatch.Gui
void OnEndOfStream ()
{
Application.Invoke (delegate {
- Seek (new Time (0), true);
- Pause ();
+ if (loadedPlaylistElement is PlaylistVideo) {
+ Config.EventsBroker.EmitNextPlaylistElement (loadedPlaylist);
+ } else {
+ Seek (new Time (0), true);
+ Pause ();
+ }
});
}
diff --git a/LongoMatch.GUI.Multimedia/gtk-gui/objects.xml b/LongoMatch.GUI.Multimedia/gtk-gui/objects.xml
index f79f24e..717a220 100644
--- a/LongoMatch.GUI.Multimedia/gtk-gui/objects.xml
+++ b/LongoMatch.GUI.Multimedia/gtk-gui/objects.xml
@@ -37,7 +37,6 @@
<itemgroups>
<itemgroup label="VideoWindow Properties">
<property name="Ready" />
- <property name="Visible" />
</itemgroup>
</itemgroups>
<signals>
diff --git a/LongoMatch.GUI/Gui/TreeView/PlayListTreeView.cs b/LongoMatch.GUI/Gui/TreeView/PlayListTreeView.cs
index ef98919..356ccbe 100644
--- a/LongoMatch.GUI/Gui/TreeView/PlayListTreeView.cs
+++ b/LongoMatch.GUI/Gui/TreeView/PlayListTreeView.cs
@@ -84,10 +84,50 @@ namespace LongoMatch.Gui.Component
c.Count = model.IterNChildren (iter);
}
- void ShowPlaylistElementMenu (Playlist playlist, IPlaylistElement element)
+ void AddVideo (Playlist playlist, IPlaylistElement element, bool prepend, TreeIter parent)
+ {
+ MediaFile file = LongoMatch.Gui.Helpers.Misc.OpenFile (this);
+ if (file != null) {
+ PlaylistVideo video = new PlaylistVideo (file);
+ int index = playlist.Elements.IndexOf (element);
+ if (!prepend) {
+ index ++;
+ }
+ playlist.Elements.Insert (index, video);
+ (Model as TreeStore).InsertWithValues (parent, index, video);
+ }
+ }
+
+ void AddImage (Playlist playlist, IPlaylistElement element, bool prepend, TreeIter parent)
+ {
+ Pixbuf pix = LongoMatch.Gui.Helpers.Misc.OpenImage (this);
+ if (pix != null) {
+ var image = new LongoMatch.Core.Common.Image (pix);
+ PlaylistImage plimage = new PlaylistImage (image, new Time (5000));
+ int index = playlist.Elements.IndexOf (element);
+ if (!prepend) {
+ index ++;
+ }
+ playlist.Elements.Insert (index, plimage);
+ (Model as TreeStore).InsertWithValues (parent, index, plimage);
+ }
+ }
+
+ Menu CreateExternalsMenu (Playlist playlist, IPlaylistElement element, bool prepend, TreeIter
parent) {
+ Menu addMenu = new Menu ();
+ MenuItem video = new MenuItem (Catalog.GetString ("External video"));
+ video.Activated += (sender, e) => AddVideo (playlist, element, prepend, parent);
+ addMenu.Append (video);
+ MenuItem stillImage = new MenuItem (Catalog.GetString ("External image"));
+ stillImage.Activated += (sender, e) => AddImage (playlist, element, prepend, parent);
+ addMenu.Append (stillImage);
+ return addMenu;
+ }
+
+ void ShowPlaylistElementMenu (Playlist playlist, IPlaylistElement element, TreeIter parent)
{
Menu menu;
- MenuItem edit, delete;
+ MenuItem edit, delete, prepend, append;
menu = new Menu ();
@@ -105,6 +145,14 @@ namespace LongoMatch.Gui.Component
menu.Append (edit);
}
+ prepend = new MenuItem (Catalog.GetString ("Insert before"));
+ prepend.Submenu = CreateExternalsMenu (playlist, element, true, parent);
+ menu.Append (prepend);
+
+ append = new MenuItem (Catalog.GetString ("Insert after"));
+ append.Submenu = CreateExternalsMenu (playlist, element, false, parent);
+ menu.Append (append);
+
delete = new MenuItem (Catalog.GetString ("Delete"));
delete.Activated += (sender, e) => {
project.Playlists.Remove (playlist);
@@ -166,7 +214,7 @@ namespace LongoMatch.Gui.Component
TreeIter parent;
Model.IterParent (out parent, selectedIter);
Playlist playlist = Model.GetValue (parent, 0) as Playlist;
- ShowPlaylistElementMenu (playlist, el as IPlaylistElement);
+ ShowPlaylistElementMenu (playlist, el as IPlaylistElement,
parent);
}
}
}
diff --git a/LongoMatch.Services/Services/PlaylistManager.cs b/LongoMatch.Services/Services/PlaylistManager.cs
index f830efa..a219494 100644
--- a/LongoMatch.Services/Services/PlaylistManager.cs
+++ b/LongoMatch.Services/Services/PlaylistManager.cs
@@ -280,7 +280,9 @@ namespace LongoMatch.Services
if (evt == null && loadedElement is PlaylistPlayElement) {
evt = (loadedElement as PlaylistPlayElement).Play;
}
- Config.EventsBroker.EmitDrawFrame (evt, -1, player.ActiveAngle, true);
+ if (evt != null) {
+ Config.EventsBroker.EmitDrawFrame (evt, -1,
player.ActiveAngle, true);
+ }
return;
case KeyAction.TogglePlay:
player.TogglePlay ();
diff --git a/LongoMatch.Services/Services/RenderingJobsManager.cs
b/LongoMatch.Services/Services/RenderingJobsManager.cs
index a29ac63..a22e003 100644
--- a/LongoMatch.Services/Services/RenderingJobsManager.cs
+++ b/LongoMatch.Services/Services/RenderingJobsManager.cs
@@ -186,6 +186,8 @@ namespace LongoMatch.Services
foreach (IPlaylistElement segment in job.Playlist.Elements) {
if (segment is PlaylistPlayElement) {
ProcessPlay (segment as PlaylistPlayElement);
+ } else if (segment is PlaylistVideo) {
+ ProcessVideo (segment as PlaylistVideo);
} else if (segment is PlaylistImage) {
ProcessImage (segment as PlaylistImage);
} else if (segment is PlaylistDrawing) {
@@ -216,7 +218,14 @@ namespace LongoMatch.Services
image.Duration));
ProcessImage (image.Image, image.Duration);
}
-
+
+ void ProcessVideo (PlaylistVideo video)
+ {
+ Log.Debug ("Adding external video " + video.File.FilePath);
+ videoEditor.AddSegment (video.File.FilePath, 0, video.File.Duration.MSeconds,
+ 1, "", video.File.HasAudio);
+ }
+
void ProcessDrawing (PlaylistDrawing drawing)
{
Image img;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]