/******************************************************************** KWin - the KDE window manager This file is part of the KDE project. Copyright (C) 2006 Lubos Lunak This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . *********************************************************************/ /* This effect allows recording a video from the session. Requires libcaptury: - git clone git://gitorious.org/capseo/mainline.git capseo - you may want to remove 1.10 from AUTOMAKE_OPTIONS in Makefile.am - ./autogen.sh - the usual configure && make && make install procedure (you may want to pass --enable-theora --with-accel=x86 [or amd64]) - git clone git://gitorious.org/libcaptury/mainline.git libcaptury - you may want to remove 1.10 from AUTOMAKE_OPTIONS in Makefile.am - ./autogen.sh - the usual configure && make && make install procedure Video is saved to $HOME/kwin_video.cps, use "cpsrecode -i kwin_video.cps -o - | mplayer -" to play, to create a video use "cpsrecode -c theora -i kwin_video.cps -o screen.ogg" or use mencoder in a similar way as mplayer. */ #include "videorecord.h" #include #include #include #include #include #include #include #include #include #include namespace KWin { KWIN_EFFECT(videorecord, VideoRecordEffect) VideoRecordEffect::VideoRecordEffect() : client(NULL) { KActionCollection* actionCollection = new KActionCollection(this); KAction* a = static_cast< KAction* >(actionCollection->addAction("VideoRecord")); a->setText(i18n("Toggle Video Recording")); a->setGlobalShortcut(KShortcut(Qt::CTRL + Qt::META + Qt::Key_V)); connect(a, SIGNAL(triggered(bool)), this, SLOT(toggleRecording())); area = QRect(0, 0, displayWidth(), displayHeight()); } VideoRecordEffect::~VideoRecordEffect() { stopRecording(); } void VideoRecordEffect::paintScreen(int mask, QRegion region, ScreenPaintData& data) { effects->paintScreen(mask, region, data); if (client != NULL) capture_region = (mask & (PAINT_WINDOW_TRANSFORMED | PAINT_SCREEN_TRANSFORMED)) ? QRect(0, 0, displayWidth(), displayHeight()) : region; } void VideoRecordEffect::postPaintScreen() { effects->postPaintScreen(); if (client != NULL) { #if 1 if (CapturyProcessRegionStart(client) == CAPTURY_SUCCESS) { capture_region &= QRect(0, 0, displayWidth(), displayHeight()); // limit to screen foreach (const QRect & r, capture_region.rects()) { int gly = displayHeight() - r.y() - r.height(); // opengl coords CapturyProcessRegion(client, r.x(), gly, r.width(), r.height()); } CapturyProcessRegionCommit(client); } #else CapturyProcessFrame(client); #endif } } void VideoRecordEffect::startRecording() { if (client != NULL) stopRecording(); bzero(&config, sizeof(config)); config.x = area.x(); config.y = area.y(); config.width = area.width(); config.height = area.height(); config.scale = 0; config.fps = 30; // TODO config.deviceType = CAPTURY_DEVICE_GLX; // TODO config.deviceHandle = display(); config.windowHandle = rootWindow(); // TODO config.cursor = true; client = CapturyOpen(&config); if (client == NULL) { kDebug(1212) << "Video recording init failed"; return; } KConfigGroup conf = EffectsHandler::effectConfig("VideoRecord"); QString videoPath = conf.readEntry("videopath", KGlobalSettings::documentPath()); QString videoName(videoPath + "/kwin_video1.cps"); while (QFile::exists(videoName)) { autoincFilename(videoName); } if (CapturySetOutputFileName(client, QFile::encodeName(videoName).constData()) != CAPTURY_SUCCESS) { kDebug(1212) << "Video recording file open failed"; return; } effects->addRepaintFull(); // trigger reading initial screen contents into buffer kDebug(1212) << "Video recording start"; } void VideoRecordEffect::autoincFilename(QString & name) { // If the name contains a number then increment it QRegExp numSearch("(^|[^\\d])(\\d+)"); // we want to match as far left as possible, and when the number is at the start of the name // Does it have a number? int start = numSearch.lastIndexIn(name); if (start != -1) { // It has a number, increment it start = numSearch.pos(2); // we are only interested in the second group QString numAsStr = numSearch.capturedTexts()[ 2 ]; QString number = QString::number(numAsStr.toInt() + 1); number = number.rightJustified(numAsStr.length(), '0'); name.replace(start, number.length(), number); } } void VideoRecordEffect::stopRecording() { if (client == NULL) return; kDebug(1212) << "Video recording stop"; CapturyClose(client); client = NULL; } void VideoRecordEffect::toggleRecording() { if (client == NULL) startRecording(); else stopRecording(); } } // namespace #include "videorecord.moc"