pyToners,
I've forked a copy of pyTone that I'm calling DanceBox. You can get a tarball of my work so far at sourceforge. No web page or mailing list exist so go to the dancebox project. http://sourceforge.net/projects/dancebox/
I'm using darcs as my vcs. The tarball contains the repository. You can pull directly from my local public repository @ http://tant.com/~dancebox/dancebox-devel
I haven't made any kind of public announcement and probably won't until I get much further along but I thought I'd mention something here so I can get some pre-alpha feedback.
What:
DanceBox is a customized version of pyTone for a Dance Studio. Specifically for a dance studio that does partner dancing. Things like Cha Cha, Hustle, Swing, Waltz etc.
Modifications from mainline pyTone:
- I added a SQLite database backend. Currently it supports _most_ of what pyTone did originally. Implementing that was how I started learning how pyTone worked. I say most of pyTone functionality because once I got where the curses interface would play a song I stopped trying to implement the remaining pyTone functionality. The primary reason for adding SQLite is supporting my song classification system. For my purposes the "song can only be 1 genre" is way to limiting. In the partner dance world a single song may be good for several different dances. So I have a full relational setup that allows a song to be categorized by class, genre, dance, speed, and style. The only limit on how many of those classifications any single song can belong to is the number of records in a a SQLite table. So for all practical purposes unlimited.
I feel that what I have set up is probably the most flexible classification system of _any_ open source jukebox and should rival commercial offerings.
- Added support for speeding up and slowing down the currently played song with the internal player. By adding code and events that change the output sample rate of pcm.rate_convert it is possible to speed up and slow down the song. Yes it changes the pitch as well but in partner dance we aren't concerned about that. Slow it down for practice/learning and then gradually speed it up back normal.
- Moved all the user interface(s) stuff into its own subdirectory of a directory called 'ui' and created packages for them. You can now create multiple user interfaces.
- Added a (fledgling) Qt interface with pyQt. My goal for DanceBox is to have it operated from a single window using a touchscreen. So I'm working on a ui that's simple and easy to use from a touchscreen. I've only just started so its very incomplete. But it does load and display some items queried from the database. No player functions yet.
Goals and Directions:
The focus for pyTone and DanceBox are very different. The object store model used with the berkley db doesn't map well into the relational SQL world in some cases. I store all the info rather then the entire object. Which means I have to re-create a song object every time. So to support that I had to create a new song_lite class that did not go read all the meta-info of a song when instantiated.
pyTone wants to parse a collection of files and display all the ID3 info in an organized manner. DanceBox doesn't care about the id3 info. The artist, title, album, year, etc are all secondary, what matters most are what dance is it and how fast is it. Speed in this setup is fuzzy. Slow, medium, fast, etc. The database has fields for BPM and MPM (Measures per minute) but a single BPM may be fast in one dance and slow in another so you can't really catagorize on BPM.
Bringing up full pyTone compatibility is left as an exercise to the pyTone community. I'll be glad to help however I can but I won't ever really complete that on my own since it doesn't match up with how DanceBox works. That said all of pyTone's functionality should be able to be implemented with the database I setup. So if someone wanted to re-tool pyTone into using SQLite this should be a great start. I saw in the archives that moving to SQLite was suggested but met some resistance due to the additional dependencies that would add.
I have plans of going cross platform as well. Windows and Max OS X are targets. I know of studios in my local area using these platforms. pyAo and apsw (the SQLite wrapper) already do both of these platforms and building pcm.rate_convert should not be much of a problem. I haven't looked yet at mad and the other dependencies
I called it a semi-fork because I'd like to stay compatible with pyTone such that both projects can use advancements from each other with minimum hassle. I just don't know if that will be possible given the very different operational methods.
The astute hacker will also notice a difference in coding styles. I strongly dislike the alllowercasefunctions naming scheme. Being a native english speaker I find this very hard to read. I do realize that you german and dutch speaking folks are used to that and that even python itself uses that style.
My code uses a mixture of underscore names (get_the_data) and Qt style StudlyCaps (getTheData) I started coding using the _ names but once I got into the PyQt stuff for the gui I started matching Qt's style. In my database code its underscores and the ui code its Qt. I'll probably continue to do that. Since I don't really care as long as its readable and to me longfuncitonnames are not readable.
If you do pull down the code to play with you will need pyQt and apsw as additional dependencies. At some point I may move from apsw to Qt's database wrapper to keep it only dependent on pyQt and also leverage Qt's ability to access several different SQL databases but apsw is very easy to use.
One drawback of apsw (from SQLite actually) is that all operations to the database must be called from the same thread the cursor was created from. Apsw complained about that early on. So right now I workaound by grabbing an new cursor every time a query is made and releasing it when I'm done. For SQLite this is very fast. But doing this with say Qt and MySQL would probably be quite a bit slower so I need to serialize the access all from one thread. I'll cross those bridges later on as I reach them. Moving to Qt database wrappers may take care of this for me.
To use dancebox you start with dancebox.py rather than pytone.py. Running pytone.py will load up the curses interface. But remember a large amount of pyTone functionality is _not_ implemented. In either case DanceBox or the original pyTone will try to look for 'dancebox.conf' rather than 'pytonerc' in the normal places. I have not modified the config.py yet to recognize that it was started as pyTone vs DanceBox. I've included my sample dancebox.conf in the ./conf directory
Thanks in advance for your time and comments
I'm using darcs as my vcs. The tarball contains the repository. You can pull directly from my local public repository @ http://tant.com/~dancebox/dancebox-devel
Oops. That should be:
http://tant.com/~dancebox/dancebox_devel
Hi Richard,
On 30.05.05, Richard Smith wrote:
I've forked a copy of pyTone that I'm calling DanceBox. You can get a tarball of my work so far at sourceforge. No web page or mailing list exist so go to the dancebox project. http://sourceforge.net/projects/dancebox/
I'm using darcs as my vcs. The tarball contains the repository. You can pull directly from my local public repository @ http://tant.com/~dancebox/dancebox-devel
I haven't made any kind of public announcement and probably won't until I get much further along but I thought I'd mention something here so I can get some pre-alpha feedback.
Here we go...
What:
DanceBox is a customized version of pyTone for a Dance Studio. Specifically for a dance studio that does partner dancing. Things like Cha Cha, Hustle, Swing, Waltz etc.
Modifications from mainline pyTone:
- I added a SQLite database backend.
Currently it supports _most_ of what pyTone did originally. Implementing that was how I started learning how pyTone worked. I say most of pyTone functionality because once I got where the curses interface would play a song I stopped trying to implement the remaining pyTone functionality. The primary reason for adding SQLite is supporting my song classification system. For my purposes the "song can only be 1 genre" is way to limiting. In the partner dance world a single song may be good for several different dances. So I have a full relational setup that allows a song to be categorized by class, genre, dance, speed, and style. The only limit on how many of those classifications any single song can belong to is the number of records in a a SQLite table. So for all practical purposes unlimited.
Note that adding more categories wouldn't be a problem with the current database code. Just add them to the dbitem.song class, and register a new index. What does not work this easily, though, is to construct the intersection of different categories, so for instance: get me all slow waltzs.
[...]
- Added support for speeding up and slowing down the currently played
song with the internal player. By adding code and events that change the output sample rate of pcm.rate_convert it is possible to speed up and slow down the song. Yes it changes the pitch as well but in partner dance we aren't concerned about that. Slow it down for practice/learning and then gradually speed it up back normal.
Ok.
- Moved all the user interface(s) stuff into its own subdirectory of a
directory called 'ui' and created packages for them. You can now create multiple user interfaces.
I like that idea.
- Added a (fledgling) Qt interface with pyQt.
My goal for DanceBox is to have it operated from a single window using a touchscreen. So I'm working on a ui that's simple and easy to use from a touchscreen. I've only just started so its very incomplete. But it does load and display some items queried from the database. No player functions yet.
I looked at it, and it looks like being designed for your specific needs, which of course is not bad but somehow limits it's general usefulness. But maybe there will be more functionality in the future?
Goals and Directions:
The focus for pyTone and DanceBox are very different. The object store model used with the berkley db doesn't map well into the relational SQL world in some cases. I store all the info rather then the entire object. Which means I have to re-create a song object every time. So to support that I had to create a new song_lite class that did not go read all the meta-info of a song when instantiated.
Actually, this is not a big problem. One could actually make the pure container class the superclass.
pyTone wants to parse a collection of files and display all the ID3 info in an organized manner. DanceBox doesn't care about the id3 info.
Yes, I've seen that. But again this makes your SQLite code not very usefull for PyTone...
The artist, title, album, year, etc are all secondary, what matters most are what dance is it and how fast is it. Speed in this setup is fuzzy. Slow, medium, fast, etc. The database has fields for BPM and MPM (Measures per minute) but a single BPM may be fast in one dance and slow in another so you can't really catagorize on BPM.
Bringing up full pyTone compatibility is left as an exercise to the pyTone community. I'll be glad to help however I can but I won't ever really complete that on my own since it doesn't match up with how DanceBox works. That said all of pyTone's functionality should be able to be implemented with the database I setup. So if someone wanted to re-tool pyTone into using SQLite this should be a great start. I saw in the archives that moving to SQLite was suggested but met some resistance due to the additional dependencies that would add.
Yes, but I still have moving to the SQLite db in mind. But IMHO this requires a bit of thinking about the database scheme before.
I have plans of going cross platform as well. Windows and Max OS X are targets. I know of studios in my local area using these platforms. pyAo and apsw (the SQLite wrapper) already do both of these platforms and building pcm.rate_convert should not be much of a problem. I haven't looked yet at mad and the other dependencies
The main obstacle so far was the curses interface which does not exist for Windows. But expect smaller issues to turn up here and there.
I called it a semi-fork because I'd like to stay compatible with pyTone such that both projects can use advancements from each other with minimum hassle. I just don't know if that will be possible given the very different operational methods.
That's ok, although syncing things is probably not so easy. Looking at your code, there are already various differences here and there, which you have to keep track off.
The astute hacker will also notice a difference in coding styles. I strongly dislike the alllowercasefunctions naming scheme. Being a native english speaker I find this very hard to read. I do realize that you german and dutch speaking folks are used to that and that even python itself uses that style.
My code uses a mixture of underscore names (get_the_data) and Qt style StudlyCaps (getTheData) I started coding using the _ names but once I got into the PyQt stuff for the gui I started matching Qt's style. In my database code its underscores and the ui code its Qt. I'll probably continue to do that. Since I don't really care as long as its readable and to me longfuncitonnames are not readable.
Coding conventions are always a matter of taste. Although I think it's good style to use the style already used in a project.
[...]
One drawback of apsw (from SQLite actually) is that all operations to the database must be called from the same thread the cursor was created from.
This seems very reasonable to me. Anyway, there should only be one thread which accesses the database.
Apsw complained about that early on. So right now I workaound by grabbing an new cursor every time a query is made and releasing it when I'm done.
Why?
For SQLite this is very fast. But doing this with say Qt and MySQL would probably be quite a bit slower so I need to serialize the access all from one thread.
See above.
Jörg
Note that adding more categories wouldn't be a problem with the current database code. Just add them to the dbitem.song class, and register a new index. What does not work this easily, though, is to construct the intersection of different categories, so for instance: get me all slow waltzs.
Right and thats just a simple search. More complex ones are possbile.
from a touchscreen. I've only just started so its very incomplete. But it does load and display some items queried from the database. No player functions yet.
I looked at it, and it looks like being designed for your specific needs, which of course is not bad but somehow limits it's general usefulness. But maybe there will be more functionality in the future?
Yes exactly to my specific needs. More functionaity in the future as I work on it.. However, I don't think I will ever target it as a general useage interface. The general case adds complexity that I don't want. By nature its specific to my goal which is the quick and simple selection of particular dance songs.
Your curses interface already provides a good general interface. So I don't see where its needed.
every time. So to support that I had to create a new song_lite class that did not go read all the meta-info of a song when instantiated.
Actually, this is not a big problem. One could actually make the pure container class the superclass.
Works for me. I'm good with any suggestions like that you have.
pyTone wants to parse a collection of files and display all the ID3 info in an organized manner. DanceBox doesn't care about the id3 info.
Yes, I've seen that. But again this makes your SQLite code not very usefull for PyTone...
I think you misunderstand. The design of DanceBox can use any id3 info that currently exists. In fact my latest build now makes the 'Import' button run the autoregistersongs. Which will populate the tables with info from the mp3s. I just didn't go all the way (yet). Eventually I'm planning on using all the ID3 info of a song if its present. its just not necesary right now in my developement stage. The user will have to input all the dance info anyway.
implemented with the database I setup. So if someone wanted to re-tool pyTone into using SQLite this should be a great start. I saw in the archives that moving to SQLite was suggested but met some resistance due to the additional dependencies that would add.
Yes, but I still have moving to the SQLite db in mind. But IMHO this requires a bit of thinking about the database scheme before.
I'm all ears. I tried to build something that would encapsulate all of PyTones functionality but if you think I missed something let me know. My design is by no means static. Nor do I think its perfect.
That's ok, although syncing things is probably not so easy. Looking at your code, there are already various differences here and there, which you have to keep track off.
Right it will never be 100% automatic. But lets say you switch to SQLite then its certainly in my best interest to try to use as much of your code as possible given the amount of work you've already put into the project. The converse may also be true. Hopefully you can take what I've done and leverage it for your use.
probably continue to do that. Since I don't really care as long as its readable and to me longfuncitonnames are not readable.
Coding conventions are always a matter of taste. Although I think it's good style to use the style already used in a project.
I agree. And with the Qt code you can see that I did exactly that.
I tried working without breaks in my function names but my english trained brain just rejected it. I eventually decided that if I were to have to continue this myself I was going to have to have entity names I could easily read.
I'm somewhat flexable here. If you did want to move pyTone to SQLite then it really dosen't make much sense to have 2 different versions of the same thing. So I might be convinced to grin and bear it until I get used to looking at it.
But thats _only_ if we can achieve a code base with a high amount of code useable by both projects.
This seems very reasonable to me. Anyway, there should only be one thread which accesses the database.
Apsw complained about that early on. So right now I workaound by grabbing an new cursor every time a query is made and releasing it when I'm done.
Why?
I'm not really sure. I thought was that all the database operations ran in a single thread. My debugging prints indicate that all the requests come from the same thread 'Main' But apsw dosen't seem to agree. I haven't put a large amount of time in figuring out the cause. Perhaps you can shed some light on the issue.
If you look in _initdb you will see a self.cursor that holds a dbcursor. If you try to use this cursor in something run via a request then apsw will whine.