diff options
author | Michael Stahl <michael.stahl@allotropia.de> | 2023-04-05 11:50:44 +0200 |
---|---|---|
committer | Michael Stahl <michael.stahl@allotropia.de> | 2023-04-05 14:34:51 +0200 |
commit | a5225ba82e94a549f44420f56a7cb9d7906561cc (patch) | |
tree | 084be80b91028e3bfbe8cd5e3b50ba97fa8b516d | |
parent | 8b4af1eb0549b6832361da85ddaa1e13be34ec76 (diff) |
avmedia,*: guess the mime type of media files based on file name
.. at least for the most popular types, and do it automatically in
MediaItem::setURL().
This should work in practice in most cases and is much simpler than
adding some type detection or calling into platform dependent avmedia
backends.
Remove the parameter that was only ever set to
"application/vnd.sun.star.media" anyway, the same value that would be
used if it's missing.
Stop using that silly type for everything, only use it when guessing
fails.
In case an ODF document is loaded, it will use the mime type loaded from
the file (see setting of MediaMimeType in SdXMLPluginShapeContext) and
not guess it because that would require updating the entry in
manifest.xml as well.
Change-Id: I8ce29cf7425678ae11dda1d8c875be818f8623af
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/150049
Tested-by: Jenkins
Reviewed-by: Michael Stahl <michael.stahl@allotropia.de>
-rw-r--r-- | avmedia/source/framework/mediaitem.cxx | 9 | ||||
-rw-r--r-- | avmedia/source/inc/mediamisc.hxx | 5 | ||||
-rw-r--r-- | avmedia/source/viewer/mediawindow_impl.cxx | 7 | ||||
-rw-r--r-- | comphelper/source/misc/graphicmimetype.cxx | 68 | ||||
-rw-r--r-- | include/comphelper/mediamimetype.hxx | 30 | ||||
-rw-r--r-- | include/svx/svdomedia.hxx | 2 | ||||
-rw-r--r-- | oox/source/export/drawingml.cxx | 5 | ||||
-rw-r--r-- | sd/source/ui/inc/View.hxx | 2 | ||||
-rw-r--r-- | sd/source/ui/view/sdview4.cxx | 8 | ||||
-rw-r--r-- | svx/source/svdraw/svdomedia.cxx | 4 | ||||
-rw-r--r-- | xmloff/source/draw/ximpshap.cxx | 5 | ||||
-rw-r--r-- | xmloff/source/text/XMLTextFrameContext.cxx | 3 |
12 files changed, 126 insertions, 22 deletions
diff --git a/avmedia/source/framework/mediaitem.cxx b/avmedia/source/framework/mediaitem.cxx index 77b28918f545..f177c8bea687 100644 --- a/avmedia/source/framework/mediaitem.cxx +++ b/avmedia/source/framework/mediaitem.cxx @@ -36,6 +36,7 @@ #include <ucbhelper/content.hxx> +#include <comphelper/mediamimetype.hxx> #include <comphelper/processfactory.hxx> #include <comphelper/storagehelper.hxx> #include <mediamisc.hxx> @@ -237,6 +238,7 @@ bool MediaItem::setURL(const OUString& rURL, const OUString& rTempURL, const OUS m_pImpl->m_URL = rURL; m_pImpl->m_TempFileURL = rTempURL; m_pImpl->m_Referer = rReferer; + setMimeType(::comphelper::GuessMediaMimeType(GetFilename(rURL))); } return bChanged; } @@ -447,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)); } diff --git a/avmedia/source/inc/mediamisc.hxx b/avmedia/source/inc/mediamisc.hxx index 061a7177f05a..f45f5b50da0b 100644 --- a/avmedia/source/inc/mediamisc.hxx +++ b/avmedia/source/inc/mediamisc.hxx @@ -19,6 +19,8 @@ #pragma once +#include <comphelper/mediamimetype.hxx> + #include <unotools/resmgr.hxx> #ifdef _WIN32 @@ -31,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_impl.cxx b/avmedia/source/viewer/mediawindow_impl.cxx index b74033e33749..82ca1b92821c 100644 --- a/avmedia/source/viewer/mediawindow_impl.cxx +++ b/avmedia/source/viewer/mediawindow_impl.cxx @@ -168,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; @@ -180,7 +180,8 @@ 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()); if (Application::GetToolkitName() == "gtk4") @@ -397,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)); diff --git a/comphelper/source/misc/graphicmimetype.cxx b/comphelper/source/misc/graphicmimetype.cxx index f9c6034ac8f9..8ae3dad5619c 100644 --- a/comphelper/source/misc/graphicmimetype.cxx +++ b/comphelper/source/misc/graphicmimetype.cxx @@ -18,6 +18,10 @@ */ #include <comphelper/graphicmimetype.hxx> +#include <comphelper/mediamimetype.hxx> + +#include <map> +#include <set> #include <com/sun/star/beans/PropertyValue.hpp> #include <com/sun/star/beans/XPropertySet.hpp> @@ -166,6 +170,70 @@ char const* GraphicMimeTypeHelper::GetExtensionForConvertDataFormat(ConvertDataF } return pExt; } + +static auto GetMediaMimes() -> std::map<OString, OString> const& +{ + static std::map<OString, OString> const mimes = { + { "mp4", "video/mp4" }, + { "ts", "video/MP2T" }, + { "mpeg", "video/mpeg" }, + { "mpg", "video/mpeg" }, + { "mkv", "video/x-matroska" }, + { "webm", "video/webm" }, + { "ogv", "video/ogg" }, + { "mov", "video/quicktime" }, + { "wmv", "video/x-ms-wmv" }, + { "avi", "video/x-msvideo" }, + { "m4a", "audio/mp4" }, + { "aac", "audio/aac" }, + { "mp3", "audio/mpeg" }, // https://bugs.chromium.org/p/chromium/issues/detail?id=227004 + { "ogg", "audio/ogg" }, + { "oga", "audio/ogg" }, + { "opus", "audio/ogg" }, + { "flac", "audio/flac" }, // missing at IANA? + // note there is RFC 2631 but i got the impression that vnd.wave + // requires specifying the codec in the container; also this page + // says "Historic" whatever that means: + // https://www.iana.org/assignments/wave-avi-codec-registry/wave-avi-codec-registry.xhtml + { "wav", "audio/x-wav" }, + }; + return mimes; +} + +auto IsMediaMimeType(::std::string_view const rMimeType) -> bool +{ + return IsMediaMimeType(OStringToOUString(rMimeType, RTL_TEXTENCODING_UTF8)); +} + +auto IsMediaMimeType(OUString const& rMimeType) -> bool +{ + static std::set<OUString> mimes; + if (mimes.empty()) + { + auto const& rMap(GetMediaMimes()); + for (auto const& it : rMap) + { + mimes.insert(OStringToOUString(it.second, RTL_TEXTENCODING_UTF8)); + } + } + return rMimeType == AVMEDIA_MIMETYPE_COMMON || mimes.find(rMimeType) != mimes.end(); +} + +auto GuessMediaMimeType(::std::u16string_view rFileName) -> OUString +{ + if (auto const i = rFileName.rfind('.'); i != ::std::string_view::npos) + { + OString const ext(OUStringToOString(rFileName.substr(i + 1), RTL_TEXTENCODING_UTF8)); + auto const& rMap(GetMediaMimes()); + auto const it(rMap.find(ext)); + if (it != rMap.end()) + { + return OStringToOUString(it->second, RTL_TEXTENCODING_ASCII_US); + } + } + return OUString(); } +} // namespace comphelper + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/comphelper/mediamimetype.hxx b/include/comphelper/mediamimetype.hxx new file mode 100644 index 000000000000..21b7ffa9211b --- /dev/null +++ b/include/comphelper/mediamimetype.hxx @@ -0,0 +1,30 @@ +/* -*- 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 <rtl/ustring.hxx> + +#include <comphelper/comphelperdllapi.h> + +inline constexpr OUStringLiteral AVMEDIA_MIMETYPE_COMMON = u"application/vnd.sun.star.media"; + +namespace comphelper +{ +COMPHELPER_DLLPUBLIC auto IsMediaMimeType(::std::string_view const rMimeType) -> bool; +COMPHELPER_DLLPUBLIC auto IsMediaMimeType(OUString const& rMimeType) -> bool; +COMPHELPER_DLLPUBLIC auto GuessMediaMimeType(::std::u16string_view rFileName) -> OUString; + +} // namespace comphelper + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/include/svx/svdomedia.hxx b/include/svx/svdomedia.hxx index 6f08611a7002..e3120c672f3d 100644 --- a/include/svx/svdomedia.hxx +++ b/include/svx/svdomedia.hxx @@ -58,7 +58,7 @@ public: virtual void AdjustToMaxRect( const tools::Rectangle& rMaxRect, bool bShrinkOnly = false ) override; - void setURL( const OUString& rURL, const OUString& rReferer, const OUString& rMimeType = OUString() ); + void setURL(const OUString& rURL, const OUString& rReferer); const OUString& getURL() const; /// Returns the URL to the temporary extracted media file. diff --git a/oox/source/export/drawingml.cxx b/oox/source/export/drawingml.cxx index d610435d0eb2..59d67393bed5 100644 --- a/oox/source/export/drawingml.cxx +++ b/oox/source/export/drawingml.cxx @@ -1425,6 +1425,11 @@ void DrawingML::WriteMediaNonVisualProperties(const css::uno::Reference<css::dra #else OUString aMimeType("none"); #endif + if (aMimeType.startsWith("audio/")) + { + eMediaType = Relationship::AUDIO; + } + else if (aMimeType == "application/vnd.sun.star.media") { // try to set something better diff --git a/sd/source/ui/inc/View.hxx b/sd/source/ui/inc/View.hxx index 4e530e3f9227..342bf7b6256a 100644 --- a/sd/source/ui/inc/View.hxx +++ b/sd/source/ui/inc/View.hxx @@ -172,7 +172,7 @@ public: void InsertMediaURL( const OUString& rMediaURL, sal_Int8& rAction, const Point& rPos, const Size& rSize, bool const bLink ); - SdrMediaObj* InsertMediaObj( const OUString& rURL, const OUString& rMimeType, sal_Int8& rAction, + SdrMediaObj* InsertMediaObj(const OUString& rURL, sal_Int8& rAction, const Point& rPos, const Size& rSize ); bool PasteRTFTable( const ::tools::SvRef<SotTempStream>& xStm, SdrPage* pPage, SdrInsertFlags nPasteOptions ); diff --git a/sd/source/ui/view/sdview4.cxx b/sd/source/ui/view/sdview4.cxx index e91ee2c691c1..f46c876dac2b 100644 --- a/sd/source/ui/view/sdview4.cxx +++ b/sd/source/ui/view/sdview4.cxx @@ -319,10 +319,10 @@ void View::InsertMediaURL( const OUString& rMediaURL, sal_Int8& rAction, #endif } - InsertMediaObj( realURL, "application/vnd.sun.star.media", rAction, rPos, rSize ); + InsertMediaObj(realURL, rAction, rPos, rSize); } -SdrMediaObj* View::InsertMediaObj( const OUString& rMediaURL, const OUString& rMimeType, sal_Int8& rAction, +SdrMediaObj* View::InsertMediaObj( const OUString& rMediaURL, sal_Int8& rAction, const Point& rPos, const Size& rSize ) { SdrEndTextEdit(); @@ -341,7 +341,7 @@ SdrMediaObj* View::InsertMediaObj( const OUString& rMediaURL, const OUString& rM if( mnAction == DND_ACTION_LINK && pPV && dynamic_cast< SdrMediaObj *>( pPickObj ) ) { pNewMediaObj = SdrObject::Clone(static_cast<SdrMediaObj&>(*pPickObj), pPickObj->getSdrModelFromSdrObject()); - pNewMediaObj->setURL( rMediaURL, ""/*TODO?*/, rMimeType ); + pNewMediaObj->setURL(rMediaURL, ""/*TODO?*/); BegUndo(SdResId(STR_UNDO_DRAGDROP)); ReplaceObjectAtView(pPickObj, *pPV, pNewMediaObj.get()); @@ -388,7 +388,7 @@ SdrMediaObj* View::InsertMediaObj( const OUString& rMediaURL, const OUString& rM if (pNewMediaObj) { - pNewMediaObj->setURL( rMediaURL, referer, rMimeType ); + pNewMediaObj->setURL(rMediaURL, referer); if( pPickObj ) { diff --git a/svx/source/svdraw/svdomedia.cxx b/svx/source/svdraw/svdomedia.cxx index 17785a5d693a..73b19ca78773 100644 --- a/svx/source/svdraw/svdomedia.cxx +++ b/svx/source/svdraw/svdomedia.cxx @@ -252,12 +252,10 @@ void SdrMediaObj::AdjustToMaxRect( const tools::Rectangle& rMaxRect, bool bShrin SetLogicRect( tools::Rectangle( aPos, aSize ) ); } -void SdrMediaObj::setURL( const OUString& rURL, const OUString& rReferer, const OUString& rMimeType ) +void SdrMediaObj::setURL(const OUString& rURL, const OUString& rReferer) { ::avmedia::MediaItem aURLItem; #if HAVE_FEATURE_AVMEDIA - if( !rMimeType.isEmpty() ) - m_xImpl->m_MediaProperties.setMimeType(rMimeType); aURLItem.setURL( rURL, "", rReferer ); #else (void) rMimeType; diff --git a/xmloff/source/draw/ximpshap.cxx b/xmloff/source/draw/ximpshap.cxx index 22f9d7ddb0a1..0e7ce7a1619f 100644 --- a/xmloff/source/draw/ximpshap.cxx +++ b/xmloff/source/draw/ximpshap.cxx @@ -61,6 +61,7 @@ #include <sax/tools/converter.hxx> #include <comphelper/sequence.hxx> #include <comphelper/diagnose_ex.hxx> +#include <comphelper/mediamimetype.hxx> #include <xmloff/families.hxx> #include<xmloff/xmlnamespace.hxx> @@ -2890,7 +2891,7 @@ void SdXMLPluginShapeContext::startFastElement (sal_Int32 /*nElement*/, { if( aIter.getToken() == XML_ELEMENT(DRAW, XML_MIME_TYPE) ) { - if( aIter.toView() == "application/vnd.sun.star.media" ) + if (::comphelper::IsMediaMimeType(aIter.toView())) mbMedia = true; // leave this loop break; @@ -3335,7 +3336,7 @@ css::uno::Reference< css::xml::sax::XFastContextHandler > SdXMLFrameShapeContext mxImplContext = nullptr; return new SvXMLImportContext(GetImport()); } - else if (pPluginContext && pPluginContext->getMimeType() == "application/vnd.sun.star.media") + else if (pPluginContext && ::comphelper::IsMediaMimeType(pPluginContext->getMimeType())) { // The media may have a preview, import it. bMedia = true; diff --git a/xmloff/source/text/XMLTextFrameContext.cxx b/xmloff/source/text/XMLTextFrameContext.cxx index bd145b5213cd..8d0bac4964dc 100644 --- a/xmloff/source/text/XMLTextFrameContext.cxx +++ b/xmloff/source/text/XMLTextFrameContext.cxx @@ -22,6 +22,7 @@ #include <sal/log.hxx> #include <comphelper/diagnose_ex.hxx> #include <comphelper/base64.hxx> +#include <comphelper/mediamimetype.hxx> #include <com/sun/star/frame/XModel.hpp> #include <com/sun/star/lang/XMultiServiceFactory.hpp> #include <com/sun/star/text/TextContentAnchorType.hpp> @@ -1493,7 +1494,7 @@ css::uno::Reference< css::xml::sax::XFastContextHandler > XMLTextFrameContext::c { if( aIter.getToken() == XML_ELEMENT(DRAW, XML_MIME_TYPE) ) { - if( aIter.toView() == "application/vnd.sun.star.media" ) + if (::comphelper::IsMediaMimeType(aIter.toView())) bMedia = true; // leave this loop |