You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kaffeine/kaffeine/src/player-parts/gstreamer-part/video.cpp

357 lines
7.6 KiB

/*
* video.cpp
*
* Copyright (C) 2006 Christophe Thommeret <hftom@free.fr>
* Copyright (C) 2004-2005 Jürgen Kofler <kaffeine@gmx.net>
*
* heavily based on kiss by Ronald Bultje <rbultje@ronald.bitfreak.net>
*
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <tqpainter.h>
#include <tqtimer.h>
#include <tqcursor.h>
#include <kstatusbar.h>
#include <tdetoolbar.h>
#include <tdemenubar.h>
#include <kdebug.h>
#include <gst/gst.h>
#if GST_CHECK_VERSION(1,0,0)
#include <gst/video/videooverlay.h>
#else
#include <gst/interfaces/xoverlay.h>
#endif
#include "video.h"
#include "video.moc"
VideoWindow::VideoWindow( TQWidget *parent, GstElement *_element )
: TQWidget (parent), m_width(0), m_height(0), m_aspectRatio(AUTO)
{
m_play = NULL;
gst_object_ref( GST_OBJECT (_element) );
m_element = _element;
setPaletteBackgroundColor(TQColor(0,0,0)); //black
setUpdatesEnabled(false);
connect( &m_mouseHideTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT(slotHideMouse()) );
}
void VideoWindow::setPlaybin( GstElement *play )
{
m_play = play;
}
VideoWindow::~VideoWindow()
{
#if GST_CHECK_VERSION(1,0,0)
if ( m_element && GST_IS_VIDEO_OVERLAY(m_element) ) {
gst_video_overlay_set_window_handle( GST_VIDEO_OVERLAY(m_element), 0 );
}
#else
if ( m_element && GST_IS_X_OVERLAY(m_element) ) {
gst_x_overlay_set_xwindow_id( GST_X_OVERLAY(m_element), 0 );
}
#endif
gst_object_unref( GST_OBJECT(m_element) );
kdDebug() << "VideoWindow: destructed" << endl;
}
void VideoWindow::refresh()
{
/* expose overlay */
#if GST_CHECK_VERSION(1,0,0)
if ( m_element && GST_IS_VIDEO_OVERLAY(m_element) ) {
gst_video_overlay_set_window_handle( GST_VIDEO_OVERLAY (m_element), winId() );
gst_video_overlay_expose( GST_VIDEO_OVERLAY (m_element) );
}
#else
if ( m_element && GST_IS_X_OVERLAY(m_element) ) {
gst_x_overlay_set_xwindow_id( GST_X_OVERLAY (m_element), winId() );
gst_x_overlay_expose( GST_X_OVERLAY (m_element) );
}
#endif
}
void VideoWindow::paintEvent(TQPaintEvent */*event*/)
{
refresh();
}
void VideoWindow::mousePressEvent(TQMouseEvent* mev)
{
if ( mev->button()==Qt::RightButton ) {
emit signalRightClick( mev->globalPos() );
mev->accept();
}
else {
mev->ignore();
}
}
void VideoWindow::newCapsset( const GstCaps *caps )
{
const GstStructure *s;
m_width = 0;
m_height = 0;
s = gst_caps_get_structure(caps, 0);
if (s) {
const GValue *par;
gst_structure_get_int(s, "width", &m_width);
gst_structure_get_int(s, "height", &m_height);
if ( (par = gst_structure_get_value (s, "pixel-aspect-ratio")) ) {
int num = gst_value_get_fraction_numerator(par),
den = gst_value_get_fraction_denominator(par);
if (num > den)
m_width = (int) ((float) num * m_width / den);
else
m_height = (int) ((float) den * m_height / num);
}
}
TQSize frame = getFrameSize();
correctByAspectRatio( frame );
emit signalNewFrameSize( frame );
//set correct geometry
setGeometry();
}
void VideoWindow::newState()
{
if ( !m_play )
return;
const GList *list = NULL;
g_object_get( G_OBJECT(m_play), "stream-info", &list, NULL );
for ( ; list != NULL; list = list->next ) {
GObject *info = (GObject *)list->data;
gint type;
GParamSpec *pspec;
GEnumValue *val;
GstPad *pad = NULL;
if ( !info )
continue;
g_object_get( info, "type", &type, NULL );
pspec = g_object_class_find_property( G_OBJECT_GET_CLASS (info), "type" );
val = g_enum_get_value( G_PARAM_SPEC_ENUM(pspec)->enum_class, type );
if ( !g_strcasecmp(val->value_nick, "video") ) {
GstCaps *caps;
g_object_get( info, "object", &pad, NULL );
if (
#if GST_CHECK_VERSION(1,0,0)
(caps=gst_pad_get_current_caps(pad))
#else
(caps=gst_pad_get_negotiated_caps(pad))
#endif
) {
newCapsset( caps );
gst_caps_unref (caps);
return;
}
}
}
m_width = 0;
m_height = 0;
TQSize frame = getFrameSize();
correctByAspectRatio( frame );
emit signalNewFrameSize( frame );
//set correct geometry
setGeometry();
}
void VideoWindow::setGeometry( int, int, int, int )
{
TQSize frame = getFrameSize();
TQSize window = parentWidget()->size();
int x = 0, y = 0, width = 0, height = 0;
if ( frame.width() == 0 || frame.height() == 0 ) {
TQWidget::setGeometry(0, 0, window.width(), window.height());
return;
}
correctByAspectRatio( frame );
float frameAspect = (float)frame.width() / (float)frame.height();
float windowAspect = (float)window.width() / (float)window.height();
if ( frameAspect >= windowAspect ) {
width = window.width();
height = (int)((float)width / frameAspect);
y = (window.height() - height) / 2;
}
else {
height = window.height();
width = (int)((float)height * frameAspect);
x = (window.width() - width) / 2;
}
//kdDebug() << "VideoWindow::setGeometry: " << x << " : " << y << " : " << width << " : " << height << endl;
TQWidget::setGeometry( x, y, width, height );
}
void VideoWindow::setGeometry()
{
setGeometry(0, 0, 0, 0);
}
void VideoWindow::correctByAspectRatio( TQSize& frame )
{
float factor = 0;
switch ( m_aspectRatio ) {
case AUTO: return;
case FOURBYTHREE: factor = 4.0 / 3.0; break;
case ANAMORPHIC: factor = 16.0 / 9.0; break;
case DVB: factor = 2.11; break;
case SQUARE: factor = 1.0; break;
}
float frameAspect = (float)frame.width() / (float)frame.height();
factor = factor / frameAspect;
if ( factor > 1.0 )
frame.setWidth((int)((float)frame.width() * factor));
else
frame.setHeight((int)((float)frame.height() / factor));
}
void VideoWindow::slotAspectRatioAuto()
{
m_aspectRatio = AUTO;
TQSize frame = getFrameSize();
correctByAspectRatio( frame );
emit signalNewFrameSize( frame );
setGeometry();
}
void VideoWindow::slotAspectRatio4_3()
{
m_aspectRatio = FOURBYTHREE;
TQSize frame = getFrameSize();
correctByAspectRatio( frame );
emit signalNewFrameSize( frame );
setGeometry();
}
void VideoWindow::slotAspectRatioAnamorphic()
{
m_aspectRatio = ANAMORPHIC;
TQSize frame = getFrameSize();
correctByAspectRatio( frame );
emit signalNewFrameSize( frame );
setGeometry();
}
void VideoWindow::slotAspectRatioDVB()
{
m_aspectRatio = DVB;
TQSize frame = getFrameSize();
correctByAspectRatio( frame );
emit signalNewFrameSize( frame );
setGeometry();
}
void VideoWindow::slotAspectRatioSquare()
{
m_aspectRatio = SQUARE;
TQSize frame = getFrameSize();
correctByAspectRatio( frame );
emit signalNewFrameSize( frame );
setGeometry();
}
/******** mouse cursor hiding on fullscreen ****/
void VideoWindow::startMouseHideTimer()
{
m_mouseHideTimer.start( 5000 );
setMouseTracking( true );
}
void VideoWindow::stopMouseHideTimer()
{
m_mouseHideTimer.stop();
setMouseTracking( false );
setCursor( TQCursor(TQt::ArrowCursor) );
}
void VideoWindow::slotHideMouse()
{
setCursor( TQCursor(TQt::BlankCursor) );
}
void VideoWindow::mouseMoveEvent( TQMouseEvent *mev )
{
if ( cursor().shape() == TQt::BlankCursor )
setCursor( TQCursor(TQt::ArrowCursor) );
mev->ignore();
}