Saturday, October 31, 2009

How to embed OpenOffice.org ODP (or office ppt) files as flash content on your webpages (including controls).

I spent some time working on this. It would have been nice to avoid "inventing" this stuff on my own, so I'm going to share it here for others to read.
My purpose was to convert my presentations to flash and then to embed them int my webpages along with nice controls. Something similar to what slideshare.com allows, but:you can do it on your websitethe slides are converted to flash using a nice and small script (which uses openoffice)First of all you need to convert your odp (or ppt or anything openoffice can read) into flash: to achieve this just open the file in openoffice and export as flash (really! openoffice can do that out of the box).
Now you can put your files on the web and serve them. If you are happy you are done :-)
If you would like to embed the flash content into the webpage you need to write something like the following into your webpage:

<div class="slides">
<object
type="application/x-shockwave-flash"
width="600"
height="450"
data="<?php echo $filename; ?>"
id="<?php echo $filename; ?>"
>
<param
name="<?php echo $filename; ?>"
value="<?php echo $filename; ?>"
>
</object>
</div>
Of course <?php echo $filename; ?> must be replaced with your filename if you are not using php :-)
Now your slides are embedded but you can't control how they are played. Let's add some controls. First of all you need some javascript functions:

function RewindSlides(slides)
{
var text = document.getElementById("Page_"+slides);
text.value = 1;
SlideGoto(slides);
}

function SlidePrev(slides)
{
SlideMove(slides, -1);
}

function SlideNext(slides)
{
SlideMove(slides, 1);
}

function SlideMove(slides, movement)
{
var flashSlide=document.getElementById(slides);
var text = document.getElementById("Page_"+slides);
text.value = parseInt(text.value)+movement;
SlideGoto(slides);
}

function SlideGoto(slides)
{
var flashSlide=document.getElementById(slides);
var totalFrames = flashSlide.TotalFrames();

var text = document.getElementById("Page_"+slides);
var n = text.value;

if (n<1)
n=1;
else if (n>totalFrames/2)
n = parseInt(totalFrames/2);
text.value = n;

if (n*2 >= totalFrames - 1 )
flashSlide.GotoFrame(totalFrames - 5);
else if (n<2)>

And then you can just out the following controls into your HTML:

<input type="button" value="Rewind" name="Rewind"
onClick="RewindSlides('<?php echo $filename; ?>');">
<input type="button" value="Prev" name="Prev"
onClick="SlidePrev('<?php echo $filename; ?>');">
<input type="button" value="Next" name="Next"
onClick="SlideNext('<?php echo $filename; ?>');">
<input type="button" value="Goto" name="Goto"
onClick="SlideGoto('<?php echo $filename; ?>');">
<input type="text"
value="1" name="Page_<?php echo $filename; ?>"
id="Page_<?php echo $filename; ?>">


The end result can be shown on my page:


Tuesday, December 09, 2008

After a long time... here it is a New Post

Since Google gave us friend connect, I felt I had to start using it from the very beginning.
I have just invited some friends to join my blog but... the last post was from Summer 2006: I guess they would not be pleased to be invited to read such old info, so I'm writing this very short blog post.

Who knows... maybe I could start blogging if I have enough fun!
The topic for new posts will probably still be KDE4: I just love it.

Monday, September 04, 2006

Phonon-NMM Status after SoC.

Wow. After months of coding together with Marco and Matthias, I could finally see the results of my efforts.
The code is on the KDE4 svn.
I could not add many new features: my main goal has been to make the backend usable in everyday use. I proof tested it to work on corner case events (short media file, multiple files played at the same time, file played to multiple AudioOutput, user pressing commands at random...) and made sure it works in a predictable manner without crashing.
I also added to the backend the ability to play files from protocols NMM does not understand (like smb:// tar:// media:// fish:// and all the ones KIO can read). I did that implementing the Phonon ByteStream protocol as an NMM plugin. That plugin is not Phonon specific: developers can use the NMM::ByteStreamNode plugin to push theyr own data into an NMM flow graph.
Apart from that I did a complete refactor of GraphHnadler, which now has almost the same API (just some bits added) but is internally coded following the Object Oriented paradigm. The immediate benefit of the refactoring is the ability of adding multiple sinks to a a branch. The code is also more readable.
Talking to my mentors has been very instructive: I have learnt theyr code so deeply that I could suggest modification in both Phonon (stop/buffering functionality) and NMM (GraphHandler, progress update).

It has been fun working with NMM and Phonon (kde) developers. NMM and Phonon are both implementations of a very smart idea: I have no doubt those ideas will have success even is the projects are still in a quite early stage of adoption. I plan to go on coding with them.

Sunday, August 13, 2006

Bugs, bugs and ... bugs!

During the last days I did not much progress on implementing new functionality.
My new schedule is to...
1) fix the backend to make ByteStream work
2) allow each branch of GraphHandler to have more sinks connected
3) port fub's gui config app to dbus
4) make kcm work (this involves frontend work as well)

The reason for my slow process have been bugs.
First I had to figure out that the Phonon ByteStream/MediaObject frontend states had problems... the KIO object setup was done only in setUrl()... Matthias fixed it in a minute.
Then I found corner cases where NMM/Phonon/KIO cooperation becomes difficolt: that is when the kio object finishes sending data before phonon-nmm has finished its initialization (happens when the media file is really short). Also this involved both backend and frontend changes.
Then the other day I updated dbus from CVS and... bang!!!! Someone on 8/8/06 has introducd a really nice in configure in. It took an entire afternoon to make dbus work again (I'm not an autotools expert, I had to learn-try-fail-learn_more-...
Then I found a nice bad bug in NMM MPEGDecodeNode. track_size is not initialized and track_duration is computed from it. If you play a live stream (for example an mp3 file streamed from Phonon::Bytestream) track_duration can't be told... a random value was inserted into the CEvent. After fixing it I found that if track_duration is 0 progress events are not emitted; I can't see the reason for this: you can have progress even if you don't know where you are inside the file.
I see from vlagrind output that there are some other uninitialized variblas on which a control statement depends on... but I was not able to fix those jet.

Those were just the things I was able to fix!
I still have some bugs. The big problem working on phonon-nmm is that you have to work on bleeding edge code (kdelibs, KIO, Phonon, NMM -should be the more stable here-, Qt4, dbus) and you have to do a lto of tricks to make them work. I have spend almost a week in the beginning writing a script to set up all the environment vars and daemons (I was inspired by a script sent to me by Matthias).
The hardest problem is that Qt4/KDE4 code confuses debuggers and memory checkers like gdb and valgrind! So you have to fill the code with debug statements and recompile and... well, when you type make in the Qt, NMM, or kdelibs source trees... you'll heat your CPU for quite a lot of time! That is way icecream (icecc) comes in the story: this tool allows you to easily cluster your machines into a renderfarm. It is one of the pieces of code in the world, it saves so many compile time! But... a tiny little bug in the kubuntu package I had made me mad... so I had compile the latest svn version, find another little bug ,report it to the icecream main developer (coolo on #kde4-devel) and wait (minutes really) for the fix.
Back to phonon-nmm my favourite bug is... UNKOWN! Maybe it is more than one bug.
The symptoms are random. Sometimes kdeinit can't unload phonon-nmm because of NMM not releasing the soundcard device. Sometimes in ByteStreamNode I push_back into a list 23 Buffers* and then I iterate on 23 elements... Ah, that is ok, I know... buth the size of the first element is the sum of the others :-)
I'm working on this bug right now. I hope to resolve this, but ATM I really don't know how to understand where it comes from.

I must be crazy anyway. Because...

I'm having fun!!!!!!

Friday, July 14, 2006

Bugs: no progress

During the last days I had problems with compiling kdelibs4. Matthias has updated phonon implementation in kdelibs4_snapshot, so I had to catch up whith that new code and install the new snapshot.
KDE4 will ship with Qt 4.2.x: for this reason the KDE4 svn qt-copy has been updated to the new 4.2.0. This version is now required to install KDE4 libs.
KDE svn hosts a copy of Qt where patches not already accepted by Qt developers are availabele: qt-copy. qt-copy has a patches subdir and an apply_patches script that applies them and keeps track of already applied patches.
Well things changed and the apply_patches script has become buggy: some patches marked as already applied are not applied... booom. I had to figure out what the prbolem was, contacted David, and finally applied a patch to fix that script.
The good news is that (after recompiling Qt, kdelibs & C.o.) a bug that prevented ByteStream from working has vanished! Great! It must have been a cmake cuased bug, it was a nasty bug that made this pointer become 0x0 after a simple member function call... I was going mad figuring out where that bug was coming from and spent quite a lot of time on it! Luckily it is gone now!
My next step will be AudioOutput.
I'm really looking forward to make config-proxy work again using dbus.

Sunday, July 02, 2006

Yay! Some fast progress now!

After resolving the kdelibs problems I started trying to improve the already (somehow) working ByteStream. One of the first things I wanted to do was to reconsider the way time reporting is done in the backend: even if NMM can sent time progrss events, the backend was using an internal timer to do time reporting. Talking to My mentors and to fub (Bernard) they all agreed that a nice thing to do would have been to use the NMM events to signal time progress. Well I was just looking at it and... done. It was indeed quite easy. And I think it could have been done even in an easier way!

In order to do it I:
Moved the callback functions from MediaObject to AbstreactMediaProducer (so they will be usefull in ByteStream too one day)
Added an Phonon::AudioPath::insertInto(NMM::GraphHandler) that inserts the AudioPath's branch into the GraphHandler. This is called from internal_addBranch in Phonon::AbstreactMediaProducer.
Made the Phonon::AudioOutput create a sink Node in the constructor (it will use info from kcm to decide the node type) and enabled setTimeProgress events from that node.
Made Phonon::AudioPath add its Phonon::AudioOutput's sink (already created) Node to the NMM::GraphHandler.

This changes make the backed architecture reflect the NMM::GraphHandler architecture better : Phonon::AudioOutput wraps a sink Node, Phonon::AudioPath wraps a brach in NMM::GraphHandler, and Phonon::AbstreactMediaProducer wraps the wole Phonon::AbstreactMediaProducer.

Thanks to this changes (that enable the sink node to send progrss events) it was easy to attach those events to callbacks in Phonon::AbstreactMediaProducer that report the event to KDE using QT signals.

Wednesday, June 28, 2006

Problems Resolved: Bugs and my understanding of NMM.

Part I kde bug.
During the last 2 weeks I had to fight against a KDE4 (kdelibs) bug: I was no more able to build a proper KDE System Configuration Cache ksycoca. Everything was set up according to the docs, the debug output of kde apps was not spotting any problem, some components were even able to run... but I could not use kcmshell (the KDE control center application and framework).
The problem with ksycoca was triggered by the presence of the /etc/xdg/menus/applications.menu file. That file is installed by the gnome-menus package on kubuntu dapper (the distro I'm using). The effect of the the bug is that kbuildsycoca is no more able to find the proper KDE4 .menu files after processing /etc/xdg/menus/applications.menu.
Finding that out was really difficolt (I'd never been able to do that on my own, Vir and dfaure helped a lot on freenode #phonon and #kde4-devel): first we had to find out that the problem was ksycoca related, then we had to figure out that this problem was caused by the presence of /etc/xdg/menus/applications.menu even if kbuildsycoca does not print a single warning or error when analyzing that file.

Part II: ByteStreamNode properly coded.
My prevoius attempt to write the ByteStreamNode was succesfull in practice, but it was coded without compliance to the NMM architecture (I was not skilled enought).
Thanks to the the help of Marco (my menthor) I finally understood how to pass data to remote running nodes using NMM proxies and interface. NMM is a so powerfull architecture that understanding all of it at a time is hard even if the docs are very usefull and cover most aspect.
Using sample code that Marco sent me I could code a proper NMM::Interface for ByteStreamNode.
The interface is:
module NMM{
interface IByteStreamNode {
void sendBuffer2(in TransferBuffer2 buffer);
int getSize();
int getMaxSize();
};
}

Using ByteStreamNode and its interface IByteStreamNode it is possible to inject arbitrary data from applications into NMM flow graphs. To achieve this the application developer creates the flow graph as described in the NMM documentiation using NMM::ByteStreamNode as the source node and using its interface to send data to the node. Data sent to the node is buffered into a streamqueue from where processBuffer (the "main/core" function of NMM nodes) extracts it later. The application can query the current fill size and maximum allowed size of the internal streamqueue using the interface functions getSize and getMaxSize.

The only cave at for using ByteStreamNode is that the first chunk of data must be passed to the node (using sendBuffer2) before initOutput is called in order to let initOutput to find data mime-type (using libmagic).

The phonon nmm backend uses ByteStreamNode as a fallback when a NMM unsupported protocol is specified in the url to be played. For such urls NMM throws an exception in GraphHandler::stage1 which is catched by Phonon and used to trigger the creation of a Phonon::ByteStream object. That object is responsible for calling GraphHandler::stage1_bs and passing data to the returned IByteStreamNode interface. Another task for Phonon::ByteStream is to suspend and resume the KIO::TransferJob as soon as the ByteStreamNode's internal StreamQueue gets full or empty.

Part III: plans
After all this learning and coding I'm becoming more experienced with both NMM andn Phonon.
I thought I would have been able to proceed faster, but KDE4 beeing not mature and NMM beeing a completely new concept to me really slowed me down since now.

My next steps will be:
  1. Resurrect the config-app
  2. Implement AudioOutputDevice selection (the interface that let users chose which NMM audio output node to use)
  3. VolumeControlNode: a software volume slider node
One idea I would like to implement is a app/user interface that detects other NMM hosts on the network and shows theyr speakers to the user. Using this is interface it would be possible to use a desktop computer and a laptop computer as a 4 speaker system (-almost- anyone has a laptop and a desktop nowdays).