Archive

Author Archive

Resizable photo frames in Qt

August 4th, 2009 Wesley No comments

Today someone asked how to copy one image into another image in Qt. I thought it was a nice idea to write an example about how to do that, plus a few extra things. We will create a resizable photo frame from just one simple image of a photo frame! It works like this:

  • Reimplement QWidget::paintEvent() and construct a QPainter(this) in the reimplementation so we can draw on the widget
  • Load the image of the photo frame and define 4 QRect objects to define the position of the frame borders – these borders are not allowed to scale
  • Draw something which will be contained inside of the frame – for example another image using QPainter::drawPixmap() or QPainter::drawImage()
  • Generate and draw the frame bars (the pieces between the borders)
    • Make use of the QImage::mirrored() function and another QPainter to create a new pixmap which contains the frame bar plus the mirrored frame bar.
    • This will make the bar look great when the frame bar is enlarged by tiling. This method is actually a very popular one in basic photo manipulation.
  • Draw the four borders

The result looks like this:

Photo frame in native size – versus – Enlarged photo frame

The code looks like this:

photowidget.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#ifndef PHOTOWIDGET_H
#define PHOTOWIDGET_H

#include <QtGui/QWidget>

class PhotoWidget : public QWidget {
    Q_OBJECT

public:
    PhotoWidget(QWidget *parent = 0);

protected:
    void paintEvent(QPaintEvent *event);

private:
    QPixmap createBar(Qt::Orientation orientation, const QPixmap &pixmap, const QRect &rect);
};

#endif // PHOTOWIDGET_H

photowidget.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#include "photowidget.h"
#include <QPainter>
#include <QPaintEvent>

#define SIZE 108

PhotoWidget::PhotoWidget(QWidget *parent) : QWidget(parent) {
    resize(400, 329);
    setWindowTitle("Photo Frame Example");
}

// This function generates a pixmap that can be used as a tiled bar.
// Note: We use a QPainter and the mirrored() function to make sure that the bar looks good when tiled.
//       This technique is often applied in basic photo manipulation.
QPixmap PhotoWidget::createBar(Qt::Orientation orientation, const QPixmap &pixmap, const QRect &rect) {
    QImage barA = pixmap.copy(rect).toImage();
    QImage barB = barA.mirrored(orientation == Qt::Horizontal ? true : false,
                                orientation == Qt::Vertical ? true : false);

    QSize size;
    size.setWidth(orientation == Qt::Horizontal ? barA.width() << 1 : barA.width());
    size.setHeight(orientation == Qt::Vertical ? barA.height() << 1 : barA.height());

    QPixmap bar(size);
    bar.fill(Qt::transparent);
    QPainter merger(&bar);

    merger.drawImage(0, 0, barA);
    if (orientation == Qt::Horizontal)
        merger.drawImage(barA.width(), 0, barB);
    else
        merger.drawImage(0, barA.height(), barB);

    return bar;
}

void PhotoWidget::paintEvent(QPaintEvent *event) {
    QPainter p(this);

    // Our frame as one full image, and an image to put in the frame
    QPixmap frame(":/img/frame.png");
    QPixmap sky(":/img/palmtree.jpg");

    // These four rectangles define the four borders of the frame
    QRect topLeft(0, 0, SIZE, SIZE);
    QRect topRight(frame.width() - SIZE, 0, SIZE, SIZE);
    QRect bottomLeft(0, frame.height() - SIZE, SIZE, SIZE);
    QRect bottomRight(frame.width() - SIZE, frame.height() - SIZE, SIZE, SIZE);

    // Draw the image first
    p.drawPixmap(QRect(40, 40, event->rect().width() - 80, event->rect().height() - 80), sky);

    // Draw the bars
    p.drawTiledPixmap(QRect(QPoint(SIZE, 0), event->rect().topRight() + QPoint(-SIZE, SIZE - 1)),
                      createBar(Qt::Horizontal, frame, QRect(QPoint(SIZE, 0), frame.rect().topRight() + QPoint(-SIZE, SIZE))));
    p.drawTiledPixmap(QRect(event->rect().bottomLeft() + QPoint(SIZE, -SIZE - 1), event->rect().bottomRight() - QPoint(SIZE, 0)),
                      createBar(Qt::Horizontal, frame, QRect(frame.rect().bottomLeft() + QPoint(SIZE, -SIZE), frame.rect().bottomRight() - QPoint(SIZE, 0))));
    p.drawTiledPixmap(QRect(QPoint(0, SIZE), event->rect().bottomLeft() + QPoint(SIZE, -SIZE)),
                      createBar(Qt::Vertical, frame, QRect(QPoint(0, SIZE), frame.rect().bottomLeft() + QPoint(SIZE, -SIZE))));
    p.drawTiledPixmap(QRect(event->rect().topRight() - QPoint(SIZE + 1, -SIZE), event->rect().bottomRight() - QPoint(0, SIZE)),
                      createBar(Qt::Vertical, frame, QRect(frame.rect().topRight() - QPoint(SIZE, -SIZE), frame.rect().bottomRight() - QPoint(0, SIZE))));

    // Draw the borders
    p.drawPixmap(QPoint(0, 0), frame, topLeft);
    p.drawPixmap(event->rect().topRight() - QPoint(SIZE, 0), frame, topRight);
    p.drawPixmap(event->rect().bottomLeft() - QPoint(0, SIZE), frame, bottomLeft);
    p.drawPixmap(event->rect().bottomRight() - QPoint(SIZE, SIZE), frame, bottomRight);
}
VN:F [1.6.3_896]
Rating: +4 (from 4 votes)
Categories: C++, Programming, Qt

NeHe OpenGL lessons in Qt – Chapter 1 and 2

August 3rd, 2009 Wesley 2 comments

Last week I have ported two chapters (the first 10 lessons) of the NeHe OpenGL lessons to make use of the Qt toolkit. You will notice that the code in Qt is much cleaner and simpler than the code in the original NeHe lessons. There is no need to create a rendering or device context yourself or anything like that, and input support like input from keyboard or mouse can simply be implemented by reimplementing one function. As an added bonus, your 3D applications will run on pretty much any platform.

First chapter: setting up an OpenGL window, polygons, colors, rotation, 3D shapes

After completing the first chapter, you will end up with a rotating pyramid and cube…

This video shows the end result (lesson 5).
You can download the Qt 4 source code for this chapter here.

Second chapter: texture mapping, texture filters, lighting, keyboard control, blending, moving bitmaps in 3D space, loading and moving through a 3D world

In the second chapter you will learn a lot about textures, among some other things. Sometimes we make use of QGLContext::bindTexture() to load an image, morph it into a texture and bind it to OpenGL all in one go. Other times we will do it manually because we want to specify the texture filter ourselves (but we do have QGLWidget::convertToGLFormat() which makes that easy as well). To handle keypresses we simply reimplement keyPressEvent(). To load in the 3D world from the file we make use of the excellent QFile and QTextStream classes. As an added bonus, we also make use of QGLWidget::renderText() to show the user what has changed when a key is pressed inside the OpenGL window. Lesson 9 also features a bonus fade-in effect for the revived stars. This makes the effect look much cooler.

This video shows the result of adding texture filters, lighting and keyboard control (lesson 7)
This video shows the result of all the above plus blending (lesson 8)
This video shows the result of moving bitmaps in 3D space (lesson 9)
This video shows the result of moving through a very simple 3D world (lesson 10)
You can download the Qt 4 source code for this chapter here.

The third and fourth chapter are almost complete as well, but I will give you the Qt ports of those chapters another time. Perhaps tomorrow.

VN:F [1.6.3_896]
Rating: +16 (from 16 votes)
Categories: C++, OpenGL, Programming, Qt

My very own Linux from scratch

August 3rd, 2009 Wesley No comments

I started with a CLFS (Cross-compiled Linux From Scratch) installation yesterday. After major issues which I encountered when trying to boot the new kernel, I managed to create a very minimalistic kernel configuration which built a kernel that was able to boot up! I now have a very minimal Linux installation.

It’s not done yet, though. I will now have to install base system software, build a more advanced kernel, and then start building and integrating different software components of my personal choice. After this project I might either start my own Linux distribution (either from scratch, or based on Arch Linux) or just provide a repository for Arch Linux which contains some special software and help with Arch Linux development – because the goals of the Arch Linux distribution are very similar to mine. I also want to provide a repository with custom kernels and software which improve performance for all laptops that are sold by Hasselt University since 2008. I would however like to improve some things upstream as well, for example add a graphical installer and create an auto-system-configure tool which sets up Arch Linux for specific usage, and I’m not entirely sure yet whether these would be welcome changes upstream. If not, I might have to resort to an Arch Linux fork or my own distribution from scratch.

VN:F [1.6.3_896]
Rating: +1 (from 1 vote)

x86 Linux assembler

August 2nd, 2009 Wesley 4 comments

The last few days I’ve been looking at x86 Linux assembler programming. I think it’s important to know how the code which you write in higher-level languages gets translated to low-level instructions and in what way things like libc or the kernel are involved. With some knowledge of assembler you can not only directly optimize some slower operations by implementing them in low-level assembly and by utilizing specific processor features, but in general you will also learn in which ways you can optimize your software by just writing the high-level code a little bit different – by anticipating how your code will translate into low-level assembler instructions.

That was my motivation for trying to do a few things with the Netwide Assembler (NASM). The result is a simple demo which utilizes libc, GLUT and OpenGL to display a rotating pyramid and cube.

ogl.asm

compiled ogl.asm application running in Ubuntu 8.04

The resulting code can be viewed here:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
; OpenGL example in x86 Linux assembler / NASM using Glut
; Author: Wesley Stessens (wesley@ubuntu.com)
;
; OpenGL calls to create pyramid and cube are from Jeff Molofee's OpenGL tutorial
; See: http://nehe.gamedev.net/data/lessons/lesson.asp?lesson=05
;
; Features:
;  - Calling C functions by cdecl conventions
;  - Using GLUT and OpenGL calls to perform 3D graphics
;  - Low-level framerate control
;
; Sample compile instructions:
; nasm -felf ogl.asm && ld -lglut -s -I/lib/ld-linux.so.2 -o ogl ogl.o
;
; This code is released as sample code in the public domain. Use it for whatever you want.
; Feel free to let me know if you found this code useful in any way.

; Glut
extern glutInit, glutInitDisplayMode, glutInitWindowSize, glutInitWindowPosition
extern glutCreateWindow, glutMainLoop
extern glutDisplayFunc, glutIdleFunc, glutReshapeFunc, glutKeyboardFunc
extern glutSwapBuffers

; Glu
extern gluPerspective

; OpenGL
extern glClearColor, glClearDepth, glDepthFunc, glEnable, glShadeModel
extern glClear, glLoadIdentity, glMatrixMode, glViewport
extern glTranslatef, glRotatef, glBegin, glEnd, glVertex3f, glColor3f

; Needed for framerate control
extern usleep

; Macros
%macro _3call 4
    push dword %4
    push dword %3
    push dword %2
    call %1
    add esp, 12
%endmacro
%macro _4call 5
    push dword %5
    push dword %4
    push dword %3
    push dword %2
    call %1
    add esp, 16
%endmacro

section .data
    title: db 'OpenGL in x86 Linux assembler / NASM using Glut', 0
    ; Data for FP math with 4 bytes
    n7: dd -7.0
    n6: dd -6.0
    n1p5: dd -1.5
    n1: dd -1.0
    p0p4: dd 0.4
    p0p5: dd 0.5
    p1: dd 1.0
    p1p5: dd 1.5
    p3: dd 3.0
    rottrm: dd 4.5
    rotsqm: dd -3.0

    ; Data for FP math with 8 bytes
    q0p1: dq 0.1
    q1: dq 1.0
    q45: dq 45.0
    q100: dq 100.0

    ; Data for framerate control
    mspf: dd 20000 ; ms per frame

section .bss
    ; Vars for rotation
    rottr: resd 1
    rotsq: resd 1
    ; Var for aspect ratio
    aspr: resq 1
    ; Vars for framerate control
    time: resd 2
    usecs: resd 1
    oldslp: resd 1

section .text
    global _start

fpsmanager:
    push eax
    push ebx
    push ecx
    push edx

    mov eax, 78 ; sys_gettimeofday
    mov ebx, time
    mov ecx, 0
    int 80h

    mov eax, [time + 4]
    sub eax, [usecs]
    mov ebx, [mspf]
    sub ebx, eax

    test eax, eax
    js keep_sleep
    test ebx, ebx
    js keep_sleep

    push ebx
    call usleep
    add esp, 4
    mov dword [oldslp], ebx
    jmp done_sleep

keep_sleep:
    push dword [oldslp]
    call usleep
    add esp, 4

done_sleep:
    mov eax, [time + 4]
    mov dword [usecs], eax

    pop edx
    pop ecx
    pop ebx
    pop eax
    ret

display:
    ; Prepare for drawing
    push dword 4100h ; GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT
    call glClear
    add esp, 4
    call glLoadIdentity

    ; Draw pyramid on the left of the screen
    _3call glTranslatef, [n1p5], 0, [n6]
    _4call glRotatef, [rottr], 0, [p1], 0
    push dword 9h ; GL_POLYGON
    call glBegin
    add esp, 4
    _3call glColor3f, [p1], 0, 0 ; Start drawing front face
    _3call glVertex3f, 0, [p1], 0
    _3call glColor3f, 0, [p1], 0
    _3call glVertex3f, [n1], [n1], [p1]
    _3call glColor3f, 0, 0, [p1]
    _3call glVertex3f, [p1], [n1], [p1]
    _3call glColor3f, [p1], 0, 0 ; Start drawing right face
    _3call glVertex3f, 0, [p1], 0
    _3call glColor3f, 0, 0, [p1]
    _3call glVertex3f, [p1], [n1], [p1]
    _3call glColor3f, 0, [p1], 0
    _3call glVertex3f, [p1], [n1], [n1]
    _3call glColor3f, [p1], 0, 0 ; Start drawing back face
    _3call glVertex3f, 0, [p1], 0
    _3call glColor3f, 0, [p1], 0
    _3call glVertex3f, [p1], [n1], [n1]
    _3call glColor3f, 0, 0, [p1]
    _3call glVertex3f, [n1], [n1], [n1]
    _3call glColor3f, [p1], 0, 0 ; Start drawing right face
    _3call glVertex3f, 0, [p1], 0
    _3call glColor3f, 0, 0, [p1]
    _3call glVertex3f, [n1], [n1], [n1]
    _3call glColor3f, 0, [p1], 0
    _3call glVertex3f, [n1], [n1], [p1]
    call glEnd

    ; Draw cube on the right of the screen
    call glLoadIdentity
    _3call glTranslatef, [p1p5], 0, [n7]
    _4call glRotatef, [rotsq], [p1], [p0p4], [p0p5]
    push dword 7h ; GL_QUADS
    call glBegin
    add esp, 4
    _3call glColor3f, 0, [p1], 0 ; Start drawing top face
    _3call glVertex3f, [p1], [p1], [n1]
    _3call glVertex3f, [n1], [p1], [n1]
    _3call glVertex3f, [n1], [p1], [p1]
    _3call glVertex3f, [p1], [p1], [p1]
    _3call glColor3f, [p1], [p0p5], 0 ; Start drawing bottom face
    _3call glVertex3f, [p1], [n1], [p1]
    _3call glVertex3f, [n1], [n1], [p1]
    _3call glVertex3f, [n1], [n1], [n1]
    _3call glVertex3f, [p1], [n1], [n1]
    _3call glColor3f, [p1], 0, 0 ; Start drawing front face
    _3call glVertex3f, [p1], [p1], [p1]
    _3call glVertex3f, [n1], [p1], [p1]
    _3call glVertex3f, [n1], [n1], [p1]
    _3call glVertex3f, [p1], [n1], [p1]
    _3call glColor3f, [p1], [p1], 0 ; Start drawing back face
    _3call glVertex3f, [p1], [n1], [n1]
    _3call glVertex3f, [n1], [n1], [n1]
    _3call glVertex3f, [n1], [p1], [n1]
    _3call glVertex3f, [p1], [p1], [n1]
    _3call glColor3f, 0, 0, [p1] ; Start drawing left face
    _3call glVertex3f, [n1], [p1], [p1]
    _3call glVertex3f, [n1], [p1], [n1]
    _3call glVertex3f, [n1], [n1], [n1]
    _3call glVertex3f, [n1], [n1], [p1]
    _3call glColor3f, [p1], 0, [p1] ; Start drawing right face
    _3call glVertex3f, [p1], [p1], [n1]
    _3call glVertex3f, [p1], [p1], [p1]
    _3call glVertex3f, [p1], [n1], [p1]
    _3call glVertex3f, [p1], [n1], [n1]
    call glEnd

    ; Update rotation
    fld dword [rottr]
    fadd dword [rottrm]
    fstp dword [rottr]
    fld dword [rotsq]
    fadd dword [rotsqm]
    fstp dword [rotsq]

    call glutSwapBuffers ; Swap buffers and display
    call fpsmanager ; Cap framerate if necessary
    ret

reshape:
    push ebp
    mov ebp, esp

    ; Prevent division by zero
    cmp dword [ebp+8], 0
    jne reshape_2
    inc dword [ebp+8]

reshape_2:
    fild dword [ebp+8]
    fidiv dword [ebp+12]
    fstp qword [aspr]

    push dword [ebp+12]
    push dword [ebp+8]
    push dword 0
    push dword 0
    call glViewport
    add esp, 16
    push dword 1701h; GL_PROJECTION
    call glMatrixMode
    add esp, 4
    call glLoadIdentity

    push dword [q100+4]
    push dword [q100]
    push dword [q0p1+4]
    push dword [q0p1]
    push dword [aspr+4]
    push dword [aspr]
    push dword [q45+4]
    push dword [q45]
    call gluPerspective
    add esp, 32

    push dword 1700h; GL_MODELVIEW
    call glMatrixMode
    add esp, 4

    pop ebp
    ret

keyhandler:
    ret

_start:
    ; Initialize glut
    push dword [esp+8]
    lea eax, [esp+8]
    push eax
    call glutInit
    add esp, 8
    push dword 1ah ; GLUT_RGBA|GLUT_DOUBLE|GLUT_ALPHA|GLUT_DEPTH
    call glutInitDisplayMode
    add esp, 4
    push dword 480
    push dword 640
    call glutInitWindowSize
    add esp, 8
    push dword 0
    push dword 0
    call glutInitWindowPosition
    add esp, 8

    ; Create window
    push title
    call glutCreateWindow
    add esp, 4

    ; Register functions
    push display
    call glutDisplayFunc
    call glutIdleFunc
    add esp, 4
    push reshape
    call glutReshapeFunc
    add esp, 4
    push keyhandler
    call glutKeyboardFunc
    add esp, 4

    ; Initialize OpenGL
    push dword 0
    push dword 0
    push dword 0
    push dword 0
    call glClearColor
    add esp, 16
    push dword [q1+4]
    push dword [q1]
    call glClearDepth
    add esp, 8
    push dword 203h; GL_LEQUAL
    call glDepthFunc
    add esp, 4
    push dword 0b71h; GL_DEPTH_TEST
    call glEnable
    add esp, 4
    push dword 1d01h; GL_SMOOTH
    call glShadeModel
    add esp, 4

    ; Frame rate cap initialization
    mov dword [oldslp], 0

    ; Enter main loop
    call glutMainLoop

    ; Exit (return with error code 0)
    mov eax, 1 ; sys_exit
    mov ebx, 0
    int 80h

I have also written two other smaller examples:
- marketing.asm is a really simple statistics application which calculates the ideal sample size given a few parameters
- alsawav.asm is a simple audio library which utilizes ALSA to play an unbuffered raw WAV/PCM sample

Please note that all these examples require an x86 Linux distribution. These examples will not work on any other operating system.

VN:F [1.6.3_896]
Rating: +6 (from 6 votes)

It’s alive!

August 2nd, 2009 Wesley 2 comments

This blog is back! After nearly a year of silence, I decided to recreate my old techblog.
Thanks to some handy UNIX tools (vim, grep, sed) I was able to reformat my old MySQL dump into a format which is accepted by this newer version of Wordpress.

I have currently hidden all my old posts though, but most of them will come on line again after a small review, because some posts contain broken links and broken images.

edit: mosts posts are back online! :-)

For the future of this blog, I will write all my blogposts in English. That way I can reach more people. I don’t think this is a big issue, since most guys and girls who are interested in technology will know enough English to read my blog. But if you have another opinion on the matter, please do tell me.

VN:F [1.6.3_896]
Rating: 0 (from 0 votes)
Categories: Blog

Akademy 2008: Great Experience

August 24th, 2008 Wesley 7 comments

Hello everyone! It’s been a very long time since my last blogpost, and I haven’t updated my blogsoftware in a long time. Apparently, some spammers noticed this as well and were able to add some hidden spam links in some of my pages. I should seriously update my WordPress one of these days…

Anyway. Let’s talk a bit about Akademy this year. It was my first Akademy and it was a great experience! I met a lot of interesting and fun people! Everyone seems to agree that this Akademy was the best one yet, so I’m very glad to have been a part of that, although honestly most work was done by Bart Cerneels and Wendy Van Craen.

The first day

The first day was the hardest day for the organization, or at least for me and Pieter Vande Wyngaerde. After helping out at the Akademy location (Campus De Nayer) we had to make sure everyone had a place to sleep at Roo?[sz]enda[ae]l (the name was spelled different on every sign!). The rooms list wasn’t all that clear, because the numbering was different from the room numbers, but after a while we were able to figure it out, and we were able to give everyone a place to sleep.

Resting out on the floor after all that hard work ;)

Resting out on the floor after all that hard work ;)

Party time!

On the second day I was just walking around the campus, helping the team with small things. I wasn’t able to see many talks, but I was able to at least see the Nokia keynote from Sebastian Nyström. A very interesting talk, although I’m still not sure exactly what direction Qt Software will be evolving towards with Nokia, but up until now it’s been going well, so that makes me happy enough for now.

Gouden Carolus Belgian BeerIn the evening it was party time: there was this social event at Het Anker in Mechelen, which meant free food and free Belgian beer! The “Gouden Carolus” beer is something even I – as a Belgian – had never drunk before. Personally, I think there are much better tasting Belgian beers, but maybe that’s just my personal taste. The beer was pretty strong though. But I’m sure that most of you noticed that :)

After the social event I went for a small evening stroll with some of the guys who were staying at Zandpoortvest. In the end, we walked all the way to the Zandpoortvest hostel, and after I had a look around the hostel, I had to walk all the way back to Rozendaal (I’ll just stick with this way of spelling it..) Unfortunately for me, I got lost. Too bad I didn’t have the N810 with its GPS (yet), otherwise I could’ve gotten back at Rozendaal a lot quicker. My cellphone batteries were dead as well – doesn’t this sound like some horror story? – so I just figured I’d walk and follow the signs pointing to Sint-Katelijne-Waver.

After a while I saw some arrows pointing to the train station, and from there, I was able to find my way back to Rozendaal. By then, it was around 5 am, and I had a big blister on my left foot from walking all night.

…I tried to stay up, but around 11 AM I felt really tired and I wanted to sleep a bit. And because of that I missed all the great presentations that I wanted to see! It was in the late afternoon somewhere that Pieter Verledens woke me up. Then I realized how late it already was and that I missed Zack Rusin’s Gallium3D talk, which I was looking forward to. Luckily, the talk was recorded and is available on blip.tv now (thanks to Bart Cerneels).

Nokia converts KDE developers to GNOME

The Mobile and Embedded day was one of the best days of Akademy. Not only because Nokia gave away a lot of Nokia N810 devices to more than 100 KDE developers, but also because the talks were really interesting. The big problem however is that it was a pretty busy day and I wasn’t able to see most of the talks (I really wanted to see the maemo, QEdje and OpenMoko talks as well). I ended up seeing only the OpenGL ES for Embedded Linux talk by Tom Cooksey, which was very interesting though. At the end of the talk he told us about the OpenPandora handheld device that will be released soon. Apparently it is a great device for OpenGL ES development. I found their website here: www.openpandora.org

Now, the title above this paragraph is inspired by Vincent Untz‘ blogpost. It refers to the free N810s that Nokia gave away. The devices run the Maemo OS, which is based on GNOME. And to be honest, I like Maemo a lot. It works very well. But I’m very interested in the progress that Marijn Kruisselbrink is making with porting KDE 4 to the Nokia internet tablets. Me myself, I haven’t done much with the device yet, aside from playing some games, listening to some music, and doing video calls with other KDE people ;) I did however manage to get some Qt applications ported to the device, but that was ridiculously easy. Hildon integration Just Works™ out of the box and there’s very little that has to be changed to make your application look great on the N810. Except for graphics operations which are a bit slow at the moment, as explained by Ariya Hidayat in his blog post, so I also hope that the performance problem gets fixed in Qt 4.5.

Nokia N810
The Nokia N810 Internet Tablet.

Oh. And my cat was chewing on my N810 adapter (even cats seem to like this gift from Nokia), so the pin doesn’t fit my N810 perfectly anymore. But it still works if I put it in carefully and don’t touch it, so I’m still good…

Boat and Barbecue

Thursday was a really nice day. A nice boat trip, and a very tasteful barbecue. I enjoyed it a lot. Jonathan Riddell was busy interviewing a lot of people, you can download the interviews from this link. I didn’t volunteer for an interview, but you can see me sitting in the back during interview number 44. That’s enough for me ;)

At the end of Akademy, Aaron and Chani treated us (the Akademy organisation team) to a nice dinner. Thanks for the good meal and the great stories.

Everyone had to leave back home on Friday or Saturday. Sad times. I’m planning to come to Akademy next year as well. It was a lot of fun this year.

To wrap it up, here are some random notes:

  • I’m not sure who’s the noisiest: the Amarok Wolves or Team Humongous
  • If you are in dire need of some music, maybe you can hire the A-Team!
  • Video’s of a lot of talks are available at http://stecchino.blip.tv/
  • The Emsys guys really like Mega Mindy
VN:F [1.6.3_896]
Rating: 0 (from 2 votes)
Categories: KDE, Linux, Open Source

Open source DJ mixxx’ing

January 6th, 2008 Wesley 3 comments

Sinds vorige week ben ik begonnen met mee te helpen aan de ontwikkeling van het open source DJ programma mixxx. Mixxx is een stabiel programma waarmee men live muziek kan mixen. Het heeft een aantal zeer interessante features, zoals bijvoorbeeld automatische ritmedetectie en ondersteuning voor een heleboel hardware.

Mixxx 1.6.0 with Collusion/WS/Green skin

Waar staan we vandaag? 1.6.0

Ik werk mee aan de nieuwe versie waarvan twee weken geleden een eerste bètaversie werd gelanceerd. Voor de nieuwe 1.6.0 versie zijn een heleboel nieuwe features gepland. Ik som even de belangrijkste veranderingen op:

  • Scratchen via timecoded vinyl-platen [ link naar flash video 1, video 2 ]
  • Kleurenschema’s voor skins
  • Nieuwe muziekbibliotheek (muziekbrowser)
  • Verbeterde ritmedetectie
  • Verbeterde ondersteuning voor MIDI-controllers (hardware)
  • HQ-equalizer toegevoegd
  • Audio core herschreven/vernieuwd
  • Ondersteuning voor LADSPA geluidseffecten
  • Live broadcasten over internet (Icecast, Shoutcast)
  • Rechtstreeks opnemen naar MP3, Ogg Vorbis, Wav, Flac

Ik werk momenteel aan de laatste twee punten. Het is niet zeker of het helemaal af zal raken voor de Hardy freeze in februari (het moment waarop programma’s naar Ubuntu 8.04 Hardy Heron geupload worden en niet meer aangepast mogen worden) maar Ogg Vorbis Icecast/Shoutcast-ondersteuning is zo goed als af, dus dat zal er waarschijnlijk zeker inzitten.

Zelf kijk ik uit naar de ondersteuning voor LADSPA geluidseffecten, maar ik vermoed dat dat niet af zal raken voor de 1.6.0-versie. Dan maar wat langer wachten…

Evolutie van de broadcasting code

Mixxx Live Broadcasting Preferences

Zoals eerder gezegd ben ik momenteel bezig met het implementeren van Icecast/Shoutcast ondersteuning zodat we een mix rechtstreeks over internet kunnen broadcasten. Aanvankelijk dachten we dat het simpel zou zijn om dit systeem te implementeren (gewoon libshout gebruiken) maar al snel bleek dat we eerst nog een encoder moesten schrijven. Ik ben de laatste dagen dus vooral bezig geweest met het schrijven van een Ogg Vorbis-encoder met behulp van libvorbis, libogg en libvorbisenc.

Afgezien van het feit dat er voor libvorbis geen technische API-documentatie beschikbaar is, is het ons uiteindelijk toch gelukt om de encoder werkend te krijgen. Alles ging goed, maar de audio latency was nu wel verhoogd omdat de ‘audio callback thread’ voor een korte periode geblokkeerd werd wanneer de encoder zijn werk deed. Toen we ook nog beseften dat we om metadata te updaten een nieuwe stream moesten initialiseren was het onvermijdelijk om een nieuw systeem te ontwerpen om de encoder parallel in een aparte thread te laten draaien (multithreaded) met een eigen buffer.

Albert ging hiermee aan de slag en na twee of drie dagen knoeien presenteerde hij een nieuwe ‘engine’ (de SideChain-engine) aan ons die de audio buffert voor andere engines (zoals de broadcast engine) en deze engines in een aparte thread draait. Het resultaat is lage audio latency en geen enkel performanceprobleem meer. Ook werd het totale CPU-verbruik verlaagd omdat de encoder nu iets minder vaak aangeroepen wordt.

Om het schematisch voor te stellen:

voor: [ afbeelding: Oorspronkelijke Broadcast Implementatie ]
na:
[ afbeelding: Threaded Broadcast Implementatie ]

Wat moet er nog gedaan worden? De SideChain-engine moet nog een klein beetje aangepast worden, er moet nog een MP3-encoder worden geschreven, het instellingenvenster moet afgemaakt worden, en tenslotte moet de code wat opgeschoond worden, en moet alles grondig getest worden!

VN:F [1.6.3_896]
Rating: 0 (from 0 votes)

Neem je Linux (of Wine) games op!

December 27th, 2007 Wesley 2 comments

Het laatste jaar zijn er twee projecten ontstaan die het mogelijk maken om OpenGL en Alsa op te nemen zonder al te veel verlies van performance. Voor de gamers die niet weten waarover ik het heb: dit is bij wijze van spreken ‘FRAPS for Linux’. Ik heb beide projecten uitgetest en ze werken allebei prachtig: yukon en glc.

glc recording

Klik hier voor de volledige video-opname op YouTube

Dit is Aquaria Demo in Wine
opgenomen met glc op 1024×768
met Compiz ingeschakeld.

Je bent vrij om te gebruiken wat voor jou het beste werkt:

Persoonlijk ben ik momenteel voorstander van glc omdat de ontwikkelaar zéér snel is met het reageren op bugreports en omdat glc is geoptimaliseerd voor multi-core systemen. Ook heeft glc enkele speciale mogelijkheden zoals on-the-fly color conversion van BGR naar YV12 (geeft grotere compressie) en je kan zowel QuickLZ als LZO gebruiken om de stream on-the-fly te comprimeren. Een andere speciale feature van glc is de mogelijkheid om meerdere OpenGL of Alsa streams tegelijkertijd op te nemen.

glc werkte perfect bij mij, maar ik had een klein probleem met het opnemen van sommige games in Wine (problemen met audio en af en toe een crash). Na een kort gesprek met de ontwikkelaar (nullkey) en na het opsturen van enkele gdb traces werd het probleem binnen 10 minuten volledig opgelost door de ontwikkelaar. Prachtig, toch? De nieuwste versie van glc is momenteel 0.4.4 en bevat de Wine patches.

VN:F [1.6.3_896]
Rating: 0 (from 0 votes)
Categories: Linux, Multimedia