Bug Summary

File:/home/gilles/Devel/8.x/core/libs/video/player/qtmm/mediaplayerview.cpp
Warning:line 412, column 5
Potential leak of memory pointed to by 'audioGroup'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name mediaplayerview.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/home/gilles/Devel/8.x/build.scan/core/libs/video -fcoverage-compilation-dir=/home/gilles/Devel/8.x/build.scan/core/libs/video -resource-dir /usr/lib/llvm-18/lib/clang/18 -D BUILDING_XMPCOMPAREANDMERGE_AS_STATIC=1 -D BUILDING_XMPCOMPAREANDMERGE_LIB=1 -D BanAllEntityUsage=1 -D CMS_NO_REGISTER_KEYWORD=1 -D EnablePluginManager=0 -D HAVE_FFMPEG_VERSION5 -D LIBPGF_DISABLE_OPENMP -D LINKING_XMPCORE_LIB=1 -D MAGICKCORE_HDRI_ENABLE=0 -D MAGICKCORE_QUANTUM_DEPTH=16 -D QT_DEPRECATED_WARNINGS -D QT_DEPRECATED_WARNINGS_SINCE=0x060000 -D QT_DISABLE_DEPRECATED_BEFORE=0x050E00 -D QT_NO_CAST_FROM_ASCII -D QT_NO_CAST_FROM_BYTEARRAY -D QT_NO_CAST_TO_ASCII -D QT_NO_FOREACH -D QT_NO_KEYWORDS -D QT_NO_NARROWING_CONVERSIONS_IN_CONNECT -D QT_NO_URL_CAST_FROM_STRING -D QT_STRICT_ITERATORS -D QT_USE_QSTRINGBUILDER -D TRANSLATION_DOMAIN="digikam" -D UNIX_ENV=1 -D USE_JASPER -D USE_JPEG -D USE_JPEG8 -D XMP_COMPONENT_INT_NAMESPACE=AdobeXMPCompareAndMerge_Int -D XMP_StaticBuild=1 -D _GNU_SOURCE -D _LARGEFILE64_SOURCE -D digikamcore_EXPORTS -D qDNGDebug=0 -D qDNGLittleEndian=1 -D qDNGThreadSafe=1 -D qDNGUseLibJPEG=1 -D qDNGUseStdInt=1 -D qDNGUseXMP=1 -D qDNGValidateTarget=1 -D qDNGXMPDocOps=0 -D qDNGXMPFiles=0 -D qLinux=1 -D qMacOS=0 -D qWinOS=0 -I /home/gilles/Devel/8.x/build.scan/core/libs/video -I /home/gilles/Devel/8.x/core/libs/video -I /home/gilles/Devel/8.x/build.scan/core/libs/video/core_videotools_obj_autogen/include -I /home/gilles/Devel/8.x/core/libs/video/player/qtmm -I /home/gilles/Devel/8.x/core/libs/album/engine -I /home/gilles/Devel/8.x/core/libs/album/manager -I /home/gilles/Devel/8.x/core/libs/album/treeview -I /home/gilles/Devel/8.x/core/libs/album/widgets -I /home/gilles/Devel/8.x/core/libs/database/collection -I /home/gilles/Devel/8.x/core/libs/database/coredb -I /home/gilles/Devel/8.x/core/libs/database/dbjobs -I /home/gilles/Devel/8.x/core/libs/database/engine -I /home/gilles/Devel/8.x/core/libs/database/haar -I /home/gilles/Devel/8.x/core/libs/database/history -I /home/gilles/Devel/8.x/core/libs/database/item/containers -I /home/gilles/Devel/8.x/core/libs/database/item/lister -I /home/gilles/Devel/8.x/core/libs/database/item/query -I /home/gilles/Devel/8.x/core/libs/database/item/scanner -I /home/gilles/Devel/8.x/core/libs/database/models -I /home/gilles/Devel/8.x/core/libs/database/server -I /home/gilles/Devel/8.x/core/libs/database/similaritydb -I /home/gilles/Devel/8.x/core/libs/database/tags -I /home/gilles/Devel/8.x/core/libs/database/thumbsdb -I /home/gilles/Devel/8.x/core/libs/database/utils/ifaces -I /home/gilles/Devel/8.x/core/libs/database/utils/scan -I /home/gilles/Devel/8.x/core/libs/database/utils/widgets -I /home/gilles/Devel/8.x/core/libs/dialogs -I /home/gilles/Devel/8.x/core/libs/dimg/color -I /home/gilles/Devel/8.x/core/libs/dimg -I /home/gilles/Devel/8.x/core/libs/dimg/filters/auto -I /home/gilles/Devel/8.x/core/libs/dimg/filters/bcg -I /home/gilles/Devel/8.x/core/libs/dimg/filters/bw -I /home/gilles/Devel/8.x/core/libs/dimg/filters/cb -I /home/gilles/Devel/8.x/core/libs/dimg/filters/curves -I /home/gilles/Devel/8.x/core/libs/dimg/filters/decorate -I /home/gilles/Devel/8.x/core/libs/dimg/filters -I /home/gilles/Devel/8.x/core/libs/dimg/filters/film -I /home/gilles/Devel/8.x/core/libs/dimg/filters/fx -I /home/gilles/Devel/8.x/core/libs/dimg/filters/greycstoration/cimg -I /home/gilles/Devel/8.x/core/libs/dimg/filters/greycstoration -I /home/gilles/Devel/8.x/core/libs/dimg/filters/hotpixels -I /home/gilles/Devel/8.x/core/libs/dimg/filters/hsl -I /home/gilles/Devel/8.x/core/libs/dimg/filters/icc -I /home/gilles/Devel/8.x/core/libs/dimg/filters/lc -I /home/gilles/Devel/8.x/core/libs/dimg/filters/lens -I /home/gilles/Devel/8.x/core/libs/dimg/filters/levels -I /home/gilles/Devel/8.x/core/libs/dimg/filters/nr -I /home/gilles/Devel/8.x/core/libs/dimg/filters/raw -I /home/gilles/Devel/8.x/core/libs/dimg/filters/redeye -I /home/gilles/Devel/8.x/core/libs/dimg/filters/sharp -I /home/gilles/Devel/8.x/core/libs/dimg/filters/transform -I /home/gilles/Devel/8.x/core/libs/dimg/filters/wb -I /home/gilles/Devel/8.x/core/libs/dimg/history -I /home/gilles/Devel/8.x/core/libs/dimg/loaders -I /home/gilles/Devel/8.x/core/libs/dngwriter -I /home/gilles/Devel/8.x/core/libs/dnnmodelmanager -I /home/gilles/Devel/8.x/core/libs/dplugins/core -I /home/gilles/Devel/8.x/core/libs/dplugins/iface -I /home/gilles/Devel/8.x/core/libs/dplugins/setup -I /home/gilles/Devel/8.x/core/libs/dplugins/webservices -I /home/gilles/Devel/8.x/core/libs/dplugins/widgets -I /home/gilles/Devel/8.x/core/libs/dragdrop -I /home/gilles/Devel/8.x/core/libs/dtrash -I /home/gilles/Devel/8.x/core/libs/facesengine/common -I /home/gilles/Devel/8.x/core/libs/facesengine/detection -I /home/gilles/Devel/8.x/core/libs/facesengine/detection/opencv-dnn -I /home/gilles/Devel/8.x/core/libs/facesengine/facedb -I /home/gilles/Devel/8.x/core/libs/facesengine/preprocessing -I /home/gilles/Devel/8.x/core/libs/facesengine/preprocessing/recognition -I /home/gilles/Devel/8.x/core/libs/facesengine/preprocessing/shape-predictor -I /home/gilles/Devel/8.x/core/libs/facesengine/recognition -I /home/gilles/Devel/8.x/core/libs/facesengine/recognition/opencv-dnn -I /home/gilles/Devel/8.x/core/libs/fileactionmanager -I /home/gilles/Devel/8.x/core/libs/filters -I /home/gilles/Devel/8.x/core/libs/imgqsort/detectors -I /home/gilles/Devel/8.x/core/libs/imgqsort -I /home/gilles/Devel/8.x/core/libs/iojobs -I /home/gilles/Devel/8.x/core/libs/jpegutils -I /home/gilles/Devel/8.x/core/libs/metadataengine/containers -I /home/gilles/Devel/8.x/core/libs/metadataengine/dmetadata -I /home/gilles/Devel/8.x/core/libs/metadataengine/engine -I /home/gilles/Devel/8.x/core/libs/metadataengine/exiftool -I /home/gilles/Devel/8.x/core/libs/metadataengine/focuspoint -I /home/gilles/Devel/8.x/core/libs/mlfoundation -I /home/gilles/Devel/8.x/core/libs/models -I /home/gilles/Devel/8.x/core/libs/networkmanager -I /home/gilles/Devel/8.x/core/libs/notificationmanager -I /home/gilles/Devel/8.x/core/libs/onlineversion -I /home/gilles/Devel/8.x/core/libs/pgfutils -I /home/gilles/Devel/8.x/core/libs/progressmanager -I /home/gilles/Devel/8.x/core/libs/properties/captions -I /home/gilles/Devel/8.x/core/libs/properties/geolocation -I /home/gilles/Devel/8.x/core/libs/properties/history -I /home/gilles/Devel/8.x/core/libs/properties/import -I /home/gilles/Devel/8.x/core/libs/properties -I /home/gilles/Devel/8.x/core/libs/qtopencvimg -I /home/gilles/Devel/8.x/core/libs/rawengine -I /home/gilles/Devel/8.x/core/libs/settings -I /home/gilles/Devel/8.x/core/libs/tags/autoassignment -I /home/gilles/Devel/8.x/core/libs/tags/autoassignment/model -I /home/gilles/Devel/8.x/core/libs/tags/engine -I /home/gilles/Devel/8.x/core/libs/tags/manager/models -I /home/gilles/Devel/8.x/core/libs/tags/manager -I /home/gilles/Devel/8.x/core/libs/tags/widgets -I /home/gilles/Devel/8.x/core/libs/template -I /home/gilles/Devel/8.x/core/libs/threadimageio/engine -I /home/gilles/Devel/8.x/core/libs/threadimageio/fileio -I /home/gilles/Devel/8.x/core/libs/threadimageio/preview -I /home/gilles/Devel/8.x/core/libs/threadimageio/thumb -I /home/gilles/Devel/8.x/core/libs/threadimageio/video -I /home/gilles/Devel/8.x/core/libs/threads -I /home/gilles/Devel/8.x/core/libs/timeadjust -I /home/gilles/Devel/8.x/core/libs/transitionmngr -I /home/gilles/Devel/8.x/core/libs/versionmanager -I /home/gilles/Devel/8.x/core/libs/video/manager -I /home/gilles/Devel/8.x/core/libs/video/osd -I /home/gilles/Devel/8.x/core/libs/video/player -I /home/gilles/Devel/8.x/core/libs/widgets/colors -I /home/gilles/Devel/8.x/core/libs/widgets/combo -I /home/gilles/Devel/8.x/core/libs/widgets/files -I /home/gilles/Devel/8.x/core/libs/widgets/fonts -I /home/gilles/Devel/8.x/core/libs/widgets/graphicsview -I /home/gilles/Devel/8.x/core/libs/widgets/history -I /home/gilles/Devel/8.x/core/libs/widgets/iccprofiles -I /home/gilles/Devel/8.x/core/libs/widgets/itemview -I /home/gilles/Devel/8.x/core/libs/widgets/layout -I /home/gilles/Devel/8.x/core/libs/widgets/mainview -I /home/gilles/Devel/8.x/core/libs/widgets/metadata/config -I /home/gilles/Devel/8.x/core/libs/widgets/metadata/exiftool -I /home/gilles/Devel/8.x/core/libs/widgets/metadata/exiv2 -I /home/gilles/Devel/8.x/core/libs/widgets/metadata/labels -I /home/gilles/Devel/8.x/core/libs/widgets/metadata/utils -I /home/gilles/Devel/8.x/core/libs/widgets/range -I /home/gilles/Devel/8.x/core/libs/widgets/text -I /home/gilles/Devel/8.x/core/libs/jpegutils/libjpeg/84 -I /home/gilles/Devel/8.x/core/app/utils -I /home/gilles/Devel/8.x/build.scan/core/app/utils -I /home/gilles/Devel/8.x/core/utilities/advancedrename -I /home/gilles/Devel/8.x/core/utilities/advancedrename/common -I /home/gilles/Devel/8.x/core/utilities/advancedrename/parser -I /home/gilles/Devel/8.x/core/utilities/advancedrename/parser/modifiers -I /home/gilles/Devel/8.x/core/utilities/advancedrename/parser/options -I /home/gilles/Devel/8.x/core/utilities/advancedrename/parser/options/database -I /home/gilles/Devel/8.x/core/utilities/advancedrename/parser/options/database/keys -I /home/gilles/Devel/8.x/core/utilities/extrasupport/addressbook -I /home/gilles/Devel/8.x/core/utilities/extrasupport/filesindexer -I /home/gilles/Devel/8.x/core/utilities/facemanagement/bench -I /home/gilles/Devel/8.x/core/utilities/facemanagement/database -I /home/gilles/Devel/8.x/core/utilities/facemanagement/dialogs -I /home/gilles/Devel/8.x/core/utilities/facemanagement/items -I /home/gilles/Devel/8.x/core/utilities/facemanagement/pipelines/detect -I /home/gilles/Devel/8.x/core/utilities/facemanagement/pipelines/detectrecognize -I /home/gilles/Devel/8.x/core/utilities/facemanagement/pipelines/edit -I /home/gilles/Devel/8.x/core/utilities/facemanagement/pipelines -I /home/gilles/Devel/8.x/core/utilities/facemanagement/pipelines/recognize -I /home/gilles/Devel/8.x/core/utilities/facemanagement/pipelines/reset -I /home/gilles/Devel/8.x/core/utilities/facemanagement/pipelines/retrain -I /home/gilles/Devel/8.x/core/utilities/facemanagement/threads -I /home/gilles/Devel/8.x/core/utilities/facemanagement/widgets -I /home/gilles/Devel/8.x/core/utilities/facemanagement/workers -I /home/gilles/Devel/8.x/core/utilities/firstrun -I /home/gilles/Devel/8.x/core/utilities/focuspointmanagement -I /home/gilles/Devel/8.x/core/utilities/fuzzysearch -I /home/gilles/Devel/8.x/core/utilities/geolocation/engine/astro -I /home/gilles/Devel/8.x/core/utilities/geolocation/engine/blendings -I /home/gilles/Devel/8.x/core/utilities/geolocation/engine/core -I /home/gilles/Devel/8.x/core/utilities/geolocation/engine/geodata/data -I /home/gilles/Devel/8.x/core/utilities/geolocation/engine/geodata/graphicsitem -I /home/gilles/Devel/8.x/core/utilities/geolocation/engine/geodata/handlers/dgml -I /home/gilles/Devel/8.x/core/utilities/geolocation/engine/geodata/handlers/kml -I /home/gilles/Devel/8.x/core/utilities/geolocation/engine/geodata/parser -I /home/gilles/Devel/8.x/core/utilities/geolocation/engine/geodata/scene -I /home/gilles/Devel/8.x/core/utilities/geolocation/engine/geodata/writer -I /home/gilles/Devel/8.x/core/utilities/geolocation/engine/geodata/writers/dgml -I /home/gilles/Devel/8.x/core/utilities/geolocation/engine/geodata/writers/kml -I /home/gilles/Devel/8.x/core/utilities/geolocation/engine/graphicsview -I /home/gilles/Devel/8.x/core/utilities/geolocation/engine/layers -I /home/gilles/Devel/8.x/core/utilities/geolocation/engine/models -I /home/gilles/Devel/8.x/core/utilities/geolocation/engine/osm -I /home/gilles/Devel/8.x/core/utilities/geolocation/engine/plugins -I /home/gilles/Devel/8.x/core/utilities/geolocation/engine/plugins/render/atmosphere -I /home/gilles/Devel/8.x/core/utilities/geolocation/engine/plugins/render/compass -I /home/gilles/Devel/8.x/core/utilities/geolocation/engine/plugins/render/crosshairs -I /home/gilles/Devel/8.x/core/utilities/geolocation/engine/plugins/render/graticule -I /home/gilles/Devel/8.x/core/utilities/geolocation/engine/plugins/render/mapscale -I /home/gilles/Devel/8.x/core/utilities/geolocation/engine/plugins/render/measure -I /home/gilles/Devel/8.x/core/utilities/geolocation/engine/plugins/render/navigation -I /home/gilles/Devel/8.x/core/utilities/geolocation/engine/plugins/render/overviewmap -I /home/gilles/Devel/8.x/core/utilities/geolocation/engine/plugins/render/progress -I /home/gilles/Devel/8.x/core/utilities/geolocation/engine/plugins/runner/cache -I /home/gilles/Devel/8.x/core/utilities/geolocation/engine/plugins/runner/gpsbabel -I /home/gilles/Devel/8.x/core/utilities/geolocation/engine/plugins/runner/gpx -I /home/gilles/Devel/8.x/core/utilities/geolocation/engine/plugins/runner/gpx/handlers -I /home/gilles/Devel/8.x/core/utilities/geolocation/engine/plugins/runner/json -I /home/gilles/Devel/8.x/core/utilities/geolocation/engine/plugins/runner/kml -I /home/gilles/Devel/8.x/core/utilities/geolocation/engine/plugins/runner/nominatim-reversegeocoding -I /home/gilles/Devel/8.x/core/utilities/geolocation/engine/plugins/runner/osm -I /home/gilles/Devel/8.x/core/utilities/geolocation/engine/plugins/runner/osm/o5mreader -I /home/gilles/Devel/8.x/core/utilities/geolocation/engine/plugins/runner/osm/translators -I /home/gilles/Devel/8.x/core/utilities/geolocation/engine/plugins/runner/osm/writers -I /home/gilles/Devel/8.x/core/utilities/geolocation/engine/plugins/runner/pn2 -I /home/gilles/Devel/8.x/core/utilities/geolocation/engine/plugins/runner/pnt -I /home/gilles/Devel/8.x/core/utilities/geolocation/engine/projections -I /home/gilles/Devel/8.x/core/utilities/geolocation/engine/runners -I /home/gilles/Devel/8.x/core/utilities/geolocation/engine/settings -I /home/gilles/Devel/8.x/core/utilities/geolocation/engine/storage -I /home/gilles/Devel/8.x/core/utilities/geolocation/engine/tile -I /home/gilles/Devel/8.x/core/utilities/geolocation/geoiface/backends -I /home/gilles/Devel/8.x/core/utilities/geolocation/geoiface/bookmark -I /home/gilles/Devel/8.x/core/utilities/geolocation/geoiface/core -I /home/gilles/Devel/8.x/core/utilities/geolocation/geoiface/correlator -I /home/gilles/Devel/8.x/core/utilities/geolocation/geoiface/dragdrop -I /home/gilles/Devel/8.x/core/utilities/geolocation/geoiface/items -I /home/gilles/Devel/8.x/core/utilities/geolocation/geoiface/lookup -I /home/gilles/Devel/8.x/core/utilities/geolocation/geoiface/reversegeocoding -I /home/gilles/Devel/8.x/core/utilities/geolocation/geoiface/tiles -I /home/gilles/Devel/8.x/core/utilities/geolocation/geoiface/tracks -I /home/gilles/Devel/8.x/core/utilities/geolocation/geoiface/widgets -I /home/gilles/Devel/8.x/core/utilities/geolocation/geomapwrapper -I /home/gilles/Devel/8.x/core/utilities/geolocation/mapsearches -I /home/gilles/Devel/8.x/core/utilities/imageeditor/core -I /home/gilles/Devel/8.x/core/utilities/imageeditor/dialogs -I /home/gilles/Devel/8.x/core/utilities/imageeditor/editor -I /home/gilles/Devel/8.x/core/utilities/imageeditor/main -I /home/gilles/Devel/8.x/core/utilities/imageeditor/widgets -I /home/gilles/Devel/8.x/core/utilities/import/backend -I /home/gilles/Devel/8.x/core/utilities/import/dialogs -I /home/gilles/Devel/8.x/core/utilities/import/items -I /home/gilles/Devel/8.x/core/utilities/import/main -I /home/gilles/Devel/8.x/core/utilities/import/models -I /home/gilles/Devel/8.x/core/utilities/import/views -I /home/gilles/Devel/8.x/core/utilities/import/widgets -I /home/gilles/Devel/8.x/core/utilities/lighttable -I /home/gilles/Devel/8.x/core/utilities/maintenance/main -I /home/gilles/Devel/8.x/core/utilities/maintenance/manager -I /home/gilles/Devel/8.x/core/utilities/maintenance/tools/autotags -I /home/gilles/Devel/8.x/core/utilities/maintenance/tools/dbcleaner -I /home/gilles/Devel/8.x/core/utilities/maintenance/tools/dbscan -I /home/gilles/Devel/8.x/core/utilities/maintenance/tools/duplicates -I /home/gilles/Devel/8.x/core/utilities/maintenance/tools/facesmanagement -I /home/gilles/Devel/8.x/core/utilities/maintenance/tools/fingerprints -I /home/gilles/Devel/8.x/core/utilities/maintenance/tools/imgqsort -I /home/gilles/Devel/8.x/core/utilities/maintenance/tools/metaremover -I /home/gilles/Devel/8.x/core/utilities/maintenance/tools/metasync -I /home/gilles/Devel/8.x/core/utilities/maintenance/tools/thumbs -I /home/gilles/Devel/8.x/core/utilities/maintenance/utils -I /home/gilles/Devel/8.x/core/utilities/queuemanager/dplugins -I /home/gilles/Devel/8.x/core/utilities/queuemanager/main -I /home/gilles/Devel/8.x/core/utilities/queuemanager/manager -I /home/gilles/Devel/8.x/core/utilities/queuemanager/views -I /home/gilles/Devel/8.x/core/utilities/searchwindow -I /home/gilles/Devel/8.x/core/utilities/setup/album -I /home/gilles/Devel/8.x/core/utilities/setup/camera -I /home/gilles/Devel/8.x/core/utilities/setup/collections -I /home/gilles/Devel/8.x/core/utilities/setup/downloader -I /home/gilles/Devel/8.x/core/utilities/setup/editor -I /home/gilles/Devel/8.x/core/utilities/setup/metadata -I /home/gilles/Devel/8.x/core/utilities/setup/misc -I /home/gilles/Devel/8.x/core/utilities/setup -I /home/gilles/Devel/8.x/core/app/main -I /home/gilles/Devel/8.x/core/app/date -I /home/gilles/Devel/8.x/core/app/dragdrop -I /home/gilles/Devel/8.x/core/app/views/stack -I /home/gilles/Devel/8.x/core/app/views/utils -I /home/gilles/Devel/8.x/core/app/items/utils -I /home/gilles/Devel/8.x/core/app/items/delegate -I /home/gilles/Devel/8.x/core/app/views/sidebar -I /opt/qt6/include/opencv4 -I /usr/include/ImageMagick-6 -I /usr/include/x86_64-linux-gnu/ImageMagick-6 -I /opt/qt6/include/QtMultimedia -I /opt/qt6/include -I /opt/qt6/include/QtCore -I /opt/qt6/mkspecs/linux-g++ -I /opt/qt6/include/QtGui -I /opt/qt6/include/QtNetwork -I /opt/qt6/include/QtMultimediaWidgets -I /opt/qt6/include/QtWidgets -I /opt/qt6/include/KF6/KI18n -I /opt/qt6/include/KF6/KConfig -I /opt/qt6/include/KF6/KConfigCore -I /opt/qt6/include/KF6/KService -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/13/../../../../include/x86_64-linux-gnu/c++/13 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/backward -internal-isystem /usr/lib/llvm-18/lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/13/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wno-long-long -Wno-deprecated-copy -std=c++20 -fdeprecated-macro -ferror-limit 19 -fvisibility=hidden -fvisibility-inlines-hidden -fno-operator-names -fopenmp -fgnuc-version=4.2.1 -fno-implicit-modules -fskip-odr-check-in-gmf -fcxx-exceptions -fexceptions -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /mnt/data/Devel/8.x/project/reports/report.scan/2025-01-07-141428-4875-1 -x c++ /home/gilles/Devel/8.x/core/libs/video/player/qtmm/mediaplayerview.cpp
1/* ============================================================
2 *
3 * This file is a part of digiKam project
4 * https://www.digikam.org
5 *
6 * Date : 2006-20-12
7 * Description : a view to embed QtMultimedia media player.
8 *
9 * SPDX-FileCopyrightText: 2006-2025 by Gilles Caulier <caulier dot gilles at gmail dot com>
10 *
11 * SPDX-License-Identifier: GPL-2.0-or-later
12 *
13 * ============================================================ */
14
15#include "mediaplayerview.h"
16
17// Qt includes
18
19#include <QApplication>
20#include <QActionGroup>
21#include <QVBoxLayout>
22#include <QMouseEvent>
23#include <QProxyStyle>
24#include <QPushButton>
25#include <QToolButton>
26#include <QFileInfo>
27#include <QToolBar>
28#include <QAction>
29#include <QSlider>
30#include <QLabel>
31#include <QFrame>
32#include <QStyle>
33#include <QMenu>
34#include <QTransform>
35#include <QGraphicsView>
36#include <QGraphicsScene>
37#include <QGraphicsVideoItem>
38#include <QVideoSink>
39#include <QVideoFrame>
40#include <QAudioOutput>
41#include <QAudioDevice>
42#include <QMediaDevices>
43#include <QMediaMetaData>
44#include <QStandardPaths>
45
46// KDE includes
47
48#include <klocalizedstring.h>
49#include <ksharedconfig.h>
50#include <kconfiggroup.h>
51
52// Local includes
53
54#include "digikam_debug.h"
55#include "digikam_globals.h"
56#include "thememanager.h"
57#include "stackedview.h"
58#include "dlayoutbox.h"
59#include "metaengine.h"
60#include "dmetadata.h"
61
62namespace Digikam
63{
64
65class Q_DECL_HIDDEN__attribute__((visibility("hidden"))) MediaPlayerMouseClickFilter : public QObject
66{
67 Q_OBJECTpublic: clang diagnostic push clang diagnostic ignored "-Winconsistent-missing-override"
clang diagnostic ignored "-Wsuggest-override" static const
QMetaObject staticMetaObject; virtual const QMetaObject *metaObject
() const; virtual void *qt_metacast(const char *); virtual int
qt_metacall(QMetaObject::Call, int, void **); static inline QString
tr(const char *s, const char *c = nullptr, int n = -1) { return
staticMetaObject.tr(s, c, n); } private: __attribute__((visibility
("hidden"))) static void qt_static_metacall(QObject *, QMetaObject
::Call, int, void **); clang diagnostic pop struct QPrivateSignal
{ explicit QPrivateSignal () = default; };
68
69public:
70
71 explicit MediaPlayerMouseClickFilter(QObject* const parent)
72 : QObject (parent),
73 m_parent(parent)
74 {
75 }
76
77protected:
78
79 bool eventFilter(QObject* obj, QEvent* event) override
80 {
81 if ((event->type() == QEvent::MouseButtonPress) || (event->type() == QEvent::MouseButtonDblClick))
82 {
83 bool singleClick = qApp(static_cast<QApplication *>(QCoreApplication::instance
()))
->style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick);
84 QMouseEvent* const mouseEvent = dynamic_cast<QMouseEvent*>(event);
85
86 if (m_parent && mouseEvent)
87 {
88 MediaPlayerView* const mplayer = dynamic_cast<MediaPlayerView*>(m_parent);
89
90 if (mplayer)
91 {
92 if (
93 (mouseEvent->button() == Qt::LeftButton) &&
94 (
95 (singleClick && (event->type() == QEvent::MouseButtonPress)) ||
96 (!singleClick && (event->type() == QEvent::MouseButtonDblClick))
97 )
98 )
99 {
100 mplayer->slotEscapePressed();
101 }
102 else if (
103 (mouseEvent->button() == Qt::RightButton) &&
104 (event->type() == QEvent::MouseButtonPress)
105 )
106 {
107 mplayer->slotRotateVideo();
108 }
109
110 return true;
111 }
112 }
113 }
114
115 return QObject::eventFilter(obj, event);
116 }
117
118private:
119
120 QObject* m_parent = nullptr;
121};
122
123// --------------------------------------------------------
124
125class Q_DECL_HIDDEN__attribute__((visibility("hidden"))) PlayerVideoStyle : public QProxyStyle
126{
127 Q_OBJECTpublic: clang diagnostic push clang diagnostic ignored "-Winconsistent-missing-override"
clang diagnostic ignored "-Wsuggest-override" static const
QMetaObject staticMetaObject; virtual const QMetaObject *metaObject
() const; virtual void *qt_metacast(const char *); virtual int
qt_metacall(QMetaObject::Call, int, void **); static inline QString
tr(const char *s, const char *c = nullptr, int n = -1) { return
staticMetaObject.tr(s, c, n); } private: __attribute__((visibility
("hidden"))) static void qt_static_metacall(QObject *, QMetaObject
::Call, int, void **); clang diagnostic pop struct QPrivateSignal
{ explicit QPrivateSignal () = default; };
128
129public:
130
131 using QProxyStyle::QProxyStyle;
132
133 int styleHint(QStyle::StyleHint hint,
134 const QStyleOption* option = nullptr,
135 const QWidget* widget = nullptr,
136 QStyleHintReturn* returnData = nullptr) const override
137 {
138 if (hint == QStyle::SH_Slider_AbsoluteSetButtons)
139 {
140 return (Qt::LeftButton | Qt::MiddleButton | Qt::RightButton);
141 }
142
143 return QProxyStyle::styleHint(hint, option, widget, returnData);
144 }
145};
146
147// --------------------------------------------------------
148
149class MediaPlayerView::Private
150{
151
152public:
153
154 enum MediaPlayerViewMode
155 {
156 ErrorView = 0,
157 PlayerView
158 };
159
160public:
161
162 Private() = default;
163
164 QFrame* errorView = nullptr;
165 QFrame* playerView = nullptr;
166
167 QAction* prevAction = nullptr;
168 QAction* nextAction = nullptr;
169 QAction* playAction = nullptr;
170 QAction* grabAction = nullptr;
171 QAction* backAction = nullptr;
172 QAction* forwAction = nullptr;
173
174 QToolButton* rateButton = nullptr;
175
176 QPushButton* loopPlay = nullptr;
177 QPushButton* speaker = nullptr;
178
179 QToolBar* toolBar = nullptr;
180
181 DInfoInterface* iface = nullptr;
182
183 QGraphicsScene* videoScene = nullptr;
184 QGraphicsView* videoView = nullptr;
185 QGraphicsVideoItem* videoItem = nullptr;
186 QMediaPlayer* player = nullptr;
187 QAudioOutput* audio = nullptr;
188
189 QSlider* slider = nullptr;
190 QSlider* volume = nullptr;
191 QLabel* tlabel = nullptr;
192
193 QUrl currentItem;
194
195 int videoOrientation = 0;
196 qint64 sliderTime = 0;
197
198 const QUrl dummyVideo = QUrl::fromLocalFile(
199 QStandardPaths::locate(
200 QStandardPaths::GenericDataLocation,
201 QLatin1String("digikam/data/video-digikam.mp4")));
202
203public:
204
205 void adjustVideoSize()
206 {
207 videoItem->resetTransform();
208
209 QSizeF nativeSize = videoItem->nativeSize();
210 int mediaOrientation = videoMediaOrientation();
211
212 if (
213 (nativeSize.width() < 1.0) ||
214 (nativeSize.height() < 1.0)
215 )
216 {
217 return;
218 }
219
220 if (
221 (mediaOrientation == 90) ||
222 (mediaOrientation == 270)
223 )
224 {
225 nativeSize.transpose();
226 }
227
228 double ratio = (nativeSize.width() /
229 nativeSize.height());
230
231 if (videoView->width() > videoView->height())
232 {
233 QSizeF vsize(videoView->height() * ratio,
234 videoView->height());
235 videoItem->setSize(vsize);
236 }
237 else
238 {
239 QSizeF vsize(videoView->width(),
240 videoView->width() / ratio);
241 videoItem->setSize(vsize);
242 }
243
244 videoView->setSceneRect(0, 0, videoItem->size().width(),
245 videoItem->size().height());
246
247 QPointF center = videoItem->boundingRect().center();
248 videoItem->setTransformOriginPoint(center);
249 videoItem->setRotation(videoOrientation);
250
251 videoView->fitInView(videoItem, Qt::KeepAspectRatio);
252 videoView->centerOn(videoItem);
253 videoView->raise();
254 };
255
256 int videoMediaOrientation() const
257 {
258 int orientation = 0;
259 QVariant val = player->metaData().value(QMediaMetaData::Orientation);
260
261 if (!val.isNull())
262 {
263 orientation = val.toInt();
264 }
265
266 return orientation;
267 };
268
269 void setVideoItemOrientation(int orientation)
270 {
271 videoOrientation = orientation;
272 adjustVideoSize();
273 };
274};
275
276MediaPlayerView::MediaPlayerView(QWidget* const parent)
277 : QStackedWidget(parent),
278 d (new Private)
279{
280 setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
281
282 const int spacing = layoutSpacing();
283
284
285 d->prevAction = new QAction(QIcon::fromTheme(QLatin1String("go-previous")),
286 i18nc("go to previous image", "Back")i18ndc("digikam", "go to previous image", "Back"), this);
287 d->nextAction = new QAction(QIcon::fromTheme(QLatin1String("go-next")),
288 i18nc("go to next image", "Forward")i18ndc("digikam", "go to next image", "Forward"), this);
289 d->backAction = new QAction(QIcon::fromTheme(QLatin1String("media-seek-backward")),
290 i18nc("video frame backward", "Frame Backward")i18ndc("digikam", "video frame backward", "Frame Backward"), this);
291 d->playAction = new QAction(QIcon::fromTheme(QLatin1String("media-playback-start")),
292 i18nc("pause/play video", "Pause/Play")i18ndc("digikam", "pause/play video", "Pause/Play"), this);
293 d->forwAction = new QAction(QIcon::fromTheme(QLatin1String("media-seek-forward")),
294 i18nc("video frame forward", "Frame Forward")i18ndc("digikam", "video frame forward", "Frame Forward"), this);
295 d->grabAction = new QAction(QIcon::fromTheme(QLatin1String("view-preview")),
296 i18nc("capture video frame", "Capture")i18ndc("digikam", "capture video frame", "Capture"), this);
297
298 d->rateButton = new QToolButton(this);
299 d->rateButton->setToolTip(i18nc("@info", "Change video playback rate")i18ndc("digikam", "@info", "Change video playback rate"));
300 d->rateButton->setIcon(QIcon::fromTheme(QLatin1String("player-time")));
301 d->rateButton->setPopupMode(QToolButton::InstantPopup);
302 d->rateButton->setArrowType(Qt::NoArrow);
303
304 QMenu* const rateMenu = new QMenu(this);
305 QActionGroup* const rateGroup = new QActionGroup(this);
306
307 QAction* const rate05 = rateGroup->addAction(i18nc("video play rate", "0.5x")i18ndc("digikam", "video play rate", "0.5x"));
308 rate05->setCheckable(true);
309 rate05->setData(0.5);
310 QAction* const rate10 = rateGroup->addAction(i18nc("video play rate", "1.0x")i18ndc("digikam", "video play rate", "1.0x"));
311 rate10->setCheckable(true);
312 rate10->setData(1.0);
313 QAction* const rate15 = rateGroup->addAction(i18nc("video play rate", "1.5x")i18ndc("digikam", "video play rate", "1.5x"));
314 rate15->setCheckable(true);
315 rate15->setData(1.5);
316 QAction* const rate20 = rateGroup->addAction(i18nc("video play rate", "2.0x")i18ndc("digikam", "video play rate", "2.0x"));
317 rate20->setCheckable(true);
318 rate20->setData(2.0);
319 QAction* const rate25 = rateGroup->addAction(i18nc("video play rate", "2.5x")i18ndc("digikam", "video play rate", "2.5x"));
320 rate25->setCheckable(true);
321 rate25->setData(2.5);
322 QAction* const rate30 = rateGroup->addAction(i18nc("video play rate", "3.0x")i18ndc("digikam", "video play rate", "3.0x"));
323 rate30->setCheckable(true);
324 rate30->setData(3.0);
325 QAction* const rate40 = rateGroup->addAction(i18nc("video play rate", "4.0x")i18ndc("digikam", "video play rate", "4.0x"));
326 rate40->setCheckable(true);
327 rate40->setData(4.0);
328 QAction* const rate50 = rateGroup->addAction(i18nc("video play rate", "5.0x")i18ndc("digikam", "video play rate", "5.0x"));
329 rate50->setCheckable(true);
330 rate50->setData(5.0);
331
332 rate10->setChecked(true);
333
334 rateMenu->addAction(rate05);
335 rateMenu->addAction(rate10);
336 rateMenu->addAction(rate15);
337 rateMenu->addAction(rate20);
338 rateMenu->addAction(rate25);
339 rateMenu->addAction(rate30);
340 rateMenu->addAction(rate40);
341 rateMenu->addAction(rate50);
342 d->rateButton->setMenu(rateMenu);
343
344 d->errorView = new QFrame(this);
345 QLabel* const errorMsg = new QLabel(i18n("An error has occurred with the media player...")i18nd("digikam", "An error has occurred with the media player..."
)
, this);
346
347 errorMsg->setAlignment(Qt::AlignCenter);
348 d->errorView->setFrameStyle(QFrame::StyledPanel | QFrame::Plain);
349 d->errorView->setLineWidth(1);
350
351 QVBoxLayout* const vbox1 = new QVBoxLayout(d->errorView);
352 vbox1->addWidget(errorMsg, 10);
353 vbox1->setContentsMargins(QMargins());
354 vbox1->setSpacing(spacing);
355
356 insertWidget(Private::ErrorView, d->errorView);
357
358 // --------------------------------------------------------------------------
359
360 d->playerView = new QFrame(this);
361 d->videoScene = new QGraphicsScene(this);
362 d->videoView = new QGraphicsView(d->videoScene);
363 d->videoView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
364 d->videoView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
365 d->videoView->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents);
366 d->videoView->setFrameShape(QFrame::NoFrame);
367 d->videoItem = new QGraphicsVideoItem();
368 d->player = new QMediaPlayer(this);
369 d->audio = new QAudioOutput;
370 d->player->setAudioOutput(d->audio);
371 d->player->setVideoOutput(d->videoItem);
372 d->videoScene->addItem(d->videoItem);
373
374 d->playerView->setFrameStyle(QFrame::StyledPanel | QFrame::Plain);
375 d->playerView->setLineWidth(1);
376
377 d->videoItem->setAspectRatioMode(Qt::IgnoreAspectRatio);
378 d->videoView->setMouseTracking(true);
379
380 DHBox* const hbox = new DHBox(this);
381 d->slider = new QSlider(Qt::Horizontal, hbox);
382 d->slider->setStyle(new PlayerVideoStyle());
383 d->slider->setRange(0, 0);
384 d->tlabel = new QLabel(hbox);
385 d->tlabel->setText(QLatin1String("00:00:00 / 00:00:00"));
386 d->loopPlay = new QPushButton(hbox);
387 d->loopPlay->setIcon(QIcon::fromTheme(QLatin1String("media-playlist-normal")));
388 d->loopPlay->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
389 d->loopPlay->setToolTip(i18n("Toggle playing in a loop")i18nd("digikam", "Toggle playing in a loop"));
390 d->loopPlay->setFocusPolicy(Qt::NoFocus);
391 d->loopPlay->setMinimumSize(22, 22);
392 d->loopPlay->setCheckable(true);
393
394 d->speaker = new QPushButton(hbox);
395 d->speaker->setIcon(QIcon::fromTheme(QLatin1String("audio-volume-high")));
396 d->speaker->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
397 d->speaker->setFocusPolicy(Qt::NoFocus);
398 d->speaker->setMinimumSize(22, 22);
399
400 QMenu* const audioMenu = new QMenu(this);
401 QActionGroup* const audioGroup = new QActionGroup(this);
1
Memory is allocated
402
403 for (const auto& device : QMediaDevices::audioOutputs())
404 {
405 QAction* const action = audioGroup->addAction(device.description());
406 action->setCheckable(true);
407 action->setData(device.id());
408 action->setChecked(device.isDefault());
409 audioMenu->addAction(action);
410 }
411
412 d->speaker->setMenu(audioMenu);
2
Potential leak of memory pointed to by 'audioGroup'
413
414 d->volume = new QSlider(Qt::Horizontal, hbox);
415 d->volume->setRange(0, 100);
416 d->volume->setValue(50);
417
418 hbox->setStretchFactor(d->slider, 10);
419 hbox->setContentsMargins(0, 0, 0, spacing);
420 hbox->setSpacing(spacing);
421
422 QVBoxLayout* const vbox2 = new QVBoxLayout(d->playerView);
423 vbox2->addWidget(d->videoView, 10);
424 vbox2->addWidget(hbox, 0);
425 vbox2->setContentsMargins(QMargins());
426 vbox2->setSpacing(spacing);
427
428 insertWidget(Private::PlayerView, d->playerView);
429
430 d->toolBar = new QToolBar(this);
431 d->toolBar->addAction(d->prevAction);
432 d->toolBar->addAction(d->nextAction);
433 d->toolBar->addAction(d->backAction);
434 d->toolBar->addAction(d->playAction);
435 d->toolBar->addAction(d->forwAction);
436 d->toolBar->addWidget(d->rateButton);
437 d->toolBar->addAction(d->grabAction);
438 d->toolBar->setStyleSheet(toolButtonStyleSheet());
439
440 setPreviewMode(Private::PlayerView);
441
442 d->errorView->installEventFilter(new MediaPlayerMouseClickFilter(this));
443 d->videoView->installEventFilter(new MediaPlayerMouseClickFilter(this));
444 d->playerView->installEventFilter(this);
445
446 KSharedConfig::Ptr config = KSharedConfig::openConfig();
447 KConfigGroup group = config->group(QLatin1String("Media Player Settings"));
448 int volume = group.readEntry("Volume", 50);
449
450 d->volume->setValue(volume);
451 d->audio->setVolume(volume / 100.0F);
452
453 // --------------------------------------------------------------------------
454
455 connect(ThemeManager::instance(), SIGNAL(signalThemeChanged())qFlagLocation("2" "signalThemeChanged()" "\0" "/home/gilles/Devel/8.x/core/libs/video/player/qtmm/mediaplayerview.cpp"
":" "455")
,
456 this, SLOT(slotThemeChanged())qFlagLocation("1" "slotThemeChanged()" "\0" "/home/gilles/Devel/8.x/core/libs/video/player/qtmm/mediaplayerview.cpp"
":" "456")
);
457
458 connect(d->prevAction, SIGNAL(triggered())qFlagLocation("2" "triggered()" "\0" "/home/gilles/Devel/8.x/core/libs/video/player/qtmm/mediaplayerview.cpp"
":" "458")
,
459 this, SIGNAL(signalPrevItem())qFlagLocation("2" "signalPrevItem()" "\0" "/home/gilles/Devel/8.x/core/libs/video/player/qtmm/mediaplayerview.cpp"
":" "459")
);
460
461 connect(d->nextAction, SIGNAL(triggered())qFlagLocation("2" "triggered()" "\0" "/home/gilles/Devel/8.x/core/libs/video/player/qtmm/mediaplayerview.cpp"
":" "461")
,
462 this, SIGNAL(signalNextItem())qFlagLocation("2" "signalNextItem()" "\0" "/home/gilles/Devel/8.x/core/libs/video/player/qtmm/mediaplayerview.cpp"
":" "462")
);
463
464 connect(d->backAction, SIGNAL(triggered())qFlagLocation("2" "triggered()" "\0" "/home/gilles/Devel/8.x/core/libs/video/player/qtmm/mediaplayerview.cpp"
":" "464")
,
465 this, SLOT(slotFrameBackward())qFlagLocation("1" "slotFrameBackward()" "\0" "/home/gilles/Devel/8.x/core/libs/video/player/qtmm/mediaplayerview.cpp"
":" "465")
);
466
467 connect(d->playAction, SIGNAL(triggered())qFlagLocation("2" "triggered()" "\0" "/home/gilles/Devel/8.x/core/libs/video/player/qtmm/mediaplayerview.cpp"
":" "467")
,
468 this, SLOT(slotPausePlay())qFlagLocation("1" "slotPausePlay()" "\0" "/home/gilles/Devel/8.x/core/libs/video/player/qtmm/mediaplayerview.cpp"
":" "468")
);
469
470 connect(d->forwAction, SIGNAL(triggered())qFlagLocation("2" "triggered()" "\0" "/home/gilles/Devel/8.x/core/libs/video/player/qtmm/mediaplayerview.cpp"
":" "470")
,
471 this, SLOT(slotFrameForward())qFlagLocation("1" "slotFrameForward()" "\0" "/home/gilles/Devel/8.x/core/libs/video/player/qtmm/mediaplayerview.cpp"
":" "471")
);
472
473 connect(d->grabAction, SIGNAL(triggered())qFlagLocation("2" "triggered()" "\0" "/home/gilles/Devel/8.x/core/libs/video/player/qtmm/mediaplayerview.cpp"
":" "473")
,
474 this, SLOT(slotCapture())qFlagLocation("1" "slotCapture()" "\0" "/home/gilles/Devel/8.x/core/libs/video/player/qtmm/mediaplayerview.cpp"
":" "474")
);
475
476 connect(d->slider, SIGNAL(sliderMoved(int))qFlagLocation("2" "sliderMoved(int)" "\0" "/home/gilles/Devel/8.x/core/libs/video/player/qtmm/mediaplayerview.cpp"
":" "476")
,
477 this, SLOT(slotPosition(int))qFlagLocation("1" "slotPosition(int)" "\0" "/home/gilles/Devel/8.x/core/libs/video/player/qtmm/mediaplayerview.cpp"
":" "477")
);
478
479 connect(d->slider, SIGNAL(valueChanged(int))qFlagLocation("2" "valueChanged(int)" "\0" "/home/gilles/Devel/8.x/core/libs/video/player/qtmm/mediaplayerview.cpp"
":" "479")
,
480 this, SLOT(slotPosition(int))qFlagLocation("1" "slotPosition(int)" "\0" "/home/gilles/Devel/8.x/core/libs/video/player/qtmm/mediaplayerview.cpp"
":" "480")
);
481
482 connect(d->volume, SIGNAL(valueChanged(int))qFlagLocation("2" "valueChanged(int)" "\0" "/home/gilles/Devel/8.x/core/libs/video/player/qtmm/mediaplayerview.cpp"
":" "482")
,
483 this, SLOT(slotVolumeChanged(int))qFlagLocation("1" "slotVolumeChanged(int)" "\0" "/home/gilles/Devel/8.x/core/libs/video/player/qtmm/mediaplayerview.cpp"
":" "483")
);
484
485 connect(d->loopPlay, SIGNAL(toggled(bool))qFlagLocation("2" "toggled(bool)" "\0" "/home/gilles/Devel/8.x/core/libs/video/player/qtmm/mediaplayerview.cpp"
":" "485")
,
486 this, SLOT(slotLoopToggled(bool))qFlagLocation("1" "slotLoopToggled(bool)" "\0" "/home/gilles/Devel/8.x/core/libs/video/player/qtmm/mediaplayerview.cpp"
":" "486")
);
487
488 connect(d->player, SIGNAL(playbackStateChanged(QMediaPlayer::PlaybackState))qFlagLocation("2" "playbackStateChanged(QMediaPlayer::PlaybackState)"
"\0" "/home/gilles/Devel/8.x/core/libs/video/player/qtmm/mediaplayerview.cpp"
":" "488")
,
489 this, SLOT(slotPlayerStateChanged(QMediaPlayer::PlaybackState))qFlagLocation("1" "slotPlayerStateChanged(QMediaPlayer::PlaybackState)"
"\0" "/home/gilles/Devel/8.x/core/libs/video/player/qtmm/mediaplayerview.cpp"
":" "489")
);
490
491 connect(d->player, SIGNAL(positionChanged(qint64))qFlagLocation("2" "positionChanged(qint64)" "\0" "/home/gilles/Devel/8.x/core/libs/video/player/qtmm/mediaplayerview.cpp"
":" "491")
,
492 this, SLOT(slotPositionChanged(qint64))qFlagLocation("1" "slotPositionChanged(qint64)" "\0" "/home/gilles/Devel/8.x/core/libs/video/player/qtmm/mediaplayerview.cpp"
":" "492")
);
493
494 connect(d->player, SIGNAL(durationChanged(qint64))qFlagLocation("2" "durationChanged(qint64)" "\0" "/home/gilles/Devel/8.x/core/libs/video/player/qtmm/mediaplayerview.cpp"
":" "494")
,
495 this, SLOT(slotDurationChanged(qint64))qFlagLocation("1" "slotDurationChanged(qint64)" "\0" "/home/gilles/Devel/8.x/core/libs/video/player/qtmm/mediaplayerview.cpp"
":" "495")
);
496
497 connect(d->player, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus))qFlagLocation("2" "mediaStatusChanged(QMediaPlayer::MediaStatus)"
"\0" "/home/gilles/Devel/8.x/core/libs/video/player/qtmm/mediaplayerview.cpp"
":" "497")
,
498 this, SLOT(slotMediaStatusChanged(QMediaPlayer::MediaStatus))qFlagLocation("1" "slotMediaStatusChanged(QMediaPlayer::MediaStatus)"
"\0" "/home/gilles/Devel/8.x/core/libs/video/player/qtmm/mediaplayerview.cpp"
":" "498")
);
499
500 connect(d->player, SIGNAL(errorOccurred(QMediaPlayer::Error,QString))qFlagLocation("2" "errorOccurred(QMediaPlayer::Error,QString)"
"\0" "/home/gilles/Devel/8.x/core/libs/video/player/qtmm/mediaplayerview.cpp"
":" "500")
,
501 this, SLOT(slotHandlePlayerError(QMediaPlayer::Error,QString))qFlagLocation("1" "slotHandlePlayerError(QMediaPlayer::Error,QString)"
"\0" "/home/gilles/Devel/8.x/core/libs/video/player/qtmm/mediaplayerview.cpp"
":" "501")
);
502
503 connect(d->videoItem, SIGNAL(nativeSizeChanged(QSizeF))qFlagLocation("2" "nativeSizeChanged(QSizeF)" "\0" "/home/gilles/Devel/8.x/core/libs/video/player/qtmm/mediaplayerview.cpp"
":" "503")
,
504 this, SLOT(slotNativeSizeChanged())qFlagLocation("1" "slotNativeSizeChanged()" "\0" "/home/gilles/Devel/8.x/core/libs/video/player/qtmm/mediaplayerview.cpp"
":" "504")
);
505
506 connect(rateMenu, SIGNAL(triggered(QAction*))qFlagLocation("2" "triggered(QAction*)" "\0" "/home/gilles/Devel/8.x/core/libs/video/player/qtmm/mediaplayerview.cpp"
":" "506")
,
507 this, SLOT(slotPlaybackRate(QAction*))qFlagLocation("1" "slotPlaybackRate(QAction*)" "\0" "/home/gilles/Devel/8.x/core/libs/video/player/qtmm/mediaplayerview.cpp"
":" "507")
);
508
509 connect(audioMenu, SIGNAL(triggered(QAction*))qFlagLocation("2" "triggered(QAction*)" "\0" "/home/gilles/Devel/8.x/core/libs/video/player/qtmm/mediaplayerview.cpp"
":" "509")
,
510 this, SLOT(slotAudioChanged(QAction*))qFlagLocation("1" "slotAudioChanged(QAction*)" "\0" "/home/gilles/Devel/8.x/core/libs/video/player/qtmm/mediaplayerview.cpp"
":" "510")
);
511}
512
513MediaPlayerView::~MediaPlayerView()
514{
515 escapePreview();
516
517 delete d;
518}
519
520void MediaPlayerView::setInfoInterface(DInfoInterface* const iface)
521{
522 d->iface = iface;
523}
524
525void MediaPlayerView::reload()
526{
527 d->player->stop();
528 d->player->setSource(d->currentItem);
529 d->player->play();
530}
531
532void MediaPlayerView::slotPlayerStateChanged(QMediaPlayer::PlaybackState newState)
533{
534 if (newState == QMediaPlayer::PlayingState)
535 {
536 d->playAction->setIcon(QIcon::fromTheme(QLatin1String("media-playback-pause")));
537
538 d->backAction->setEnabled(true);
539 d->forwAction->setEnabled(true);
540 }
541 else
542 {
543 d->playAction->setIcon(QIcon::fromTheme(QLatin1String("media-playback-start")));
544
545 if (
546 (newState == QMediaPlayer::StoppedState) ||
547 (d->player->mediaStatus() == QMediaPlayer::EndOfMedia)
548 )
549 {
550 qCDebug(DIGIKAM_GENERAL_LOG)for (QLoggingCategoryMacroHolder<QtDebugMsg> qt_category
((DIGIKAM_GENERAL_LOG)()); qt_category; qt_category.control =
false) QMessageLogger(static_cast<const char *>("/home/gilles/Devel/8.x/core/libs/video/player/qtmm/mediaplayerview.cpp"
), 550, static_cast<const char *>(__PRETTY_FUNCTION__),
qt_category.name()).debug()
<< "Play video with QtMultimedia completed:" << d->player->source();
551
552 if (d->player->error() != QMediaPlayer::NoError)
553 {
554 setPreviewMode(Private::ErrorView);
555 }
556
557 d->backAction->setEnabled(false);
558 d->forwAction->setEnabled(false);
559 }
560 }
561}
562
563void MediaPlayerView::slotMediaStatusChanged(QMediaPlayer::MediaStatus newStatus)
564{
565 if (newStatus == QMediaPlayer::LoadedMedia)
566 {
567 int rotate = d->videoMediaOrientation();
568
569 qCDebug(DIGIKAM_GENERAL_LOG)for (QLoggingCategoryMacroHolder<QtDebugMsg> qt_category
((DIGIKAM_GENERAL_LOG)()); qt_category; qt_category.control =
false) QMessageLogger(static_cast<const char *>("/home/gilles/Devel/8.x/core/libs/video/player/qtmm/mediaplayerview.cpp"
), 569, static_cast<const char *>(__PRETTY_FUNCTION__),
qt_category.name()).debug()
<< "Found video orientation with QtMultimedia:"
570 << rotate;
571
572 rotate = (-rotate) + d->videoOrientation;
573
574 if ((rotate > 270) || (rotate < 0))
575 {
576 rotate = d->videoOrientation;
577 }
578
579 d->setVideoItemOrientation(rotate);
580 }
581 else if (newStatus == QMediaPlayer::InvalidMedia)
582 {
583 setPreviewMode(Private::ErrorView);
584 }
585}
586
587void MediaPlayerView::escapePreview()
588{
589 d->player->stop();
590 d->player->setSource(d->dummyVideo);
591}
592
593void MediaPlayerView::slotThemeChanged()
594{
595 QPalette palette;
596 palette.setColor(d->errorView->backgroundRole(), qApp(static_cast<QApplication *>(QCoreApplication::instance
()))
->palette().color(QPalette::Base));
597 d->errorView->setPalette(palette);
598
599 QPalette palette2;
600 palette2.setColor(d->playerView->backgroundRole(), qApp(static_cast<QApplication *>(QCoreApplication::instance
()))
->palette().color(QPalette::Base));
601 d->playerView->setPalette(palette2);
602}
603
604void MediaPlayerView::slotEscapePressed()
605{
606 Q_EMIT signalEscapePreview();
607}
608
609void MediaPlayerView::slotRotateVideo()
610{
611 if (d->player->playbackState() != QMediaPlayer::StoppedState)
612 {
613 int orientation = 0;
614
615 switch (d->videoOrientation)
616 {
617 case 0:
618 {
619 orientation = 90;
620 break;
621 }
622
623 case 90:
624 {
625 orientation = 180;
626 break;
627 }
628
629 case 180:
630 {
631 orientation = 270;
632 break;
633 }
634
635 default:
636 {
637 orientation = 0;
638 break;
639 }
640 }
641
642 d->setVideoItemOrientation(orientation);
643 }
644}
645
646void MediaPlayerView::slotPausePlay()
647{
648 if (!d->player->isPlaying())
649 {
650 d->player->play();
651
652 return;
653 }
654
655 d->player->pause();
656}
657
658void MediaPlayerView::slotFrameBackward()
659{
660 if (d->player->isPlaying())
661 {
662 d->player->pause();
663
664 return;
665 }
666
667 QVariant frameRateVar = d->player->metaData().value(QMediaMetaData::VideoFrameRate);
668
669 if (frameRateVar.isValid())
670 {
671 double frameRate = frameRateVar.toDouble();
672
673 if (frameRate > 0.0)
674 {
675 double frame = 1000.0 / frameRate;
676 d->player->setPosition(d->player->position() - frame);
677 }
678 }
679}
680
681void MediaPlayerView::slotFrameForward()
682{
683 if (d->player->isPlaying())
684 {
685 d->player->pause();
686
687 return;
688 }
689
690 QVariant frameRateVar = d->player->metaData().value(QMediaMetaData::VideoFrameRate);
691
692 if (frameRateVar.isValid())
693 {
694 double frameRate = frameRateVar.toDouble();
695
696 if (frameRate > 0.0)
697 {
698 double frame = 1000.0 / frameRate;
699 d->player->setPosition(d->player->position() + frame);
700 }
701 }
702}
703
704void MediaPlayerView::slotCapture()
705{
706 if (d->player->playbackState() != QMediaPlayer::StoppedState)
707 {
708 int capturePosition = d->player->position();
709 QVideoSink* const sink = d->player->videoSink();
710 QVideoFrame frame = sink->videoFrame();
711 QImage image = frame.toImage();
712
713 if (!image.isNull() && d->currentItem.isValid())
714 {
715 QFileInfo info(d->currentItem.toLocalFile());
716 QDateTime dateTime;
717
718 if (d->iface)
719 {
720 DItemInfo dinfo(d->iface->itemInfo(d->currentItem));
721 dateTime = dinfo.dateTime();
722 }
723 else
724 {
725 QScopedPointer<DMetadata> meta2(new DMetadata);
726
727 if (meta2->load(d->currentItem.toLocalFile()))
728 {
729 dateTime = meta2->getItemDateTime();
730 }
731 }
732
733 if (dateTime.isValid())
734 {
735 dateTime = dateTime.addMSecs(capturePosition);
736 }
737 else
738 {
739 dateTime = QDateTime::currentDateTime();
740 }
741
742 QTransform transform;
743 transform.rotate(d->videoOrientation);
744 image = std::move(image.transformed(transform));
745
746 QString tempPath = QString::fromUtf8("%1/%2-%3.digikamtempfile.jpg")
747 .arg(info.path())
748 .arg(info.baseName())
749 .arg(capturePosition);
750
751 if (image.save(tempPath, "JPG", 100))
752 {
753 QScopedPointer<DMetadata> meta(new DMetadata);
754
755 if (meta->load(tempPath))
756 {
757 meta->setItemOrientation(MetaEngine::ORIENTATION_NORMAL);
758 meta->setImageDateTime(dateTime, true);
759 meta->setItemDimensions(image.size());
760 meta->save(tempPath, true);
761 }
762
763 QString finalPath = QString::fromUtf8("%1/%2-%3.jpg")
764 .arg(info.path())
765 .arg(info.baseName())
766 .arg(capturePosition);
767
768 if (QFile::rename(tempPath, finalPath))
769 {
770 if (d->iface)
771 {
772 d->iface->slotMetadataChangedForUrl(QUrl::fromLocalFile(finalPath));
773 }
774 }
775 else
776 {
777 QFile::remove(tempPath);
778 }
779 }
780 }
781 }
782}
783
784int MediaPlayerView::previewMode()
785{
786 return indexOf(currentWidget());
787}
788
789void MediaPlayerView::setPreviewMode(int mode)
790{
791 if ((mode != Private::ErrorView) && (mode != Private::PlayerView))
792 {
793 return;
794 }
795
796 setCurrentIndex(mode);
797
798 d->toolBar->adjustSize();
799 d->toolBar->raise();
800}
801
802void MediaPlayerView::setCurrentItem(const QUrl& url, bool hasPrevious, bool hasNext)
803{
804 d->prevAction->setEnabled(hasPrevious);
805 d->nextAction->setEnabled(hasNext);
806 d->adjustVideoSize();
807
808 if (url.isEmpty())
809 {
810 d->player->stop();
811 d->currentItem = url;
812
813 return;
814 }
815
816 if (
817 (d->currentItem == url) &&
818 (
819 (d->player->playbackState() == QMediaPlayer::PlayingState) ||
820 (d->player->playbackState() == QMediaPlayer::PausedState)
821 )
822 )
823 {
824 return;
825 }
826
827 d->player->stop();
828 int orientation = 0;
829 d->currentItem = url;
830
831 if (d->iface)
832 {
833 DItemInfo info(d->iface->itemInfo(url));
834
835 orientation = info.orientation();
836 }
837
838 switch (orientation)
839 {
840 case MetaEngine::ORIENTATION_ROT_90:
841 case MetaEngine::ORIENTATION_ROT_90_HFLIP:
842 case MetaEngine::ORIENTATION_ROT_90_VFLIP:
843 {
844 d->videoOrientation = 90;
845 break;
846 }
847
848 case MetaEngine::ORIENTATION_ROT_180:
849 {
850 d->videoOrientation = 180;
851 break;
852 }
853
854 case MetaEngine::ORIENTATION_ROT_270:
855 {
856 d->videoOrientation = 270;
857 break;
858 }
859
860 default:
861 {
862 d->videoOrientation = 0;
863 break;
864 }
865 }
866
867 d->player->setSource(d->currentItem);
868 setPreviewMode(Private::PlayerView);
869 d->player->play();
870
871 qCDebug(DIGIKAM_GENERAL_LOG)for (QLoggingCategoryMacroHolder<QtDebugMsg> qt_category
((DIGIKAM_GENERAL_LOG)()); qt_category; qt_category.control =
false) QMessageLogger(static_cast<const char *>("/home/gilles/Devel/8.x/core/libs/video/player/qtmm/mediaplayerview.cpp"
), 871, static_cast<const char *>(__PRETTY_FUNCTION__),
qt_category.name()).debug()
<< "Play video with QtMultimedia started:" << d->player->source();
872}
873
874void MediaPlayerView::slotPositionChanged(qint64 position)
875{
876 if (
877 (d->sliderTime < position) &&
878 ((d->sliderTime + 100) > position)
879 )
880 {
881 return;
882 }
883
884 d->sliderTime = position;
885
886 if (!d->slider->isSliderDown())
887 {
888 d->slider->blockSignals(true);
889 d->slider->setValue(position);
890 d->slider->blockSignals(false);
891 }
892
893 d->tlabel->setText(QString::fromLatin1("%1 / %2")
894 .arg(QTime(0, 0, 0).addMSecs(position).toString(QLatin1String("HH:mm:ss")))
895 .arg(QTime(0, 0, 0).addMSecs(d->slider->maximum()).toString(QLatin1String("HH:mm:ss"))));
896}
897
898void MediaPlayerView::slotVolumeChanged(int volume)
899{
900 d->audio->setVolume(volume / 100.0F);
901
902 if (objectName() != QLatin1String("main_media_player"))
903 {
904 return;
905 }
906
907 KSharedConfig::Ptr config = KSharedConfig::openConfig();
908 KConfigGroup group = config->group(QLatin1String("Media Player Settings"));
909 group.writeEntry("Volume", volume);
910}
911
912void MediaPlayerView::slotLoopToggled(bool loop)
913{
914 if (loop)
915 {
916 d->loopPlay->setIcon(QIcon::fromTheme(QLatin1String("media-playlist-repeat")));
917 d->player->setLoops(QMediaPlayer::Infinite);
918 }
919 else
920 {
921 d->loopPlay->setIcon(QIcon::fromTheme(QLatin1String("media-playlist-normal")));
922 d->player->setLoops(QMediaPlayer::Once);
923 }
924}
925
926void MediaPlayerView::slotDurationChanged(qint64 duration)
927{
928 qint64 max = qMax((qint64)1, duration);
929 d->slider->setRange(0, max);
930}
931
932void MediaPlayerView::slotPlaybackRate(QAction* action)
933{
934 if (action)
935 {
936 d->player->setPlaybackRate(action->data().toReal());
937 }
938}
939
940void MediaPlayerView::slotAudioChanged(QAction* action)
941{
942 if (action)
943 {
944 for (const auto& device : QMediaDevices::audioOutputs())
945 {
946 if (action->data().toByteArray() == device.id())
947 {
948 d->audio->setDevice(device);
949 break;
950 }
951 }
952 }
953}
954
955void MediaPlayerView::slotPosition(int position)
956{
957 if (d->player->isSeekable())
958 {
959 d->player->setPosition((qint64)position);
960 }
961}
962
963void MediaPlayerView::slotHandlePlayerError(QMediaPlayer::Error /*error*/, const QString& errStr)
964{
965 setPreviewMode(Private::ErrorView);
966
967 qCDebug(DIGIKAM_GENERAL_LOG)for (QLoggingCategoryMacroHolder<QtDebugMsg> qt_category
((DIGIKAM_GENERAL_LOG)()); qt_category; qt_category.control =
false) QMessageLogger(static_cast<const char *>("/home/gilles/Devel/8.x/core/libs/video/player/qtmm/mediaplayerview.cpp"
), 967, static_cast<const char *>(__PRETTY_FUNCTION__),
qt_category.name()).debug()
<< "QtMultimedia Error: " << errStr;
968}
969
970void MediaPlayerView::slotNativeSizeChanged()
971{
972 d->adjustVideoSize();
973}
974
975bool MediaPlayerView::eventFilter(QObject* watched, QEvent* event)
976{
977 if ((watched == d->playerView) && (event->type() == QEvent::Resize))
978 {
979 d->adjustVideoSize();
980 }
981
982 return QStackedWidget::eventFilter(watched, event);
983}
984
985} // namespace Digikam
986
987#include "mediaplayerview.moc"
988
989#include "moc_mediaplayerview.cpp"