[banshee/gst#] gst#: port the BPM detector from libbanshee



commit b20b62479f5e33a081b59a010d4bf91b090ccbec
Author: Gabriel Burt <gabriel burt gmail com>
Date:   Fri May 6 17:22:18 2011 -0500

    gst#: port the BPM detector from libbanshee

 .../Banshee.GStreamerSharp.addin.xml               |    4 +
 .../Banshee.GStreamerSharp.csproj                  |    1 +
 .../Banshee.GStreamerSharp/BpmDetector.cs          |  224 ++++++++++++++++++++
 src/Backends/Banshee.GStreamerSharp/Makefile.am    |    1 +
 .../Banshee.MediaEngine/IBpmDetector.cs            |    1 -
 src/Extensions/Banshee.Bpm/Banshee.Bpm.addin.xml   |    1 -
 6 files changed, 230 insertions(+), 2 deletions(-)
---
diff --git a/src/Backends/Banshee.GStreamerSharp/Banshee.GStreamerSharp.addin.xml b/src/Backends/Banshee.GStreamerSharp/Banshee.GStreamerSharp.addin.xml
index 9da20c3..f5e4c40 100644
--- a/src/Backends/Banshee.GStreamerSharp/Banshee.GStreamerSharp.addin.xml
+++ b/src/Backends/Banshee.GStreamerSharp/Banshee.GStreamerSharp.addin.xml
@@ -20,6 +20,10 @@
   <Extension path="/Banshee/MediaEngine/PlayerEngine">
     <PlayerEngine class="Banshee.GStreamerSharp.PlayerEngine"/>
   </Extension>
+
+  <Extension path="/Banshee/MediaEngine/BpmDetector">
+    <BpmDetector class="Banshee.GStreamerSharp.BpmDetector"/>
+  </Extension>
   
   <!--
   <Extension path="/Banshee/MediaEngine/AudioCdRipper">
diff --git a/src/Backends/Banshee.GStreamerSharp/Banshee.GStreamerSharp.csproj b/src/Backends/Banshee.GStreamerSharp/Banshee.GStreamerSharp.csproj
index b762ac9..d59e593 100644
--- a/src/Backends/Banshee.GStreamerSharp/Banshee.GStreamerSharp.csproj
+++ b/src/Backends/Banshee.GStreamerSharp/Banshee.GStreamerSharp.csproj
@@ -71,6 +71,7 @@
   </ItemGroup>
   <ItemGroup>
     <Compile Include="Banshee.GStreamerSharp\PlayerEngine.cs" />
+    <Compile Include="Banshee.GStreamerSharp\BpmDetector.cs" />
   </ItemGroup>
   <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
 </Project>
diff --git a/src/Backends/Banshee.GStreamerSharp/Banshee.GStreamerSharp/BpmDetector.cs b/src/Backends/Banshee.GStreamerSharp/Banshee.GStreamerSharp/BpmDetector.cs
new file mode 100644
index 0000000..723c206
--- /dev/null
+++ b/src/Backends/Banshee.GStreamerSharp/Banshee.GStreamerSharp/BpmDetector.cs
@@ -0,0 +1,224 @@
+//
+// BpmDetector.cs
+//
+// Author:
+//   Gabriel Burt <gburt novell com>
+//
+// Copyright (C) 2008-2011 Novell, Inc.
+//
+// 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.Linq;
+using System.Collections;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+
+using Mono.Unix;
+
+using Gst;
+
+using Hyena;
+using Hyena.Data;
+
+using Banshee.Base;
+using Banshee.Streaming;
+using Banshee.MediaEngine;
+using Banshee.ServiceStack;
+using Banshee.Configuration;
+using Banshee.Preferences;
+using Gst.CorePlugins;
+using Gst.BasePlugins;
+
+namespace Banshee.GStreamerSharp
+{
+    public class BpmDetector : IBpmDetector
+    {
+        SafeUri current_uri;
+        Dictionary<int, int> bpm_histogram = new Dictionary<int, int> ();
+
+        Pipeline pipeline;
+        FileSrc filesrc;
+        FakeSink fakesink;
+
+        public event BpmEventHandler FileFinished;
+
+        public BpmDetector ()
+        {
+            Console.WriteLine ("Trying to make bpm dtector...");
+            try {
+                pipeline = new Pipeline ();
+                filesrc          = new FileSrc ();
+                var decodebin    = new DecodeBin2 ();
+                var audioconvert = Make ("audioconvert");
+                var bpmdetect    = Make ("bpmdetect");
+                fakesink         = new FakeSink ();
+
+                pipeline.Add (filesrc, decodebin, audioconvert, bpmdetect, fakesink);
+
+                if (!filesrc.Link (decodebin)) {
+                    Log.Error ("Could not link pipeline elements");
+                    throw new Exception ();
+                }
+
+                // decodebin and audioconvert are linked dynamically when the decodebin creates a new pad
+                decodebin.NewDecodedPad += delegate(object o, DecodeBin2.NewDecodedPadArgs args) {
+                    var audiopad = audioconvert.GetStaticPad ("sink");
+                    if (audiopad.IsLinked) {
+                        return;
+                    }
+
+                    using (var caps = args.Pad.Caps) {
+                        using (var str = caps[0]) {
+                            if (!str.Name.Contains ("audio"))
+                                return;
+                        }
+                    }
+
+                    args.Pad.Link (audiopad);
+                };
+
+                if (!Element.Link (audioconvert, bpmdetect, fakesink)) {
+                    Log.Error ("Could not link pipeline elements");
+                    throw new Exception ();
+                }
+
+                pipeline.Bus.AddWatch (OnBusMessage);
+                //gst_bus_add_watch (gst_pipeline_get_bus (GST_PIPELINE (detector->pipeline)), bbd_pipeline_bus_callback, detector);
+            } catch (Exception e) {
+                Log.Exception (e);
+                throw new ApplicationException (Catalog.GetString ("Could not create BPM detection driver."), e);
+            }
+        }
+
+        private bool OnBusMessage (Bus bus, Message msg)
+        {
+            switch (msg.Type) {
+            case MessageType.Tag:
+                Pad pad;
+                TagList tag_list;
+                msg.ParseTag (out pad, out tag_list);
+
+                foreach (var name in tag_list.Tags) {
+                    if (name == "beats-per-minute") {
+                        if (tag_list.GetTagSize (name) < 1) continue;
+                        var tag = tag_list.GetTag (name);
+                        foreach (var val in tag) {
+                            if (val is double) {
+                                double bpm = (double)val;
+                                int rounded = (int) Math.Round (bpm);
+                                if (!bpm_histogram.ContainsKey(rounded)) {
+                                    bpm_histogram[rounded] = 1;
+                                } else {
+                                    bpm_histogram[rounded]++;
+                                }
+                            }
+                            break;
+                        }
+                    }
+                }
+
+                tag_list.Dispose ();
+                break;
+
+            case MessageType.Error:
+                Enum error_type;
+                string err_msg, debug;
+                msg.ParseError (out error_type, out err_msg, out debug);
+
+                IsDetecting = false;
+                Log.ErrorFormat ("BPM Detection error", err_msg);
+                break;
+
+            case MessageType.Eos:
+                IsDetecting = false;
+                pipeline.SetState (State.Null);
+
+                SafeUri uri = current_uri;
+                int best_bpm = -1, best_bpm_count = 0;
+                foreach (int bpm in bpm_histogram.Keys) {
+                    int count = bpm_histogram[bpm];
+                    if (count > best_bpm_count) {
+                        best_bpm_count = count;
+                        best_bpm = bpm;
+                    }
+                }
+
+                Reset ();
+
+                var handler = FileFinished;
+                if (handler != null) {
+                    handler (this, new BpmEventArgs (uri, best_bpm));
+                }
+
+                break;
+            }
+
+            return true;
+        }
+
+        public void Dispose ()
+        {
+            Reset ();
+
+            if (pipeline != null) {
+                pipeline.SetState (State.Null);
+                pipeline.Dispose ();
+                pipeline = null;
+            }
+        }
+
+        public bool IsDetecting { get; private set; }
+
+        public void ProcessFile (SafeUri uri)
+        {
+            Reset ();
+            current_uri = uri;
+            string path = uri.LocalPath;
+
+            try {
+                Log.DebugFormat ("GStreamer running beat detection on {0}", path);
+                IsDetecting = true;
+                fakesink.SetState (State.Null);
+                filesrc.Location = path;
+                pipeline.SetState (State.Playing);
+            } catch (Exception e) {
+                Log.Exception (e);
+            }
+        }
+
+        private void Reset ()
+        {
+            current_uri = null;
+            bpm_histogram.Clear ();
+        }
+
+        private static Gst.Element Make (string name)
+        {
+            var e = ElementFactory.Make (name);
+            if (e == null) {
+                Log.ErrorFormat ("BPM Detector unable to make element '{0}'", name);
+                throw new Exception ();
+            }
+            return e;
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/Backends/Banshee.GStreamerSharp/Makefile.am b/src/Backends/Banshee.GStreamerSharp/Makefile.am
index d738781..0a58174 100644
--- a/src/Backends/Banshee.GStreamerSharp/Makefile.am
+++ b/src/Backends/Banshee.GStreamerSharp/Makefile.am
@@ -4,6 +4,7 @@ LINK = $(REF_BACKEND_GSTREAMER) $(GST_SHARP_LIBS)
 INSTALL_DIR = $(BACKENDS_INSTALL_DIR)
 
 SOURCES =  \
+	Banshee.GStreamerSharp/BpmDetector.cs \
 	Banshee.GStreamerSharp/PlayerEngine.cs
 
 RESOURCES = Banshee.GStreamerSharp.addin.xml
diff --git a/src/Core/Banshee.Services/Banshee.MediaEngine/IBpmDetector.cs b/src/Core/Banshee.Services/Banshee.MediaEngine/IBpmDetector.cs
index bb53279..c0478e3 100644
--- a/src/Core/Banshee.Services/Banshee.MediaEngine/IBpmDetector.cs
+++ b/src/Core/Banshee.Services/Banshee.MediaEngine/IBpmDetector.cs
@@ -54,6 +54,5 @@ namespace Banshee.MediaEngine
         event BpmEventHandler FileFinished;
 
         void ProcessFile (SafeUri uri);
-        void Cancel ();
     }
 }
diff --git a/src/Extensions/Banshee.Bpm/Banshee.Bpm.addin.xml b/src/Extensions/Banshee.Bpm/Banshee.Bpm.addin.xml
index c504502..8745477 100644
--- a/src/Extensions/Banshee.Bpm/Banshee.Bpm.addin.xml
+++ b/src/Extensions/Banshee.Bpm/Banshee.Bpm.addin.xml
@@ -13,7 +13,6 @@
 
   <Dependencies>
     <Addin id="Banshee.Services" version="1.0"/>
-    <Addin id="Banshee.GStreamer" version="1.0"/>
   </Dependencies>
 
   <Extension path="/Banshee/ServiceManager/Service">



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]