Tuesday, November 15, 2011

Building Release dll from Source

To generate a release of the banshee-community-extensions with our NoNoise plug-in first call
make prepare-release
which generates archives containing the release files. To install the plug-in, first extract one of the archives (for example 'banshee-community-extensions-2.2.0.zip'). After that run
./configure
make
in the extraction directory to build the dlls. At last, run
sudo cp ./bin/Banshee.NoNoise.dll* /usr/lib/banshee/Extensions
sudo cp ./bin/clutter-gtk-sharp.dll* /usr/lib/banshee/Extensions
sudo cp ./bin/clutter-sharp.dll*  /usr/lib/banshee/Extensions
to copy the dlls into the banshee folder (the location of this folder may vary on different systems). Now, if you run banshee, you can enable the NoNoise plug-in in the Edit > Preferences > Extensions menu. Do not forget to install Mirage or the banshee-community-extensions first. Otherwise our plug-in will not work.

Friday, October 28, 2011

Useful methods for getting track infos from banshee music library

Since I spent quite some time wondering how to do this, I decided to write down how you can get TrackInfos for certain TrackIds from banshee.

First you need banshee's DatabaseTrackModelProvider which can be found in Banshee.Collection.Database. One way of accessing the DatabaseTrackModelProvider<DatabaseTrackInfo> is using the static attribute Provider in DatabaseTrackInfo.
With this provider it is possible to get the TrackInfo for a track with a certain id using the following code:

TrackInfo ti = DatabaseTrackInfo.Provider.FetchSingle (bid) as TrackInfo; 

with bid being the ID used by banshee. In other words bid equals DatabaseTrackInfo.Provider.FetchSingle (bid).TrackId.

The provider can also be used for iterating over all tracks in banshee's database.

foreach (DatabaseTrackInfo dti in DatabaseTrackInfo.Provider.FetchAll ()) {
    // do something with dti
}

Tuesday, September 20, 2011

Merging two git repositories and keeping their history

To merge our repositories together we use the instructions given in [1].

<might be unnecessary>
First we create a new branch with
git branch newbranch
on MIRPCADB and switch to it using
git checkout newbranch 
and push it using
git push -u origin newbranch
</might be unnecessary>

Now we move over to our No.Noise repository and use the following command to fetch the contents of MIRPCADB in a new branch of No.Noise
git fetch git@github.com:tjom/MIRPCADB.git master:newbranch
To be able to use the commit history we use the following command to move the files from newbranch into a directory called old in our master branch
git filter-branch --index-filter \
    'git ls-files -s | \
        sed "s-\t-&'"old"'/-" | \
        GIT_INDEX_FILE=$GIT_INDEX_FILE.new git update-index --index-info && \
        mv $GIT_INDEX_FILE.new $GIT_INDEX_FILE
    ' "newbranch"
followed by
git merge newbranch
Now we can simply move (copy and delete(!)) the files to our NoNoise plug-in src directory. After calling
git add -u
all files should be recognized as 'renamed', which means that their history will be preserved.

After committing and pushing the changes to the desired branch, we call
git branch -d newbranch
to remove the dummy branch.


[1] http://zrajm.org/ref/git-repo-merging.html

Friday, September 16, 2011

Had to add the following to BANSHEE_LIBS/the LINK variable in the makefile to use these packages.

BANSHEE_LIBS = ... -r:System.Data -r:Mono.Data.SqliteClient

Monday, September 5, 2011

Adding Math.NET lib

Nothing entirely new. Just to remember how it is done.

Add the path to the redistributable dll to the LINK variable of the project make file (e.g. Foo) with a leading "-r:". It should look like the following.

LINK = $(BANSHEE_LIBS) $(am__append_1) -r:/home/thomas/NoNoise/MathNet.Iridium-2008.8.16.470/ForRedistribution/MathNet.Iridium.dll 

PS: Also had to copy the dll to /bin/addins although I'm sure there's a better solution to that.

Monday, June 6, 2011

Compiling with unsafe code blocks

To compile code with unsafe blocks, it is necessary to add/alter the following line in the Makefile:

GMCS_FLAGS = -unsafe

Thursday, May 5, 2011

BPM detection using Banshee.Bpm

Banshee has a built-in extension to detect Beats Per Minute (BPM) in Banshee.Bpm. Unfortunately it is not possible to use this extension directly for our purpose, because the visibility of GetDetector () is set to internal. A quick and dirty solution to this is to copy the BpmDetectJob.cs file (which can be found in /banshee/src/Extensions/Banshee.Bpm/Banshee.Bpm/ after checking out the source from the git repository) to our project and change the visibility to public, since everything else we need is accessible from the Banshee API.

To see if the detection works, we use the following pieces of code.

We declare the private member IBpmDetector detector in our extension class and use the following code to initialize it in the constructor and set the FileFinished handler:

detector = BpmDetectJob.GetDetector ();
if (detector != null) {
    detector.FileFinished += OnFileFinished;
}

with

private void OnFileFinished (object o, BpmEventArgs args)
{
    Hyena.ThreadAssist.ProxyToMain (delegate {
        Hyena.Log.DebugFormat ("Foo1 - Detected BPM of {0} for {1}", args.Bpm, args.Uri);
    });
}

This simply outputs the BPM to the log. Now all we have to do is use the detector on a track, which can be done using the following method.

private void DetectBPMs(TrackInfo track) 
{
    if (track != null) {
        detector.ProcessFile (track.Uri);
    }
}

Now if we call DetectBPMs(TrackInfo track) with the first song in our library (i.e. ServiceManager.SourceManager.MusicLibrary.TrackModel[0]) as parameter, we get an output like "Foo1 - Detected BPM of 65 for file:///home/thomas/Musik/Black%20Holes%20and%20Revelations/Muse%20-%2001%20-%20Take%20a%20Bow.mp3".

Caution:
The class ThreadAssist was recently moved from Banshee.Base to Hyena!

Friday, April 29, 2011

Accessing the music library using the Banshee API

Since it is not so obvious which classes can be used to access the meta data of the files in banshee's music library, here is an example of how it can be done using ServiceManager.SourceManager.MusicLibrary.TrackModel.

private string GetMetaData(int index) {
    return ServiceManager.SourceManager.MusicLibrary.TrackModel[index].ArtistName + " - " +
    ServiceManager.SourceManager.MusicLibrary.TrackModel[index].TrackTitle + " (" +
    ServiceManager.SourceManager.MusicLibrary.TrackModel[index].AlbumTitle + ")";
}

Calling this method within a loop over all TrackModels in the MusicLibrary and outputting it to the log

for (int i = 0; i < ServiceManager.SourceManager.MusicLibrary.TrackModel.Count; i++) {
    Hyena.Log.Debug(GetMetaData(i));
} 

generates output similar to this:

Muse - Exo-Politics (Black Holes and Revelations)

Thursday, April 28, 2011

Using clutter in banshee extension

To write a banshee extension, the create-extension command in the banshee-community-extensions repository is used. This extension can then be modified in MonoDevelop. However, to use clutter-sharp, the makefile must be modified otherwise mono would not find clutter-sharp, even if it is properly referenced in MonoDevelop. The LINK variable in the makefile must contain CLUTTER_SHARP_LIBS. This is shown in my example below:
LINK = $(BANSHEE_LIBS) $(BANSHEE_NOWPLAYING_LIBS) \
 $(CLUTTER_SHARP_LIBS) -r:Mono.Cairo -pkg:gtk-sharp-2.0 \
 $(am__append_1)
Additionally, to prevent MonoDevelop to overwrite those changes I disabled the makefile integration in the project properties. However, this means that every sourcefile that is added to the project hast to be added to the SOURCES in the makefile. There is a way to link the references of the makefile in the makefile integration dialog, but this did not work out for me as desired. 

Simple clutter-sharp window


I will quickly show howto create a clutter window using clutter-sharp. Clutter-sharp can be installed using the Ubuntu packet manager.

First of all, a class is needed which provides functions to initialize clutter and call the main loop. This class is named ClutterHelper.

1. Reference clutter functions
[DllImport ("clutter")]
static extern void clutter_main();
  
[DllImport ("clutter")]
static extern void clutter_init (int argc, IntPtr argv);

2. Encapsulate those funcitons
public static void Init( ) {
   clutter_init (0, IntPtr.Zero);
}
  
public static void Main() {
   //Call clutter main loop
   clutter_main(); 
}


The name in DllImport references the dll assembly. In windows this would be "clutter.dll", however in linux the library is named otherwise. To tell mono which name should be used in linux, a config file is used. This config file must have the same name as the assembly with an appendix ".config" (for instance "MyAssembly.exe.config") and must be in the same directory. In this config file the name of the windows library and the linux library are then mapped.





After creating this helper class, a main class Main is used to create a clutter window. In the Main function of this class clutter is initialized, a new stage is created and the main-loop is called.

static void Main ()
{
   ClutterHelper.Init();

   Stage stage = Stage.Default;
   stage.Color = new Clutter.Color(0,0,0,255);
   stage.SetSize(512,512);

   stage.Show();
   
   ClutterHelper.Main();
}

Code highlighting test

protected void UpdatePositions ()
  {
   /* TODO: variable heights need to be handled */
   float x = marginX; float y = marginY;
   text.Hide ();
   foreach (Actor actor in this) {
    if (actor!=text) {
     actor.Hide ();
     actor.SetPosition (x, y);
     x += actor.Width + spacing;
     actor.Show ();
    }
   }

   UpdateTexture ();
  }

Tutorial: Adding Syntax Highlighting to Blogger