[banshee] gst#: port the BPM detector from libbanshee
- From: Bertrand Lorentz <blorentz src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [banshee] gst#: port the BPM detector from libbanshee
- Date: Thu, 18 Aug 2011 19:48:26 +0000 (UTC)
commit 118e308b4e70da089a97bb80fe2f8083b331018d
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]