iPod support

BlitzMax Forums/Brucey's Modules/iPod support

Artemis(Posted 2009) [#1]
Hi Brucey,

I've thought for days for a ipod support in BlitzMax because I'm probably going to write a more or less little media player which completely fits my needs. Therefore I would need iPod support.

I went through the net and searched for iPod libraries but in the beginning I just found libraries which have not been developed since nearly 3 years like http://libipod.sourceforge.net/ or which are not just iPod libraries like http://mlipod.sourceforge.net/

At least I found one which is still under development namely http://www.gtkpod.org/libgpod.html but when I had a look at it I realized that I would never be able to do a BlitzMax wrap because of my lack of more then rudimental c/c++ knowledge.

So why don't ask Brucey, he will do this in a couple of hours. ;-)

I just want to ask you whether you could have a look upon it or maybe anyone else knows a better iPod library around which one should have a look at?

EDIT:

Despite my little c knowledge I am trying to do this so please don't start this, too. ;-)
But please tell me if I can ask you questions sometimes about the c/c++ blitzmax integration.


Brucey(Posted 2009) [#2]
Sure. No problem :-)

You know this is LGPL?

I don't think it supports iPhone or Touch.


Artemis(Posted 2009) [#3]
You know this is LGPL?

I had a quick look at the LGPL conditions and there it is that I'm only allowed to use the library in my program if this is also distributed under the LGPL, is that correct?

I don't think it supports iPhone or Touch.

Yes and no, it only supports jailbreaked iPhone and Touch, but since I have neither of them I don't care. Or is there an other library out there which supports it?


Brucey(Posted 2009) [#4]
I'm only allowed to use the library in my program if this is also distributed under the LGPL

If the library is a DLL/.dylib/.so then you can license your code any way you like.
If you want to compile the library INTO your code, then yes, your own code would need to be GPL.

Or is there an other library out there which supports it?

Not that I know of.


Artemis(Posted 2009) [#5]
I'm nearly finished…

…with my nerves and my knowledge.


Since including and building of the source code did not work as expected due to an gettext error I was not able to resolve (yes libgpod needs glib and gettext) I then got me windows libgpod binaries from the songbird ipod extension repository but when trying to include the .lib and .dll files together with some c-code there just more errors than with the source.

EDIT:

I just gave it another try: I just included the .lib file in BlitzMax put the .dll in root directory and now it seems to work. This way all work has to be done in BlitzMax rather c - not that I am not loving it but I may be hard to port the structs to BlitzMax.

I will post my advance here or tell you when I comletely fail.

BTW: Is there a way so I can put the dll file into a subdirectory or so because 5 dlls (1*libgpod, 2*glib, 1*gettext, 1*iconv) in the main directory disturbs me a bit.


Brucey(Posted 2009) [#6]
Good fun, eh? :-)

Is there a way so I can put the dll file into a subdirectory

As far as I know, you'd need to add the subdirectory to the PATH, on Windows.

I've also found glib to be a bit of a pain to use on Win32 and Mac, also thinking that just borrowing a dll is the easier option ;-)


Artemis(Posted 2009) [#7]
I'm nearly finished getting this libgpod running *from source*. What I did was not building the needed libraries (glib, gdk-pixbuf, gettext) but getting them es prebuilt .lib files from here: http://www.gtk.org/download-windows.html which really made it almost easy.

But now I still have a undefined reference in the code, namely to the function *sync*. This function as I have found out is defined in the unistd.h but not on windows, so i think this function (which flushes write operations to the disks) is linux-only. Is there a similar function on windows, too, or is it ok when i just create a little dummy function called *sync*?


Brucey(Posted 2009) [#8]
is it ok when i just create a little dummy function called *sync*

Yeh, based on this :
http://74.125.77.132/search?q=cache:ZfBkWYaLxJcJ:www.mail-archive.com/commit-grub%40gnu.org/msg00873.html+mingw+sync+unistd&hl=en&ct=clnk&cd=5&client=safari
(see near bottom of page - highlighted in yellow)

Looks like it's safe to add something like this :
void sync(void)
{
}



Artemis(Posted 2009) [#9]
Ok, that works now.

The only thing that disturbes me is that you need six dlls in your project for this ipod support.


Artemis(Posted 2009) [#10]
Just another question for the c functions I am going to create: Is it better to give a BBString as a parameter and handle the conversion in the c code or expect a const *char as parameter and handle the conversion in the blitzmax code. And what about string return values? BBString or const *char/byte ptr?


Brucey(Posted 2009) [#11]
You can pass a String directly into a function with a param such as text:Byte Ptr. It works.
But I'm not so keen to use it like that, because if you ever need to change the string conversion, you anyway need to go and change everything.
Which is why I tend to these days pass in String, and in C/C++ define as BBString * text.
You can then do bbStringToCString(), remembering to bbMemFree() the created char * pointer.

For returning back, I find it's better to try to return a BBString *. Recently, in CEGUI I found I had to, as the char* data that I was returning would sometimes be GC'd before my call to String.FromCString() ran... which was a little annoying.
At least if you do the conversion in the C/C++ you know the data is still in scope :-)

Of course, at the end of the day, it's up to you to implement it the way you think is best ;-)


Artemis(Posted 2009) [#12]
The next "problem" I'm thinking about is this:

There is a struct which represents an iPod database. This struct contains a list with tracks and a list with playlists and an other struct:
typedef struct {
    GList *tracks;
    GList *playlists;
    gchar *filename;
    Itdb_Device *device;
    ...
}

A GList is somewhat a linked list in blitzmax: http://library.gnome.org/devel/glib/stable/glib-Doubly-Linked-Lists.html#GList (and gchar* = char*).

My iPod database type will contain a pointer to the struct as field and all methods will call c helper functions which operate on the struct. (I think this is the best, and maybe only?, good way.)

So if want to access filename in BlitzMax I call db.getFilename(). But now, how to acess the list? Shall I make a copy the list in BlitzMax? I think having to call db.getTrack(id) is not very convenient.


Artemis(Posted 2009) [#13]
Ok,

I've been working on it and now I am encountering an (I think) memory error but I don't know where it's coming from and how to eleminate it.

Maybe some of you can help me sorting this out? The only problem is that you need an iPod to help me. Or at least a copy of the content of an iPod.
And currently it is only for Windows.

Please get the module from https://svn.blitzforum.de/artemis.mod/ipod.mod/ - in the folder tests there is a test.bmx in which you should set you iPod path and then start it.

My problem is:
When you compile it as a release version and you ipod database is big enough at some point the memory usage (the number at beginning of the line) goes low and from that point on there are no real titles and artists but just random characters and sometimes real titles or paths of it.

Funny enough is that when you start it in debug mode no such problem occurrs.

I have a suspicion that the error might come from the Garbage Collector (the lowering memory indicates it?) so that the collector takes away some needed memory.


EDIT:
My second suspicion was correct. If i change my code this way it works both in release and debug mode. But why does it work now and where does the GC take the memory away where it's needed?
SuperStrict

Framework Artemis.iPod
Import Brl.StandardIO

GCSuspend()

Local database:TiPodDatabase = New TiPodDatabase.Create("I:\")

If Not database Then
	Print "ERROR: Please modify your iPod-Path"
	End
EndIf

Print "iPod:"
Print "~tFilename  : " + database.getFilename()
Print "~tVersion   : " + database.getVersion()
Print "~tId        : " + database.getId()
Print "~tMountpoint: " + database.getMountpoint()
Print "~tTracks    : " + database.getTrackNumber()
Print "~tPlaylists : " + database.getPlaylistNumber()

Print "Tracks:"

For Local track:TiPodTrack = EachIn database.tracks
	Print GCMemAlloced() + "~t~t" + track.getArtist() + " - " + track.getTitle()
Next

GCResume()



Artemis(Posted 2009) [#14]
Addition to the above problem:

I've made a zip of the module available here: -url removed-
And for the ones without iPod: -url removed-
Extract this onto an usb stick and give it's device letter in the test program.

In hope that someone might help me ;-)


Brucey(Posted 2009) [#15]
I'm a bit short of spare time at the moment, otherwise I would have had a look at this already...

You shouldn't be suspending the GC ;-)


Artemis(Posted 2009) [#16]
Yes, that was never my intention but just a test to verify that the GC is the cause of the strange output.

I'm a bit short of spare time at the moment, otherwise I would have had a look at this already...

No problem, I appreciate that you are helping people and creating great modules at the same time ;-).


Artemis(Posted 2009) [#17]
Hey, I don't want to bother you, but did you have a look at it?
If not and at the moment there is no good time, just tell me, when you think you'll have some time to look at it.

Thanks,
Artemis


Brucey(Posted 2009) [#18]
Try this :
SuperStrict

Framework Artemis.iPod
Import Brl.StandardIO

Local database:TiPodDatabase = New TiPodDatabase.Create("I:\")

If Not database Then
	Print "ERROR: Please modify your iPod-Path"
	End
EndIf

Print "iPod:"
Print "~tFilename  : " + database.getFilename()
Print "~tVersion   : " + database.getVersion()
Print "~tId        : " + database.getId()
Print "~tMountpoint: " + database.getMountpoint()
Print "~tTracks    : " + database.getTrackNumber()
Print "~tPlaylists : " + database.getPlaylistNumber()

Print "Tracks:"

fred(database)

Function fred(database:TiPodDatabase)
	For Local track:TiPodTrack = EachIn database.tracks
		Print GCMemAlloced() + "~t~t" + track.getArtist() + " - " + track.getTitle()
	Next
End Function



Artemis(Posted 2009) [#19]
Wow, that works. But where is the difference? You just packed it into a function and called it, didn't you? Why does that make it work?


Brucey(Posted 2009) [#20]
It might be a bug with BlitzMax, with variables in the "application scope".

I admit, it is a bit strange.