// Iterator.cs - Custom iterator wrapper for IEnumerable // // Authors: // Maarten Bosmans // Sebastian Dröge // Stephan Sundermann // // Copyright (c) 2009 Maarten Bosmans // Copyright (c) 2009 Sebastian Dröge // Copyright (c) 2013 Stephan Sundermann // // This program is free software; you can redistribute it and/or // modify it under the terms of version 2 of the Lesser GNU General // Public License as published by the Free Software Foundation. // // 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 // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this program; if not, write to the // Free Software Foundation, Inc., 59 Temple Place - Suite 330, // Boston, MA 02111-1307, USA. namespace Gst { using System; using System.Collections; using System.Collections.Generic; using System.Runtime.InteropServices; using GLib; public partial class Iterator : IEnumerable { [DllImport ("libgobject-2.0-0.dll", CallingConvention = CallingConvention.Cdecl)] static extern IntPtr g_value_reset (ref GLib.Value val); [DllImport("libgstreamer-1.0-0.dll", CallingConvention = CallingConvention.Cdecl)] static extern int gst_iterator_next(IntPtr raw, ref GLib.Value elem); public Gst.IteratorResult Next(ref GLib.Value elem) { int raw_ret = gst_iterator_next(Handle, ref elem); Gst.IteratorResult ret = (Gst.IteratorResult) raw_ret; return ret; } private class Enumerator : IEnumerator { Iterator iterator; Hashtable seen = new Hashtable (); private object current = null; public object Current { get { return current; } } public bool MoveNext () { IntPtr raw_ret; bool retry = false; if (iterator.Handle == IntPtr.Zero) return false; do { GLib.Value value = new GLib.Value (GLib.GType.Boolean); value.Dispose (); IteratorResult ret = iterator.Next (ref value); switch (ret) { case IteratorResult.Done: return false; case IteratorResult.Ok: if (seen.Contains (value)) { retry = true; break; } seen.Add (value , null); current = value.Val; return true; case IteratorResult.Resync: iterator.Resync (); retry = true; break; default: case IteratorResult.Error: throw new Exception ("Error while iterating"); } } while (retry); return false; } public void Reset () { seen.Clear (); if (iterator.Handle != IntPtr.Zero) iterator.Resync (); } public Enumerator (Iterator iterator) { this.iterator = iterator; } } private Enumerator enumerator = null; public IEnumerator GetEnumerator () { if (this.enumerator == null) this.enumerator = new Enumerator (this); return this.enumerator; } ~Iterator () { if (Raw != IntPtr.Zero) Free (Handle); } } }