summaryrefslogtreecommitdiffstats
path: root/avmedia/source
diff options
context:
space:
mode:
Diffstat (limited to 'avmedia/source')
-rw-r--r--avmedia/source/framework/MediaControlBase.cxx77
-rw-r--r--avmedia/source/framework/mediacontrol.cxx17
-rw-r--r--avmedia/source/framework/mediaitem.cxx162
-rw-r--r--avmedia/source/framework/mediaplayer.cxx1
-rw-r--r--avmedia/source/framework/soundhandler.cxx12
-rw-r--r--avmedia/source/gstreamer/gstframegrabber.cxx21
-rw-r--r--avmedia/source/gstreamer/gstmanager.cxx2
-rw-r--r--avmedia/source/gstreamer/gstplayer.cxx99
-rw-r--r--avmedia/source/gstreamer/gstplayer.hxx1
-rw-r--r--avmedia/source/gstreamer/gstwindow.cxx5
-rw-r--r--avmedia/source/gstreamer/gstwindow.hxx2
-rw-r--r--avmedia/source/gtk/avmediagtk.component16
-rw-r--r--avmedia/source/gtk/gstwindow.cxx12
-rw-r--r--avmedia/source/gtk/gtkmanager.cxx58
-rw-r--r--avmedia/source/gtk/gtkmanager.hxx34
-rw-r--r--avmedia/source/gtk/gtkplayer.cxx469
-rw-r--r--avmedia/source/gtk/gtkplayer.hxx89
-rw-r--r--avmedia/source/inc/mediamisc.hxx6
-rw-r--r--avmedia/source/viewer/mediawindow.cxx161
-rw-r--r--avmedia/source/viewer/mediawindow_impl.cxx35
-rw-r--r--avmedia/source/viewer/mediawindow_impl.hxx1
-rw-r--r--avmedia/source/win/framegrabber.cxx14
-rw-r--r--avmedia/source/win/player.cxx4
-rw-r--r--avmedia/source/win/window.cxx89
-rw-r--r--avmedia/source/win/window.hxx13
25 files changed, 1122 insertions, 278 deletions
diff --git a/avmedia/source/framework/MediaControlBase.cxx b/avmedia/source/framework/MediaControlBase.cxx
index c572bed7d0e6..fb8f91066b67 100644
--- a/avmedia/source/framework/MediaControlBase.cxx
+++ b/avmedia/source/framework/MediaControlBase.cxx
@@ -20,14 +20,15 @@
#include <avmedia/mediaplayer.hxx>
#include <avmedia/mediaitem.hxx>
#include <tools/time.hxx>
+#include <tools/duration.hxx>
#include <unotools/localedatawrapper.hxx>
#include <strings.hrc>
#include <helpids.h>
#include <mediamisc.hxx>
constexpr sal_Int32 AVMEDIA_DB_RANGE = -40;
-#define AVMEDIA_LINEINCREMENT 1.0
-#define AVMEDIA_PAGEINCREMENT 10.0
+constexpr double AVMEDIA_LINEINCREMENT = 1.0;
+constexpr double AVMEDIA_PAGEINCREMENT = 10.0;
namespace avmedia {
@@ -46,9 +47,11 @@ void MediaControlBase::UpdateTimeField( MediaItem const & aMediaItem, double fTi
SvtSysLocale aSysLocale;
const LocaleDataWrapper& rLocaleData = aSysLocale.GetLocaleData();
- aTimeString += rLocaleData.getDuration( tools::Time( 0, 0, static_cast< sal_uInt32 >( floor( fTime ) ) ) ) +
+ aTimeString += rLocaleData.getDuration(
+ tools::Duration( 0, 0, 0, static_cast<sal_uInt32>( floor( fTime )), 0)) +
" / " +
- rLocaleData.getDuration( tools::Time( 0, 0, static_cast< sal_uInt32 >( floor( aMediaItem.getDuration() ) )) );
+ rLocaleData.getDuration(
+ tools::Duration( 0, 0, 0, static_cast<sal_uInt32>( floor( aMediaItem.getDuration())), 0));
if( mxTimeEdit->get_text() != aTimeString )
mxTimeEdit->set_text( aTimeString );
@@ -104,15 +107,10 @@ void MediaControlBase::UpdateTimeSlider( MediaItem const & aMediaItem )
void MediaControlBase::InitializeWidgets()
{
mxPlayToolBox->set_item_help_id("play", HID_AVMEDIA_TOOLBOXITEM_PLAY);
- mxPlayToolBox->set_item_label("play", AvmResId(AVMEDIA_STR_PLAY));
mxPlayToolBox->set_item_help_id("pause", HID_AVMEDIA_TOOLBOXITEM_PAUSE);
- mxPlayToolBox->set_item_label("pause", AvmResId(AVMEDIA_STR_PAUSE));
mxPlayToolBox->set_item_help_id("stop", HID_AVMEDIA_TOOLBOXITEM_STOP);
- mxPlayToolBox->set_item_label("stop", AvmResId(AVMEDIA_STR_STOP));
mxPlayToolBox->set_item_help_id("loop", HID_AVMEDIA_TOOLBOXITEM_LOOP);
- mxPlayToolBox->set_item_label("loop", AvmResId(AVMEDIA_STR_LOOP));
mxMuteToolBox->set_item_help_id("mute", HID_AVMEDIA_TOOLBOXITEM_MUTE);
- mxMuteToolBox->set_item_label("mute", AvmResId(AVMEDIA_STR_MUTE));
mxZoomListBox->append(OUString::number(AVMEDIA_ZOOMLEVEL_50), AvmResId( AVMEDIA_STR_ZOOM_50 ));
mxZoomListBox->append(OUString::number(AVMEDIA_ZOOMLEVEL_100), AvmResId( AVMEDIA_STR_ZOOM_100 ));
@@ -133,6 +131,28 @@ void MediaControlBase::InitializeWidgets()
mxTimeSlider->set_tooltip_text( AvmResId( AVMEDIA_STR_POSITION ));
}
+void MediaControlBase::UpdatePlayState(const MediaItem& rMediaItem)
+{
+ if (rMediaItem.getState() == MediaState::Play)
+ {
+ mxPlayToolBox->set_item_active("play", true);
+ mxPlayToolBox->set_item_active("pause", false);
+ mxPlayToolBox->set_item_active("stop", false);
+ }
+ else if( rMediaItem.getState() == MediaState::Pause )
+ {
+ mxPlayToolBox->set_item_active("play", false);
+ mxPlayToolBox->set_item_active("pause", true);
+ mxPlayToolBox->set_item_active("stop", false);
+ }
+ else
+ {
+ mxPlayToolBox->set_item_active("play", false);
+ mxPlayToolBox->set_item_active("pause", false);
+ mxPlayToolBox->set_item_active("stop", true);
+ }
+}
+
void MediaControlBase::UpdateToolBoxes(const MediaItem& rMediaItem)
{
const bool bValidURL = !rMediaItem.getURL().isEmpty();
@@ -150,24 +170,7 @@ void MediaControlBase::UpdateToolBoxes(const MediaItem& rMediaItem)
{
mxPlayToolBox->set_sensitive(true);
mxMuteToolBox->set_sensitive(true);
- if( rMediaItem.getState() == MediaState::Play )
- {
- mxPlayToolBox->set_item_active("play", true);
- mxPlayToolBox->set_item_active("pause", false);
- mxPlayToolBox->set_item_active("stop", false);
- }
- else if( rMediaItem.getState() == MediaState::Pause )
- {
- mxPlayToolBox->set_item_active("play", false);
- mxPlayToolBox->set_item_active("pause", true);
- mxPlayToolBox->set_item_active("stop", false);
- }
- else
- {
- mxPlayToolBox->set_item_active("play", false);
- mxPlayToolBox->set_item_active("pause", false);
- mxPlayToolBox->set_item_active("stop", true);
- }
+ UpdatePlayState(rMediaItem);
mxPlayToolBox->set_item_active("loop", rMediaItem.isLoop());
mxMuteToolBox->set_item_active("mute", rMediaItem.isMute());
if (!mbCurrentlySettingZoom)
@@ -209,16 +212,16 @@ void MediaControlBase::UpdateToolBoxes(const MediaItem& rMediaItem)
}
}
-void MediaControlBase::SelectPlayToolBoxItem( MediaItem& aExecItem, MediaItem const & aItem, std::string_view rId)
+void MediaControlBase::SelectPlayToolBoxItem( MediaItem& aExecItem, MediaItem const & aItem, std::u16string_view rId)
{
- if (rId == "apply")
+ if (rId == u"apply")
{
MediaFloater* pFloater = avmedia::getMediaFloater();
if( pFloater )
pFloater->dispatchCurrentURL();
}
- else if (rId == "play")
+ else if (rId == u"play")
{
aExecItem.setState( MediaState::Play );
@@ -226,21 +229,27 @@ void MediaControlBase::SelectPlayToolBoxItem( MediaItem& aExecItem, MediaItem co
aExecItem.setTime( 0.0 );
else
aExecItem.setTime( aItem.getTime() );
+
+ UpdatePlayState(aExecItem);
}
- else if (rId == "pause")
+ else if (rId == u"pause")
{
aExecItem.setState( MediaState::Pause );
+
+ UpdatePlayState(aExecItem);
}
- else if (rId == "stop")
+ else if (rId == u"stop")
{
aExecItem.setState( MediaState::Stop );
aExecItem.setTime( 0.0 );
+
+ UpdatePlayState(aExecItem);
}
- else if (rId == "mute")
+ else if (rId == u"mute")
{
aExecItem.setMute( mxMuteToolBox->get_item_active("mute") );
}
- else if (rId == "loop")
+ else if (rId == u"loop")
{
aExecItem.setLoop( mxPlayToolBox->get_item_active("loop") );
}
diff --git a/avmedia/source/framework/mediacontrol.cxx b/avmedia/source/framework/mediacontrol.cxx
index 55286145bb39..a9c33ff45455 100644
--- a/avmedia/source/framework/mediacontrol.cxx
+++ b/avmedia/source/framework/mediacontrol.cxx
@@ -39,8 +39,7 @@ MediaControl::MediaControl( vcl::Window* pParent, MediaControlStyle eControlStyl
maChangeTimeIdle( "avmedia MediaControl Change Time Idle" ),
maItem( 0, AVMediaSetMask::ALL ),
mbLocked( false ),
- meControlStyle( eControlStyle ),
- mfTime(0.0)
+ meControlStyle( eControlStyle )
{
mxPlayToolBox = m_xBuilder->weld_toolbar("playtoolbox");
mxTimeSlider = m_xBuilder->weld_scale("timeslider");
@@ -50,8 +49,6 @@ MediaControl::MediaControl( vcl::Window* pParent, MediaControlStyle eControlStyl
mxTimeEdit = m_xBuilder->weld_entry("timeedit");
mxMediaPath = m_xBuilder->weld_label("url");
- // TODO SetParentClipMode( ParentClipMode::NoClip );
-
InitializeWidgets();
mxPlayToolBox->connect_clicked( LINK( this, MediaControl, implSelectHdl ) );
@@ -89,9 +86,7 @@ void MediaControl::InitializeWidgets()
if( meControlStyle != MediaControlStyle::SingleLine )
{
mxPlayToolBox->set_item_help_id("open", HID_AVMEDIA_TOOLBOXITEM_OPEN);
- mxPlayToolBox->set_item_label("open", AvmResId(AVMEDIA_STR_OPEN));
mxPlayToolBox->set_item_help_id("apply", HID_AVMEDIA_TOOLBOXITEM_INSERT);
- mxPlayToolBox->set_item_label("apply", AvmResId(AVMEDIA_STR_INSERT));
}
avmedia::MediaControlBase::InitializeWidgets();
}
@@ -116,11 +111,11 @@ void MediaControl::UpdateURLField(MediaItem const & tempItem)
void MediaControl::setState( const MediaItem& rItem )
{
- double fTime = rItem.getTime();
- if( !mbLocked && fTime != mfTime)
+ if (mbLocked)
+ return;
+ bool bChanged = maItem.merge(rItem);
+ if (bChanged)
{
- mfTime = fTime;
- maItem.merge( rItem );
if( rItem.getURL().isEmpty() && meControlStyle == MediaControlStyle::SingleLine )
mxPlayToolBox->set_sensitive(false);
UpdateToolBoxes( maItem );
@@ -161,7 +156,7 @@ IMPL_LINK( MediaControl, implVolumeHdl, weld::Scale&, rSlider, void )
update();
}
-IMPL_LINK( MediaControl, implSelectHdl, const OString&, rIdent, void )
+IMPL_LINK( MediaControl, implSelectHdl, const OUString&, rIdent, void )
{
MediaItem aExecItem;
if (rIdent == "open")
diff --git a/avmedia/source/framework/mediaitem.cxx b/avmedia/source/framework/mediaitem.cxx
index 127ad8af243f..320a24bc9bfe 100644
--- a/avmedia/source/framework/mediaitem.cxx
+++ b/avmedia/source/framework/mediaitem.cxx
@@ -30,16 +30,18 @@
#include <com/sun/star/uri/UriReferenceFactory.hpp>
#include <com/sun/star/uri/XUriReference.hpp>
#include <com/sun/star/uri/XUriReferenceFactory.hpp>
+#include <com/sun/star/text/GraphicCrop.hpp>
#include <sal/log.hxx>
#include <ucbhelper/content.hxx>
+#include <comphelper/mediamimetype.hxx>
#include <comphelper/processfactory.hxx>
#include <comphelper/storagehelper.hxx>
#include <mediamisc.hxx>
#include <osl/file.hxx>
-#include <tools/diagnose_ex.h>
+#include <comphelper/diagnose_ex.hxx>
#include <vcl/graph.hxx>
using namespace ::com::sun::star;
@@ -64,6 +66,7 @@ struct MediaItem::Impl
bool m_bMute;
css::media::ZoomLevel m_eZoom;
Graphic m_aGraphic;
+ text::GraphicCrop m_aCrop;
explicit Impl(AVMediaSetMask nMaskSet)
: m_nMaskSet( nMaskSet )
@@ -107,6 +110,7 @@ bool MediaItem::operator==( const SfxPoolItem& rItem ) const
&& m_pImpl->m_Referer == rOther.m_pImpl->m_Referer
&& m_pImpl->m_sMimeType == rOther.m_pImpl->m_sMimeType
&& m_pImpl->m_aGraphic == rOther.m_pImpl->m_aGraphic
+ && m_pImpl->m_aCrop == rOther.m_pImpl->m_aCrop
&& m_pImpl->m_eState == rOther.m_pImpl->m_eState
&& m_pImpl->m_fDuration == rOther.m_pImpl->m_fDuration
&& m_pImpl->m_fTime == rOther.m_pImpl->m_fTime
@@ -178,187 +182,216 @@ bool MediaItem::PutValue( const css::uno::Any& rVal, sal_uInt8 )
return bRet;
}
-
-void MediaItem::merge( const MediaItem& rMediaItem )
+bool MediaItem::merge(const MediaItem& rMediaItem)
{
+ bool bChanged = false;
+
const AVMediaSetMask nMaskSet = rMediaItem.getMaskSet();
if( AVMediaSetMask::URL & nMaskSet )
- setURL( rMediaItem.getURL(), rMediaItem.getTempURL(), rMediaItem.getReferer() );
+ bChanged |= setURL(rMediaItem.getURL(), rMediaItem.getTempURL(), rMediaItem.getReferer());
if( AVMediaSetMask::MIME_TYPE & nMaskSet )
- setMimeType( rMediaItem.getMimeType() );
+ bChanged |= setMimeType(rMediaItem.getMimeType());
if (nMaskSet & AVMediaSetMask::GRAPHIC)
- setGraphic(rMediaItem.getGraphic());
+ bChanged |= setGraphic(rMediaItem.getGraphic());
+
+ if (nMaskSet & AVMediaSetMask::CROP)
+ bChanged |= setCrop(rMediaItem.getCrop());
if( AVMediaSetMask::STATE & nMaskSet )
- setState( rMediaItem.getState() );
+ bChanged |= setState( rMediaItem.getState() );
if( AVMediaSetMask::DURATION & nMaskSet )
- setDuration( rMediaItem.getDuration() );
+ bChanged |= setDuration(rMediaItem.getDuration());
if( AVMediaSetMask::TIME & nMaskSet )
- setTime( rMediaItem.getTime() );
+ bChanged |= setTime(rMediaItem.getTime());
if( AVMediaSetMask::LOOP & nMaskSet )
- setLoop( rMediaItem.isLoop() );
+ bChanged |= setLoop(rMediaItem.isLoop());
if( AVMediaSetMask::MUTE & nMaskSet )
- setMute( rMediaItem.isMute() );
+ bChanged |= setMute(rMediaItem.isMute());
if( AVMediaSetMask::VOLUMEDB & nMaskSet )
- setVolumeDB( rMediaItem.getVolumeDB() );
+ bChanged |= setVolumeDB(rMediaItem.getVolumeDB());
if( AVMediaSetMask::ZOOM & nMaskSet )
- setZoom( rMediaItem.getZoom() );
-}
+ bChanged |= setZoom(rMediaItem.getZoom());
+ return bChanged;
+}
AVMediaSetMask MediaItem::getMaskSet() const
{
return m_pImpl->m_nMaskSet;
}
-
-void MediaItem::setURL( const OUString& rURL, const OUString& rTempURL, const OUString& rReferer )
+bool MediaItem::setURL(const OUString& rURL, const OUString& rTempURL, const OUString& rReferer)
{
m_pImpl->m_nMaskSet |= AVMediaSetMask::URL;
- m_pImpl->m_URL = rURL;
- m_pImpl->m_TempFileURL = rTempURL;
- m_pImpl->m_Referer = rReferer;
+ bool bChanged = rURL != m_pImpl->m_URL || rTempURL != m_pImpl->m_TempFileURL || rReferer != m_pImpl->m_Referer;
+ if (bChanged)
+ {
+ m_pImpl->m_URL = rURL;
+ m_pImpl->m_TempFileURL = rTempURL;
+ m_pImpl->m_Referer = rReferer;
+ setMimeType(::comphelper::GuessMediaMimeType(GetFilename(rURL)));
+ }
+ return bChanged;
}
-
const OUString& MediaItem::getURL() const
{
return m_pImpl->m_URL;
}
-
const OUString& MediaItem::getTempURL() const
{
return m_pImpl->m_TempFileURL;
}
-
const OUString& MediaItem::getReferer() const
{
return m_pImpl->m_Referer;
}
-
-void MediaItem::setMimeType( const OUString& rMimeType )
+bool MediaItem::setMimeType(const OUString& rMimeType)
{
m_pImpl->m_nMaskSet |= AVMediaSetMask::MIME_TYPE;
- m_pImpl->m_sMimeType = rMimeType;
+ bool bChanged = rMimeType != m_pImpl->m_sMimeType;
+ if (bChanged)
+ m_pImpl->m_sMimeType = rMimeType;
+ return bChanged;
}
-
OUString MediaItem::getMimeType() const
{
return !m_pImpl->m_sMimeType.isEmpty() ? m_pImpl->m_sMimeType : AVMEDIA_MIMETYPE_COMMON;
}
-void MediaItem::setGraphic(const Graphic& rGraphic)
+bool MediaItem::setGraphic(const Graphic& rGraphic)
{
m_pImpl->m_nMaskSet |= AVMediaSetMask::GRAPHIC;
- m_pImpl->m_aGraphic = rGraphic;
+ bool bChanged = rGraphic != m_pImpl->m_aGraphic;
+ if (bChanged)
+ m_pImpl->m_aGraphic = rGraphic;
+ return bChanged;
}
const Graphic & MediaItem::getGraphic() const { return m_pImpl->m_aGraphic; }
-void MediaItem::setState( MediaState eState )
+bool MediaItem::setCrop(const text::GraphicCrop& rCrop)
{
- m_pImpl->m_eState = eState;
- m_pImpl->m_nMaskSet |= AVMediaSetMask::STATE;
+ m_pImpl->m_nMaskSet |= AVMediaSetMask::CROP;
+ bool bChanged = rCrop != m_pImpl->m_aCrop;
+ if (bChanged)
+ m_pImpl->m_aCrop = rCrop;
+ return bChanged;
}
+const text::GraphicCrop& MediaItem::getCrop() const { return m_pImpl->m_aCrop; }
+
+bool MediaItem::setState(MediaState eState)
+{
+ m_pImpl->m_nMaskSet |= AVMediaSetMask::STATE;
+ bool bChanged = eState != m_pImpl->m_eState;
+ if (bChanged)
+ m_pImpl->m_eState = eState;
+ return bChanged;
+}
MediaState MediaItem::getState() const
{
return m_pImpl->m_eState;
}
-
-void MediaItem::setDuration( double fDuration )
+bool MediaItem::setDuration(double fDuration)
{
- m_pImpl->m_fDuration = fDuration;
m_pImpl->m_nMaskSet |= AVMediaSetMask::DURATION;
+ bool bChanged = fDuration != m_pImpl->m_fDuration;
+ if (bChanged)
+ m_pImpl->m_fDuration = fDuration;
+ return bChanged;
}
-
double MediaItem::getDuration() const
{
return m_pImpl->m_fDuration;
}
-
-void MediaItem::setTime( double fTime )
+bool MediaItem::setTime(double fTime)
{
- m_pImpl->m_fTime = fTime;
m_pImpl->m_nMaskSet |= AVMediaSetMask::TIME;
+ bool bChanged = fTime != m_pImpl->m_fTime;
+ if (bChanged)
+ m_pImpl->m_fTime = fTime;
+ return bChanged;
}
-
double MediaItem::getTime() const
{
return m_pImpl->m_fTime;
}
-
-void MediaItem::setLoop( bool bLoop )
+bool MediaItem::setLoop(bool bLoop)
{
- m_pImpl->m_bLoop = bLoop;
m_pImpl->m_nMaskSet |= AVMediaSetMask::LOOP;
+ bool bChanged = bLoop != m_pImpl->m_bLoop;
+ if (bChanged)
+ m_pImpl->m_bLoop = bLoop;
+ return bChanged;
}
-
bool MediaItem::isLoop() const
{
return m_pImpl->m_bLoop;
}
-
-void MediaItem::setMute( bool bMute )
+bool MediaItem::setMute(bool bMute)
{
- m_pImpl->m_bMute = bMute;
m_pImpl->m_nMaskSet |= AVMediaSetMask::MUTE;
+ bool bChanged = bMute != m_pImpl->m_bMute;
+ if (bChanged)
+ m_pImpl->m_bMute = bMute;
+ return bChanged;
}
-
bool MediaItem::isMute() const
{
return m_pImpl->m_bMute;
}
-
-void MediaItem::setVolumeDB( sal_Int16 nDB )
+bool MediaItem::setVolumeDB(sal_Int16 nDB)
{
- m_pImpl->m_nVolumeDB = nDB;
m_pImpl->m_nMaskSet |= AVMediaSetMask::VOLUMEDB;
+ bool bChanged = nDB != m_pImpl->m_nVolumeDB;
+ if (bChanged)
+ m_pImpl->m_nVolumeDB = nDB;
+ return bChanged;
}
-
sal_Int16 MediaItem::getVolumeDB() const
{
return m_pImpl->m_nVolumeDB;
}
-
-void MediaItem::setZoom( css::media::ZoomLevel eZoom )
+bool MediaItem::setZoom(css::media::ZoomLevel eZoom)
{
- m_pImpl->m_eZoom = eZoom;
m_pImpl->m_nMaskSet |= AVMediaSetMask::ZOOM;
+ bool bChanged = eZoom != m_pImpl->m_eZoom;
+ if (bChanged)
+ m_pImpl->m_eZoom = eZoom;
+ return bChanged;
}
-
css::media::ZoomLevel MediaItem::getZoom() const
{
return m_pImpl->m_eZoom;
}
-
OUString GetFilename(OUString const& rSourceURL)
{
uno::Reference<uri::XUriReferenceFactory> const xUriFactory(
@@ -392,13 +425,13 @@ CreateStream(uno::Reference<embed::XStorage> const& xStorage,
if (xStorage->hasByName(filename))
{
- OUString basename;
- OUString suffix;
+ std::u16string_view basename;
+ std::u16string_view suffix;
sal_Int32 const nIndex(rFilename.lastIndexOf('.'));
if (0 < nIndex)
{
- basename = rFilename.copy(0, nIndex);
- suffix = rFilename.copy(nIndex);
+ basename = rFilename.subView(0, nIndex);
+ suffix = rFilename.subView(nIndex);
}
sal_Int32 count(0); // sigh... try to generate non-existent name
do
@@ -416,10 +449,9 @@ CreateStream(uno::Reference<embed::XStorage> const& xStorage,
uno::Reference< beans::XPropertySet > const xStreamProps(xStream,
uno::UNO_QUERY);
if (xStreamProps.is()) { // this is NOT supported in FileSystemStorage
- xStreamProps->setPropertyValue("MediaType", uno::Any(OUString(
- //FIXME how to detect real media type?
- //but currently xmloff has this one hardcoded anyway...
- "application/vnd.sun.star.media")));
+ OUString const guessed(::comphelper::GuessMediaMimeType(filename));
+ xStreamProps->setPropertyValue("MediaType",
+ uno::Any(guessed.isEmpty() ? AVMEDIA_MIMETYPE_COMMON : guessed));
xStreamProps->setPropertyValue( // turn off compression
"Compressed", uno::Any(false));
}
@@ -437,7 +469,7 @@ bool EmbedMedia(uno::Reference<frame::XModel> const& xModel,
uno::Reference<embed::XStorage> const xStorage(
xSBD->getDocumentStorage(), uno::UNO_SET_THROW);
- OUString const media("Media");
+ static constexpr OUString media(u"Media"_ustr);
uno::Reference<embed::XStorage> const xSubStorage(
xStorage->openStorageElement(media, embed::ElementModes::WRITE));
diff --git a/avmedia/source/framework/mediaplayer.cxx b/avmedia/source/framework/mediaplayer.cxx
index 258f23ff4645..b4acad37c741 100644
--- a/avmedia/source/framework/mediaplayer.cxx
+++ b/avmedia/source/framework/mediaplayer.cxx
@@ -25,6 +25,7 @@
#include <helpids.h>
#include <svl/stritem.hxx>
+#include <svl/itemset.hxx>
#include <sfx2/sfxsids.hrc>
#include <sfx2/bindings.hxx>
#include <sfx2/dispatch.hxx>
diff --git a/avmedia/source/framework/soundhandler.cxx b/avmedia/source/framework/soundhandler.cxx
index 7d26c252201b..d3cc8b724d39 100644
--- a/avmedia/source/framework/soundhandler.cxx
+++ b/avmedia/source/framework/soundhandler.cxx
@@ -85,14 +85,12 @@ css::uno::Sequence< css::uno::Type > SAL_CALL SoundHandler::getTypes()
return aTypeCollection.getTypes();
}
-constexpr OUStringLiteral IMPLEMENTATIONNAME_SOUNDHANDLER = u"com.sun.star.comp.framework.SoundHandler";
-
/*===========================================================================================================*/
/* XServiceInfo */
/*===========================================================================================================*/
OUString SAL_CALL SoundHandler::getImplementationName()
{
- return IMPLEMENTATIONNAME_SOUNDHANDLER;
+ return u"com.sun.star.comp.framework.SoundHandler"_ustr;
}
// XServiceInfo
@@ -104,7 +102,7 @@ sal_Bool SAL_CALL SoundHandler::supportsService( const OUString& sServiceName )
// XServiceInfo
css::uno::Sequence< OUString > SAL_CALL SoundHandler::getSupportedServiceNames()
{
- return { "com.sun.star.frame.ContentHandler" };
+ return { u"com.sun.star.frame.ContentHandler"_ustr };
}
/*-************************************************************************************************************
@@ -144,7 +142,7 @@ SoundHandler::~SoundHandler()
@short try to load audio file
@descr This method try to load given audio file by URL and play it. We use vcl/Sound class to do that.
- Playing of sound is asynchron every time.
+ Playing of sound is asynchronous every time.
@attention We must hold us alive by ourself ... because we use async. vcl sound player ... but playing is started
in async interface call "dispatch()" too. And caller forget us immediately. But then our uno ref count
@@ -195,7 +193,7 @@ void SAL_CALL SoundHandler::dispatchWithNotification(const css::util::URL&
m_xPlayer.set( avmedia::MediaWindow::createPlayer( aURL.Complete, aDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_REFERRER, OUString()) ), css::uno::UNO_SET_THROW );
// OK- we can start async playing ...
// Count this request and initialize self-holder against dying by uno ref count ...
- m_xSelfHold.set(static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY);
+ m_xSelfHold.set(getXWeak());
m_xPlayer->start();
m_aUpdateIdle.SetPriority( TaskPriority::HIGH_IDLE );
m_aUpdateIdle.Start();
@@ -255,7 +253,7 @@ OUString SAL_CALL SoundHandler::detect( css::uno::Sequence< css::beans::Property
// I think we can the following ones:
// a) look for given extension of url to map our type decision HARD CODED!!!
// b) return preferred type every time... it's easy :-)
- sTypeName = "wav_Wave_Audio_File";
+ sTypeName = u"wav_Wave_Audio_File"_ustr;
aDescriptor[utl::MediaDescriptor::PROP_TYPENAME] <<= sTypeName;
aDescriptor >> lDescriptor;
}
diff --git a/avmedia/source/gstreamer/gstframegrabber.cxx b/avmedia/source/gstreamer/gstframegrabber.cxx
index ece799d87530..d8f96bd5e568 100644
--- a/avmedia/source/gstreamer/gstframegrabber.cxx
+++ b/avmedia/source/gstreamer/gstframegrabber.cxx
@@ -31,8 +31,7 @@
#include <string>
-constexpr OUStringLiteral AVMEDIA_GST_FRAMEGRABBER_IMPLEMENTATIONNAME = u"com.sun.star.comp.avmedia.FrameGrabber_GStreamer";
-constexpr OUStringLiteral AVMEDIA_GST_FRAMEGRABBER_SERVICENAME = u"com.sun.star.media.FrameGrabber_GStreamer";
+constexpr OUString AVMEDIA_GST_FRAMEGRABBER_SERVICENAME = u"com.sun.star.media.FrameGrabber_GStreamer"_ustr;
using namespace ::com::sun::star;
@@ -50,11 +49,9 @@ void FrameGrabber::disposePipeline()
FrameGrabber::FrameGrabber( std::u16string_view rURL )
{
- gchar *pPipelineStr;
- pPipelineStr = g_strdup_printf(
- "uridecodebin uri=%s ! videoconvert ! videoscale ! appsink "
- "name=sink caps=\"video/x-raw,format=RGB,pixel-aspect-ratio=1/1\"",
- OUStringToOString( rURL, RTL_TEXTENCODING_UTF8 ).getStr() );
+ const char pPipelineStr[] =
+ "uridecodebin name=source ! videoconvert ! videoscale ! appsink "
+ "name=sink caps=\"video/x-raw,format=RGB,pixel-aspect-ratio=1/1\"";
GError *pError = nullptr;
mpPipeline = gst_parse_launch( pPipelineStr, &pError );
@@ -65,6 +62,12 @@ FrameGrabber::FrameGrabber( std::u16string_view rURL )
}
if( mpPipeline ) {
+
+ if (GstElement *pUriDecode = gst_bin_get_by_name(GST_BIN(mpPipeline), "source"))
+ g_object_set(pUriDecode, "uri", OUStringToOString(rURL, RTL_TEXTENCODING_UTF8).getStr(), nullptr);
+ else
+ g_warning("Missing 'source' element in gstreamer pipeline");
+
// pre-roll
switch( gst_element_set_state( mpPipeline, GST_STATE_PAUSED ) ) {
case GST_STATE_CHANGE_FAILURE:
@@ -146,7 +149,7 @@ uno::Reference< graphic::XGraphic > SAL_CALL FrameGrabber::grabFrame( double fMe
pData = aMapInfo.data;
int nStride = GST_ROUND_UP_4( nWidth * 3 );
- BitmapEx aBmp = vcl::bitmap::CreateFromData(pData, nWidth, nHeight, nStride, vcl::PixelFormat::N24_BPP);
+ BitmapEx aBmp = vcl::bitmap::CreateFromData(pData, nWidth, nHeight, nStride, /*nBitsPerPixel*/24);
gst_buffer_unmap( pBuf, &aMapInfo );
xRet = Graphic( aBmp ).GetXGraphic();
@@ -157,7 +160,7 @@ uno::Reference< graphic::XGraphic > SAL_CALL FrameGrabber::grabFrame( double fMe
OUString SAL_CALL FrameGrabber::getImplementationName( )
{
- return AVMEDIA_GST_FRAMEGRABBER_IMPLEMENTATIONNAME;
+ return u"com.sun.star.comp.avmedia.FrameGrabber_GStreamer"_ustr;
}
sal_Bool SAL_CALL FrameGrabber::supportsService( const OUString& ServiceName )
diff --git a/avmedia/source/gstreamer/gstmanager.cxx b/avmedia/source/gstreamer/gstmanager.cxx
index 1803b5880bc1..54d23541676e 100644
--- a/avmedia/source/gstreamer/gstmanager.cxx
+++ b/avmedia/source/gstreamer/gstmanager.cxx
@@ -50,7 +50,7 @@ uno::Reference< media::XPlayer > SAL_CALL Manager::createPlayer( const OUString&
OUString SAL_CALL Manager::getImplementationName( )
{
- return "com.sun.star.comp.avmedia.Manager_GStreamer";
+ return "com.sun.star.comp.media.Manager_GStreamer";
}
sal_Bool SAL_CALL Manager::supportsService( const OUString& ServiceName )
diff --git a/avmedia/source/gstreamer/gstplayer.cxx b/avmedia/source/gstreamer/gstplayer.cxx
index b28be1678207..1a91a689299e 100644
--- a/avmedia/source/gstreamer/gstplayer.cxx
+++ b/avmedia/source/gstreamer/gstplayer.cxx
@@ -30,6 +30,8 @@
#include <vector>
#include <math.h>
+#include <com/sun/star/text/GraphicCrop.hpp>
+
#include <cppuhelper/supportsservice.hxx>
#include <sal/log.hxx>
#include <rtl/string.hxx>
@@ -37,6 +39,8 @@
#include <vcl/svapp.hxx>
#include <vcl/syschild.hxx>
#include <vcl/sysdata.hxx>
+#include <vcl/graph.hxx>
+#include <avmedia/mediaitem.hxx>
#include "gstplayer.hxx"
#include "gstframegrabber.hxx"
@@ -46,8 +50,6 @@
#include <gst/pbutils/missing-plugins.h>
#include <gst/pbutils/pbutils.h>
-constexpr OUStringLiteral AVMEDIA_GST_PLAYER_IMPLEMENTATIONNAME = u"com.sun.star.comp.avmedia.Player_GStreamer";
-constexpr OUStringLiteral AVMEDIA_GST_PLAYER_SERVICENAME = u"com.sun.star.media.Player_GStreamer";
#define AVVERSION "gst 1.0: "
using namespace ::com::sun::star;
@@ -95,7 +97,7 @@ private:
DECL_STATIC_LINK(MissingPluginInstaller, launchUi, void*, void);
- std::mutex mutex_;
+ std::recursive_mutex mutex_;
std::set<OString> reported_;
std::map<OString, std::set<rtl::Reference<Player>>> queued_;
rtl::Reference<MissingPluginInstallerThread> currentThread_;
@@ -242,13 +244,15 @@ IMPL_STATIC_LINK(MissingPluginInstaller, launchUi, void *, p, void)
}
-struct TheMissingPluginInstaller:
- public rtl::Static<MissingPluginInstaller, TheMissingPluginInstaller>
-{};
+MissingPluginInstaller& TheMissingPluginInstaller()
+{
+ static MissingPluginInstaller theInstaller;
+ return theInstaller;
+}
void MissingPluginInstallerThread::execute() {
- MissingPluginInstaller & inst = TheMissingPluginInstaller::get();
+ MissingPluginInstaller & inst = TheMissingPluginInstaller();
for (;;) {
std::vector<OString> details;
{
@@ -285,7 +289,6 @@ Player::Player() :
mbUseGtkSink( false ),
mbFakeVideo (false ),
mnUnmutedVolume( 0 ),
- mbPlayPending ( false ),
mbMuted( false ),
mbLooping( false ),
mbInitialized( false ),
@@ -328,7 +331,7 @@ Player::~Player()
void SAL_CALL Player::disposing()
{
- TheMissingPluginInstaller::get().detach(this);
+ TheMissingPluginInstaller().detach(this);
::osl::MutexGuard aGuard(m_aMutex);
@@ -385,7 +388,6 @@ void Player::processMessage( GstMessage *message )
switch( GST_MESSAGE_TYPE( message ) ) {
case GST_MESSAGE_EOS:
gst_element_set_state( mpPlaybin, GST_STATE_READY );
- mbPlayPending = false;
if (mbLooping)
start();
break;
@@ -401,9 +403,6 @@ void Player::processMessage( GstMessage *message )
{
gst_video_overlay_expose(mpXOverlay);
}
-
- if (mbPlayPending)
- mbPlayPending = ((newstate == GST_STATE_READY) || (newstate == GST_STATE_PAUSED));
}
break;
default:
@@ -447,6 +446,28 @@ GstBusSyncReply Player::processSyncMessage( GstMessage *message )
"error: '" << error->message << "' debug: '"
<< error_debug << "'");
}
+ else if ( GST_MESSAGE_TYPE( message ) == GST_MESSAGE_WARNING )
+ {
+ GError* error;
+ gchar* error_debug;
+
+ gst_message_parse_warning( message, &error, &error_debug );
+ SAL_WARN(
+ "avmedia.gstreamer",
+ "warning: '" << error->message << "' debug: '"
+ << error_debug << "'");
+ }
+ else if ( GST_MESSAGE_TYPE( message ) == GST_MESSAGE_INFO )
+ {
+ GError* error;
+ gchar* error_debug;
+
+ gst_message_parse_info( message, &error, &error_debug );
+ SAL_WARN(
+ "avmedia.gstreamer",
+ "info: '" << error->message << "' debug: '"
+ << error_debug << "'");
+ }
#endif
if (!mbUseGtkSink)
@@ -512,7 +533,7 @@ GstBusSyncReply Player::processSyncMessage( GstMessage *message )
maSizeCondition.set();
}
} else if (gst_is_missing_plugin_message(message)) {
- TheMissingPluginInstaller::get().report(this, message);
+ TheMissingPluginInstaller().report(this, message);
if( mnWidth == 0 ) {
// an error occurred, set condition so that OOo thread doesn't wait for us
maSizeCondition.set();
@@ -532,7 +553,6 @@ void Player::preparePlaybin( std::u16string_view rURL, GstElement *pSink )
if (mpPlaybin != nullptr)
{
gst_element_set_state( mpPlaybin, GST_STATE_NULL );
- mbPlayPending = false;
g_object_unref( mpPlaybin );
}
@@ -597,7 +617,6 @@ bool Player::create( const OUString& rURL )
preparePlaybin( rURL, gst_element_factory_make( "fakesink", nullptr ) );
gst_element_set_state( mpPlaybin, GST_STATE_PAUSED );
- mbPlayPending = false;
bRet = true;
}
@@ -610,7 +629,6 @@ bool Player::create( const OUString& rURL )
return bRet;
}
-
void SAL_CALL Player::start()
{
::osl::MutexGuard aGuard(m_aMutex);
@@ -619,10 +637,10 @@ void SAL_CALL Player::start()
if( mbInitialized && mpPlaybin != nullptr )
{
gst_element_set_state( mpPlaybin, GST_STATE_PLAYING );
- mbPlayPending = true;
}
-}
+ SAL_INFO( "avmedia.gstreamer", AVVERSION "start " << mpPlaybin );
+}
void SAL_CALL Player::stop()
{
@@ -632,29 +650,24 @@ void SAL_CALL Player::stop()
if( mpPlaybin )
gst_element_set_state( mpPlaybin, GST_STATE_PAUSED );
- mbPlayPending = false;
SAL_INFO( "avmedia.gstreamer", AVVERSION "stop " << mpPlaybin );
}
-
sal_Bool SAL_CALL Player::isPlaying()
{
::osl::MutexGuard aGuard(m_aMutex);
- bool bRet = mbPlayPending;
+ bool bRet = false;
- // return whether the pipeline is in PLAYING STATE or not
- if( !mbPlayPending && mbInitialized && mpPlaybin )
+ // return whether the pipeline target is PLAYING STATE or not
+ if (mbInitialized && mpPlaybin)
{
- bRet = GST_STATE( mpPlaybin ) == GST_STATE_PLAYING;
+ bRet = GST_STATE_TARGET(mpPlaybin) == GST_STATE_PLAYING;
}
- SAL_INFO( "avmedia.gstreamer", AVVERSION "isPlaying " << bRet );
-
return bRet;
}
-
double SAL_CALL Player::getDuration()
{
::osl::MutexGuard aGuard(m_aMutex);
@@ -880,6 +893,32 @@ uno::Reference< ::media::XPlayerWindow > SAL_CALL Player::createPlayerWindow( co
g_object_set(G_OBJECT(mpPlaybin), "video-sink", pVideosink, nullptr);
g_object_set(G_OBJECT(mpPlaybin), "force-aspect-ratio", FALSE, nullptr);
+ if ((rArguments.getLength() >= 4) && (rArguments[3] >>= pIntPtr) && pIntPtr)
+ {
+ auto pItem = reinterpret_cast<const avmedia::MediaItem*>(pIntPtr);
+ Graphic aGraphic = pItem->getGraphic();
+ const text::GraphicCrop& rCrop = pItem->getCrop();
+ if (!aGraphic.IsNone() && (rCrop.Bottom > 0 || rCrop.Left > 0 || rCrop.Right > 0 || rCrop.Top > 0))
+ {
+ // The media item has a non-empty cropping set. Try to crop the video accordingly.
+ Size aPref = aGraphic.GetPrefSize();
+ Size aPixel = aGraphic.GetSizePixel();
+ tools::Long nLeft = aPixel.getWidth() * rCrop.Left / aPref.getWidth();
+ tools::Long nTop = aPixel.getHeight() * rCrop.Top / aPref.getHeight();
+ tools::Long nRight = aPixel.getWidth() * rCrop.Right / aPref.getWidth();
+ tools::Long nBottom = aPixel.getHeight() * rCrop.Bottom / aPref.getHeight();
+ GstElement* pVideoFilter = gst_element_factory_make("videocrop", nullptr);
+ if (pVideoFilter)
+ {
+ g_object_set(G_OBJECT(pVideoFilter), "left", nLeft, nullptr);
+ g_object_set(G_OBJECT(pVideoFilter), "top", nTop, nullptr);
+ g_object_set(G_OBJECT(pVideoFilter), "right", nRight, nullptr);
+ g_object_set(G_OBJECT(pVideoFilter), "bottom", nBottom, nullptr);
+ g_object_set(G_OBJECT(mpPlaybin), "video-filter", pVideoFilter, nullptr);
+ }
+ }
+ }
+
if (!mbUseGtkSink)
{
mnWindowID = pEnvData->GetWindowHandle(pParentWindow->ImplGetFrame());
@@ -910,7 +949,7 @@ uno::Reference< media::XFrameGrabber > SAL_CALL Player::createFrameGrabber()
OUString SAL_CALL Player::getImplementationName()
{
- return AVMEDIA_GST_PLAYER_IMPLEMENTATIONNAME;
+ return u"com.sun.star.comp.avmedia.Player_GStreamer"_ustr;
}
@@ -922,7 +961,7 @@ sal_Bool SAL_CALL Player::supportsService( const OUString& ServiceName )
uno::Sequence< OUString > SAL_CALL Player::getSupportedServiceNames()
{
- return { AVMEDIA_GST_PLAYER_SERVICENAME };
+ return { u"com.sun.star.media.Player_GStreamer"_ustr };
}
} // namespace
diff --git a/avmedia/source/gstreamer/gstplayer.hxx b/avmedia/source/gstreamer/gstplayer.hxx
index a82dac3f2b39..2694ac00ce7e 100644
--- a/avmedia/source/gstreamer/gstplayer.hxx
+++ b/avmedia/source/gstreamer/gstplayer.hxx
@@ -86,7 +86,6 @@ private:
bool mbFakeVideo;
gdouble mnUnmutedVolume;
- bool mbPlayPending;
bool mbMuted;
bool mbLooping;
bool mbInitialized;
diff --git a/avmedia/source/gstreamer/gstwindow.cxx b/avmedia/source/gstreamer/gstwindow.cxx
index 5f7958e723c3..2d9aec0418b3 100644
--- a/avmedia/source/gstreamer/gstwindow.cxx
+++ b/avmedia/source/gstreamer/gstwindow.cxx
@@ -22,10 +22,9 @@
#include <cppuhelper/supportsservice.hxx>
#include "gstwindow.hxx"
-#include "gstplayer.hxx"
-constexpr OUStringLiteral AVMEDIA_GST_WINDOW_IMPLEMENTATIONNAME = u"com.sun.star.comp.avmedia.Window_GStreamer";
-constexpr OUStringLiteral AVMEDIA_GST_WINDOW_SERVICENAME = u"com.sun.star.media.Window_GStreamer";
+constexpr OUString AVMEDIA_GST_WINDOW_IMPLEMENTATIONNAME = u"com.sun.star.comp.avmedia.Window_GStreamer"_ustr;
+constexpr OUString AVMEDIA_GST_WINDOW_SERVICENAME = u"com.sun.star.media.Window_GStreamer"_ustr;
using namespace ::com::sun::star;
diff --git a/avmedia/source/gstreamer/gstwindow.hxx b/avmedia/source/gstreamer/gstwindow.hxx
index c9d633d5434f..ff8a7cc91566 100644
--- a/avmedia/source/gstreamer/gstwindow.hxx
+++ b/avmedia/source/gstreamer/gstwindow.hxx
@@ -19,10 +19,10 @@
#pragma once
-#include "gstcommon.hxx"
#include <cppuhelper/implbase.hxx>
#include <cppuhelper/interfacecontainer.h>
+#include <com/sun/star/lang/XServiceInfo.hpp>
#include <com/sun/star/media/XPlayerWindow.hpp>
namespace avmedia::gstreamer {
diff --git a/avmedia/source/gtk/avmediagtk.component b/avmedia/source/gtk/avmediagtk.component
new file mode 100644
index 000000000000..e3930dc9e65d
--- /dev/null
+++ b/avmedia/source/gtk/avmediagtk.component
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+-->
+<component loader="com.sun.star.loader.SharedLibrary" environment="@CPPU_ENV@"
+ xmlns="http://openoffice.org/2010/uno-components">
+ <implementation name="com.sun.star.comp.media.Manager_Gtk"
+ constructor="com_sun_star_comp_media_Manager_Gtk_get_implementation">
+ <service name="com.sun.star.comp.avmedia.Manager_Gtk"/>
+ </implementation>
+</component>
diff --git a/avmedia/source/gtk/gstwindow.cxx b/avmedia/source/gtk/gstwindow.cxx
new file mode 100644
index 000000000000..48c70df98e7d
--- /dev/null
+++ b/avmedia/source/gtk/gstwindow.cxx
@@ -0,0 +1,12 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "../gstreamer/gstwindow.cxx"
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/avmedia/source/gtk/gtkmanager.cxx b/avmedia/source/gtk/gtkmanager.cxx
new file mode 100644
index 000000000000..fe823c1f49ed
--- /dev/null
+++ b/avmedia/source/gtk/gtkmanager.cxx
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <cppuhelper/supportsservice.hxx>
+
+#include "gtkmanager.hxx"
+#include "gtkplayer.hxx"
+
+#include <tools/urlobj.hxx>
+#include <rtl/ref.hxx>
+
+using namespace ::com::sun::star;
+
+namespace avmedia::gtk
+{
+Manager::Manager() {}
+
+Manager::~Manager() {}
+
+uno::Reference<media::XPlayer> SAL_CALL Manager::createPlayer(const OUString& rURL)
+{
+ const INetURLObject aURL(rURL);
+ OUString sMainURL = aURL.GetMainURL(INetURLObject::DecodeMechanism::Unambiguous);
+
+ rtl::Reference<GtkPlayer> xPlayer(new GtkPlayer);
+ if (!xPlayer->create(sMainURL))
+ xPlayer.clear();
+ return xPlayer;
+}
+
+OUString SAL_CALL Manager::getImplementationName() { return "com.sun.star.comp.media.Manager_Gtk"; }
+
+sal_Bool SAL_CALL Manager::supportsService(const OUString& ServiceName)
+{
+ return cppu::supportsService(this, ServiceName);
+}
+
+uno::Sequence<OUString> SAL_CALL Manager::getSupportedServiceNames()
+{
+ return { "com.sun.star.media.Manager" };
+}
+
+} // namespace
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+com_sun_star_comp_media_Manager_Gtk_get_implementation(css::uno::XComponentContext*,
+ css::uno::Sequence<css::uno::Any> const&)
+{
+ return cppu::acquire(new avmedia::gtk::Manager());
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/avmedia/source/gtk/gtkmanager.hxx b/avmedia/source/gtk/gtkmanager.hxx
new file mode 100644
index 000000000000..9cf6d93f5b68
--- /dev/null
+++ b/avmedia/source/gtk/gtkmanager.hxx
@@ -0,0 +1,34 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <cppuhelper/implbase.hxx>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/media/XManager.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+
+namespace avmedia::gtk
+{
+class Manager : public cppu::WeakImplHelper<css::media::XManager, css::lang::XServiceInfo>
+{
+public:
+ explicit Manager();
+ virtual ~Manager() override;
+
+ virtual css::uno::Reference<css::media::XPlayer>
+ SAL_CALL createPlayer(const OUString& aURL) override;
+
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+ virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+};
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/avmedia/source/gtk/gtkplayer.cxx b/avmedia/source/gtk/gtkplayer.cxx
new file mode 100644
index 000000000000..4dca3e202a24
--- /dev/null
+++ b/avmedia/source/gtk/gtkplayer.cxx
@@ -0,0 +1,469 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <sal/config.h>
+
+#include <mutex>
+
+#include <cppuhelper/supportsservice.hxx>
+#include <sal/log.hxx>
+#include <rtl/string.hxx>
+#include <tools/link.hxx>
+#include <vcl/BitmapTools.hxx>
+#include <vcl/graph.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/syschild.hxx>
+#include <vcl/sysdata.hxx>
+#include <vcl/timer.hxx>
+
+#include <gstwindow.hxx>
+#include "gtkplayer.hxx"
+
+#include <gtk/gtk.h>
+
+constexpr OUStringLiteral AVMEDIA_GTK_PLAYER_IMPLEMENTATIONNAME
+ = u"com.sun.star.comp.avmedia.Player_Gtk";
+constexpr OUString AVMEDIA_GTK_PLAYER_SERVICENAME = u"com.sun.star.media.Player_Gtk"_ustr;
+
+using namespace ::com::sun::star;
+
+namespace avmedia::gtk
+{
+GtkPlayer::GtkPlayer()
+ : GtkPlayer_BASE(m_aMutex)
+ , m_lListener(m_aMutex)
+ , m_pStream(nullptr)
+ , m_pVideo(nullptr)
+ , m_nNotifySignalId(0)
+ , m_nInvalidateSizeSignalId(0)
+ , m_nTimeoutId(0)
+ , m_nUnmutedVolume(0)
+{
+}
+
+GtkPlayer::~GtkPlayer() { disposing(); }
+
+static gboolean gtk_media_stream_unref(gpointer user_data)
+{
+ g_object_unref(user_data);
+ return FALSE;
+}
+
+void GtkPlayer::cleanup()
+{
+ if (m_pVideo)
+ {
+ gtk_widget_unparent(m_pVideo);
+ m_pVideo = nullptr;
+ }
+
+ if (m_pStream)
+ {
+ uninstallNotify();
+
+ // shouldn't have to attempt this unref on idle, but with gtk4-4.4.1 I get
+ // intermittent "instance of invalid non-instantiable type '(null)'"
+ // on some mysterious gst dbus callback
+ if (g_main_context_default())
+ g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, gtk_media_stream_unref, m_pStream, nullptr);
+ else
+ g_object_unref(m_pStream);
+ m_pStream = nullptr;
+ }
+}
+
+void SAL_CALL GtkPlayer::disposing()
+{
+ osl::MutexGuard aGuard(m_aMutex);
+
+ stop();
+
+ cleanup();
+}
+
+static void do_notify(GtkPlayer* pThis)
+{
+ rtl::Reference<GtkPlayer> xThis(pThis);
+ xThis->notifyListeners();
+ xThis->uninstallNotify();
+}
+
+static void invalidate_size_cb(GdkPaintable* /*pPaintable*/, GtkPlayer* pThis) { do_notify(pThis); }
+
+static void notify_cb(GtkMediaStream* /*pStream*/, GParamSpec* pspec, GtkPlayer* pThis)
+{
+ if (g_str_equal(pspec->name, "prepared") || g_str_equal(pspec->name, "error"))
+ do_notify(pThis);
+}
+
+static bool timeout_cb(GtkPlayer* pThis)
+{
+ do_notify(pThis);
+ return false;
+}
+
+void GtkPlayer::installNotify()
+{
+ if (m_nNotifySignalId)
+ return;
+ m_nNotifySignalId = g_signal_connect(m_pStream, "notify", G_CALLBACK(notify_cb), this);
+ // notify should be enough, but there is an upstream bug so also try "invalidate-size" and add a timeout for
+ // audio-only case where that won't happen, see: https://gitlab.gnome.org/GNOME/gtk/-/merge_requests/4513
+ m_nInvalidateSizeSignalId
+ = g_signal_connect(m_pStream, "invalidate-size", G_CALLBACK(invalidate_size_cb), this);
+ m_nTimeoutId = g_timeout_add_seconds(10, G_SOURCE_FUNC(timeout_cb), this);
+}
+
+void GtkPlayer::uninstallNotify()
+{
+ if (!m_nNotifySignalId)
+ return;
+ g_signal_handler_disconnect(m_pStream, m_nNotifySignalId);
+ m_nNotifySignalId = 0;
+ g_signal_handler_disconnect(m_pStream, m_nInvalidateSizeSignalId);
+ m_nInvalidateSizeSignalId = 0;
+ g_source_remove(m_nTimeoutId);
+ m_nTimeoutId = 0;
+}
+
+bool GtkPlayer::create(const OUString& rURL)
+{
+ bool bRet = false;
+
+ cleanup();
+
+ if (!rURL.isEmpty())
+ {
+ GFile* pFile = g_file_new_for_uri(OUStringToOString(rURL, RTL_TEXTENCODING_UTF8).getStr());
+ m_pStream = gtk_media_file_new_for_file(pFile);
+ g_object_unref(pFile);
+
+ bRet = gtk_media_stream_get_error(m_pStream) == nullptr;
+ }
+
+ if (bRet)
+ m_aURL = rURL;
+ else
+ m_aURL.clear();
+
+ return bRet;
+}
+
+void GtkPlayer::notifyListeners()
+{
+ comphelper::OInterfaceContainerHelper2* pContainer
+ = m_lListener.getContainer(cppu::UnoType<css::media::XPlayerListener>::get());
+ if (!pContainer)
+ return;
+
+ css::lang::EventObject aEvent;
+ aEvent.Source = getXWeak();
+
+ comphelper::OInterfaceIteratorHelper2 pIterator(*pContainer);
+ while (pIterator.hasMoreElements())
+ {
+ css::uno::Reference<css::media::XPlayerListener> xListener(
+ static_cast<css::media::XPlayerListener*>(pIterator.next()));
+ xListener->preferredPlayerWindowSizeAvailable(aEvent);
+ }
+}
+
+void SAL_CALL GtkPlayer::start()
+{
+ osl::MutexGuard aGuard(m_aMutex);
+
+ if (m_pStream)
+ gtk_media_stream_play(m_pStream);
+}
+
+void SAL_CALL GtkPlayer::stop()
+{
+ osl::MutexGuard aGuard(m_aMutex);
+
+ if (m_pStream)
+ gtk_media_stream_pause(m_pStream);
+}
+
+sal_Bool SAL_CALL GtkPlayer::isPlaying()
+{
+ osl::MutexGuard aGuard(m_aMutex);
+
+ bool bRet = false;
+
+ if (m_pStream)
+ bRet = gtk_media_stream_get_playing(m_pStream);
+
+ return bRet;
+}
+
+double SAL_CALL GtkPlayer::getDuration()
+{
+ osl::MutexGuard aGuard(m_aMutex);
+
+ double duration = 0.0;
+
+ if (m_pStream)
+ duration = gtk_media_stream_get_duration(m_pStream) / 1000000.0;
+
+ return duration;
+}
+
+void SAL_CALL GtkPlayer::setMediaTime(double fTime)
+{
+ osl::MutexGuard aGuard(m_aMutex);
+
+ if (!m_pStream)
+ return;
+
+ gint64 gst_position = llround(fTime * 1000000);
+
+ gtk_media_stream_seek(m_pStream, gst_position);
+
+ // on resetting back to zero the reported timestamp doesn't seem to get
+ // updated in a reasonable time, so on zero just force an update of
+ // timestamp to 0
+ if (gst_position == 0 && gtk_media_stream_is_prepared(m_pStream))
+ gtk_media_stream_update(m_pStream, gst_position);
+}
+
+double SAL_CALL GtkPlayer::getMediaTime()
+{
+ osl::MutexGuard aGuard(m_aMutex);
+
+ double position = 0.0;
+
+ if (m_pStream)
+ position = gtk_media_stream_get_timestamp(m_pStream) / 1000000.0;
+
+ return position;
+}
+
+void SAL_CALL GtkPlayer::setPlaybackLoop(sal_Bool bSet)
+{
+ osl::MutexGuard aGuard(m_aMutex);
+ gtk_media_stream_set_loop(m_pStream, bSet);
+}
+
+sal_Bool SAL_CALL GtkPlayer::isPlaybackLoop()
+{
+ osl::MutexGuard aGuard(m_aMutex);
+ return gtk_media_stream_get_loop(m_pStream);
+}
+
+// gtk4-4.4.1 docs state: "Muting a stream will cause no audio to be played, but
+// it does not modify the volume. This means that muting and then unmuting the
+// stream will restore the volume settings." but that doesn't seem to be my
+// experience at all
+void SAL_CALL GtkPlayer::setMute(sal_Bool bSet)
+{
+ osl::MutexGuard aGuard(m_aMutex);
+ bool bMuted = gtk_media_stream_get_muted(m_pStream);
+ if (bMuted == static_cast<bool>(bSet))
+ return;
+ gtk_media_stream_set_muted(m_pStream, bSet);
+ if (!bSet)
+ setVolumeDB(m_nUnmutedVolume);
+}
+
+sal_Bool SAL_CALL GtkPlayer::isMute()
+{
+ osl::MutexGuard aGuard(m_aMutex);
+ return gtk_media_stream_get_muted(m_pStream);
+}
+
+void SAL_CALL GtkPlayer::setVolumeDB(sal_Int16 nVolumeDB)
+{
+ osl::MutexGuard aGuard(m_aMutex);
+
+ // range is -40 for silence to 0 for full volume
+ m_nUnmutedVolume = std::clamp<sal_Int16>(nVolumeDB, -40, 0);
+ double fValue = (m_nUnmutedVolume + 40) / 40.0;
+ gtk_media_stream_set_volume(m_pStream, fValue);
+}
+
+sal_Int16 SAL_CALL GtkPlayer::getVolumeDB()
+{
+ osl::MutexGuard aGuard(m_aMutex);
+
+ if (gtk_media_stream_get_muted(m_pStream))
+ return m_nUnmutedVolume;
+
+ double fVolume = gtk_media_stream_get_volume(m_pStream);
+
+ m_nUnmutedVolume = (fVolume * 40) - 40;
+
+ return m_nUnmutedVolume;
+}
+
+awt::Size SAL_CALL GtkPlayer::getPreferredPlayerWindowSize()
+{
+ osl::MutexGuard aGuard(m_aMutex);
+
+ awt::Size aSize(0, 0);
+
+ if (m_pStream)
+ {
+ aSize.Width = gdk_paintable_get_intrinsic_width(GDK_PAINTABLE(m_pStream));
+ aSize.Height = gdk_paintable_get_intrinsic_height(GDK_PAINTABLE(m_pStream));
+ }
+
+ return aSize;
+}
+
+uno::Reference<::media::XPlayerWindow>
+ SAL_CALL GtkPlayer::createPlayerWindow(const uno::Sequence<uno::Any>& rArguments)
+{
+ osl::MutexGuard aGuard(m_aMutex);
+
+ uno::Reference<::media::XPlayerWindow> xRet;
+
+ if (rArguments.getLength() > 1)
+ rArguments[1] >>= m_aArea;
+
+ if (rArguments.getLength() <= 2)
+ {
+ xRet = new ::avmedia::gstreamer::Window;
+ return xRet;
+ }
+
+ sal_IntPtr pIntPtr = 0;
+ rArguments[2] >>= pIntPtr;
+ SystemChildWindow* pParentWindow = reinterpret_cast<SystemChildWindow*>(pIntPtr);
+ if (!pParentWindow)
+ return nullptr;
+
+ const SystemEnvData* pEnvData = pParentWindow->GetSystemData();
+ if (!pEnvData)
+ return nullptr;
+
+ m_pVideo = gtk_picture_new_for_paintable(GDK_PAINTABLE(m_pStream));
+#if GTK_CHECK_VERSION(4, 7, 2)
+ gtk_picture_set_content_fit(GTK_PICTURE(m_pVideo), GTK_CONTENT_FIT_FILL);
+#else
+ gtk_picture_set_keep_aspect_ratio(GTK_PICTURE(m_pVideo), false);
+#endif
+ gtk_widget_set_can_target(m_pVideo, false);
+ gtk_widget_set_vexpand(m_pVideo, true);
+ gtk_widget_set_hexpand(m_pVideo, true);
+
+ GtkWidget* pParent = static_cast<GtkWidget*>(pEnvData->pWidget);
+ gtk_widget_set_can_target(pParent, false);
+ gtk_grid_attach(GTK_GRID(pParent), m_pVideo, 0, 0, 1, 1);
+ // "‘void gtk_widget_show(GtkWidget*)’ is deprecated: Use 'gtk_widget_set_visible or
+ // gtk_window_present' instead":
+ SAL_WNODEPRECATED_DECLARATIONS_PUSH
+ gtk_widget_show(m_pVideo);
+ gtk_widget_show(pParent);
+ SAL_WNODEPRECATED_DECLARATIONS_POP
+
+ xRet = new ::avmedia::gstreamer::Window;
+
+ return xRet;
+}
+
+void SAL_CALL
+GtkPlayer::addPlayerListener(const css::uno::Reference<css::media::XPlayerListener>& rListener)
+{
+ m_lListener.addInterface(cppu::UnoType<css::media::XPlayerListener>::get(), rListener);
+ if (gtk_media_stream_is_prepared(m_pStream))
+ {
+ css::lang::EventObject aEvent;
+ aEvent.Source = getXWeak();
+ rListener->preferredPlayerWindowSizeAvailable(aEvent);
+ }
+ else
+ installNotify();
+}
+
+void SAL_CALL
+GtkPlayer::removePlayerListener(const css::uno::Reference<css::media::XPlayerListener>& rListener)
+{
+ m_lListener.removeInterface(cppu::UnoType<css::media::XPlayerListener>::get(), rListener);
+}
+
+namespace
+{
+class GtkFrameGrabber : public ::cppu::WeakImplHelper<css::media::XFrameGrabber>
+{
+private:
+ awt::Size m_aSize;
+ GtkMediaStream* m_pStream;
+
+public:
+ GtkFrameGrabber(GtkMediaStream* pStream, const awt::Size& rSize)
+ : m_aSize(rSize)
+ , m_pStream(pStream)
+ {
+ g_object_ref(m_pStream);
+ }
+
+ virtual ~GtkFrameGrabber() override { g_object_unref(m_pStream); }
+
+ // XFrameGrabber
+ virtual css::uno::Reference<css::graphic::XGraphic>
+ SAL_CALL grabFrame(double fMediaTime) override
+ {
+ gint64 gst_position = llround(fMediaTime * 1000000);
+ gtk_media_stream_seek(m_pStream, gst_position);
+
+ cairo_surface_t* surface
+ = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, m_aSize.Width, m_aSize.Height);
+
+ GtkSnapshot* snapshot = gtk_snapshot_new();
+ gdk_paintable_snapshot(GDK_PAINTABLE(m_pStream), snapshot, m_aSize.Width, m_aSize.Height);
+ GskRenderNode* node = gtk_snapshot_free_to_node(snapshot);
+
+ cairo_t* cr = cairo_create(surface);
+ gsk_render_node_draw(node, cr);
+ cairo_destroy(cr);
+
+ gsk_render_node_unref(node);
+
+ std::unique_ptr<BitmapEx> xBitmap(
+ vcl::bitmap::CreateFromCairoSurface(Size(m_aSize.Width, m_aSize.Height), surface));
+
+ cairo_surface_destroy(surface);
+
+ return Graphic(*xBitmap).GetXGraphic();
+ }
+};
+}
+
+uno::Reference<media::XFrameGrabber> SAL_CALL GtkPlayer::createFrameGrabber()
+{
+ osl::MutexGuard aGuard(m_aMutex);
+
+ rtl::Reference<GtkFrameGrabber> xFrameGrabber;
+
+ const awt::Size aPrefSize(getPreferredPlayerWindowSize());
+
+ if (aPrefSize.Width > 0 && aPrefSize.Height > 0)
+ xFrameGrabber.set(new GtkFrameGrabber(m_pStream, aPrefSize));
+
+ return xFrameGrabber;
+}
+
+OUString SAL_CALL GtkPlayer::getImplementationName()
+{
+ return AVMEDIA_GTK_PLAYER_IMPLEMENTATIONNAME;
+}
+
+sal_Bool SAL_CALL GtkPlayer::supportsService(const OUString& ServiceName)
+{
+ return cppu::supportsService(this, ServiceName);
+}
+
+uno::Sequence<OUString> SAL_CALL GtkPlayer::getSupportedServiceNames()
+{
+ return { AVMEDIA_GTK_PLAYER_SERVICENAME };
+}
+
+} // namespace
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/avmedia/source/gtk/gtkplayer.hxx b/avmedia/source/gtk/gtkplayer.hxx
new file mode 100644
index 000000000000..46e416e79e25
--- /dev/null
+++ b/avmedia/source/gtk/gtkplayer.hxx
@@ -0,0 +1,89 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#pragma once
+
+#include <sal/config.h>
+
+#include <string_view>
+
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/media/XPlayer.hpp>
+#include <com/sun/star/media/XPlayerNotifier.hpp>
+#include <comphelper/multicontainer2.hxx>
+#include <cppuhelper/compbase.hxx>
+#include <cppuhelper/basemutex.hxx>
+
+typedef struct _GtkMediaStream GtkMediaStream;
+typedef struct _GtkWidget GtkWidget;
+
+namespace avmedia::gtk
+{
+typedef cppu::WeakComponentImplHelper<css::media::XPlayer, css::media::XPlayerNotifier,
+ css::lang::XServiceInfo>
+ GtkPlayer_BASE;
+
+class GtkPlayer final : public cppu::BaseMutex, public GtkPlayer_BASE
+{
+public:
+ explicit GtkPlayer();
+ virtual ~GtkPlayer() override;
+
+ bool create(const OUString& rURL);
+
+ virtual void SAL_CALL start() override;
+ virtual void SAL_CALL stop() override;
+ virtual sal_Bool SAL_CALL isPlaying() override;
+ virtual double SAL_CALL getDuration() override;
+ virtual void SAL_CALL setMediaTime(double fTime) override;
+ virtual double SAL_CALL getMediaTime() override;
+ virtual void SAL_CALL setPlaybackLoop(sal_Bool bSet) override;
+ virtual sal_Bool SAL_CALL isPlaybackLoop() override;
+ virtual void SAL_CALL setMute(sal_Bool bSet) override;
+ virtual sal_Bool SAL_CALL isMute() override;
+ virtual void SAL_CALL setVolumeDB(sal_Int16 nVolumeDB) override;
+ virtual sal_Int16 SAL_CALL getVolumeDB() override;
+ virtual css::awt::Size SAL_CALL getPreferredPlayerWindowSize() override;
+ virtual css::uno::Reference<css::media::XPlayerWindow>
+ SAL_CALL createPlayerWindow(const css::uno::Sequence<css::uno::Any>& rArgs) override;
+ virtual css::uno::Reference<css::media::XFrameGrabber> SAL_CALL createFrameGrabber() override;
+
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+ virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+
+ virtual void SAL_CALL
+ addPlayerListener(const css::uno::Reference<css::media::XPlayerListener>& rListener) override;
+ virtual void SAL_CALL removePlayerListener(
+ const css::uno::Reference<css::media::XPlayerListener>& rListener) override;
+
+ virtual void SAL_CALL disposing() final override;
+
+ void notifyListeners();
+ void installNotify();
+ void uninstallNotify();
+
+private:
+ void cleanup();
+
+ comphelper::OMultiTypeInterfaceContainerHelper2 m_lListener;
+
+ OUString m_aURL;
+ css::awt::Rectangle m_aArea; // Area of the player window.
+ GtkMediaStream* m_pStream;
+ GtkWidget* m_pVideo;
+ unsigned long m_nNotifySignalId;
+ unsigned long m_nInvalidateSizeSignalId;
+ unsigned long m_nTimeoutId;
+ sal_Int16 m_nUnmutedVolume;
+};
+
+} // namespace avmedia::gtk
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/avmedia/source/inc/mediamisc.hxx b/avmedia/source/inc/mediamisc.hxx
index b0f9964d18f9..f45f5b50da0b 100644
--- a/avmedia/source/inc/mediamisc.hxx
+++ b/avmedia/source/inc/mediamisc.hxx
@@ -19,9 +19,10 @@
#pragma once
+#include <comphelper/mediamimetype.hxx>
+
#include <unotools/resmgr.hxx>
-#define AVMEDIA_MANAGER_SERVICE_PREFERRED "com.sun.star.comp.avmedia.Manager_GStreamer"
#ifdef _WIN32
#define AVMEDIA_MANAGER_SERVICE_NAME "com.sun.star.comp.avmedia.Manager_DirectX"
#else
@@ -32,9 +33,6 @@
#endif
#endif
-// Mime types
-inline constexpr OUStringLiteral AVMEDIA_MIMETYPE_COMMON = u"application/vnd.sun.star.media";
-
inline OUString AvmResId(TranslateId aId)
{
return Translate::get(aId, Translate::Create("avmedia"));
diff --git a/avmedia/source/viewer/mediawindow.cxx b/avmedia/source/viewer/mediawindow.cxx
index 6c61a7e9b361..cc369bed6264 100644
--- a/avmedia/source/viewer/mediawindow.cxx
+++ b/avmedia/source/viewer/mediawindow.cxx
@@ -23,18 +23,25 @@
#include <bitmaps.hlst>
#include <strings.hrc>
#include <tools/urlobj.hxx>
+#include <utility>
#include <vcl/graph.hxx>
#include <vcl/svapp.hxx>
#include <vcl/weld.hxx>
#include <sfx2/filedlghelper.hxx>
#include <com/sun/star/awt/Size.hpp>
+#include <com/sun/star/frame/XDispatchHelper.hpp>
#include <com/sun/star/media/XPlayer.hpp>
+#include <com/sun/star/media/XPlayerNotifier.hpp>
#include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp>
#include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
#include <com/sun/star/ui/dialogs/XFilePicker3.hpp>
#include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp>
+#include <com/sun/star/util/URLTransformer.hpp>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/propertysequence.hxx>
#include <memory>
#include <sal/log.hxx>
+#include <o3tl/string_view.hxx>
#define AVMEDIA_FRAMEGRABBER_DEFAULTFRAME_MEDIATIME 3.0
@@ -142,30 +149,30 @@ bool MediaWindow::start()
return mpImpl->start();
}
-
void MediaWindow::updateMediaItem( MediaItem& rItem ) const
{
mpImpl->updateMediaItem( rItem );
}
-
void MediaWindow::executeMediaItem( const MediaItem& rItem )
{
mpImpl->executeMediaItem( rItem );
}
-
void MediaWindow::show()
{
mpImpl->Show();
}
-
void MediaWindow::hide()
{
mpImpl->Hide();
}
+bool MediaWindow::isVisible() const
+{
+ return mpImpl->IsVisible();
+}
vcl::Window* MediaWindow::getWindow() const
{
@@ -226,7 +233,7 @@ bool MediaWindow::executeMediaURLDialog(weld::Window* pParent, OUString& rURL, b
if( !aAllTypes.isEmpty() )
aAllTypes.append(aSeparator);
- aAllTypes.append(aWildcard + filter.second.getToken( 0, ';', nIndex ));
+ aAllTypes.append(OUString::Concat(aWildcard) + o3tl::getToken(filter.second, 0, ';', nIndex ));
}
}
@@ -242,7 +249,7 @@ bool MediaWindow::executeMediaURLDialog(weld::Window* pParent, OUString& rURL, b
if( !aTypes.isEmpty() )
aTypes.append(aSeparator);
- aTypes.append(aWildcard + filter.second.getToken( 0, ';', nIndex ));
+ aTypes.append(OUString::Concat(aWildcard) + o3tl::getToken(filter.second, 0, ';', nIndex ));
}
// add single filters
@@ -296,14 +303,14 @@ void MediaWindow::executeFormatErrorBox(weld::Window* pParent)
xBox->run();
}
-bool MediaWindow::isMediaURL( const OUString& rURL, const OUString& rReferer, bool bDeep, Size* pPreferredSizePixel )
+bool MediaWindow::isMediaURL(std::u16string_view rURL, const OUString& rReferer, bool bDeep, const rtl::Reference<PlayerListener>& xPreferredPixelSizeListener)
{
const INetURLObject aURL( rURL );
if( aURL.GetProtocol() == INetProtocol::NotValid )
return false;
- if( bDeep || pPreferredSizePixel )
+ if (bDeep || xPreferredPixelSizeListener)
{
try
{
@@ -313,14 +320,20 @@ bool MediaWindow::isMediaURL( const OUString& rURL, const OUString& rReferer, bo
if( xPlayer.is() )
{
- if( pPreferredSizePixel )
+ if (xPreferredPixelSizeListener)
{
- const awt::Size aAwtSize( xPlayer->getPreferredPlayerWindowSize() );
-
- pPreferredSizePixel->setWidth( aAwtSize.Width );
- pPreferredSizePixel->setHeight( aAwtSize.Height );
+ uno::Reference<media::XPlayerNotifier> xPlayerNotifier(xPlayer, css::uno::UNO_QUERY);
+ if (xPlayerNotifier)
+ {
+ // wait until it's possible to query this to get a sensible answer
+ xPreferredPixelSizeListener->startListening(xPlayerNotifier);
+ }
+ else
+ {
+ // assume the size is possible to query immediately
+ xPreferredPixelSizeListener->callPlayerWindowSizeAvailable(xPlayer);
+ }
}
-
return true;
}
}
@@ -337,7 +350,7 @@ bool MediaWindow::isMediaURL( const OUString& rURL, const OUString& rReferer, bo
{
for( sal_Int32 nIndex = 0; nIndex >= 0; )
{
- if( aExt.equalsIgnoreAsciiCase( filter.second.getToken( 0, ';', nIndex ) ) )
+ if( aExt.equalsIgnoreAsciiCase( o3tl::getToken(filter.second, 0, ';', nIndex ) ) )
return true;
}
}
@@ -346,20 +359,17 @@ bool MediaWindow::isMediaURL( const OUString& rURL, const OUString& rReferer, bo
return false;
}
-
uno::Reference< media::XPlayer > MediaWindow::createPlayer( const OUString& rURL, const OUString& rReferer, const OUString* pMimeType )
{
return priv::MediaWindowImpl::createPlayer( rURL, rReferer, pMimeType );
}
-
-uno::Reference< graphic::XGraphic > MediaWindow::grabFrame( const OUString& rURL,
- const OUString& rReferer,
- const OUString& sMimeType )
+uno::Reference<graphic::XGraphic>
+MediaWindow::grabFrame(const uno::Reference<media::XPlayer>& xPlayer,
+ const uno::Reference<graphic::XGraphic>& rGraphic)
{
- uno::Reference< media::XPlayer > xPlayer( createPlayer( rURL, rReferer, &sMimeType ) );
uno::Reference< graphic::XGraphic > xRet;
- std::unique_ptr< Graphic > xGraphic;
+ std::optional< Graphic > oGraphic;
if( xPlayer.is() )
{
@@ -382,23 +392,120 @@ uno::Reference< graphic::XGraphic > MediaWindow::grabFrame( const OUString& rURL
if( !aPrefSize.Width && !aPrefSize.Height )
{
const BitmapEx aBmpEx(AVMEDIA_BMP_AUDIOLOGO);
- xGraphic.reset( new Graphic( aBmpEx ) );
+ oGraphic.emplace( aBmpEx );
}
}
}
- if (!xRet.is() && !xGraphic)
+ if (!xRet.is() && !oGraphic)
{
const BitmapEx aBmpEx(AVMEDIA_BMP_EMPTYLOGO);
- xGraphic.reset( new Graphic( aBmpEx ) );
+ oGraphic.emplace( aBmpEx );
}
- if (xGraphic)
- xRet = xGraphic->GetXGraphic();
+ if (oGraphic)
+ {
+ if (rGraphic)
+ oGraphic.emplace(rGraphic);
+ xRet = oGraphic->GetXGraphic();
+ }
return xRet;
}
+uno::Reference< graphic::XGraphic > MediaWindow::grabFrame(const OUString& rURL,
+ const OUString& rReferer,
+ const OUString& sMimeType,
+ const rtl::Reference<PlayerListener>& xPreferredPixelSizeListener)
+{
+ uno::Reference<media::XPlayer> xPlayer(createPlayer(rURL, rReferer, &sMimeType));
+
+ if (xPreferredPixelSizeListener)
+ {
+ uno::Reference<media::XPlayerNotifier> xPlayerNotifier(xPlayer, css::uno::UNO_QUERY);
+ if (xPlayerNotifier)
+ {
+ // set a callback to call when a more sensible result is available, which
+ // might be called immediately if already available
+ xPreferredPixelSizeListener->startListening(xPlayerNotifier);
+ }
+ else
+ {
+ // assume the size is possible to query immediately
+ xPreferredPixelSizeListener->callPlayerWindowSizeAvailable(xPlayer);
+ }
+
+ return nullptr;
+ }
+
+ return grabFrame(xPlayer);
+}
+
+void MediaWindow::dispatchInsertAVMedia(const css::uno::Reference<css::frame::XDispatchProvider>& rDispatchProvider,
+ const css::awt::Size& rSize, const OUString& rURL, bool bLink)
+{
+ util::URL aDispatchURL;
+ aDispatchURL.Complete = ".uno:InsertAVMedia";
+
+ css::uno::Reference<css::util::XURLTransformer> xTrans(css::util::URLTransformer::create(::comphelper::getProcessComponentContext()));
+ xTrans->parseStrict(aDispatchURL);
+
+ css::uno::Reference<css::frame::XDispatch> xDispatch = rDispatchProvider->queryDispatch(aDispatchURL, "", 0);
+ css::uno::Sequence<css::beans::PropertyValue> aArgs(comphelper::InitPropertySequence({
+ { "URL", css::uno::Any(rURL) },
+ { "Size.Width", uno::Any(rSize.Width)},
+ { "Size.Height", uno::Any(rSize.Height)},
+ { "IsLink", css::uno::Any(bLink) },
+ }));
+ xDispatch->dispatch(aDispatchURL, aArgs);
+}
+
+PlayerListener::PlayerListener(std::function<void(const css::uno::Reference<css::media::XPlayer>&)> fn)
+ : m_aFn(std::move(fn))
+{
+}
+
+void PlayerListener::disposing(std::unique_lock<std::mutex>& rGuard)
+{
+ stopListening(rGuard);
+ WeakComponentImplHelperBase::disposing(rGuard);
+}
+
+void PlayerListener::startListening(const css::uno::Reference<media::XPlayerNotifier>& rNotifier)
+{
+ std::unique_lock aGuard(m_aMutex);
+
+ m_xNotifier = rNotifier;
+ m_xNotifier->addPlayerListener(this);
+}
+
+void PlayerListener::stopListening(std::unique_lock<std::mutex>&)
+{
+ if (!m_xNotifier)
+ return;
+ m_xNotifier->removePlayerListener(this);
+ m_xNotifier.clear();
+}
+
+void SAL_CALL PlayerListener::preferredPlayerWindowSizeAvailable(const css::lang::EventObject&)
+{
+ std::unique_lock aGuard(m_aMutex);
+
+ css::uno::Reference<media::XPlayer> xPlayer(m_xNotifier, css::uno::UNO_QUERY_THROW);
+ aGuard.unlock();
+ callPlayerWindowSizeAvailable(xPlayer);
+ aGuard.lock();
+
+ stopListening(aGuard);
+}
+
+void SAL_CALL PlayerListener::disposing(const css::lang::EventObject&)
+{
+}
+
+PlayerListener::~PlayerListener()
+{
+}
} // namespace avmedia
diff --git a/avmedia/source/viewer/mediawindow_impl.cxx b/avmedia/source/viewer/mediawindow_impl.cxx
index 1ff4c46bd65a..82ca1b92821c 100644
--- a/avmedia/source/viewer/mediawindow_impl.cxx
+++ b/avmedia/source/viewer/mediawindow_impl.cxx
@@ -29,7 +29,8 @@
#include <sal/log.hxx>
#include <comphelper/processfactory.hxx>
-#include <tools/diagnose_ex.h>
+#include <comphelper/diagnose_ex.hxx>
+#include <comphelper/scopeguard.hxx>
#include <tools/urlobj.hxx>
#include <unotools/securityoptions.hxx>
#include <vcl/bitmapex.hxx>
@@ -37,6 +38,7 @@
#include <vcl/commandevent.hxx>
#include <vcl/event.hxx>
#include <vcl/ptrstyle.hxx>
+#include <vcl/svapp.hxx>
#include <com/sun/star/awt/SystemPointer.hpp>
#include <com/sun/star/lang/XComponent.hpp>
@@ -166,7 +168,7 @@ void MediaWindowImpl::dispose()
Control::dispose();
}
-uno::Reference<media::XPlayer> MediaWindowImpl::createPlayer(const OUString& rURL, const OUString& rReferer, const OUString* pMimeType)
+uno::Reference<media::XPlayer> MediaWindowImpl::createPlayer(const OUString& rURL, const OUString& rReferer, const OUString*)
{
uno::Reference<media::XPlayer> xPlayer;
@@ -178,22 +180,14 @@ uno::Reference<media::XPlayer> MediaWindowImpl::createPlayer(const OUString& rUR
return xPlayer;
}
- if (!pMimeType || *pMimeType == AVMEDIA_MIMETYPE_COMMON)
+ // currently there isn't anything else, throw any mime type to the media players
+ //if (!pMimeType || *pMimeType == AVMEDIA_MIMETYPE_COMMON)
{
uno::Reference<uno::XComponentContext> xContext(::comphelper::getProcessComponentContext());
-
- static std::u16string_view aServiceManagers[] =
- {
- u"" AVMEDIA_MANAGER_SERVICE_PREFERRED,
- u"" AVMEDIA_MANAGER_SERVICE_NAME,
- };
-
- for (const auto& rServiceName : aServiceManagers)
- {
- xPlayer = createPlayer(rURL, OUString(rServiceName), xContext);
- if (xPlayer)
- break;
- }
+ if (Application::GetToolkitName() == "gtk4")
+ xPlayer = createPlayer(rURL, "com.sun.star.comp.avmedia.Manager_Gtk", xContext);
+ else
+ xPlayer = createPlayer(rURL, AVMEDIA_MANAGER_SERVICE_NAME, xContext);
}
return xPlayer;
@@ -306,6 +300,9 @@ void MediaWindowImpl::updateMediaItem( MediaItem& rItem ) const
void MediaWindowImpl::executeMediaItem( const MediaItem& rItem )
{
+ mpItem = &rItem;
+ comphelper::ScopeGuard g([this] { this->mpItem = nullptr; });
+
const AVMediaSetMask nMaskSet = rItem.getMaskSet();
// set URL first
@@ -401,7 +398,7 @@ void MediaWindowImpl::stopPlayingInternal(bool bStop)
void MediaWindowImpl::onURLChanged()
{
- if (m_sMimeType == AVMEDIA_MIMETYPE_COMMON)
+ //if (m_sMimeType == AVMEDIA_MIMETYPE_COMMON)
{
mpChildWindow.disposeAndClear();
mpChildWindow.reset(VclPtr<MediaChildWindow>::Create(this));
@@ -426,7 +423,9 @@ void MediaWindowImpl::onURLChanged()
uno::Sequence<uno::Any> aArgs{
uno::Any(nParentWindowHandle),
uno::Any(awt::Rectangle(aPoint.X(), aPoint.Y(), aSize.Width(), aSize.Height())),
- uno::Any(reinterpret_cast<sal_IntPtr>(mpChildWindow.get()))
+ uno::Any(reinterpret_cast<sal_IntPtr>(mpChildWindow.get())),
+ // Media item contains media properties, e.g. cropping.
+ uno::Any(reinterpret_cast<sal_IntPtr>(mpItem))
};
try
diff --git a/avmedia/source/viewer/mediawindow_impl.hxx b/avmedia/source/viewer/mediawindow_impl.hxx
index 8bceebb08d15..aa95fde22444 100644
--- a/avmedia/source/viewer/mediawindow_impl.hxx
+++ b/avmedia/source/viewer/mediawindow_impl.hxx
@@ -150,6 +150,7 @@ private:
VclPtr<MediaWindowControl> mpMediaWindowControl;
std::unique_ptr<BitmapEx> mpEmptyBmpEx;
std::unique_ptr<BitmapEx> mpAudioBmpEx;
+ const MediaItem* mpItem = nullptr;
};
}} // end namespace avmedia::priv
diff --git a/avmedia/source/win/framegrabber.cxx b/avmedia/source/win/framegrabber.cxx
index 42e30219caf3..84e9d1b187e8 100644
--- a/avmedia/source/win/framegrabber.cxx
+++ b/avmedia/source/win/framegrabber.cxx
@@ -38,9 +38,10 @@
#include <vcl/graph.hxx>
#include <vcl/dibtools.hxx>
#include <o3tl/char16_t2wchar_t.hxx>
+#include <systools/win32/oleauto.hxx>
constexpr OUStringLiteral AVMEDIA_WIN_FRAMEGRABBER_IMPLEMENTATIONNAME = u"com.sun.star.comp.avmedia.FrameGrabber_DirectX";
-constexpr OUStringLiteral AVMEDIA_WIN_FRAMEGRABBER_SERVICENAME = u"com.sun.star.media.FrameGrabber_DirectX";
+constexpr OUString AVMEDIA_WIN_FRAMEGRABBER_SERVICENAME = u"com.sun.star.media.FrameGrabber_DirectX"_ustr;
using namespace ::com::sun::star;
@@ -62,22 +63,15 @@ sal::systools::COMReference<IMediaDet> implCreateMediaDet( const OUString& rURL
{
sal::systools::COMReference<IMediaDet> pDet;
- if( SUCCEEDED(pDet.TryCoCreateInstance(CLSID_MediaDet, nullptr, CLSCTX_INPROC_SERVER)) )
+ if( SUCCEEDED(pDet.CoCreateInstance(CLSID_MediaDet, nullptr, CLSCTX_INPROC_SERVER)) )
{
OUString aLocalStr;
if( osl::FileBase::getSystemPathFromFileURL( rURL, aLocalStr )
== osl::FileBase::E_None )
{
- BSTR bstrFilename = SysAllocString(o3tl::toW(aLocalStr.getStr()));
- if( !SUCCEEDED( pDet->put_Filename( bstrFilename ) ) )
- {
- // Shouldn't we free this string unconditionally, not only in case of failure?
- // I cannot find information why do we pass a newly allocated BSTR to the put_Filename
- // and if it frees the string internally
- SysFreeString(bstrFilename);
+ if( !SUCCEEDED( pDet->put_Filename(sal::systools::BStr(aLocalStr)) ) )
pDet.clear();
- }
}
}
diff --git a/avmedia/source/win/player.cxx b/avmedia/source/win/player.cxx
index 7f6660ab8462..b52ac8171dfc 100644
--- a/avmedia/source/win/player.cxx
+++ b/avmedia/source/win/player.cxx
@@ -32,7 +32,7 @@
#include <rtl/ref.hxx>
constexpr OUStringLiteral AVMEDIA_WIN_PLAYER_IMPLEMENTATIONNAME = u"com.sun.star.comp.avmedia.Player_DirectX";
-constexpr OUStringLiteral AVMEDIA_WIN_PLAYER_SERVICENAME = u"com.sun.star.media.Player_DirectX";
+constexpr OUString AVMEDIA_WIN_PLAYER_SERVICENAME = u"com.sun.star.media.Player_DirectX"_ustr;
using namespace ::com::sun::star;
@@ -95,7 +95,7 @@ bool Player::create( const OUString& rURL )
{
bool bRet = false;
- if( SUCCEEDED(mpGB.TryCoCreateInstance(CLSID_FilterGraph, nullptr, CLSCTX_INPROC_SERVER)) )
+ if( SUCCEEDED(mpGB.CoCreateInstance(CLSID_FilterGraph, nullptr, CLSCTX_INPROC_SERVER)) )
{
// Don't use the overlay mixer on Windows Vista
// It disables the desktop composition as soon as RenderFile is called
diff --git a/avmedia/source/win/window.cxx b/avmedia/source/win/window.cxx
index 4f4ef47456e6..8cf3fee74d3d 100644
--- a/avmedia/source/win/window.cxx
+++ b/avmedia/source/win/window.cxx
@@ -29,7 +29,7 @@
#include "player.hxx"
constexpr OUStringLiteral AVMEDIA_WIN_WINDOW_IMPLEMENTATIONNAME = u"com.sun.star.comp.avmedia.Window_DirectX";
-constexpr OUStringLiteral AVMEDIA_WIN_WINDOW_SERVICENAME = u"com.sun.star.media.Window_DirectX";
+constexpr OUString AVMEDIA_WIN_WINDOW_SERVICENAME = u"com.sun.star.media.Window_DirectX"_ustr;
using namespace ::com::sun::star;
@@ -98,7 +98,6 @@ static WNDCLASSW* lcl_getWndClass()
}
Window::Window( Player& rPlayer ) :
- maListeners( maMutex ),
meZoomLevel( media::ZoomLevel_NOT_AVAILABLE ),
mrPlayer( rPlayer ),
mnFrameWnd( nullptr ),
@@ -349,62 +348,74 @@ void SAL_CALL Window::setFocus( )
void SAL_CALL Window::addWindowListener( const uno::Reference< awt::XWindowListener >& xListener )
{
- maListeners.addInterface( cppu::UnoType<decltype(xListener)>::get(), xListener );
+ std::unique_lock g(maMutex);
+ maWindowListeners.addInterface( g, xListener );
}
void SAL_CALL Window::removeWindowListener( const uno::Reference< awt::XWindowListener >& xListener )
{
- maListeners.removeInterface( cppu::UnoType<decltype(xListener)>::get(), xListener );
+ std::unique_lock g(maMutex);
+ maWindowListeners.removeInterface( g, xListener );
}
void SAL_CALL Window::addFocusListener( const uno::Reference< awt::XFocusListener >& xListener )
{
- maListeners.addInterface( cppu::UnoType<decltype(xListener)>::get(), xListener );
+ std::unique_lock g(maMutex);
+ maFocusListeners.addInterface( g, xListener );
}
void SAL_CALL Window::removeFocusListener( const uno::Reference< awt::XFocusListener >& xListener )
{
- maListeners.removeInterface( cppu::UnoType<decltype(xListener)>::get(), xListener );
+ std::unique_lock g(maMutex);
+ maFocusListeners.removeInterface( g, xListener );
}
void SAL_CALL Window::addKeyListener( const uno::Reference< awt::XKeyListener >& xListener )
{
- maListeners.addInterface( cppu::UnoType<decltype(xListener)>::get(), xListener );
+ std::unique_lock g(maMutex);
+ maKeyListeners.addInterface( g, xListener );
}
void SAL_CALL Window::removeKeyListener( const uno::Reference< awt::XKeyListener >& xListener )
{
- maListeners.removeInterface( cppu::UnoType<decltype(xListener)>::get(), xListener );
+ std::unique_lock g(maMutex);
+ maKeyListeners.removeInterface( g, xListener );
}
void SAL_CALL Window::addMouseListener( const uno::Reference< awt::XMouseListener >& xListener )
{
- maListeners.addInterface( cppu::UnoType<decltype(xListener)>::get(), xListener );
+ std::unique_lock g(maMutex);
+ maMouseListeners.addInterface( g, xListener );
}
void SAL_CALL Window::removeMouseListener( const uno::Reference< awt::XMouseListener >& xListener )
{
- maListeners.removeInterface( cppu::UnoType<decltype(xListener)>::get(), xListener );
+ std::unique_lock g(maMutex);
+ maMouseListeners.removeInterface( g, xListener );
}
void SAL_CALL Window::addMouseMotionListener( const uno::Reference< awt::XMouseMotionListener >& xListener )
{
- maListeners.addInterface( cppu::UnoType<decltype(xListener)>::get(), xListener );
+ std::unique_lock g(maMutex);
+ maMouseMotionListeners.addInterface( g, xListener );
}
void SAL_CALL Window::removeMouseMotionListener( const uno::Reference< awt::XMouseMotionListener >& xListener )
{
- maListeners.removeInterface( cppu::UnoType<decltype(xListener)>::get(), xListener );
+ std::unique_lock g(maMutex);
+ maMouseMotionListeners.removeInterface( g, xListener );
}
void SAL_CALL Window::addPaintListener( const uno::Reference< awt::XPaintListener >& xListener )
{
- maListeners.addInterface( cppu::UnoType<decltype(xListener)>::get(), xListener );
+ std::unique_lock g(maMutex);
+ maPaintListeners.addInterface( g, xListener );
}
void SAL_CALL Window::removePaintListener( const uno::Reference< awt::XPaintListener >& xListener )
{
- maListeners.removeInterface( cppu::UnoType<decltype(xListener)>::get(), xListener );
+ std::unique_lock g(maMutex);
+ maPaintListeners.removeInterface( g, xListener );
}
void SAL_CALL Window::dispose( )
@@ -413,64 +424,38 @@ void SAL_CALL Window::dispose( )
void SAL_CALL Window::addEventListener( const uno::Reference< lang::XEventListener >& xListener )
{
- maListeners.addInterface( cppu::UnoType<decltype(xListener)>::get(), xListener );
+ std::unique_lock g(maMutex);
+ maEventListeners.addInterface( g, xListener );
}
void SAL_CALL Window::removeEventListener( const uno::Reference< lang::XEventListener >& xListener )
{
- maListeners.removeInterface( cppu::UnoType<decltype(xListener)>::get(), xListener );
+ std::unique_lock g(maMutex);
+ maEventListeners.removeInterface( g, xListener );
}
void Window::fireMousePressedEvent( const css::awt::MouseEvent& rEvt )
{
- comphelper::OInterfaceContainerHelper2* pContainer = maListeners.getContainer( cppu::UnoType<awt::XMouseListener>::get());
-
- if( pContainer )
- {
- comphelper::OInterfaceIteratorHelper2 aIter( *pContainer );
-
- while( aIter.hasMoreElements() )
- static_cast< awt::XMouseListener* >( aIter.next() )->mousePressed( rEvt );
- }
+ std::unique_lock g(maMutex);
+ maMouseListeners.notifyEach(g, &awt::XMouseListener::mousePressed, rEvt);
}
void Window::fireMouseReleasedEvent( const css::awt::MouseEvent& rEvt )
{
- comphelper::OInterfaceContainerHelper2* pContainer = maListeners.getContainer( cppu::UnoType<awt::XMouseListener>::get());
-
- if( pContainer )
- {
- comphelper::OInterfaceIteratorHelper2 aIter( *pContainer );
-
- while( aIter.hasMoreElements() )
- static_cast< awt::XMouseListener* >( aIter.next() )->mouseReleased( rEvt );
- }
+ std::unique_lock g(maMutex);
+ maMouseListeners.notifyEach(g, &awt::XMouseListener::mouseReleased, rEvt);
}
void Window::fireMouseMovedEvent( const css::awt::MouseEvent& rEvt )
{
- comphelper::OInterfaceContainerHelper2* pContainer = maListeners.getContainer( cppu::UnoType<awt::XMouseMotionListener>::get());
-
- if( pContainer )
- {
- comphelper::OInterfaceIteratorHelper2 aIter( *pContainer );
-
- while( aIter.hasMoreElements() )
- static_cast< awt::XMouseMotionListener* >( aIter.next() )->mouseMoved( rEvt );
- }
+ std::unique_lock g(maMutex);
+ maMouseMotionListeners.notifyEach(g, &awt::XMouseMotionListener::mouseMoved, rEvt);
}
void Window::fireSetFocusEvent( const css::awt::FocusEvent& rEvt )
{
- comphelper::OInterfaceContainerHelper2* pContainer = maListeners.getContainer( cppu::UnoType<awt::XFocusListener>::get());
-
- if( pContainer )
- {
- comphelper::OInterfaceIteratorHelper2 aIter( *pContainer );
-
- while( aIter.hasMoreElements() )
- static_cast< awt::XFocusListener* >( aIter.next() )->focusGained( rEvt );
- }
+ std::unique_lock g(maMutex);
+ maFocusListeners.notifyEach(g, &awt::XFocusListener::focusGained, rEvt);
}
OUString SAL_CALL Window::getImplementationName( )
diff --git a/avmedia/source/win/window.hxx b/avmedia/source/win/window.hxx
index 39d5aec626c4..0ab691ffbb82 100644
--- a/avmedia/source/win/window.hxx
+++ b/avmedia/source/win/window.hxx
@@ -25,7 +25,8 @@
#include "wincommon.hxx"
#include <cppuhelper/implbase.hxx>
-#include <comphelper/multicontainer2.hxx>
+#include <comphelper/interfacecontainer4.hxx>
+#include <mutex>
#include <com/sun/star/media/XPlayerWindow.hpp>
@@ -95,8 +96,14 @@ public:
private:
- ::osl::Mutex maMutex;
- comphelper::OMultiTypeInterfaceContainerHelper2 maListeners;
+ std::mutex maMutex;
+ comphelper::OInterfaceContainerHelper4<css::awt::XWindowListener> maWindowListeners;
+ comphelper::OInterfaceContainerHelper4<css::awt::XFocusListener> maFocusListeners;
+ comphelper::OInterfaceContainerHelper4<css::awt::XKeyListener> maKeyListeners;
+ comphelper::OInterfaceContainerHelper4<css::awt::XMouseListener> maMouseListeners;
+ comphelper::OInterfaceContainerHelper4<css::awt::XMouseMotionListener> maMouseMotionListeners;
+ comphelper::OInterfaceContainerHelper4<css::awt::XPaintListener> maPaintListeners;
+ comphelper::OInterfaceContainerHelper4<css::lang::XEventListener> maEventListeners;
css::media::ZoomLevel meZoomLevel;
Player& mrPlayer;
HWND mnFrameWnd;