summaryrefslogtreecommitdiff
path: root/sources/custom/Iterator.cs
blob: 4028c8c97bfa898a7868c30835b9a08623f60e6a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
// Iterator.cs - Custom iterator wrapper for IEnumerable
//
// Authors:
//     Maarten Bosmans <mkbosmans@gmail.com>
//     Sebastian Dröge <slomo@circular-chaos.org>
//     Stephan Sundermann <stephansundermann@gmail.com>
//
// 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);
		}

	}
}