2018-02-27 18:06:05 +01:00
/*
* Strawberry Music Player
* This file was part of Clementine .
* Copyright 2010 , David Sansome < me @ davidsansome . com >
2021-06-21 19:54:12 +02:00
* Copyright 2018 - 2021 , Jonas Kvinge < jonas @ jkvinge . net >
2018-02-27 18:06:05 +01:00
*
* Strawberry is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
*
* Strawberry is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with Strawberry . If not , see < http : //www.gnu.org/licenses/>.
2018-08-09 18:39:44 +02:00
*
2018-02-27 18:06:05 +01:00
*/
# include "config.h"
# include <QFile>
2018-05-01 00:41:33 +02:00
# include <QSize>
# include <QString>
# include <QImage>
2018-02-27 18:06:05 +01:00
# include "core/song.h"
# include "core/tagreaderclient.h"
2023-05-14 11:34:55 +02:00
# include "albumcoverloaderoptions.h"
2020-02-09 02:29:35 +01:00
# include "albumcoverexport.h"
2018-02-27 18:06:05 +01:00
# include "coverexportrunnable.h"
2023-07-21 07:17:26 +02:00
CoverExportRunnable : : CoverExportRunnable ( const AlbumCoverExport : : DialogResult & dialog_result , const AlbumCoverLoaderOptions : : Types & cover_types , const Song & song , QObject * parent )
2021-07-11 07:40:57 +02:00
: QObject ( parent ) ,
dialog_result_ ( dialog_result ) ,
2023-05-14 11:34:55 +02:00
cover_types_ ( cover_types ) ,
2021-07-11 07:40:57 +02:00
song_ ( song ) { }
2018-02-27 18:06:05 +01:00
void CoverExportRunnable : : run ( ) {
2023-05-14 11:34:55 +02:00
if ( song_ . art_unset ( ) | | ( ! song_ . art_embedded ( ) & & ! song_ . art_automatic_is_valid ( ) & & ! song_ . art_manual_is_valid ( ) ) ) {
2018-02-27 18:06:05 +01:00
EmitCoverSkipped ( ) ;
}
else {
2021-08-23 21:21:08 +02:00
if ( dialog_result_ . RequiresCoverProcessing ( ) ) {
2018-02-27 18:06:05 +01:00
ProcessAndExportCover ( ) ;
2021-08-23 21:21:08 +02:00
}
else {
2018-02-27 18:06:05 +01:00
ExportCover ( ) ;
2021-08-23 21:21:08 +02:00
}
2018-02-27 18:06:05 +01:00
}
}
// Exports a single album cover using a "save QImage to file" approach.
2018-05-01 00:41:33 +02:00
// For performance reasons this method will be invoked only if loading and in memory processing of images is necessary for current settings which means that:
2018-02-27 18:06:05 +01:00
// - either the force size flag is being used
// - or the "overwrite smaller" mode is used
// In all other cases, the faster ExportCover() method will be used.
void CoverExportRunnable : : ProcessAndExportCover ( ) {
2023-05-14 11:34:55 +02:00
QImage image ;
QString extension ;
for ( const AlbumCoverLoaderOptions : : Type cover_type : cover_types_ ) {
switch ( cover_type ) {
case AlbumCoverLoaderOptions : : Type : : Unset :
if ( song_ . art_unset ( ) ) {
EmitCoverSkipped ( ) ;
return ;
}
break ;
case AlbumCoverLoaderOptions : : Type : : Embedded :
if ( song_ . art_embedded ( ) & & dialog_result_ . export_embedded_ ) {
image = TagReaderClient : : Instance ( ) - > LoadEmbeddedArtAsImageBlocking ( song_ . url ( ) . toLocalFile ( ) ) ;
if ( ! image . isNull ( ) ) {
2024-04-09 23:20:26 +02:00
extension = QStringLiteral ( " jpg " ) ;
2023-05-14 11:34:55 +02:00
}
}
break ;
case AlbumCoverLoaderOptions : : Type : : Manual :
if ( dialog_result_ . export_downloaded_ & & song_ . art_manual_is_valid ( ) ) {
const QString cover_path = song_ . art_manual ( ) . toLocalFile ( ) ;
if ( image . load ( cover_path ) ) {
2024-04-11 02:56:01 +02:00
extension = cover_path . section ( QLatin1Char ( ' . ' ) , - 1 ) ;
2023-05-14 11:34:55 +02:00
}
}
break ;
case AlbumCoverLoaderOptions : : Type : : Automatic :
if ( dialog_result_ . export_downloaded_ & & song_ . art_automatic_is_valid ( ) ) {
const QString cover_path = song_ . art_automatic ( ) . toLocalFile ( ) ;
if ( image . load ( cover_path ) ) {
2024-04-11 02:56:01 +02:00
extension = cover_path . section ( QLatin1Char ( ' . ' ) , - 1 ) ;
2023-05-14 11:34:55 +02:00
}
}
break ;
2018-02-27 18:06:05 +01:00
}
2023-05-14 11:34:55 +02:00
if ( ! image . isNull ( ) & & ! extension . isEmpty ( ) ) break ;
2018-02-27 18:06:05 +01:00
}
2023-05-14 11:34:55 +02:00
if ( image . isNull ( ) | | extension . isEmpty ( ) ) {
EmitCoverSkipped ( ) ;
return ;
2018-02-27 18:06:05 +01:00
}
2023-05-14 11:34:55 +02:00
// Rescale if necessary
2018-02-27 18:06:05 +01:00
if ( dialog_result_ . IsSizeForced ( ) ) {
2023-05-14 11:34:55 +02:00
image = image . scaled ( QSize ( dialog_result_ . width_ , dialog_result_ . height_ ) , Qt : : IgnoreAspectRatio ) ;
2018-02-27 18:06:05 +01:00
}
2024-04-11 02:56:01 +02:00
QString cover_dir = song_ . url ( ) . toLocalFile ( ) . section ( QLatin1Char ( ' / ' ) , 0 , - 2 ) ;
QString new_file = cover_dir + QLatin1Char ( ' / ' ) + dialog_result_ . filename_ + QLatin1Char ( ' . ' ) + ( song_ . art_embedded ( ) ? QStringLiteral ( " jpg " ) : extension ) ;
2018-02-27 18:06:05 +01:00
// If the file exists, do not override!
2023-02-18 14:09:27 +01:00
if ( dialog_result_ . overwrite_ = = AlbumCoverExport : : OverwriteMode : : None & & QFile : : exists ( new_file ) ) {
2018-02-27 18:06:05 +01:00
EmitCoverSkipped ( ) ;
return ;
}
2023-05-14 11:34:55 +02:00
// We're handling overwrite as remove + copy so we need to delete the old file first
2023-02-18 14:09:27 +01:00
if ( QFile : : exists ( new_file ) & & dialog_result_ . overwrite_ ! = AlbumCoverExport : : OverwriteMode : : None ) {
2018-02-27 18:06:05 +01:00
2018-05-01 00:41:33 +02:00
// if the mode is "overwrite smaller" then skip the cover if a bigger one is already available in the folder
2023-02-18 14:09:27 +01:00
if ( dialog_result_ . overwrite_ = = AlbumCoverExport : : OverwriteMode : : Smaller ) {
2023-05-14 11:34:55 +02:00
QImage image_existing ;
image_existing . load ( new_file ) ;
2018-02-27 18:06:05 +01:00
2023-05-14 11:34:55 +02:00
if ( image_existing . isNull ( ) | | image_existing . size ( ) . height ( ) > = image . size ( ) . height ( ) | | image_existing . size ( ) . width ( ) > = image . size ( ) . width ( ) ) {
2018-02-27 18:06:05 +01:00
EmitCoverSkipped ( ) ;
return ;
}
}
if ( ! QFile : : remove ( new_file ) ) {
EmitCoverSkipped ( ) ;
return ;
}
}
2023-05-14 11:34:55 +02:00
if ( image . save ( new_file ) ) {
2018-02-27 18:06:05 +01:00
EmitCoverExported ( ) ;
2021-08-23 21:21:08 +02:00
}
else {
2018-02-27 18:06:05 +01:00
EmitCoverSkipped ( ) ;
2021-08-23 21:21:08 +02:00
}
2018-02-27 18:06:05 +01:00
}
// Exports a single album cover using a "copy file" approach.
void CoverExportRunnable : : ExportCover ( ) {
2023-05-14 11:34:55 +02:00
QImage image ;
QString extension ;
QString cover_path ;
bool embedded_cover = false ;
for ( const AlbumCoverLoaderOptions : : Type cover_type : cover_types_ ) {
switch ( cover_type ) {
case AlbumCoverLoaderOptions : : Type : : Unset :
if ( song_ . art_unset ( ) ) {
EmitCoverSkipped ( ) ;
return ;
}
break ;
case AlbumCoverLoaderOptions : : Type : : Embedded :
if ( song_ . art_embedded ( ) & & dialog_result_ . export_embedded_ ) {
image = TagReaderClient : : Instance ( ) - > LoadEmbeddedArtAsImageBlocking ( song_ . url ( ) . toLocalFile ( ) ) ;
if ( ! image . isNull ( ) ) {
embedded_cover = true ;
2024-04-09 23:20:26 +02:00
extension = QStringLiteral ( " jpg " ) ;
2023-05-14 11:34:55 +02:00
}
}
break ;
case AlbumCoverLoaderOptions : : Type : : Manual :
if ( dialog_result_ . export_downloaded_ & & song_ . art_manual_is_valid ( ) ) {
cover_path = song_ . art_manual ( ) . toLocalFile ( ) ;
if ( image . load ( cover_path ) ) {
2024-04-11 02:56:01 +02:00
extension = cover_path . section ( QLatin1Char ( ' . ' ) , - 1 ) ;
2023-05-14 11:34:55 +02:00
}
}
break ;
case AlbumCoverLoaderOptions : : Type : : Automatic :
if ( dialog_result_ . export_downloaded_ & & song_ . art_automatic_is_valid ( ) ) {
cover_path = song_ . art_automatic ( ) . toLocalFile ( ) ;
if ( image . load ( cover_path ) ) {
2024-04-11 02:56:01 +02:00
extension = cover_path . section ( QLatin1Char ( ' . ' ) , - 1 ) ;
2023-05-14 11:34:55 +02:00
}
}
break ;
}
if ( ! image . isNull ( ) & & ! extension . isEmpty ( ) & & ( embedded_cover | | ! cover_path . isEmpty ( ) ) ) break ;
}
2018-02-27 18:06:05 +01:00
2023-05-14 11:34:55 +02:00
if ( image . isNull ( ) | | extension . isEmpty ( ) ) {
EmitCoverSkipped ( ) ;
return ;
}
2018-02-27 18:06:05 +01:00
2024-04-11 02:56:01 +02:00
QString cover_dir = song_ . url ( ) . toLocalFile ( ) . section ( QLatin1Char ( ' / ' ) , 0 , - 2 ) ;
QString new_file = cover_dir + QLatin1Char ( ' / ' ) + dialog_result_ . filename_ + QLatin1Char ( ' . ' ) + extension ;
2018-02-27 18:06:05 +01:00
// If the file exists, do not override!
2023-02-18 14:09:27 +01:00
if ( dialog_result_ . overwrite_ = = AlbumCoverExport : : OverwriteMode : : None & & QFile : : exists ( new_file ) ) {
2018-02-27 18:06:05 +01:00
EmitCoverSkipped ( ) ;
return ;
}
2019-07-07 21:14:24 +02:00
// We're handling overwrite as remove + copy so we need to delete the old file first
2023-02-18 14:09:27 +01:00
if ( dialog_result_ . overwrite_ ! = AlbumCoverExport : : OverwriteMode : : None & & QFile : : exists ( new_file ) ) {
2018-02-27 18:06:05 +01:00
if ( ! QFile : : remove ( new_file ) ) {
EmitCoverSkipped ( ) ;
return ;
}
}
2023-05-14 11:34:55 +02:00
if ( embedded_cover ) {
if ( ! image . save ( new_file ) ) {
2018-02-27 18:06:05 +01:00
EmitCoverSkipped ( ) ;
return ;
}
}
else {
2019-07-07 21:14:24 +02:00
// Automatic or manual cover, available in an image file
2018-02-27 18:06:05 +01:00
if ( ! QFile : : copy ( cover_path , new_file ) ) {
EmitCoverSkipped ( ) ;
return ;
}
}
2023-05-14 11:34:55 +02:00
2018-02-27 18:06:05 +01:00
EmitCoverExported ( ) ;
}
void CoverExportRunnable : : EmitCoverExported ( ) { emit CoverExported ( ) ; }
void CoverExportRunnable : : EmitCoverSkipped ( ) { emit CoverSkipped ( ) ; }