Coverage Report

Created: 2026-11-06 11:29

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/svx/source/svdraw/svdomedia.cxx
Line
Count
Source
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column:100 -*- */
2
/*
3
 * This file is part of the LibreOffice project.
4
 *
5
 * This Source Code Form is subject to the terms of the Mozilla Public
6
 * License, v. 2.0. If a copy of the MPL was not distributed with this
7
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8
 *
9
 * This file incorporates work covered by the following license notice:
10
 *
11
 *   Licensed to the Apache Software Foundation (ASF) under one or more
12
 *   contributor license agreements. See the NOTICE file distributed
13
 *   with this work for additional information regarding copyright
14
 *   ownership. The ASF licenses this file to you under the Apache
15
 *   License, Version 2.0 (the "License"); you may not use this file
16
 *   except in compliance with the License. You may obtain a copy of
17
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18
 */
19
20
#include <config_features.h>
21
22
#include <svx/svdomedia.hxx>
23
24
#include <com/sun/star/text/GraphicCrop.hpp>
25
#include <com/sun/star/uno/Any.hxx>
26
27
#include <rtl/ustring.hxx>
28
#include <sal/log.hxx>
29
30
#include <ucbhelper/content.hxx>
31
#include <comphelper/processfactory.hxx>
32
#include <comphelper/storagehelper.hxx>
33
34
#include <vcl/svapp.hxx>
35
36
#include <svx/svdmodel.hxx>
37
#include <svx/dialmgr.hxx>
38
#include <svx/strings.hrc>
39
#include <sdr/contact/viewcontactofsdrmediaobj.hxx>
40
#include <avmedia/mediawindow.hxx>
41
#include <comphelper/diagnose_ex.hxx>
42
#include <comphelper/embeddedobjectcontainer.hxx>
43
#include <sfx2/lnkbase.hxx>
44
#include <sfx2/linkmgr.hxx>
45
#include <sfx2/objsh.hxx>
46
47
using namespace ::com::sun::star;
48
49
50
// A media object that points at an external URL is a document link. Registering
51
// it with the link manager lets it share the normal link update permission: the
52
// snapshot is only fetched from the URL once the user has allowed link updates.
53
class SdrMediaLink final : public sfx2::SvBaseLink
54
{
55
    SdrMediaObj& mrMediaObj;
56
57
public:
58
    explicit SdrMediaLink(SdrMediaObj& rObj);
59
60
    virtual void Closed() override;
61
    virtual ::sfx2::SvBaseLink::UpdateResult DataChanged(
62
        const OUString& rMimeType, const css::uno::Any& rValue) override;
63
};
64
65
struct SdrMediaObj::Impl
66
{
67
    ::avmedia::MediaItem                  m_MediaProperties;
68
#if HAVE_FEATURE_AVMEDIA
69
    // Note: the temp file is read only, until it is deleted!
70
    // It may be shared between multiple documents in case of copy/paste,
71
    // hence the shared_ptr.
72
    std::shared_ptr< ::avmedia::MediaTempFile >  m_pTempFile;
73
    rtl::Reference<avmedia::PlayerListener> m_xPlayerListener;
74
#endif
75
    uno::Reference< graphic::XGraphic >   m_xCachedSnapshot;
76
    OUString m_LastFailedPkgURL;
77
    // owned by the link manager while registered, null otherwise
78
    SdrMediaLink* m_pMediaLink = nullptr;
79
    // true when the user picked this media reference in this session, false when it arrived with
80
    // the document
81
    bool m_bLinkAllowed = false;
82
};
83
84
SdrMediaLink::SdrMediaLink(SdrMediaObj& rObj)
85
0
    : ::sfx2::SvBaseLink(::SfxLinkUpdateMode::ONCALL, SotClipboardFormatId::SIMPLE_FILE)
86
0
    , mrMediaObj(rObj)
87
0
{
88
0
    SetSynchron(false);
89
0
}
90
91
::sfx2::SvBaseLink::UpdateResult SdrMediaLink::DataChanged(
92
    const OUString&, const css::uno::Any&)
93
0
{
94
    // Reached only after a link update was allowed, so drop the placeholder
95
    // and fetch a fresh snapshot now, like a linked graphic refetches.
96
0
    mrMediaObj.m_xImpl->m_xCachedSnapshot.clear();
97
0
#if HAVE_FEATURE_AVMEDIA
98
0
    mrMediaObj.m_xImpl->m_xPlayerListener.clear();
99
0
    OUString aRealURL = mrMediaObj.m_xImpl->m_MediaProperties.getTempURL();
100
0
    if (aRealURL.isEmpty())
101
0
        aRealURL = mrMediaObj.m_xImpl->m_MediaProperties.getURL();
102
0
    if (!aRealURL.isEmpty())
103
0
        mrMediaObj.grabSnapshot(aRealURL);
104
0
#endif
105
0
    mrMediaObj.ActionChanged();
106
0
    return SUCCESS;
107
0
}
108
109
void SdrMediaLink::Closed()
110
0
{
111
0
    mrMediaObj.m_xImpl->m_pMediaLink = nullptr;
112
0
    SvBaseLink::Closed();
113
0
}
114
115
SdrMediaObj::SdrMediaObj(SdrModel& rSdrModel)
116
0
:   SdrRectObj(rSdrModel)
117
0
    ,m_xImpl( new Impl )
118
0
{
119
0
}
120
121
SdrMediaObj::SdrMediaObj(SdrModel& rSdrModel, SdrMediaObj const & rSource)
122
0
:   SdrRectObj(rSdrModel, rSource)
123
0
    ,m_xImpl( new Impl )
124
0
{
125
0
#if HAVE_FEATURE_AVMEDIA
126
0
    m_xImpl->m_pTempFile = rSource.m_xImpl->m_pTempFile; // before props
127
0
#endif
128
0
    setMediaProperties( rSource.getMediaProperties() );
129
0
    m_xImpl->m_xCachedSnapshot = rSource.m_xImpl->m_xCachedSnapshot;
130
    // A copy of media the user picked stays picked by the user, so duplicating or moving a shape
131
    // keeps it playable.
132
0
    m_xImpl->m_bLinkAllowed = rSource.m_xImpl->m_bLinkAllowed;
133
0
}
134
135
SdrMediaObj::SdrMediaObj(
136
    SdrModel& rSdrModel,
137
    const tools::Rectangle& rRect)
138
0
:   SdrRectObj(rSdrModel, rRect)
139
0
    ,m_xImpl( new Impl )
140
0
{
141
0
    osl_atomic_increment(&m_refCount);
142
143
0
    const bool bUndo(rSdrModel.IsUndoEnabled());
144
0
    rSdrModel.EnableUndo(false);
145
0
    MakeNameUnique();
146
0
    rSdrModel.EnableUndo(bUndo);
147
148
0
    osl_atomic_decrement(&m_refCount);
149
0
}
150
151
SdrMediaObj::~SdrMediaObj()
152
0
{
153
0
    ImpDeregisterLink();
154
0
}
155
156
bool SdrMediaObj::HasTextEdit() const
157
0
{
158
0
    return false;
159
0
}
160
161
std::unique_ptr<sdr::contact::ViewContact> SdrMediaObj::CreateObjectSpecificViewContact()
162
0
{
163
0
    return std::make_unique<sdr::contact::ViewContactOfSdrMediaObj>( *this );
164
0
}
165
166
void SdrMediaObj::TakeObjInfo( SdrObjTransformInfoRec& rInfo ) const
167
0
{
168
0
    rInfo.bMoveAllowed = true;
169
0
    rInfo.bResizeFreeAllowed = true;
170
0
    rInfo.bResizePropAllowed = true;
171
0
    rInfo.bRotateFreeAllowed = false;
172
0
    rInfo.bRotate90Allowed = false;
173
0
    rInfo.bMirrorFreeAllowed = false;
174
0
    rInfo.bMirror45Allowed = false;
175
0
    rInfo.bMirror90Allowed = false;
176
0
    rInfo.bTransparenceAllowed = false;
177
0
    rInfo.bShearAllowed = false;
178
0
    rInfo.bEdgeRadiusAllowed = false;
179
0
    rInfo.bNoOrthoDesired = false;
180
0
    rInfo.bNoContortion = false;
181
0
    rInfo.bCanConvToPath = false;
182
0
    rInfo.bCanConvToPoly = false;
183
0
    rInfo.bCanConvToContour = false;
184
0
    rInfo.bCanConvToPathLineToArea = false;
185
0
    rInfo.bCanConvToPolyLineToArea = false;
186
0
}
187
188
SdrObjKind SdrMediaObj::GetObjIdentifier() const
189
0
{
190
0
    return SdrObjKind::Media;
191
0
}
192
193
OUString SdrMediaObj::TakeObjNameSingul() const
194
0
{
195
0
    OUString sName(SvxResId(STR_ObjNameSingulMEDIA));
196
197
0
    OUString aName(GetName());
198
199
0
    if (!aName.isEmpty())
200
0
        sName += " '" + aName + "'";
201
202
0
    return sName;
203
0
}
204
205
OUString SdrMediaObj::TakeObjNamePlural() const
206
0
{
207
0
    return SvxResId(STR_ObjNamePluralMEDIA);
208
0
}
209
210
rtl::Reference<SdrObject> SdrMediaObj::implCloneSdrObject(SdrModel& rTargetModel) const
211
0
{
212
0
    return new SdrMediaObj(rTargetModel, *this);
213
0
}
214
215
uno::Reference< graphic::XGraphic > const & SdrMediaObj::getSnapshot() const
216
0
{
217
0
#if HAVE_FEATURE_AVMEDIA
218
0
    if( !m_xImpl->m_xCachedSnapshot.is() )
219
0
    {
220
0
        Graphic aGraphic = m_xImpl->m_MediaProperties.getGraphic();
221
0
        if (!aGraphic.IsNone())
222
0
        {
223
0
            Size aPref = aGraphic.GetPrefSize();
224
0
            Size aPixel = aGraphic.GetSizePixel();
225
0
            const text::GraphicCrop& rCrop = m_xImpl->m_MediaProperties.getCrop();
226
0
            if (rCrop.Bottom > 0 || rCrop.Left > 0 || rCrop.Right > 0 || rCrop.Top > 0)
227
0
            {
228
0
                tools::Long nLeft = aPixel.getWidth() * rCrop.Left / aPref.getWidth();
229
0
                tools::Long nTop = aPixel.getHeight() * rCrop.Top / aPref.getHeight();
230
0
                tools::Long nRight = aPixel.getWidth() * rCrop.Right / aPref.getWidth();
231
0
                tools::Long nBottom = aPixel.getHeight() * rCrop.Bottom / aPref.getHeight();
232
0
                Bitmap aBitmap = aGraphic.GetBitmap();
233
0
                aBitmap.Crop({nLeft, nTop, aPixel.getWidth() - nRight, aPixel.getHeight() - nBottom});
234
0
                aGraphic = aBitmap;
235
0
            }
236
237
            // We have an explicit graphic for this media object, then go with that instead of
238
            // generating our own one.
239
0
            m_xImpl->m_xCachedSnapshot = aGraphic.GetXGraphic();
240
0
            return m_xImpl->m_xCachedSnapshot;
241
0
        }
242
243
0
        OUString aRealURL = m_xImpl->m_MediaProperties.getTempURL();
244
0
        if( aRealURL.isEmpty() )
245
0
        {
246
            // No extracted copy inside the document, so the media is reached
247
            // through its URL. Treat it like a linked graphic and only fetch
248
            // once the link is allowed, so opening or converting a document
249
            // never silently fetches the referenced content.
250
0
            if (!isLinkAllowed())
251
0
                return m_xImpl->m_xCachedSnapshot;
252
0
            aRealURL = m_xImpl->m_MediaProperties.getURL();
253
0
        }
254
0
        grabSnapshot(aRealURL);
255
0
    }
256
0
#endif
257
0
    return m_xImpl->m_xCachedSnapshot;
258
0
}
259
260
void SdrMediaObj::grabSnapshot(const OUString& rRealURL) const
261
0
{
262
0
#if HAVE_FEATURE_AVMEDIA
263
0
    OUString sReferer = m_xImpl->m_MediaProperties.getReferer();
264
0
    OUString sMimeType = m_xImpl->m_MediaProperties.getMimeType();
265
0
    uno::Reference<graphic::XGraphic> xCachedSnapshot = m_xImpl->m_xCachedSnapshot;
266
267
0
    m_xImpl->m_xPlayerListener.set(new avmedia::PlayerListener(
268
0
        [this, xCachedSnapshot, rRealURL, sReferer, sMimeType](const css::uno::Reference<css::media::XPlayer>& rPlayer){
269
0
            SolarMutexGuard g;
270
0
            uno::Reference<graphic::XGraphic> xGraphic
271
0
                = m_xImpl->m_MediaProperties.getGraphic().GetXGraphic();
272
0
            m_xImpl->m_xCachedSnapshot = avmedia::MediaWindow::grabFrame(rPlayer, xGraphic);
273
0
            ActionChanged();
274
0
        }));
275
276
0
    avmedia::MediaWindow::grabFrame(rRealURL, sReferer, sMimeType, m_xImpl->m_xPlayerListener);
277
#else
278
    (void)rRealURL;
279
#endif
280
0
}
281
282
void SdrMediaObj::AdjustToMaxRect( const tools::Rectangle& rMaxRect, bool bShrinkOnly /* = false */ )
283
0
{
284
0
    Size aSize( Application::GetDefaultDevice()->PixelToLogic(
285
0
                    static_cast< sdr::contact::ViewContactOfSdrMediaObj& >( GetViewContact() ).getPreferredSize(),
286
0
                    MapMode(MapUnit::Map100thMM)) );
287
0
    Size aMaxSize( rMaxRect.GetSize() );
288
289
0
    if( aSize.IsEmpty() )
290
0
        return;
291
292
0
    Point aPos( rMaxRect.TopLeft() );
293
294
    // if graphic is too large, fit it to the page
295
0
    if ( (!bShrinkOnly                          ||
296
0
         ( aSize.Height() > aMaxSize.Height() ) ||
297
0
         ( aSize.Width()  > aMaxSize.Width()  ) )&&
298
0
         aSize.Height() && aMaxSize.Height() )
299
0
    {
300
0
        float fGrfWH =  static_cast<float>(aSize.Width()) /
301
0
                        static_cast<float>(aSize.Height());
302
0
        float fWinWH =  static_cast<float>(aMaxSize.Width()) /
303
0
                        static_cast<float>(aMaxSize.Height());
304
305
        // scale graphic to page size
306
0
        if ( fGrfWH < fWinWH )
307
0
        {
308
0
            aSize.setWidth( static_cast<tools::Long>(aMaxSize.Height() * fGrfWH) );
309
0
            aSize.setHeight( aMaxSize.Height() );
310
0
        }
311
0
        else if ( fGrfWH > 0.F )
312
0
        {
313
0
            aSize.setWidth( aMaxSize.Width() );
314
0
            aSize.setHeight( static_cast<tools::Long>(aMaxSize.Width() / fGrfWH) );
315
0
        }
316
317
0
        aPos = rMaxRect.Center();
318
0
    }
319
320
0
    if( bShrinkOnly )
321
0
        aPos = getRectangle().TopLeft();
322
323
0
    aPos.AdjustX( -(aSize.Width() / 2) );
324
0
    aPos.AdjustY( -(aSize.Height() / 2) );
325
0
    SetLogicRect( tools::Rectangle( aPos, aSize ) );
326
0
}
327
328
void SdrMediaObj::setURL(const OUString& rURL, const OUString& rReferer)
329
0
{
330
0
    ::avmedia::MediaItem aURLItem;
331
0
#if HAVE_FEATURE_AVMEDIA
332
0
    aURLItem.setURL( rURL, u""_ustr, rReferer );
333
#else
334
    (void) rURL;
335
    (void) rReferer;
336
#endif
337
0
    setMediaProperties( aURLItem );
338
0
}
339
340
const OUString& SdrMediaObj::getURL() const
341
0
{
342
0
#if HAVE_FEATURE_AVMEDIA
343
0
    return m_xImpl->m_MediaProperties.getURL();
344
#else
345
    static OUString ret;
346
    return ret;
347
#endif
348
0
}
349
350
void SdrMediaObj::setLinkAllowed(bool bAllowed)
351
0
{
352
0
    m_xImpl->m_bLinkAllowed = bAllowed;
353
0
}
354
355
bool SdrMediaObj::isLinkAllowed() const
356
0
{
357
0
    if (m_xImpl->m_bLinkAllowed)
358
0
        return true;
359
    // A model with no document shell has no user to ask, so its links stay disallowed.
360
0
    sfx2::LinkManager* pLinkManager(getSdrModelFromSdrObject().GetLinkManager());
361
0
    SfxObjectShell* pShell = pLinkManager ? pLinkManager->GetPersist() : nullptr;
362
0
    return pShell && pShell->getEmbeddedObjectContainer().getUserAllowsLinkUpdate();
363
0
}
364
365
const OUString& SdrMediaObj::getTempURL() const
366
0
{
367
0
#if HAVE_FEATURE_AVMEDIA
368
0
    return m_xImpl->m_MediaProperties.getTempURL();
369
#else
370
static OUString ret;
371
    return ret;
372
#endif
373
0
}
374
375
void SdrMediaObj::setMediaProperties( const ::avmedia::MediaItem& rState )
376
0
{
377
0
    mediaPropertiesChanged( rState );
378
0
    static_cast< sdr::contact::ViewContactOfSdrMediaObj& >( GetViewContact() ).executeMediaItem( getMediaProperties() );
379
0
}
380
381
const ::avmedia::MediaItem& SdrMediaObj::getMediaProperties() const
382
0
{
383
0
    return m_xImpl->m_MediaProperties;
384
0
}
385
386
uno::Reference<io::XInputStream> SdrMediaObj::GetInputStream() const
387
0
{
388
0
#if HAVE_FEATURE_AVMEDIA
389
0
    if (!m_xImpl->m_pTempFile)
390
0
    {
391
0
        SAL_WARN("svx", "this is only intended for embedded media");
392
0
        return nullptr;
393
0
    }
394
0
    ucbhelper::Content tempFile(m_xImpl->m_pTempFile->m_TempFileURL,
395
0
                uno::Reference<ucb::XCommandEnvironment>(),
396
0
                comphelper::getProcessComponentContext());
397
0
    return tempFile.openStream();
398
#else
399
    return nullptr;
400
#endif
401
0
}
402
403
void SdrMediaObj::SetInputStream(uno::Reference<io::XInputStream> const& xStream)
404
0
{
405
#if !HAVE_FEATURE_AVMEDIA
406
    (void) xStream;
407
#else
408
0
    if (m_xImpl->m_pTempFile || m_xImpl->m_LastFailedPkgURL.isEmpty())
409
0
    {
410
0
        SAL_WARN("svx", "this is only intended for embedded media");
411
0
        return;
412
0
    }
413
414
0
    OUString tempFileURL;
415
0
    const bool bSuccess(
416
0
        ::avmedia::CreateMediaTempFile(
417
0
            xStream,
418
0
            tempFileURL,
419
0
            u""));
420
421
0
    if (bSuccess)
422
0
    {
423
0
        m_xImpl->m_pTempFile = std::make_shared<::avmedia::MediaTempFile>(tempFileURL);
424
0
        m_xImpl->m_MediaProperties.setURL(
425
0
            m_xImpl->m_LastFailedPkgURL, tempFileURL, u""_ustr);
426
0
    }
427
0
    m_xImpl->m_LastFailedPkgURL.clear(); // once only
428
0
#endif
429
0
}
430
431
/// copy a stream from XStorage to temp file
432
#if HAVE_FEATURE_AVMEDIA
433
static bool lcl_HandlePackageURL(
434
    OUString const & rURL,
435
    const SdrModel& rModel,
436
    OUString & o_rTempFileURL)
437
0
{
438
0
    ::comphelper::LifecycleProxy sourceProxy;
439
0
    uno::Reference<io::XInputStream> xInStream;
440
0
    try {
441
0
        xInStream = rModel.GetDocumentStream(rURL, sourceProxy);
442
0
    }
443
0
    catch (container::NoSuchElementException const&)
444
0
    {
445
0
        SAL_INFO("svx", "not found: '" << rURL << "'");
446
0
        return false;
447
0
    }
448
0
    catch (uno::Exception const&)
449
0
    {
450
0
        TOOLS_WARN_EXCEPTION("svx", "");
451
0
        return false;
452
0
    }
453
0
    if (!xInStream.is())
454
0
    {
455
0
        SAL_WARN("svx", "no stream?");
456
0
        return false;
457
0
    }
458
    // Make sure the temporary copy has the same file name extension as the original media file
459
    // (like .mp4). That seems to be important for some AVFoundation APIs. For random extension-less
460
    // file names, they don't seem to even bother looking inside the file.
461
0
    sal_Int32 nLastDot = rURL.lastIndexOf('.');
462
0
    sal_Int32 nLastSlash = rURL.lastIndexOf('/');
463
0
    OUString sDesiredExtension;
464
0
    if (nLastDot > nLastSlash && nLastDot+1 < rURL.getLength())
465
0
        sDesiredExtension = rURL.copy(nLastDot);
466
0
    return ::avmedia::CreateMediaTempFile(xInStream, o_rTempFileURL, sDesiredExtension);
467
0
}
468
#endif
469
470
void SdrMediaObj::mediaPropertiesChanged( const ::avmedia::MediaItem& rNewProperties )
471
0
{
472
0
    bool bBroadcastChanged = false;
473
0
#if HAVE_FEATURE_AVMEDIA
474
0
    const AVMediaSetMask nMaskSet = rNewProperties.getMaskSet();
475
476
    // use only a subset of MediaItem properties for own properties
477
0
    if( AVMediaSetMask::MIME_TYPE & nMaskSet )
478
0
        m_xImpl->m_MediaProperties.setMimeType( rNewProperties.getMimeType() );
479
480
0
    if (nMaskSet & AVMediaSetMask::GRAPHIC)
481
0
    {
482
0
        m_xImpl->m_MediaProperties.setGraphic(rNewProperties.getGraphic());
483
0
    }
484
485
0
    if (nMaskSet & AVMediaSetMask::CROP)
486
0
    {
487
0
        m_xImpl->m_MediaProperties.setCrop(rNewProperties.getCrop());
488
0
    }
489
490
0
    if( ( AVMediaSetMask::URL & nMaskSet ) &&
491
0
        ( rNewProperties.getURL() != getURL() ))
492
0
    {
493
0
        m_xImpl->m_xCachedSnapshot.clear();
494
0
        m_xImpl->m_xPlayerListener.clear();
495
        // the URL is changing, so any link registered for the old one is stale
496
0
        ImpDeregisterLink();
497
0
        m_xImpl->m_MediaProperties.setFallbackURL( rNewProperties.getFallbackURL() );
498
0
        OUString const& url(rNewProperties.getURL());
499
0
        if (url.startsWithIgnoreAsciiCase("vnd.sun.star.Package:"))
500
0
        {
501
0
            if (   !m_xImpl->m_pTempFile
502
0
                || (m_xImpl->m_pTempFile->m_TempFileURL !=
503
0
                                rNewProperties.getTempURL()))
504
0
            {
505
0
                OUString tempFileURL;
506
0
                const bool bSuccess(
507
0
                    lcl_HandlePackageURL(
508
0
                        url,
509
0
                        getSdrModelFromSdrObject(),
510
0
                        tempFileURL));
511
512
0
                if (bSuccess)
513
0
                {
514
0
                    m_xImpl->m_pTempFile =
515
0
                            std::make_shared<::avmedia::MediaTempFile>(tempFileURL);
516
0
                    m_xImpl->m_MediaProperties.setURL(url, tempFileURL, u""_ustr);
517
0
                }
518
0
                else // this case is for Clone via operator=
519
0
                {
520
0
                    m_xImpl->m_pTempFile.reset();
521
0
                    m_xImpl->m_MediaProperties.setURL(u""_ustr, u""_ustr, u""_ustr);
522
                    // UGLY: oox import also gets here, because unlike ODF
523
                    // getDocumentStorage() is not the imported file...
524
0
                    m_xImpl->m_LastFailedPkgURL = url;
525
0
                }
526
0
            }
527
0
            else
528
0
            {
529
0
                m_xImpl->m_MediaProperties.setURL(url,
530
0
                        rNewProperties.getTempURL(), u""_ustr);
531
0
            }
532
0
        }
533
0
        else
534
0
        {
535
0
            m_xImpl->m_pTempFile.reset();
536
0
            m_xImpl->m_MediaProperties.setURL(url, u""_ustr, rNewProperties.getReferer());
537
0
        }
538
0
        ImpRegisterLink();
539
0
        bBroadcastChanged = true;
540
0
    }
541
542
0
    if( AVMediaSetMask::LOOP & nMaskSet )
543
0
        m_xImpl->m_MediaProperties.setLoop( rNewProperties.isLoop() );
544
545
0
    if( AVMediaSetMask::MUTE & nMaskSet )
546
0
        m_xImpl->m_MediaProperties.setMute( rNewProperties.isMute() );
547
548
0
    if( AVMediaSetMask::VOLUMEDB & nMaskSet )
549
0
        m_xImpl->m_MediaProperties.setVolumeDB( rNewProperties.getVolumeDB() );
550
551
0
    if( AVMediaSetMask::ZOOM & nMaskSet )
552
0
        m_xImpl->m_MediaProperties.setZoom( rNewProperties.getZoom() );
553
#else
554
    (void) rNewProperties;
555
#endif
556
557
0
    if( bBroadcastChanged )
558
0
    {
559
0
        SetChanged();
560
0
        BroadcastObjectChange();
561
0
    }
562
0
}
563
564
void SdrMediaObj::ImpRegisterLink()
565
0
{
566
0
    sfx2::LinkManager* pLinkManager(getSdrModelFromSdrObject().GetLinkManager());
567
0
    if (!pLinkManager || m_xImpl->m_pMediaLink)
568
0
        return;
569
570
0
#if HAVE_FEATURE_AVMEDIA
571
    // Media copied into the document is extracted to a temporary file and is
572
    // not a link. Only an external reference gets registered.
573
0
    if (m_xImpl->m_pTempFile)
574
0
        return;
575
0
#endif
576
0
    const OUString& rURL = m_xImpl->m_MediaProperties.getURL();
577
0
    if (rURL.isEmpty() || rURL.startsWithIgnoreAsciiCase("vnd.sun.star.Package:"))
578
0
        return;
579
580
    // Registration happens even in a build without media playback, so the
581
    // external reference stays visible to the user as a document link.
582
0
    m_xImpl->m_pMediaLink = new SdrMediaLink(*this);
583
0
    pLinkManager->InsertFileLink(*m_xImpl->m_pMediaLink,
584
0
                                 sfx2::SvBaseLinkObjectType::ClientFile, rURL);
585
0
}
586
587
void SdrMediaObj::ImpDeregisterLink()
588
0
{
589
0
    sfx2::LinkManager* pLinkManager(getSdrModelFromSdrObject().GetLinkManager());
590
0
    if (pLinkManager && m_xImpl->m_pMediaLink)
591
0
    {
592
        // Remove implicitly deletes the link object
593
0
        pLinkManager->Remove(m_xImpl->m_pMediaLink);
594
0
        m_xImpl->m_pMediaLink = nullptr;
595
0
    }
596
0
}
597
598
void SdrMediaObj::handlePageChange(SdrPage* pOldPage, SdrPage* pNewPage)
599
0
{
600
0
    const bool bRemove(pNewPage == nullptr && pOldPage != nullptr);
601
0
    const bool bInsert(pNewPage != nullptr && pOldPage == nullptr);
602
603
0
    if (bRemove)
604
0
        ImpDeregisterLink();
605
606
0
    SdrRectObj::handlePageChange(pOldPage, pNewPage);
607
608
0
    if (bInsert)
609
0
        ImpRegisterLink();
610
0
}
611
612
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */