Sunday, September 25, 2011

Convert foobar2000 playlists into something useful

Because i had switched from Windows to Ubuntu (on my desktop computer) a week ago, i had the problem, that i had to say "good bye" to my favorite music player called "foobar2000", because he is only available for Windows.
I had some really cool online radio stations stored in foobar2000.
The biggest problem: foobar2000 stores the playlists (and my radio stations) in a non-open binary file format.

So I decided to write the program called "foobarConverter". It is capable to convert a foobar2000 playlist (".fpl") into ".pls", ".m3u" and extended ".m3u" playlists.
As it is written in Java, it should run on a variety of operating systems.

The program is freeware for non-commercial use.

Example of usage:
xxxx@ubuntu:~/$ java -jar ./foobarConverter.jar ../Radio_2011-09-09.fpl pls
Starting foobar2000 playlist converter.
Converting file to 'pls'...
Conversion done! :)

If you are interested in some details, look there: http://www.foobar2000.org/FAQ
(Question: "Are specifications of the FPL playlist format available? Why doesn't foobar2000 use some user-editable XML-based playlist file format instead?")

Have fun! :)

Saturday, July 23, 2011

New bool solver

Last year i released bool_solver - a little tool to convert boolean algebra into truth tables. I rewrote the program completely from scratch in C. It is now shorter and easier to understand than the old C++ version I hope.

Friday, July 22, 2011

Parsing source code files for function headers and function calls

Some weeks ago I wrote a small program, which is able to print a list of functions and function calls used in a program. It can parse a directory recursively for a given file type.

Here is the source code: functiondiagram.d
And here is the source as a "quote" (a function to present formated source code is missing on blogger.com...):
/*
    This console apllication written in D is able to parse C, C++, D and many more file types.
    It scans the files for functions and function calls and prints a list with all matches for every file.
    As first parameter you must specify a directory name, where the search will start. This folder will be scanned recursively for matches.
    The type of file must be specified by the second parameter.
  
    This code stands under the do-with-it-what-you-want license.
  
    Author: Energized
    E-mail: undervoltage@safe-mail.net
    Blog: http://electric-handicraft.blogspot.com
*/


import std.file;
import std.stdio;
import std.stream;
import std.regexp;

/*
TODO:
- Self defined data types are not recognized
- Comments will be parsed too. This can result in false "positives".
*/


/*
    Function is searching in a line of text/code for function calls and function headers:
*/
string[] returnFunctions( string data )
{
    string regex = r"([\w\d]+)\s*[(]";
    string[] rv;
  

    foreach( m; RegExp( regex, "ig" ).search( data ) )
    {
        if ( (m !is null) && (m.match(1) !is null) ) //is something was found:
        {
            //writefln("> '" ~ m.match(1) ~ "'");
            if ( RegExp( r"^(if|for|foreach|return|while|finally|try|catch)$" ).match( m.match(1) ) is null ) //is the match a reserved word?
            {
                rv ~= m.match(1); //if not, it will be part of our result

                //if no datatype is in front of the match, it is a function call:
                auto n = search( m.pre, r"^\s{0,}(string|bool|int|byte|char|long|short|float|double|void|signed|unsigned|HBITMAP)", "i" );
                if ( n is null )
                    rv ~= ";";
                else
                {
                    /*
                        If an assignment is done (function to variable), false positives will be produced.
                        Then the function call will be misinterpreted as a function header. Thats why we are searching for a
                        semicolon here. Is a semicolon in this line, it is a function call (or a forward declaration).
                    */
                    if ( std.string.find( m.post, ';' ) != -1 ) rv ~= ";";
                }
            }
        }
    }
    return rv;
}


/*
    Shows the result:
*/
void printTree( string[] data )
{
    if (data.length == 1)
        writefln( "\nFunction \"%s()\":", data[0] );
    else
    {
        foreach( t; data )
            if (t != ";") writefln("\t%s();", t);
    }
}


void main( char[][] parameters )
{
    string path = parameters[1];      //as first parameter the program needs a path name
    string extension = parameters[2]; //extension (like "*.cpp")
    string[] result = listdir( path, extension ); //crawl through all files with the given extension in the given directory and all sub directories and store the filenames in the "result" array.
  
    foreach( filename; result ) //scan one file after the other:
    {
        BufferedFile file = new BufferedFile( filename, FileMode.In ); //open the file for reading

        writefln( "\nFile: " ~ filename ); //print the filename
      
        foreach(ulong n, string line; file) //go through the lines and scan them for function names or function calls:
        {
            string[] functions = returnFunctions( line );
          
            if (functions !is null) printTree( functions ); //if the end of file is reached, print the result
        }
        file.close();
    }
}
 And here is an example, how the result looks like:

File: C:\functiondiagram.d

Function "returnFunctions()":
        RegExp();
        search();
        match();
        writefln();
        match();
        RegExp();
        match();
        match();
        match();
        search();
        done();
        call();
        find();

Function "printTree()":
        writefln();
        s();
        writefln();
        s();

Function "main()":

Function "extension()":
        listdir();
        BufferedFile();
        writefln();
        returnFunctions();
        printTree();
        close();

The program is not perfect yet. Some false positives are possible like in the example the function "s()" which is not a function but a regular expression.

Sunday, May 22, 2011

Old dosimeter disassembled

Today i have disassembled an old dosimeter. It is an old soviet model manufactered in (or for) east germany. I made some photos of it, so you can enjoy the old technology used in this device. ;D























Sunday, May 15, 2011

New firmware for the thermometer

Here is an up-to-date version of the clock-thermometer firmware: Thermometer4_-_LCD.c
Because of school I did not have much time to make improvements.

Tuesday, February 22, 2011

Some current and finished projects...

Last month i rewrote my bool solver from scratch. This time i wrote it in pure C - without C++ elements. It has almost all functions of the old version plus some new ones, but the new program is much shorter. Documentation and comments are in german... thats why i do not upload it.

Because the old firmware (version 4) of the AtTiny clock was pretty ugly, i rewrote and changed many parts of the firmware. The new version has the number 5. The new code runs like a charm and as a bonus it eliminates the problems i had with the buttons (it was not a hardware problem).
Release will be soon. Only a calibration function for the quartz is still missing. ^.^°

And one last thing: i disassembled my old Acer travelmate 220 notbook and under the sticker of an IC i found an Atmel AtTiny25 as part of the charging circuit. It communicates directly with the laptop battery through TWI/I²C. The foto was made with my Canon EO350 / Digital Rebel XT / Kiss Digital N with an hand hold lens in retro position - the IC was so damn small:

Thursday, February 17, 2011

Movie about the build of integrated circuits

A movie made by Fairchild semiconductor about building integrated circuits. The video is from 1967!

Fairchild Briefing on Integrated Circuits

I finally watched the whole video (i have never found the time till today)... interesting. :D