public static Gst.Caps NewEmpty () { return new Gst.Caps (); } public Caps (Structure s) : this () { Append (s); } public Caps (Structure[] s) : this () { foreach (Structure o in s) Append (o); } public Caps (string mediaType, params object[] fields) : this () { Append (new Structure (mediaType, fields)); } [DllImport ("gstreamersharpglue-0.10.dll") ] extern static uint gstsharp_gst_caps_get_refcount_offset (); static uint refcount_offset = gstsharp_gst_caps_get_refcount_offset (); private int Refcount { get { unsafe { int* raw_ptr = (int*) ( ( (byte*) Handle) + refcount_offset); return (*raw_ptr); } } } public bool IsWritable { get { return (Refcount == 1); } } /* FIXME: This is not optimal! */ public void MakeWritable() { if (IsWritable) return; RemoveStructureReferences (); IntPtr copy = gst_caps_copy (Raw); Raw = copy; /* ^--- Takes a second ref, not good */ Unref (Raw); /* ^--- Sets Owned = false, wrong! */ Owned = true; } private Hashtable structures = new Hashtable (); private void RemoveStructureReference (Structure s) { structures.Remove (s.Handle); s.CreateNativeCopy (); } private void RemoveStructureReferences () { foreach (Structure s in structures.Values) { s.CreateNativeCopy (); } structures.Clear (); } [DllImport ("libgstreamer-0.10.dll") ] private static extern IntPtr gst_caps_get_structure (IntPtr handle, uint index); public Structure this [uint index] { get { if (index >= Size) throw new ArgumentOutOfRangeException (); IntPtr raw_ptr = gst_caps_get_structure (Handle, (uint) index); if (structures.Contains (raw_ptr)) { Structure ret = (Gst.Structure) structures[raw_ptr]; return ret; } else { Structure ret = new Gst.Structure (raw_ptr); ret.FreeNative = false; structures.Add (raw_ptr, ret); return ret; } } } private class StructureEnumerator : IEnumerator { Gst.Caps caps; long index; public StructureEnumerator (Gst.Caps caps) { this.caps = caps; index = -1; } public object Current { get { if (index >= caps.Size) throw new ArgumentOutOfRangeException (); if (index == -1) throw new ArgumentException (); return caps[ (uint) index]; } } public bool MoveNext () { index += 1; return (index < caps.Size); } public void Reset () { index = -1; } } public IEnumerator GetEnumerator() { return new StructureEnumerator (this); } [DllImport ("libgstreamer-0.10.dll") ] static extern void gst_caps_append_structure (IntPtr caps, IntPtr structure); [DllImport ("libgstreamer-0.10.dll") ] static extern IntPtr gst_structure_copy (IntPtr raw); public void Append (Structure s) { if (!IsWritable) throw new ApplicationException (); gst_caps_append_structure (Handle, gst_structure_copy (s.Handle)); } [DllImport ("libgstreamer-0.10.dll") ] static extern void gst_caps_append (IntPtr caps, IntPtr caps2); public void Append (Caps caps) { if (!IsWritable) throw new ApplicationException (); gst_caps_append (Handle, gst_caps_copy (caps.Handle)); } [DllImport ("libgstreamer-0.10.dll") ] static extern void gst_caps_merge_structure (IntPtr caps, IntPtr structure); public void Merge (Structure s) { if (!IsWritable) throw new ApplicationException (); gst_caps_merge_structure (Handle, gst_structure_copy (s.Handle)); } [DllImport ("libgstreamer-0.10.dll") ] static extern void gst_caps_merge (IntPtr caps, IntPtr caps2); public void Merge (Caps caps) { if (!IsWritable) throw new ApplicationException (); /* Removes all structures! */ if (caps.IsAny) { RemoveStructureReferences (); } gst_caps_merge (Handle, gst_caps_copy (caps.Handle)); } [DllImport ("libgstreamer-0.10.dll") ] static extern void gst_caps_remove_structure (IntPtr caps, uint index); public void RemoveStructure (uint index) { if (!IsWritable) throw new ApplicationException (); if (index >= Size) throw new ArgumentOutOfRangeException (); if (structures.Contains (this[index].Handle)) { RemoveStructureReference (this[index]); } gst_caps_remove_structure (Handle, index); } [DllImport ("libgstreamer-0.10.dll") ] static extern bool gst_caps_do_simplify (IntPtr caps); public bool DoSimplify () { if (!IsWritable) throw new ApplicationException (); /* FIXME: This is not optimal but we don't know before * which structures will be removed */ RemoveStructureReferences (); return gst_caps_do_simplify (Handle); } [DllImport ("libgstreamer-0.10.dll") ] static extern void gst_caps_truncate (IntPtr caps); public void Truncate () { if (!IsWritable) throw new ApplicationException (); for (uint i = 1; i < Size; i++) RemoveStructureReference (this[i]); gst_caps_truncate (Handle); } [DllImport ("libgstreamer-0.10.dll") ] static extern void gst_caps_unref (IntPtr raw); protected override void Unref (IntPtr raw) { RemoveStructureReferences (); if (Owned) { gst_caps_unref (raw); Owned = false; } } class FinalizerInfo { IntPtr handle; public FinalizerInfo (IntPtr handle) { this.handle = handle; } public bool Handler () { gst_caps_unref (handle); return false; } } ~Caps () { if (!Owned) return; RemoveStructureReferences (); FinalizerInfo info = new FinalizerInfo (Handle); Gst.GLib.Timeout.Add (50, new Gst.GLib.TimeoutHandler (info.Handler)); } protected override Gst.GLib.Opaque Copy (IntPtr raw) { return Gst.GLib.Opaque.GetOpaque (gst_caps_ref (raw), typeof (Caps), true); }