diff options
author | Michele Calgaro <[email protected]> | 2020-06-13 22:45:28 +0900 |
---|---|---|
committer | Michele Calgaro <[email protected]> | 2020-06-13 22:45:28 +0900 |
commit | 5f44f7b187093ef290315b7f8766b540a31de35f (patch) | |
tree | 27ffb7b218199ca04f240c390c52426c65f45dce /src/app/videoWindow.cpp | |
download | codeine-5f44f7b187093ef290315b7f8766b540a31de35f.tar.gz codeine-5f44f7b187093ef290315b7f8766b540a31de35f.zip |
Initial code import from debian snapshot
https://snapshot.debian.org/package/codeine/1.0.1-3.dfsg-3.1/
Signed-off-by: Michele Calgaro <[email protected]>
Diffstat (limited to 'src/app/videoWindow.cpp')
-rw-r--r-- | src/app/videoWindow.cpp | 380 |
1 files changed, 380 insertions, 0 deletions
diff --git a/src/app/videoWindow.cpp b/src/app/videoWindow.cpp new file mode 100644 index 0000000..00f2542 --- /dev/null +++ b/src/app/videoWindow.cpp @@ -0,0 +1,380 @@ +// (C) 2005 Max Howell ([email protected]) +// See COPYING file for licensing information + +#define CODEINE_DEBUG_PREFIX "VideoWindow" + +#include "actions.h" +#include <cmath> //std::log10 +#include <cstdlib> +#include "debug.h" +#include <kapplication.h> //::makeStandardCaption +#include <kconfig.h> +#include <kiconloader.h> +#include <kpopupmenu.h> +#include <kwin.h> +#include "mxcl.library.h" +#include <qcursor.h> +#include <qevent.h> +#include "slider.h" +#include "theStream.h" +#include <X11/Xlib.h> +#include <xine.h> +#include "xineEngine.h" + + +namespace Codeine +{ + namespace X + { + // we get thread locks if we don't cache these values + // (I don't know which ones exactly) + Display *d; + int s, w; + } + + +void +VideoWindow::initVideo() +{ + X::d = XOpenDisplay( std::getenv("DISPLAY") ); + X::s = DefaultScreen( X::d ); + X::w = winId(); + + XLockDisplay( X::d ); + XSelectInput( X::d, X::w, ExposureMask ); + + { + using X::d; using X::s; + + //these are Xlib macros + double w = DisplayWidth( d, s ) * 1000 / DisplayWidthMM( d, s ); + double h = DisplayHeight( d, s ) * 1000 / DisplayHeightMM( d, s ); + + m_displayRatio = w / h; + } + + connect( &m_timer, SIGNAL(timeout()), SLOT(hideCursor()) ); + + XUnlockDisplay( X::d ); +} + +void +VideoWindow::cleanUpVideo() +{ + XCloseDisplay( X::d ); +} + +void* +VideoWindow::x11Visual() const +{ + DEBUG_FUNC_INFO + + x11_visual_t* visual = new x11_visual_t; + + visual->display = X::d; + visual->screen = X::s; + visual->d = winId();//X::w; + visual->dest_size_cb = &VideoWindow::destSizeCallBack; + visual->frame_output_cb = &VideoWindow::frameOutputCallBack; + visual->user_data = (void*)this; + + return visual; +} + +void +VideoWindow::destSizeCallBack( + void* p, int /*video_width*/, int /*video_height*/, + double /*video_aspect*/, int* dest_width, + int* dest_height, double* dest_aspect ) +{ + if( !p ) + return; + + #define vw static_cast<VideoWindow*>(p) + + *dest_width = vw->width(); + *dest_height = vw->height(); + *dest_aspect = vw->m_displayRatio; +} + +void +VideoWindow::frameOutputCallBack( + void* p, int video_width, int video_height, double video_aspect, + int* dest_x, int* dest_y, int* dest_width, int* dest_height, + double* dest_aspect, int* win_x, int* win_y ) +{ + if( !p ) + return; + + *dest_x = 0; + *dest_y = 0 ; + *dest_width = vw->width(); + *dest_height = vw->height(); + *win_x = vw->x(); + *win_y = vw->y(); + *dest_aspect = vw->m_displayRatio; + + // correct size with video aspect + // TODO what's this about? + if( video_aspect >= vw->m_displayRatio ) + video_width = (int) ( (double) (video_width * video_aspect / vw->m_displayRatio + 0.5) ); + else + video_height = (int) ( (double) (video_height * vw->m_displayRatio / video_aspect) + 0.5); + + #undef vw +} + +void +VideoWindow::contextMenuEvent( QContextMenuEvent *e ) +{ + e->accept(); + + KPopupMenu popup; + + if( state() == Engine::Playing ) + popup.insertItem( SmallIconSet("player_pause"), i18n("Pause"), 1 ); + else + action( "play" )->plug( &popup ); + + popup.insertSeparator(); + + if( TheStream::url().protocol() == "dvd" ) + action( "toggle_dvd_menu" )->plug( &popup ), + popup.insertSeparator(); + if( !((KToggleAction*)actionCollection()->action( "fullscreen" ))->isChecked() ) + action( "reset_zoom" )->plug( &popup ); + action( "capture_frame" )->plug( &popup ); + popup.insertSeparator(); + action( "video_settings" )->plug( &popup ); + popup.insertSeparator(); + action( "fullscreen" )->plug( &popup ); + //show zoom information? + + if( e->state() & Qt::MetaButton ) { //only on track end, or for special users + popup.insertSeparator(); + action( "file_quit" )->plug( &popup ); + } + + if( popup.exec( e->globalPos() ) == 1 && state() == Engine::Playing ) + // we check we are still paused as the menu generates a modal event loop + // so anything might have happened in the meantime. + pause(); +} + +bool +VideoWindow::event( QEvent *e ) +{ + //TODO it would perhaps make things more responsive to + // deactivate mouse tracking and use the x11Event() function to transfer mouse move events? + // perhaps even better would be a x11 implementation + + switch( e->type() ) + { + case QEvent::DragEnter: + case QEvent::Drop: + //FIXME why don't we just ignore the event? It should propogate down + return QApplication::sendEvent( qApp->mainWidget(), e ); + + case QEvent::Resize: + if( !TheStream::url().isEmpty() ) { + const QSize defaultSize = TheStream::defaultVideoSize(); + const bool notDefaultSize = width() != defaultSize.width() && height() != defaultSize.height(); + + Codeine::action( "reset_zoom" )->setEnabled( notDefaultSize ); + + //showOSD( i18n("Scale: %1%").arg( size() + } + break; + + case QEvent::Leave: + m_timer.stop(); + break; + + // Xlib.h sucks fucking balls!!!!11!!1! + #undef FocusOut + case QEvent::FocusOut: + // if the user summons some dialog via a shortcut or whatever we need to ensure + // the mouse gets shown, because if it is modal, we won't get mouse events after + // it is shown! This works because we are always the focus widget. + // @see MainWindow::MainWindow where we setFocusProxy() + case QEvent::Enter: + case QEvent::MouseMove: + case QEvent::MouseButtonPress: + unsetCursor(); + if( hasFocus() ) + // see above comment + m_timer.start( CURSOR_HIDE_TIMEOUT, true ); + break; + + case QEvent::MouseButtonDblClick: + Codeine::action( "fullscreen" )->activate(); + break; + + default: ; + } + + if( !m_xine ) + return QWidget::event( e ); + + switch( e->type() ) + { + case QEvent::Close: + stop(); + return false; + + case VideoWindow::ExposeEvent: + //see VideoWindow::x11Event() + + return true; + + // Xlib.h sucks fucking balls!!!!11!!1! + #undef KeyPress + case QEvent::KeyPress: { + if( m_url.protocol() != "dvd" ) + // let MainWindow handle this + return QWidget::event( e ); + + //FIXME left and right keys don't work during DVDs + + int keyCode = XINE_EVENT_INPUT_UP; + + //#define XINE_EVENT_INPUT_UP 110 + //#define XINE_EVENT_INPUT_DOWN 111 + //#define XINE_EVENT_INPUT_LEFT 112 + //#define XINE_EVENT_INPUT_RIGHT 113 + //#define XINE_EVENT_INPUT_SELECT 114 + + switch( static_cast<QKeyEvent*>(e)->key() ) { + case Key_Return: + case Key_Enter: keyCode++; + case Key_Right: keyCode++; + case Key_Left: keyCode++; + case Key_Down: keyCode++; + case Key_Up: + { + //this whole shebang is cheeky as xine doesn't + //guarentee the codes will stay the same + + xine_event_t xineEvent; + + xineEvent.type = keyCode; + xineEvent.data = NULL; + xineEvent.data_length = 0; + + xine_event_send( m_stream, &xineEvent ); + + return true; + } + default: + return false; + } + } + + case QEvent::MouseButtonPress: + + #define mouseEvent static_cast<QMouseEvent*>(e) + + if( mouseEvent->button() != Qt::LeftButton ) + return false; + + mouseEvent->accept(); + + //FALL THROUGH + + case QEvent::MouseMove: + { + x11_rectangle_t x11Rect; + xine_event_t xineEvent; + xine_input_data_t xineInput; + + x11Rect.x = mouseEvent->x(); + x11Rect.y = mouseEvent->y(); + x11Rect.w = 0; + x11Rect.h = 0; + + xine_gui_send_vo_data( m_stream, XINE_GUI_SEND_TRANSLATE_GUI_TO_VIDEO, (void*)&x11Rect ); + + xineEvent.type = e->type() == QEvent::MouseMove ? XINE_EVENT_INPUT_MOUSE_MOVE : XINE_EVENT_INPUT_MOUSE_BUTTON; + xineEvent.data = &xineInput; + xineEvent.data_length = sizeof( xine_input_data_t ); + xineInput.button = 1; //HACK e->type() == QEvent::MouseMove ? 0 : 1; + xineInput.x = x11Rect.x; + xineInput.y = x11Rect.y; + xine_event_send( m_stream, &xineEvent ); + + return e->type() == QEvent::MouseMove ? false : true; + + #undef mouseEvent + } + + case QEvent::Wheel: + { + //TODO seek amount should depend on the length, basically seek at most say 30s, and at least 0.5s + //TODO this is replicated (somewhat) in MainWindow::keyPressEvent + + int pos, time, length; + xine_get_pos_length( m_stream, &pos, &time, &length ); + pos += int(std::log10( (double)length ) * static_cast<QWheelEvent*>(e)->delta()); + + seek( pos > 0 ? (uint)pos : 0 ); + + return true; + } + + default: ; + } + + return QWidget::event( e ); +} + +bool +VideoWindow::x11Event( XEvent *e ) +{ + if( m_stream && e->type == Expose && e->xexpose.count == 0 ) { + xine_gui_send_vo_data( + m_stream, + XINE_GUI_SEND_EXPOSE_EVENT, + e ); + + return true; + } + + return false; +} + +void +VideoWindow::hideCursor() +{ + setCursor( Qt::BlankCursor ); +} + +QSize +VideoWindow::sizeHint() const //virtual +{ + QSize s = TheStream::profile()->readSizeEntry( "Preferred Size" ); + + if( !s.isValid() ) + s = TheStream::defaultVideoSize(); + + if( s.isValid() && !s.isNull() ) + return s; + + return minimumSizeHint(); +} + +QSize +VideoWindow::minimumSizeHint() const //virtual +{ + const int x = fontMetrics().width( "x" ) * 4; + + return QSize( x * 12, x * 4 ); //FIXME +} + +void +VideoWindow::resetZoom() +{ + TheStream::profile()->deleteEntry( "Preferred Size" ); + topLevelWidget()->adjustSize(); +} + +} //namespace Codeine |