diff options
Diffstat (limited to 'src/utilities/cameragui/umscamera.cpp')
| -rw-r--r-- | src/utilities/cameragui/umscamera.cpp | 519 | 
1 files changed, 519 insertions, 0 deletions
| diff --git a/src/utilities/cameragui/umscamera.cpp b/src/utilities/cameragui/umscamera.cpp new file mode 100644 index 00000000..537c29ba --- /dev/null +++ b/src/utilities/cameragui/umscamera.cpp @@ -0,0 +1,519 @@ +/* ============================================================ + * + * This file is a part of digiKam project + * http://www.digikam.org + * + * Date        : 2004-12-21 + * Description : USB Mass Storage camera interface + * + * Copyright (C) 2004-2005 by Renchi Raju <renchi@pooh.tam.uiuc.edu> + * Copyright (C) 2005-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>  + * + * This program 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 2, or (at your option) + * any later version. + * + * This program 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. + * + * ============================================================ */ + +// C Ansi includes. + +extern "C" +{ +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <utime.h> +} + +// TQt includes. + +#include <tqdir.h> +#include <tqfileinfo.h> +#include <tqfile.h> +#include <tqstringlist.h> +#include <tqdeepcopy.h> +#include <tqwmatrix.h> + +// KDE includes. + +#include <tdelocale.h> +#include <tdefilemetainfo.h> + +// LibKDcraw includes. + +#include <libkdcraw/kdcraw.h> + +// Local includes. + +#include "ddebug.h" +#include "dimg.h" +#include "dmetadata.h" +#include "umscamera.h" + +namespace Digikam +{ + +UMSCamera::UMSCamera(const TQString& title, const TQString& model, const TQString& port, const TQString& path) +         : DKCamera(title, model, port, path) +{ +    m_cancel = false; +} + +UMSCamera::~UMSCamera() +{ +} + +bool UMSCamera::doConnect() +{ +    return true; +} + +void UMSCamera::cancel() +{ +    // set the cancel flag +    m_cancel = true; +} + +void UMSCamera::getAllFolders(const TQString& folder, TQStringList& subFolderList) +{ +    m_cancel = false; +    subFolderList.clear(); +    subFolderList.append(folder); +    listFolders(folder, subFolderList); +} + +bool UMSCamera::getItemsInfoList(const TQString& folder, GPItemInfoList& infoList, bool getImageDimensions) +{ +    m_cancel = false; +    infoList.clear(); + +    TQDir dir(folder); +    dir.setFilter(TQDir::Files); + +    const TQFileInfoList *list = dir.entryInfoList(); +    if (!list) +        return false; + +    TQFileInfoListIterator it(*list); +    TQFileInfo *fi; +    TQFileInfo thmlo, thmup; +    DMetadata meta; + +    while ((fi = it.current()) != 0 && !m_cancel) +    { +        ++it; + +        TQString mime = mimeType(fi->extension(false).lower()); + +        if (!mime.isEmpty()) +        { +            TQSize      dims; +            TQDateTime  dt; +            GPItemInfo info; +            thmlo.setFile(folder + TQString("/") + fi->baseName() + TQString(".thm")); +            thmup.setFile(folder + TQString("/") + fi->baseName() + TQString(".THM")); + +            if (thmlo.exists()) +            { +                // Try thumbnail sidecar files with lowercase extension. +                meta.load(thmlo.filePath()); +                dt   = meta.getImageDateTime(); +                dims = meta.getImageDimensions(); +            } +            else if (thmup.exists()) +            { +                // Try thumbnail sidecar files with uppercase extension. +                meta.load(thmup.filePath()); +                dt   = meta.getImageDateTime(); +                dims = meta.getImageDimensions(); +            } +            else if (mime == TQString("image/x-raw")) +            { +                // If no thumbnail sidecar file available , try to load image metadata with Raw files. +                meta.load(fi->filePath()); +                dt   = meta.getImageDateTime(); +                dims = meta.getImageDimensions(); +            } +            else +            { +                meta.load(fi->filePath()); +                dt   = meta.getImageDateTime(); +                dims = meta.getImageDimensions(); + +                if (dims.isNull()) +                { +                    // In all others case, try KFileMetaInfo. +                    KFileMetaInfo kmeta(fi->filePath()); +                    if (kmeta.isValid()) +                    { +                        if (kmeta.containsGroup("Jpeg EXIF Data")) +                            dims = kmeta.group("Jpeg EXIF Data").item("Dimensions").value().toSize(); +                        else if (kmeta.containsGroup("General")) +                            dims = kmeta.group("General").item("Dimensions").value().toSize(); +                        else if (kmeta.containsGroup("Technical")) +                            dims = kmeta.group("Technical").item("Dimensions").value().toSize(); +                    } +                } +            } + +            if (dt.isNull()) +            { +                // If date is not found in metadata, use file time stamp +                dt = fi->created(); +            } + +            info.name             = fi->fileName(); +            info.folder           = !folder.endsWith("/") ? folder + TQString("/") : folder; +            info.mime             = mime; +            info.mtime            = dt.toTime_t(); +            info.size             = fi->size(); +            info.width            = getImageDimensions ? dims.width()  : -1; +            info.height           = getImageDimensions ? dims.height() : -1; +            info.downloaded       = GPItemInfo::DownloadUnknow; +            info.readPermissions  = fi->isReadable(); +            info.writePermissions = fi->isWritable(); + +            infoList.append(info); +        } +    } + +    return true; +} + +bool UMSCamera::getThumbnail(const TQString& folder, const TQString& itemName, TQImage& thumbnail) +{ +    m_cancel = false; + +    // JPEG files: try to get thumbnail from Exif data. + +    DMetadata metadata(TQFile::encodeName(folder + TQString("/") + itemName)); +    thumbnail = metadata.getExifThumbnail(true); +    if (!thumbnail.isNull()) +        return true; + +    // RAW files : try to extract embedded thumbnail using dcraw + +    KDcrawIface::KDcraw::loadDcrawPreview(thumbnail, TQString(folder + TQString("/") + itemName)); +    if (!thumbnail.isNull()) +        return true; + +    // THM files: try to get thumbnail from '.thm' files if we didn't manage to get  +    // thumbnail from Exif. Any cameras provides *.thm files like JPEG files with RAW/video files.  +    // Using this way speed up thumbnailization and limit data transfered between camera and computer. +    // NOTE: the thumbnail extracted with this method can provide a poor quality preview. + +    TQFileInfo fi(folder + TQString("/") + itemName); + +    if (thumbnail.load(folder + TQString("/") + fi.baseName() + TQString(".thm")))        // Lowercase +    { +        if (!thumbnail.isNull()) +           return true; +    } +    else if (thumbnail.load(folder + TQString("/") + fi.baseName() + TQString(".THM")))   // Uppercase +    { +        if (!thumbnail.isNull()) +           return true; +    } + +    // Finaly, we trying to get thumbnail using DImg API (slow). + +    DImg dimgThumb(TQCString(TQFile::encodeName(folder + TQString("/") + itemName))); + +    if (!dimgThumb.isNull()) +    { +        thumbnail = dimgThumb.copyTQImage(); +        return true; +    } + +    return false; +} + +bool UMSCamera::getExif(const TQString&, const TQString&, char **, int&) +{ +    // not necessary to implement this. read it directly from the file +    // (done in camera controller) +    DWarning() << "exif implemented yet in camera controller" << endl; +    return false; +} + +bool UMSCamera::downloadItem(const TQString& folder, const TQString& itemName, const TQString& saveFile) +{ +    m_cancel     = false; +    TQString src  = folder + TQString("/") + itemName; +    TQString dest = saveFile; + +    TQFile sFile(src); +    TQFile dFile(dest); + +    if ( !sFile.open(IO_ReadOnly) ) +    { +        DWarning() << "Failed to open source file for reading: " +                   << src << endl; +        return false; +    } + +    if ( !dFile.open(IO_WriteOnly) ) +    { +        sFile.close(); +        DWarning() << "Failed to open dest file for writing: " +                    << dest << endl; +        return false; +    } + +    const int MAX_IPC_SIZE = (1024*32); +    char buffer[MAX_IPC_SIZE]; + +    TQ_LONG len; +    while ((len = sFile.readBlock(buffer, MAX_IPC_SIZE)) != 0 && !m_cancel) +    { +        if (len == -1 || dFile.writeBlock(buffer, (TQ_ULONG)len) != len) +        { +            sFile.close(); +            dFile.close(); +            return false; +        } +    } + +    sFile.close(); +    dFile.close(); + +    // set the file modification time of the downloaded file to that +    // of the original file +    struct stat st; +    ::stat(TQFile::encodeName(src), &st); + +    struct utimbuf ut; +    ut.modtime = st.st_mtime; +    ut.actime  = st.st_atime; + +    ::utime(TQFile::encodeName(dest), &ut); + +    return true; +} + +bool UMSCamera::setLockItem(const TQString& folder, const TQString& itemName, bool lock) +{ +    TQString src = folder + TQString("/") + itemName; + +    if (lock) +    { +        // Lock the file to set read only flag +        if (::chmod(TQFile::encodeName(src), S_IREAD) == -1) +            return false;  +    } +    else +    { +        // Unlock the file to set read/write flag +        if (::chmod(TQFile::encodeName(src), S_IREAD | S_IWRITE) == -1) +            return false;  +    } + +    return true; +} + +bool UMSCamera::deleteItem(const TQString& folder, const TQString& itemName) +{ +    m_cancel = false; + +    // Any camera provide THM (thumbnail) file with real image. We need to remove it also. + +    TQFileInfo fi(folder + TQString("/") + itemName); + +    TQFileInfo thmLo(folder + TQString("/") + fi.baseName() + ".thm");          // Lowercase + +    if (thmLo.exists()) +        ::unlink(TQFile::encodeName(thmLo.filePath())); + +    TQFileInfo thmUp(folder + TQString("/") + fi.baseName() + ".THM");          // Uppercase + +    if (thmUp.exists()) +        ::unlink(TQFile::encodeName(thmUp.filePath())); + +    // Remove the real image. +    return (::unlink(TQFile::encodeName(folder + TQString("/") + itemName)) == 0); +} + +bool UMSCamera::uploadItem(const TQString& folder, const TQString& itemName, const TQString& localFile, +                           GPItemInfo& info, bool getImageDimensions) +{ +    m_cancel     = false; +    TQString dest = folder + TQString("/") + itemName; +    TQString src  = localFile; + +    TQFile sFile(src); +    TQFile dFile(dest); + +    if ( !sFile.open(IO_ReadOnly) ) +    { +        DWarning() << "Failed to open source file for reading: " +                    << src << endl; +        return false; +    } + +    if ( !dFile.open(IO_WriteOnly) ) +    { +        sFile.close(); +        DWarning() << "Failed to open dest file for writing: " +                    << dest << endl; +        return false; +    } + +    const int MAX_IPC_SIZE = (1024*32); +    char buffer[MAX_IPC_SIZE]; + +    TQ_LONG len; +    while ((len = sFile.readBlock(buffer, MAX_IPC_SIZE)) != 0 && !m_cancel) +    { +        if (len == -1 || dFile.writeBlock(buffer, (TQ_ULONG)len) == -1) +        { +            sFile.close(); +            dFile.close(); +            return false; +        } +    } + +    sFile.close(); +    dFile.close(); + +    // set the file modification time of the uploaded file to that +    // of the original file +    struct stat st; +    ::stat(TQFile::encodeName(src), &st); + +    struct utimbuf ut; +    ut.modtime = st.st_mtime; +    ut.actime  = st.st_atime; + +    ::utime(TQFile::encodeName(dest), &ut); + +    // Get new camera item information. + +    DMetadata meta; +    TQFileInfo fi(dest); +    TQString   mime = mimeType(fi.extension(false).lower()); + +    if (!mime.isEmpty()) +    { +        TQSize     dims; +        TQDateTime dt; + +        if (mime == TQString("image/x-raw")) +        { +            // Try to load image metadata with Raw files. +            meta.load(fi.filePath()); +            dt   = meta.getImageDateTime(); +            dims = meta.getImageDimensions(); +        } +        else +        { +            meta.load(fi.filePath()); +            dt   = meta.getImageDateTime(); +            dims = meta.getImageDimensions(); + +            if (dims.isNull()) +            { +                // In all others case, try KFileMetaInfo. +                KFileMetaInfo kmeta(fi.filePath()); +                if (kmeta.isValid()) +                { +                    if (kmeta.containsGroup("Jpeg EXIF Data")) +                        dims = kmeta.group("Jpeg EXIF Data").item("Dimensions").value().toSize(); +                    else if (kmeta.containsGroup("General")) +                        dims = kmeta.group("General").item("Dimensions").value().toSize(); +                    else if (kmeta.containsGroup("Technical")) +                        dims = kmeta.group("Technical").item("Dimensions").value().toSize(); +                } +            } +        } + +        if (dt.isNull()) +        { +            // If date is not found in metadata, use file time stamp +            dt = fi.created(); +        } + +        info.name             = fi.fileName(); +        info.folder           = !folder.endsWith("/") ? folder + TQString("/") : folder; +        info.mime             = mime; +        info.mtime            = dt.toTime_t(); +        info.size             = fi.size(); +        info.width            = getImageDimensions ? dims.width()  : -1; +        info.height           = getImageDimensions ? dims.height() : -1; +        info.downloaded       = GPItemInfo::DownloadUnknow; +        info.readPermissions  = fi.isReadable(); +        info.writePermissions = fi.isWritable(); +    } + +    return true; +} + +void UMSCamera::listFolders(const TQString& folder, TQStringList& subFolderList) +{ +    if (m_cancel) +        return; + +    TQDir dir(folder); +    dir.setFilter(TQDir::Dirs|TQDir::Executable); + +    const TQFileInfoList *list = dir.entryInfoList(); +    if (!list) +        return; + +    TQFileInfoListIterator it( *list ); +    TQFileInfo *fi; + +    while ((fi = it.current()) != 0 && !m_cancel) +    { +        ++it; + +        if (fi->fileName() == "." || fi->fileName() == "..") +            continue; + +        TQString subfolder = folder + TQString(folder.endsWith("/") ? "" : "/") + fi->fileName(); +        subFolderList.append(subfolder); +        listFolders(subfolder, subFolderList); +    } +} + +bool UMSCamera::cameraSummary(TQString& summary) +{ +    summary = TQString(i18n("<b>Mounted Camera</b> driver for USB/IEEE1394 mass storage cameras and " +                           "Flash disk card readers.<br><br>")); + +    summary.append(i18n("Title: %1<br>" +                        "Model: %2<br>" +                        "Port: %3<br>" +                        "Path: %4<br>") +                        .arg(title()) +                        .arg(model()) +                        .arg(port()) +                        .arg(path())); +    return true; +} + +bool UMSCamera::cameraManual(TQString& manual) +{ +    manual = TQString(i18n("For more information about the <b>Mounted Camera</b> driver, " +                          "please read <b>Supported Digital Still " +                          "Cameras</b> section in the digiKam manual.")); +    return true; +} + +bool UMSCamera::cameraAbout(TQString& about) +{ +    about = TQString(i18n("The <b>Mounted Camera</b> driver is a simple interface to a camera disk " +                         "mounted locally on your system.<br><br>" +                         "It doesn't use libgphoto2 drivers.<br><br>" +                         "To report any problems with this driver, please contact the digiKam team at:<br><br>" +                         "http://www.digikam.org/?q=contact")); +    return true; +} + +}  // namespace Digikam | 
