summaryrefslogtreecommitdiffstats
path: root/src/utilities/cameragui/umscamera.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/utilities/cameragui/umscamera.cpp')
-rw-r--r--src/utilities/cameragui/umscamera.cpp519
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