Wednesday, August 13. 2008download and test Quasar![]() So, there's much interest in the Phonon + Quasar code - as I had hoped To reproduce the result on your computer you need to get current phonon, current phonon-xine (with libxine >= 1.1.12) and current quasar from SVN. For those that don't know where Quasar lives, you can find it here: http://websvn.kde.org/trunk/playground/base/quasar/. To compile quasar you need to set the KDEDIR environment variable to the prefix where you installed phonon and then run qmake and make in the source dir. Then go to the examples/phonon subdir and run ./phonon /path/to/video.ogg. With S and Shift-S you can change the edge detection threshold. Have fun detecting edges in your videos ... Phonon + Quasar![]() I've got it working a long time ago, but since this Akademy it is finally available in KDE trunk: Phonon now can give the raw video frames (as RGB, YV12 or YUY2) to an application and Quasar gained a node to upload those frames as textures and uses Shaders to convert YUV formats to RGB and then do arbitrary effects with them. The cool part about that, obviously, is that the data intensive calculations are happening on the graphics card (you need OpenGL 2 for this to work). To demonstrate the power of this I wrote a simple example that connects the PhononInputNode to an EdgeDetection node and then to a RenderNode. I did a screencapture of the result, but that looks a lot worse than the real performance, which is totally smooth and, of course, doesn't show much CPU usage. You can also see me adjusting the threshold value of the edge detection filter with a keyboard shortcut. Here's the code: m_input = new PhononInputNode(); connect(m_input, SIGNAL(needUpdate()), SLOT(updateGL())); m_compo.addNode(m_input); m_displayNode = m_compo.createNode("/output/render"); m_saturationNode = m_compo.createNode("/color/edgedetect"); Quasar::link(m_input, "output", m_saturationNode, "texture"); Quasar::link(m_saturationNode, "output", m_displayNode, "texture"); Phonon::createPath(m_media, m_input); m_compo.prepare(); connect(m_media, SIGNAL(finished()), m_media, SLOT(play())); m_media->play(); Things to note:
Tuesday, July 29. 2008Akademy Travel
![]() As For the train I'd probably take the ICE 610 (12:35 Mannheim - Köln) and ICE 14 (14:44 Köln - Bruxelles-Nord) on Fr, 8th, of course. But sharing a car ride would probably be cheaper. Now back to exam preparations... Monday, January 21. 2008more UI feedback![]() After a month of no KDE coding I'm back to do a few things in KDE again - though I really want to (and need to) do more for University if I ever want to get done with it... Anyway, what I wanted to show is how to do simple animations in the UI that should help the user to understand how the different UI elements play together. I have one such case with the Phonon KCM where I now tried the following animation to clear things up a bit: The way I achieved this effect was to add a special Animation widget that sits above the other widgets and is not added to any QLayout. Reimplement the paintEvent to draw the animation frames and use a QTimeLine member to call repaint(). It needs two pixmaps: one of the old content of the QListView at the right and one with the new content. The paintEvent then draws the old content over the QListView so that it seems the widget contents have not changed yet and draws the new content depending on the frame number of QTimeLine (with 50% opacity). QTimeLine::finished() is connected to the deleteLater slot which removes the animation widget. Here's the code: class SelectionChangeAnimation : public QWidget
{ public: SelectionChangeAnimation(const QRect &sourceRect, QWidget *destWidget, QWidget *parent); void start(); protected: void paintEvent(QPaintEvent *); bool eventFilter(QObject *, QEvent *); private: QTimeLine m_timeLine; QPixmap m_old, m_new; QRect m_sourceRect; QRect m_destRect; QWidget *m_destWidget; bool m_needPixmapUpdate; }; SelectionChangeAnimation::SelectionChangeAnimation(const QRect &sourceRect, QWidget *destWidget, QWidget *parent) : QWidget(parent), m_timeLine(200), m_sourceRect(sourceRect), m_destRect(destWidget->mapTo(parent, QPoint(0, 0)), destWidget->size()), m_destWidget(destWidget), m_needPixmapUpdate(true) { setGeometry(m_sourceRect | m_destRect); m_sourceRect.moveTopLeft(mapFrom(parent, m_sourceRect.topLeft())); m_destRect.moveTopLeft(mapFrom(parent, m_destRect.topLeft())); m_old = QPixmap::grabWidget(m_destWidget); m_timeLine.setFrameRange(0, 63); connect(&m_timeLine, SIGNAL(finished()), SLOT(deleteLater())); m_destWidget->installEventFilter(this); show(); } void SelectionChangeAnimation::start() { m_timeLine.start(); connect(&m_timeLine, SIGNAL(frameChanged(int)), SLOT(repaint())); } bool SelectionChangeAnimation::eventFilter(QObject *o, QEvent *e) { if (o == m_destWidget && e->type() == QEvent::Paint) { m_needPixmapUpdate = true; } return QWidget::eventFilter(o, e); } void SelectionChangeAnimation::paintEvent(QPaintEvent *) { const int f = m_timeLine.currentFrame(); const QRect animRect = QRect( m_sourceRect.x() + ((m_destRect.x() - m_sourceRect.x()) * f >> 6), m_sourceRect.y() + ((m_destRect.y() - m_sourceRect.y()) * f >> 6), m_sourceRect.width() + ((m_destRect.width() - m_sourceRect.width()) * f >> 6), m_sourceRect.height() + ((m_destRect.height() - m_sourceRect.height()) * f >> 6)); // by masking the widget the flicker when deleting the animation widget is reduced setMask(QRegion(animRect) + QRegion(m_destRect)); QPainter p(this); p.drawPixmap(m_destRect, m_old); if (m_needPixmapUpdate) { m_destWidget->removeEventFilter(this); m_new = QPixmap::grabWidget(m_destWidget); m_destWidget->installEventFilter(this); } p.setOpacity(0.5); p.drawPixmap(animRect, m_new); } Thursday, December 13. 2007got a present today![]() Today I checked my mails and saw a few Phonon-related commits. I always read those commit messages with priority... and I was a bit surprised. I knew this day would come. But I didn't know when and I didn't know whether it's going to be GPL+commercial or LGPL. And I found the commit messages all said "[License: LGPL]". *dance* Now what does that license mean? It means everybody can contribute without having to sign a copyright assignment. That just makes it so much easier to handle contributions! Now I know what code I'm going to read and play with the next days. Sunday, December 9. 2007going crazySaturday, December 8. 2007QWidget::render
![]() Yesterday on IRC I was reminded of the nice abstractions Qt has with QPaintDevice. (There are many useful paint devices, but most important for this discourse are QWidget, QPixmap and QImage.) So there are several things Qt4 allows you to do:
Inspired by the video from Mirco Müller I wanted to see what could be done with those functions. I started with setRedirected but couldn't make it work immediately. So I did what the docs said and tried QPixmap::grabWidget. And without much effort I was able to draw a widget someplace else. But then I wanted to transform the image which needs a conversion to QImage. Expecting that Qt might optimize a bit if it renders directly into a QImage instead of a QPixmap and then converts to QImage I used QWidget::render to render a widget directly onto a QImage. Piece of cake. Now I had a QImage, transformed and painted into a different widget. Last missing piece is to update the image if the original widget changes (e.g. mouse or keyboard events). QObject::installEventFilter makes it easy to listen for paint events on the other widget and update accordingly. And to make it a fully featured class I added the ability to look for child widget paint events and made it repaint only as little as needed. The result is this code: int main(int argc, char **argv) { QApplication app(argc, argv); QWidget topLevel; QWidget w(&topLevel); WidgetMirror leMirror(&topLevel); leMirror.setMirroredWidget(&w); QPushButton b("Button", &w); QLineEdit le(&w); QListWidget lw(&w); lw.setMaximumHeight(64); lw.addItems(QStringList() << "Item 1" << "Item 2" << "Item 3" << "Item 4" << "Item 5" << "Item 6" << "Item 7" << "Item 8"); QGridLayout layout(&w); layout.setMargin(0); layout.addWidget(&b, 0, 0, Qt::AlignBottom); layout.addWidget(&le, 0, 1, Qt::AlignBottom); layout.addWidget(&lw, 0, 2, Qt::AlignBottom); QVBoxLayout outerLayout(&topLevel); outerLayout.setSpacing(0); outerLayout.addWidget(&w); outerLayout.addWidget(&leMirror); topLevel.show(); return app.exec(); } which makes for this (All the artifacts and "unsmoothness" are results of the screen-capture). Today I wanted to see whether this eye-candy can be put into KDE at some place and I have not succeeded. Perhaps somebody can make a mockup of how this could be used without making you feel "something is wrong". Notice that all this is just fooling around with what Qt provides. This is neither useful nor going into KDE 4.0 For the interested people, the implementation of WidgetMirror looks like this: Continue reading "QWidget::render" Wednesday, November 28. 2007Practicing my template skills
![]() While working on assignments for the Computergraphics course I'm taking this semester I was missing signals and slots. Using Qt for the assignments is not possible (well actually I didn't ask explicitly whether I could use it), so I felt challenged to code the convenient things I'm so used to... I knew that boost had some implementation of signals and slots that used templates but I had never actually taken a look at it. And I didn't want to, yet. I wanted to think about the problem myself first. Basically I came up with that a signal needs to be an object where as a slot may not have to be an object, but must also work as a member function. After a few iterations I came up with a header that now allows me to do the following: #include "signal.h" #include <iostream> struct A { void operator()() { std::cout << "A::operator()" << std::endl; } void f() { std::cout << "A::f" << std::endl; } }; struct B { void operator()(int x) { std::cout << "B::operator() " << x << std::endl; } void f(int x) { std::cout << "B::f " << x << std::endl; } }; void g() { std::cout << "g" << std::endl; } void g(int x) { std::cout << "g " << x << std::endl; } int main() { A a; Signal<> s; s.connect(&a); s.connect(&a, &A::f); s.connect(&g); s(); B b; Signal<int> s2; s2.connect(&b); s2.connect(&b, &B::f); s2.connect(&g); s2(5); return 0; } The output of that program is:
Now you probably want to see the code for Signal: Continue reading "Practicing my template skills" Thursday, November 1. 2007volume change popup Just playing around with our libs:first look second look Ignore the not-smooth blends, it's only in the video. On screen it's smooth. Thursday, September 20. 2007Mixer API Design![]() After playing with the mixer API a bit I feel confident to be able to go forward a propose a design. I'm happy for people to look over it. Don't think about implementation details but whether this API would be easy to understand, use and still powerful enough for all our desktop uses. Update: latest version of the diagram at http://vir.homelinux.org/phononmixer.png Wednesday, September 19. 2007Mastering the Mixer![]() After a phonon/phonon-xine debug session (where I got stuck at KIO playback showing inexplicable memory access violations inside xine-lib) I had to do something creative again. So I tackled the mixer. First I started with trying out ALSA's softvol plugin, and whether that would have less latency than the software volume control inside xine-lib. As it's close to impossible to measure I have to rely on my senses and that's telling me there's no audible difference. Ok, so for AudioOutput's volume property I could stay with xine-lib's offering, but seeing softvol work for the first time that got me started on exploring the ALSA mixer. When an application uses an ALSA "device" that contains the softvol plugin then this will add a new "integer control" to the mixer. KMix and also alsamixer do not show the new control without a restart, and the control does not disappear again when the application is done and no app uses the softvol anymore. From there I went to look at kmix (trunk)'s abilities wrt. custom layout definitions and whether it would be possible to group KDE made softvol controls in a sensible way. This was not getting where I wanted without touching the code so I finally started libphononmixer. When you want to use libasound (ALSA's user space lib) to fulfill a task it is, IMHO, best to not go from the doxygen generated documentation (which partially on their website is empty anyway) but open an editor in the libasound code and look at the header and source files. As the doxygen comments often don't tell much more than the function and parameter names already do the code is really the best to go with. And now I have a Mixer class that can be constructed from a Phonon::AudioOutputDevice object, a QString or an enum value. This installs a QSocketNotifier on the poll_descriptors libasound gives me and reads out all the events when the filedescriptor is ready for reading. With this I get all change notifications of a given mixer, even when a softvol control is added. From there I'll go and make a nice high-level mixer API that lists all available mixers, gives notifications when a mixer appears/disappears, lists all the elements of a mixer, makes those elements give value change notifications and so on. I'll look into the possibility of removing softvol controls from the mixer, and whether it's possible to identify their origin and group them correctly. Once this is all ready it'll be the perfect base for a Plasma Data Engine and then a Plasma Applet for controlling your sound. Personal Note: I'm close to being done with my sickness and probably today I'll go back home (where I'm alone because my wife is far away in Spain Tuesday, September 4. 2007computer labThursday, August 30. 2007Phonon-Trolltech![]()
Before
Path changes
MediaObject *media = new MediaObject; AudioPath *path = new AudioPath; AudioOutput *output = new AudioOutput(Phonon::MusicCategory); media->addAudioPath(path); path->addOutput(output); vs. MediaObject *media = new MediaObject; AudioOutput *output = new AudioOutput(Phonon::MusicCategory); /*Path path =*/ Phonon::createPath(media, output);
/*Effect *effect =*/ path.insertEffect(effectDescription); Mixing
What's the gain?
Trolltech
Sevilla
![]() I'll be gone for 10 days to visit Sevilla, Spain. My wife will spend a semester abroad (and I'll stay in Heidelberg)
Tuesday, August 14. 2007Yay!
(Page 1 of 4, totaling 46 entries)
» next page
|
Choose LanguageCalendar
QuicksearchArchivesCategoriesSyndicate This BlogBlog Administration |
|||||||||||||||||||||||||||||||||||||||||||||||||
