From 2e25fa39cd67cca2472d3eabdb478feb517d72a5 Mon Sep 17 00:00:00 2001 From: Timothy Pearson Date: Sun, 27 Jan 2013 01:03:37 -0600 Subject: Rename a number of libraries and executables to avoid conflicts with KDE4 --- kamera/CMakeLists.txt | 2 +- kamera/Makefile.am | 2 +- kamera/kcontrol/CMakeLists.txt | 2 +- kamera/kcontrol/kamera.desktop | 2 +- kamera/kcontrol/kameradevice.cpp | 2 +- kamera/kioslave/CMakeLists.txt | 37 -- kamera/kioslave/Makefile.am | 17 - kamera/kioslave/camera.protocol | 16 - kamera/kioslave/kamera.cpp | 1074 ------------------------------------- kamera/kioslave/kamera.h | 82 --- kamera/tdeioslave/CMakeLists.txt | 37 ++ kamera/tdeioslave/Makefile.am | 17 + kamera/tdeioslave/camera.protocol | 16 + kamera/tdeioslave/kamera.cpp | 1074 +++++++++++++++++++++++++++++++++++++ kamera/tdeioslave/kamera.h | 82 +++ 15 files changed, 1231 insertions(+), 1231 deletions(-) delete mode 100644 kamera/kioslave/CMakeLists.txt delete mode 100644 kamera/kioslave/Makefile.am delete mode 100644 kamera/kioslave/camera.protocol delete mode 100644 kamera/kioslave/kamera.cpp delete mode 100644 kamera/kioslave/kamera.h create mode 100644 kamera/tdeioslave/CMakeLists.txt create mode 100644 kamera/tdeioslave/Makefile.am create mode 100644 kamera/tdeioslave/camera.protocol create mode 100644 kamera/tdeioslave/kamera.cpp create mode 100644 kamera/tdeioslave/kamera.h (limited to 'kamera') diff --git a/kamera/CMakeLists.txt b/kamera/CMakeLists.txt index 700fe6a9..56e7c70d 100644 --- a/kamera/CMakeLists.txt +++ b/kamera/CMakeLists.txt @@ -11,6 +11,6 @@ include( ConfigureChecks.cmake ) -add_subdirectory( kioslave ) +add_subdirectory( tdeioslave ) add_subdirectory( kcontrol ) add_subdirectory( pics ) diff --git a/kamera/Makefile.am b/kamera/Makefile.am index f012f4a1..e7776502 100644 --- a/kamera/Makefile.am +++ b/kamera/Makefile.am @@ -1 +1 @@ -SUBDIRS = kcontrol kioslave pics +SUBDIRS = kcontrol tdeioslave pics diff --git a/kamera/kcontrol/CMakeLists.txt b/kamera/kcontrol/CMakeLists.txt index c4a395ab..c901d4b4 100644 --- a/kamera/kcontrol/CMakeLists.txt +++ b/kamera/kcontrol/CMakeLists.txt @@ -31,6 +31,6 @@ install( FILES kamera.desktop DESTINATION ${XDG_APPS_INSTALL_DIR} ) tde_add_kpart( kcm_kamera SHARED AUTOMOC SOURCES kamera.cpp kameradevice.cpp kameraconfigdialog.cpp - LINK kio-shared ${GPHOTO2_LIBRARIES} + LINK tdeio-shared ${GPHOTO2_LIBRARIES} DESTINATION ${PLUGIN_INSTALL_DIR} ) diff --git a/kamera/kcontrol/kamera.desktop b/kamera/kcontrol/kamera.desktop index ac9f737e..d06c4be9 100644 --- a/kamera/kcontrol/kamera.desktop +++ b/kamera/kcontrol/kamera.desktop @@ -188,6 +188,6 @@ Type=Application X-TDE-Library=kamera X-TDE-ModuleType=Library Icon=camera -Exec=kcmshell kamera +Exec=tdecmshell kamera DocPath=kamera/index.html Categories=Qt;TDE;Settings;X-TDE-settings-hardware; diff --git a/kamera/kcontrol/kameradevice.cpp b/kamera/kcontrol/kameradevice.cpp index 20d090fa..e6f26449 100644 --- a/kamera/kcontrol/kameradevice.cpp +++ b/kamera/kcontrol/kameradevice.cpp @@ -32,7 +32,7 @@ #include #include -#include +#include #include #include #include diff --git a/kamera/kioslave/CMakeLists.txt b/kamera/kioslave/CMakeLists.txt deleted file mode 100644 index d480f90e..00000000 --- a/kamera/kioslave/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -################################################# -# -# (C) 2010-2011 Calvin Morrison -# mutantturkey@gmail.com -# -# Improvements and feedback are welcome -# -# This file is released under GPL >= 2 -# -################################################# - -include_directories( - ${CMAKE_CURRENT_BINARY_DIR} - ${CMAKE_BINARY_DIR} - ${TDE_INCLUDE_DIR} - ${TQT_INCLUDE_DIRS} - ${GPHOTO2_INCLUDE_DIRS} -) - - -link_directories( - ${TQT_LIBRARY_DIRS} -) - - -##### other data ################################ - -install( FILES camera.protocol DESTINATION ${SERVICES_INSTALL_DIR} ) - - -#### kamera (module) ############################ - -tde_add_kpart( kio_kamera AUTOMOC - SOURCES kamera.cpp - LINK kio-shared ${GPHOTO2_LIBRARIES} - DESTINATION ${PLUGIN_INSTALL_DIR} -) diff --git a/kamera/kioslave/Makefile.am b/kamera/kioslave/Makefile.am deleted file mode 100644 index bfb0d198..00000000 --- a/kamera/kioslave/Makefile.am +++ /dev/null @@ -1,17 +0,0 @@ -# $Id$ -# Makefile for tdebase/kioslave/kamera - -INCLUDES= -I$(srcdir)/../.. -I$(srcdir)/.. $(all_includes) $(GPHOTO2_INCS) - -####### Files - -kde_module_LTLIBRARIES = kio_kamera.la - -kio_kamera_la_SOURCES = kamera.cpp -kio_kamera_la_LIBADD = $(LIB_KIO) -lgphoto2 -kio_kamera_la_LDFLAGS = $(all_libraries) $(GPHOTO2_LIBS) -module $(KDE_PLUGIN) - -noinst_HEADERS = kamera.h - -kde_services_DATA = camera.protocol - diff --git a/kamera/kioslave/camera.protocol b/kamera/kioslave/camera.protocol deleted file mode 100644 index 947d02b9..00000000 --- a/kamera/kioslave/camera.protocol +++ /dev/null @@ -1,16 +0,0 @@ -[Protocol] -exec=kio_kamera -protocol=camera -input=none -output=filesystem -listing=Name,Type -reading=true -writing=false -deleting=true -source=true -makedir=false -linking=false -moving=false -Icon=camera -maxInstances=1 -Class=:local diff --git a/kamera/kioslave/kamera.cpp b/kamera/kioslave/kamera.cpp deleted file mode 100644 index 9806a132..00000000 --- a/kamera/kioslave/kamera.cpp +++ /dev/null @@ -1,1074 +0,0 @@ -/* - - Copyright (C) 2001 The Kompany - 2001-2003 Ilya Konstantinov - 2001-2007 Marcus Meissner - - 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 of the License, 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. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -*/ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "kamera.h" - -#define MAXIDLETIME 30 /* seconds */ - -#define tocstr(x) ((x).local8Bit()) - -using namespace TDEIO; - -extern "C" -{ - KDE_EXPORT int kdemain(int argc, char **argv); - - static void frontendCameraStatus(GPContext *context, const char *format, va_list args, void *data); - static unsigned int frontendProgressStart( - GPContext *context, float totalsize, const char *format, - va_list args, void *data - ); - static void frontendProgressUpdate( - GPContext *context, unsigned int id, float current, void *data - ); -} - -int kdemain(int argc, char **argv) -{ - TDEInstance instance("kio_kamera"); - - if(argc != 4) { - kdDebug(7123) << "Usage: kio_kamera protocol " - "domain-socket1 domain-socket2" << endl; - exit(-1); - } - KameraProtocol slave(argv[2], argv[3]); - slave.dispatchLoop(); - return 0; -} - -KameraProtocol::KameraProtocol(const TQCString &pool, const TQCString &app) -: SlaveBase("camera", pool, app), -m_camera(NULL) -{ - // attempt to initialize libgphoto2 and chosen camera (requires locking) - // (will init m_camera, since the m_camera's configuration is empty) - m_camera = 0; - m_file = NULL; - m_config = new KSimpleConfig(KProtocolInfo::config("camera")); - m_context = gp_context_new(); - actiondone = true; - cameraopen = false; - m_modelSpecified = true; - m_lockfile = locateLocal("tmp", "kamera"); - idletime = 0; -} - -// This handler is getting called every second. We use it to do the -// delayed close of the camera. -// Logic is: -// - No more requests in the queue (signaled by actiondone) AND -// - We are MAXIDLETIME seconds idle OR -// - Another slave wants to have access to the camera. -// -// The existance of a lockfile is used to signify "please give up camera". -// -void KameraProtocol::special(const TQByteArray&) { - kdDebug(7123) << "KameraProtocol::special() at " << getpid() << endl; - - if (!actiondone && cameraopen) { - struct stat stbuf; - if ((-1!=::stat(m_lockfile.utf8(),&stbuf)) || (idletime++ >= MAXIDLETIME)) { - kdDebug(7123) << "KameraProtocol::special() closing camera." << endl; - closeCamera(); - setTimeoutSpecialCommand(-1); - } else { - // continue to wait - setTimeoutSpecialCommand(1); - } - } else { - // We let it run until the slave gets no actions anymore. - setTimeoutSpecialCommand(1); - } - actiondone = false; -} - -KameraProtocol::~KameraProtocol() -{ - kdDebug(7123) << "KameraProtocol::~KameraProtocol()" << endl; - delete m_config; - if(m_camera) { - closeCamera(); - gp_camera_free(m_camera); - m_camera = NULL; - } -} - -// initializes the camera for usage - should be done before operations over the wire -bool KameraProtocol::openCamera(TQString &str) { - idletime = 0; - actiondone = true; - if (!m_camera) { - reparseConfiguration(); - } else { - if (!cameraopen) { - int ret, tries = 15; - kdDebug(7123) << "KameraProtocol::openCamera at " << getpid() << endl; - while (tries--) { - ret = gp_camera_init(m_camera, m_context); - if ( (ret == GP_ERROR_IO_USB_CLAIM) || - (ret == GP_ERROR_IO_LOCK)) { - // just create / touch if not there - int fd = ::open(m_lockfile.utf8(),O_CREAT|O_WRONLY,0600); - if (fd != -1) ::close(fd); - ::sleep(1); - kdDebug(7123) << "openCamera at " << getpid() << "- busy, ret " << ret << ", trying again." << endl; - continue; - } - if (ret == GP_OK) break; - str = gp_result_as_string(ret); - return false; - } - ::unlink(m_lockfile.utf8()); - setTimeoutSpecialCommand(1); - kdDebug(7123) << "openCamera succeeded at " << getpid() << endl; - if (!m_modelSpecified) { - gp_camera_get_abilities(m_camera, &m_abilities); - m_modelSpecified = true; - } - cameraopen = true; - } - } - return true; -} - -// should be done after operations over the wire -void KameraProtocol::closeCamera(void) -{ - int gpr; - - if (!m_camera) - return; - - kdDebug(7123) << "KameraProtocol::closeCamera at " << getpid() << endl; - if ((gpr=gp_camera_exit(m_camera,m_context))!=GP_OK) { - kdDebug(7123) << "closeCamera failed with " << gp_result_as_string(gpr) << endl; - } - // HACK: gp_camera_exit() in gp 2.0 does not close the port if there - // is no camera_exit function. - gp_port_close(m_camera->port); - cameraopen = false; - return; -} - -static TQString fix_foldername(TQString ofolder) { - TQString folder = ofolder; - if (folder.length() > 1) { - while ((folder.length()>1) && (folder.right(1) == "/")) - folder = folder.left(folder.length()-1); - } - if (folder.length() == 0) - folder = "/"; - return folder; -} - -// The KIO slave "get" function (starts a download from the camera) -// The actual returning of the data is done in the frontend callback functions. -void KameraProtocol::get(const KURL &url) -{ - kdDebug(7123) << "KameraProtocol::get(" << url.path() << ")" << endl; - - CameraFileType fileType; - int gpr; - if (url.host().isEmpty()) { - error(TDEIO::ERR_DOES_NOT_EXIST, url.path()); - return; - } - - if(!openCamera()) { - error(TDEIO::ERR_DOES_NOT_EXIST, url.path()); - return; - } - - // fprintf(stderr,"get(%s)\n",url.path().latin1()); - -#define GPHOTO_TEXT_FILE(xx) \ - if (!url.path().compare("/" #xx ".txt")) { \ - CameraText xx; \ - gpr = gp_camera_get_##xx(m_camera, &xx, m_context); \ - if (gpr != GP_OK) { \ - error(TDEIO::ERR_DOES_NOT_EXIST, url.path()); \ - return; \ - } \ - TQByteArray chunkDataBuffer; \ - chunkDataBuffer.setRawData(xx.text, strlen(xx.text)); \ - data(chunkDataBuffer); \ - processedSize(strlen(xx.text)); \ - chunkDataBuffer.resetRawData(xx.text, strlen(xx.text)); \ - finished(); \ - return; \ - } - - GPHOTO_TEXT_FILE(about); - GPHOTO_TEXT_FILE(manual); - GPHOTO_TEXT_FILE(summary); - -#undef GPHOTO_TEXT_FILE - // emit info message - infoMessage( i18n("Retrieving data from camera %1").arg(url.user()) ); - - // Note: There's no need to re-read directory for each get() anymore - gp_file_new(&m_file); - - // emit the total size (we must do it before sending data to allow preview) - CameraFileInfo info; - - gpr = gp_camera_file_get_info(m_camera, tocstr(fix_foldername(url.directory(false))), tocstr(url.fileName()), &info, m_context); - if (gpr != GP_OK) { - // fprintf(stderr,"Folder %s / File %s not found, gpr is %d\n",folder.latin1(), url.fileName().latin1(), gpr); - gp_file_unref(m_file); - if ((gpr == GP_ERROR_FILE_NOT_FOUND) || (gpr == GP_ERROR_DIRECTORY_NOT_FOUND)) - error(TDEIO::ERR_DOES_NOT_EXIST, url.path()); - else - error(TDEIO::ERR_UNKNOWN, gp_result_as_string(gpr)); - return; - } - - // at last, a proper API to determine whether a thumbnail was requested. - if(cameraSupportsPreview() && metaData("thumbnail") == "1") { - kdDebug(7123) << "get() retrieving the thumbnail" << endl; - fileType = GP_FILE_TYPE_PREVIEW; - if (info.preview.fields & GP_FILE_INFO_SIZE) - totalSize(info.preview.size); - if (info.preview.fields & GP_FILE_INFO_TYPE) - mimeType(info.preview.type); - } else { - kdDebug(7123) << "get() retrieving the full-scale photo" << endl; - fileType = GP_FILE_TYPE_NORMAL; - if (info.file.fields & GP_FILE_INFO_SIZE) - totalSize(info.file.size); - if (info.preview.fields & GP_FILE_INFO_TYPE) - mimeType(info.file.type); - } - - // fetch the data - m_fileSize = 0; - gpr = gp_camera_file_get(m_camera, tocstr(fix_foldername(url.directory(false))), tocstr(url.fileName()), fileType, m_file, m_context); - if ( (gpr == GP_ERROR_NOT_SUPPORTED) && - (fileType == GP_FILE_TYPE_PREVIEW) - ) { - // If we get here, the file info command information - // will either not be used, or still valid. - fileType = GP_FILE_TYPE_NORMAL; - gpr = gp_camera_file_get(m_camera, tocstr(fix_foldername(url.directory(false))), tocstr(url.fileName()), fileType, m_file, m_context); - } - switch(gpr) { - case GP_OK: - break; - case GP_ERROR_FILE_NOT_FOUND: - case GP_ERROR_DIRECTORY_NOT_FOUND: - gp_file_unref(m_file); - m_file = NULL; - error(TDEIO::ERR_DOES_NOT_EXIST, url.fileName()); - return ; - default: - gp_file_unref(m_file); - m_file = NULL; - error(TDEIO::ERR_UNKNOWN, gp_result_as_string(gpr)); - return; - } - // emit the mimetype - // NOTE: we must first get the file, so that CameraFile->name would be set - const char *fileMimeType; - gp_file_get_mime_type(m_file, &fileMimeType); - mimeType(fileMimeType); - - // We need to pass left over data here. Some camera drivers do not - // implement progress callbacks! - const char *fileData; - long unsigned int fileSize; - // This merely returns us a pointer to gphoto's internal data - // buffer -- there's no expensive memcpy - gpr = gp_file_get_data_and_size(m_file, &fileData, &fileSize); - if (gpr != GP_OK) { - kdDebug(7123) << "get():: get_data_and_size failed." << endl; - gp_file_free(m_file); - m_file = NULL; - error(TDEIO::ERR_UNKNOWN, gp_result_as_string(gpr)); - return; - } - // make sure we're not sending zero-sized chunks (=EOF) - // also make sure we send only if the progress did not send the data - // already. - if ((fileSize > 0) && (fileSize - m_fileSize)>0) { - unsigned long written = 0; - TQByteArray chunkDataBuffer; - - // We need to split it up here. Someone considered it funny - // to discard any data() larger than 16MB. - // - // So nearly any Movie will just fail.... - while (written < fileSize-m_fileSize) { - unsigned long towrite = 1024*1024; // 1MB - - if (towrite > fileSize-m_fileSize-written) - towrite = fileSize-m_fileSize-written; - chunkDataBuffer.setRawData(fileData + m_fileSize + written, towrite); - processedSize(m_fileSize + written + towrite); - data(chunkDataBuffer); - chunkDataBuffer.resetRawData(fileData + m_fileSize + written, towrite); - written += towrite; - } - m_fileSize = fileSize; - setFileSize(fileSize); - } - - finished(); - gp_file_unref(m_file); /* just unref, might be stored in fs */ - m_file = NULL; -} - -// The KIO slave "stat" function. -void KameraProtocol::stat(const KURL &url) -{ - kdDebug(7123) << "stat(\"" << url.path() << "\")" << endl; - - if (url.path() == "") { - KURL rooturl(url); - - kdDebug(7123) << "redirecting to /" << endl; - rooturl.setPath("/"); - rooturl.setHost(url.host()); - rooturl.setUser(url.user()); - redirection(rooturl); - finished(); - return; - } - - if(url.path() == "/") - statRoot(); - else - statRegular(url); -} - -// Implements stat("/") -- which always returns the same value. -void KameraProtocol::statRoot(void) -{ - UDSEntry entry; - UDSAtom atom; - - atom.m_uds = UDS_NAME; - atom.m_str = "/"; - entry.append(atom); - - atom.m_uds = UDS_FILE_TYPE; - atom.m_long = S_IFDIR; - entry.append(atom); - - atom.m_uds = UDS_ACCESS; - atom.m_long = S_IRUSR | S_IRGRP | S_IROTH | - S_IWUSR | S_IWGRP | S_IWOTH; - entry.append(atom); - - statEntry(entry); - - finished(); - - // This call happens on autodetect by kdemm. So close the camera, but - // only if no more requests are pending. - idletime = MAXIDLETIME; -} - -// Implements a regular stat() of a file / directory, returning all we know about it -void KameraProtocol::statRegular(const KURL &url) -{ - UDSEntry entry; - int gpr; - - kdDebug(7123) << "statRegular(\"" << url.path() << "\")" << endl; - if (openCamera() == false) { - error(TDEIO::ERR_DOES_NOT_EXIST, url.path()); - return; - } - - // fprintf(stderr,"statRegular(%s)\n",url.path().latin1()); - - // Is "url" a directory? - CameraList *dirList; - gp_list_new(&dirList); - kdDebug(7123) << "statRegular() Requesting directories list for " << url.directory() << endl; - - gpr = gp_camera_folder_list_folders(m_camera, tocstr(fix_foldername(url.directory(false))), dirList, m_context); - if (gpr != GP_OK) { - if ((gpr == GP_ERROR_FILE_NOT_FOUND) || (gpr == GP_ERROR_DIRECTORY_NOT_FOUND)) - error(TDEIO::ERR_DOES_NOT_EXIST, url.path()); - else - error(TDEIO::ERR_UNKNOWN, gp_result_as_string(gpr)); - gp_list_free(dirList); - return; - } - -#define GPHOTO_TEXT_FILE(xx) \ - if (!url.path().compare("/"#xx".txt")) { \ - CameraText xx; \ - gpr = gp_camera_get_about(m_camera, &xx, m_context); \ - if (gpr != GP_OK) { \ - error(TDEIO::ERR_DOES_NOT_EXIST, url.fileName()); \ - return; \ - } \ - translateTextToUDS(entry,#xx".txt",xx.text); \ - statEntry(entry); \ - finished(); \ - return; \ - } - GPHOTO_TEXT_FILE(about); - GPHOTO_TEXT_FILE(manual); - GPHOTO_TEXT_FILE(summary); -#undef GPHOTO_TEXT_FILE - - const char *name; - for(int i = 0; i < gp_list_count(dirList); i++) { - gp_list_get_name(dirList, i, &name); - if (url.fileName().compare(name) == 0) { - gp_list_free(dirList); - UDSEntry entry; - translateDirectoryToUDS(entry, url.fileName()); - statEntry(entry); - finished(); - return; - } - } - gp_list_free(dirList); - - // Is "url" a file? - CameraFileInfo info; - gpr = gp_camera_file_get_info(m_camera, tocstr(fix_foldername(url.directory(false))), tocstr(url.fileName()), &info, m_context); - if (gpr != GP_OK) { - if ((gpr == GP_ERROR_FILE_NOT_FOUND) || (gpr == GP_ERROR_DIRECTORY_NOT_FOUND)) - error(TDEIO::ERR_DOES_NOT_EXIST, url.path()); - else - error(TDEIO::ERR_UNKNOWN, gp_result_as_string(gpr)); - return; - } - translateFileToUDS(entry, info, url.fileName()); - statEntry(entry); - finished(); -} - -// The KIO slave "del" function. -void KameraProtocol::del(const KURL &url, bool isFile) -{ - kdDebug(7123) << "KameraProtocol::del(" << url.path() << ")" << endl; - - if(!openCamera()) { - error(TDEIO::ERR_CANNOT_DELETE, url.fileName()); - return; - } - if (!cameraSupportsDel()) { - error(TDEIO::ERR_CANNOT_DELETE, url.fileName()); - return; - } - if(isFile){ - CameraList *list; - gp_list_new(&list); - int ret; - - ret = gp_camera_file_delete(m_camera, tocstr(fix_foldername(url.directory(false))), tocstr(url.fileName()), m_context); - - if(ret != GP_OK) { - error(TDEIO::ERR_CANNOT_DELETE, url.fileName()); - } else { - finished(); - } - } -} - -// The KIO slave "listDir" function. -void KameraProtocol::listDir(const KURL &url) -{ - kdDebug(7123) << "KameraProtocol::listDir(" << url.path() << ")" << endl; - - if (url.host().isEmpty()) { - KURL xurl; - // List the available cameras - TQStringList groupList = m_config->groupList(); - kdDebug(7123) << "Found cameras: " << groupList.join(", ") << endl; - TQStringList::Iterator it; - UDSEntry entry; - UDSAtom atom; - - - /* - * What we do: - * - Autodetect cameras and remember them with their ports. - * - List all saved and possible offline cameras. - * - List all autodetected and not yet printed cameras. - */ - TQMap ports, names; - TQMap modelcnt; - - /* Autodetect USB cameras ... */ - GPContext *glob_context = NULL; - int i, count; - CameraList *list; - CameraAbilitiesList *al; - GPPortInfoList *il; - - gp_list_new (&list); - gp_abilities_list_new (&al); - gp_abilities_list_load (al, glob_context); - gp_port_info_list_new (&il); - gp_port_info_list_load (il); - gp_abilities_list_detect (al, il, list, glob_context); - gp_abilities_list_free (al); - gp_port_info_list_free (il); - - count = gp_list_count (list); - - for (i = 0 ; isetGroup(model); - m_config->writeEntry("Model",model); - m_config->writeEntry("Path",value); - modelcnt[model]++; - } - gp_list_free (list); - - /* Avoid duplicated entry for usb: and usb:001,042 entries. */ - if (ports.contains("usb:") && names[ports["usb:"]]!="usb:") - ports.remove("usb:"); - - for (it = groupList.begin(); it != groupList.end(); it++) { - TQString m_cfgPath; - if (*it == "") - continue; - - m_config->setGroup(*it); - m_cfgPath = m_config->readEntry("Path"); - - /* If autodetect by USB autodetect ... skip it here. - * We leave unattached USB cameras in here, because the user - * might plug them in later and does not want to press reload. - * We add them with port "usb:". - */ - if (modelcnt[*it] > 0) - continue; - - entry.clear(); - atom.m_uds = UDS_FILE_TYPE;atom.m_long = S_IFDIR;entry.append(atom); - atom.m_uds = UDS_NAME;atom.m_str = *it;entry.append(atom); - atom.m_uds = UDS_ACCESS; - atom.m_long = S_IRUSR | S_IRGRP | S_IROTH | - S_IWUSR | S_IWGRP | S_IWOTH; - entry.append(atom); - - atom.m_uds = UDS_URL; - - xurl.setProtocol("camera"); - xurl.setUser(*it); - /* Avoid setting usb:xxx,yyy. */ - if (m_cfgPath.contains("usb:")>0) { - names[*it] = "usb:"; - xurl.setHost("usb:"); - } else { - xurl.setHost(m_cfgPath); - } - xurl.setPath("/"); - atom.m_str = xurl.url(); - entry.append(atom); - - listEntry(entry, false); - } - - TQMap::iterator portsit; - - for (portsit = ports.begin(); portsit != ports.end(); portsit++) { - entry.clear(); - atom.m_uds = UDS_FILE_TYPE;atom.m_long = S_IFDIR; entry.append(atom); - atom.m_uds = UDS_NAME;atom.m_str = portsit.data();entry.append(atom); - - atom.m_uds = UDS_ACCESS; - atom.m_long = S_IRUSR | S_IRGRP | S_IROTH | - S_IWUSR | S_IWGRP | S_IWOTH; - entry.append(atom); - - atom.m_uds = UDS_URL; - xurl.setProtocol("camera"); - xurl.setHost(portsit.key()); - xurl.setUser(portsit.data()); - xurl.setPath("/"); - atom.m_str = xurl.url(); - entry.append(atom); - - listEntry(entry, false); - } - listEntry(entry, true); - - finished(); - return; - } - - if (url.path() == "") { - KURL rooturl(url); - - kdDebug(7123) << "redirecting to /" << endl; - rooturl.setPath("/"); - rooturl.setHost(url.host()); - rooturl.setUser(url.user()); - redirection(rooturl); - finished(); - return; - } - - if (!openCamera()) { - error(TDEIO::ERR_COULD_NOT_READ,url.path()); - return; - } - - CameraList *dirList; - CameraList *fileList; - CameraList *specialList; - gp_list_new(&dirList); - gp_list_new(&fileList); - gp_list_new(&specialList); - int gpr; - - if (!url.path().compare("/")) { - CameraText text; - if (GP_OK == gp_camera_get_manual(m_camera, &text, m_context)) - gp_list_append(specialList,"manual.txt",NULL); - if (GP_OK == gp_camera_get_about(m_camera, &text, m_context)) - gp_list_append(specialList,"about.txt",NULL); - if (GP_OK == gp_camera_get_summary(m_camera, &text, m_context)) - gp_list_append(specialList,"summary.txt",NULL); - } - - gpr = readCameraFolder(url.path(), dirList, fileList); - if(gpr != GP_OK) { - kdDebug(7123) << "read Camera Folder failed:" << gp_result_as_string(gpr) <getFile()) - return; - gp_file_get_data_and_size(object->getFile(), &fileData, &fileSize); - // make sure we're not sending zero-sized chunks (=EOF) - if (fileSize > 0) { - // XXX using assign() here causes segfault, prolly because - // gp_file_free is called before chunkData goes out of scope - TQByteArray chunkDataBuffer; - chunkDataBuffer.setRawData(fileData + object->getFileSize(), fileSize - object->getFileSize()); - // Note: this will fail with sizes > 16MB ... - object->data(chunkDataBuffer); - object->processedSize(fileSize); - chunkDataBuffer.resetRawData(fileData + object->getFileSize(), fileSize - object->getFileSize()); - object->setFileSize(fileSize); - } -} - -unsigned int frontendProgressStart( - GPContext * /*context*/, float totalsize, const char *format, va_list args, - void *data -) { - KameraProtocol *object = (KameraProtocol*)data; - char *status; - - /* We must copy the va_list to walk it twice, or all hell - * breaks loose on non-i386 platforms. - */ -#if defined(HAVE_VA_COPY) || defined(HAVE___VA_COPY) - va_list xvalist; -# ifdef HAVE_VA_COPY - va_copy(xvalist, args); -# elif HAVE___VA_COPY - __va_copy(xvalist, args); -# endif - int size=vsnprintf(NULL, 0, format, xvalist); - if(size<=0) - return GP_OK; // vsnprintf is broken, better don't do anything. - - status=new char[size+1]; -# ifdef HAVE_VA_COPY - va_copy(xvalist, args); -# elif HAVE___VA_COPY - __va_copy(xvalist, args); -# endif - vsnprintf(status, size+1, format, xvalist); -#else - /* We cannot copy the va_list, so make sure we - * walk it just _once_. - */ - status=new char[300]; - vsnprintf(status, 300, format, args); -#endif - - object->infoMessage(TQString::fromLocal8Bit(status)); - delete [] status; - object->totalSize((int)totalsize); // hack: call slot directly - return GP_OK; -} - -// this callback function is activated on every status message from gphoto2 -static void frontendCameraStatus(GPContext * /*context*/, const char *format, va_list args, void *data) -{ - KameraProtocol *object = (KameraProtocol*)data; - char *status; - - /* We must copy the va_list to walk it twice, or all hell - * breaks loose on non-i386 platforms. - */ -#if defined(HAVE_VA_COPY) || defined(HAVE___VA_COPY) - va_list xvalist; -# ifdef HAVE_VA_COPY - va_copy(xvalist, args); -# elif HAVE___VA_COPY - __va_copy(xvalist, args); -# endif - int size=vsnprintf(NULL, 0, format, xvalist); - if(size<=0) - return; // vsnprintf is broken, better don't do anything. - - status=new char[size+1]; -# ifdef HAVE_VA_COPY - va_copy(xvalist, args); -# elif HAVE___VA_COPY - __va_copy(xvalist, args); -# endif - vsnprintf(status, size+1, format, xvalist); -#else - /* We cannot copy the va_list, so make sure we - * walk it just _once_. - */ - status=new char[300]; - vsnprintf(status, 300, format, args); -#endif - object->infoMessage(TQString::fromLocal8Bit(status)); - delete [] status; -} diff --git a/kamera/kioslave/kamera.h b/kamera/kioslave/kamera.h deleted file mode 100644 index f569f4ac..00000000 --- a/kamera/kioslave/kamera.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - - Copyright (C) 2001 The Kompany - 2001-2003 Ilya Konstantinov - 2001-2007 Marcus Meissner - - 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 of the License, 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. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -*/ - -#ifndef __kamera_h__ -#define __kamera_h__ - -#include -#include -#include - -class KSimpleConfig; - -class KameraProtocol : public TDEIO::SlaveBase -{ -public: - KameraProtocol(const TQCString &pool, const TQCString &app); - virtual ~KameraProtocol(); - - virtual void get(const KURL &url); - virtual void stat(const KURL &url); - virtual void del(const KURL &url, bool isFile); - virtual void setHost(const TQString& host, int port, const TQString& user, const TQString& pass ); - virtual void listDir(const KURL &url); - virtual void special(const TQByteArray &data); - - CameraFile *getFile() { return m_file; } - int getFileSize() { return m_fileSize; } - void setFileSize(int newfs) { m_fileSize = newfs; } - -private: - Camera *m_camera; - CameraAbilities m_abilities; - KSimpleConfig *m_config; - - GPContext *m_context; - - void reparseConfiguration(void); - bool openCamera(TQString& str); - bool openCamera(void ) { - TQString errstr; - return openCamera(errstr); - } - void closeCamera(void); - - void statRoot(void); - void statRegular(const KURL &url); - void translateTextToUDS(TDEIO::UDSEntry &udsEntry, const TQString &info, const char *txt); - void translateFileToUDS(TDEIO::UDSEntry &udsEntry, const CameraFileInfo &info, TQString name); - void translateDirectoryToUDS(TDEIO::UDSEntry &udsEntry, const TQString &dirname); - bool cameraSupportsPreview(void); - bool cameraSupportsDel(void); - bool cameraSupportsPut(void); - int readCameraFolder(const TQString &folder, CameraList *dirList, CameraList *fileList); - - TQString m_lockfile; - int idletime; - - int m_fileSize; - CameraFile *m_file; - bool actiondone, cameraopen; - bool m_modelSpecified; -}; -#endif diff --git a/kamera/tdeioslave/CMakeLists.txt b/kamera/tdeioslave/CMakeLists.txt new file mode 100644 index 00000000..33ca815e --- /dev/null +++ b/kamera/tdeioslave/CMakeLists.txt @@ -0,0 +1,37 @@ +################################################# +# +# (C) 2010-2011 Calvin Morrison +# mutantturkey@gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_BINARY_DIR} + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} + ${GPHOTO2_INCLUDE_DIRS} +) + + +link_directories( + ${TQT_LIBRARY_DIRS} +) + + +##### other data ################################ + +install( FILES camera.protocol DESTINATION ${SERVICES_INSTALL_DIR} ) + + +#### kamera (module) ############################ + +tde_add_kpart( kio_kamera AUTOMOC + SOURCES kamera.cpp + LINK tdeio-shared ${GPHOTO2_LIBRARIES} + DESTINATION ${PLUGIN_INSTALL_DIR} +) diff --git a/kamera/tdeioslave/Makefile.am b/kamera/tdeioslave/Makefile.am new file mode 100644 index 00000000..80877fa7 --- /dev/null +++ b/kamera/tdeioslave/Makefile.am @@ -0,0 +1,17 @@ +# $Id$ +# Makefile for tdebase/tdeioslave/kamera + +INCLUDES= -I$(srcdir)/../.. -I$(srcdir)/.. $(all_includes) $(GPHOTO2_INCS) + +####### Files + +kde_module_LTLIBRARIES = kio_kamera.la + +kio_kamera_la_SOURCES = kamera.cpp +kio_kamera_la_LIBADD = $(LIB_KIO) -lgphoto2 +kio_kamera_la_LDFLAGS = $(all_libraries) $(GPHOTO2_LIBS) -module $(KDE_PLUGIN) + +noinst_HEADERS = kamera.h + +kde_services_DATA = camera.protocol + diff --git a/kamera/tdeioslave/camera.protocol b/kamera/tdeioslave/camera.protocol new file mode 100644 index 00000000..947d02b9 --- /dev/null +++ b/kamera/tdeioslave/camera.protocol @@ -0,0 +1,16 @@ +[Protocol] +exec=kio_kamera +protocol=camera +input=none +output=filesystem +listing=Name,Type +reading=true +writing=false +deleting=true +source=true +makedir=false +linking=false +moving=false +Icon=camera +maxInstances=1 +Class=:local diff --git a/kamera/tdeioslave/kamera.cpp b/kamera/tdeioslave/kamera.cpp new file mode 100644 index 00000000..45d11970 --- /dev/null +++ b/kamera/tdeioslave/kamera.cpp @@ -0,0 +1,1074 @@ +/* + + Copyright (C) 2001 The Kompany + 2001-2003 Ilya Konstantinov + 2001-2007 Marcus Meissner + + 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 of the License, 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. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "kamera.h" + +#define MAXIDLETIME 30 /* seconds */ + +#define tocstr(x) ((x).local8Bit()) + +using namespace TDEIO; + +extern "C" +{ + KDE_EXPORT int kdemain(int argc, char **argv); + + static void frontendCameraStatus(GPContext *context, const char *format, va_list args, void *data); + static unsigned int frontendProgressStart( + GPContext *context, float totalsize, const char *format, + va_list args, void *data + ); + static void frontendProgressUpdate( + GPContext *context, unsigned int id, float current, void *data + ); +} + +int kdemain(int argc, char **argv) +{ + TDEInstance instance("kio_kamera"); + + if(argc != 4) { + kdDebug(7123) << "Usage: kio_kamera protocol " + "domain-socket1 domain-socket2" << endl; + exit(-1); + } + KameraProtocol slave(argv[2], argv[3]); + slave.dispatchLoop(); + return 0; +} + +KameraProtocol::KameraProtocol(const TQCString &pool, const TQCString &app) +: SlaveBase("camera", pool, app), +m_camera(NULL) +{ + // attempt to initialize libgphoto2 and chosen camera (requires locking) + // (will init m_camera, since the m_camera's configuration is empty) + m_camera = 0; + m_file = NULL; + m_config = new KSimpleConfig(KProtocolInfo::config("camera")); + m_context = gp_context_new(); + actiondone = true; + cameraopen = false; + m_modelSpecified = true; + m_lockfile = locateLocal("tmp", "kamera"); + idletime = 0; +} + +// This handler is getting called every second. We use it to do the +// delayed close of the camera. +// Logic is: +// - No more requests in the queue (signaled by actiondone) AND +// - We are MAXIDLETIME seconds idle OR +// - Another slave wants to have access to the camera. +// +// The existance of a lockfile is used to signify "please give up camera". +// +void KameraProtocol::special(const TQByteArray&) { + kdDebug(7123) << "KameraProtocol::special() at " << getpid() << endl; + + if (!actiondone && cameraopen) { + struct stat stbuf; + if ((-1!=::stat(m_lockfile.utf8(),&stbuf)) || (idletime++ >= MAXIDLETIME)) { + kdDebug(7123) << "KameraProtocol::special() closing camera." << endl; + closeCamera(); + setTimeoutSpecialCommand(-1); + } else { + // continue to wait + setTimeoutSpecialCommand(1); + } + } else { + // We let it run until the slave gets no actions anymore. + setTimeoutSpecialCommand(1); + } + actiondone = false; +} + +KameraProtocol::~KameraProtocol() +{ + kdDebug(7123) << "KameraProtocol::~KameraProtocol()" << endl; + delete m_config; + if(m_camera) { + closeCamera(); + gp_camera_free(m_camera); + m_camera = NULL; + } +} + +// initializes the camera for usage - should be done before operations over the wire +bool KameraProtocol::openCamera(TQString &str) { + idletime = 0; + actiondone = true; + if (!m_camera) { + reparseConfiguration(); + } else { + if (!cameraopen) { + int ret, tries = 15; + kdDebug(7123) << "KameraProtocol::openCamera at " << getpid() << endl; + while (tries--) { + ret = gp_camera_init(m_camera, m_context); + if ( (ret == GP_ERROR_IO_USB_CLAIM) || + (ret == GP_ERROR_IO_LOCK)) { + // just create / touch if not there + int fd = ::open(m_lockfile.utf8(),O_CREAT|O_WRONLY,0600); + if (fd != -1) ::close(fd); + ::sleep(1); + kdDebug(7123) << "openCamera at " << getpid() << "- busy, ret " << ret << ", trying again." << endl; + continue; + } + if (ret == GP_OK) break; + str = gp_result_as_string(ret); + return false; + } + ::unlink(m_lockfile.utf8()); + setTimeoutSpecialCommand(1); + kdDebug(7123) << "openCamera succeeded at " << getpid() << endl; + if (!m_modelSpecified) { + gp_camera_get_abilities(m_camera, &m_abilities); + m_modelSpecified = true; + } + cameraopen = true; + } + } + return true; +} + +// should be done after operations over the wire +void KameraProtocol::closeCamera(void) +{ + int gpr; + + if (!m_camera) + return; + + kdDebug(7123) << "KameraProtocol::closeCamera at " << getpid() << endl; + if ((gpr=gp_camera_exit(m_camera,m_context))!=GP_OK) { + kdDebug(7123) << "closeCamera failed with " << gp_result_as_string(gpr) << endl; + } + // HACK: gp_camera_exit() in gp 2.0 does not close the port if there + // is no camera_exit function. + gp_port_close(m_camera->port); + cameraopen = false; + return; +} + +static TQString fix_foldername(TQString ofolder) { + TQString folder = ofolder; + if (folder.length() > 1) { + while ((folder.length()>1) && (folder.right(1) == "/")) + folder = folder.left(folder.length()-1); + } + if (folder.length() == 0) + folder = "/"; + return folder; +} + +// The KIO slave "get" function (starts a download from the camera) +// The actual returning of the data is done in the frontend callback functions. +void KameraProtocol::get(const KURL &url) +{ + kdDebug(7123) << "KameraProtocol::get(" << url.path() << ")" << endl; + + CameraFileType fileType; + int gpr; + if (url.host().isEmpty()) { + error(TDEIO::ERR_DOES_NOT_EXIST, url.path()); + return; + } + + if(!openCamera()) { + error(TDEIO::ERR_DOES_NOT_EXIST, url.path()); + return; + } + + // fprintf(stderr,"get(%s)\n",url.path().latin1()); + +#define GPHOTO_TEXT_FILE(xx) \ + if (!url.path().compare("/" #xx ".txt")) { \ + CameraText xx; \ + gpr = gp_camera_get_##xx(m_camera, &xx, m_context); \ + if (gpr != GP_OK) { \ + error(TDEIO::ERR_DOES_NOT_EXIST, url.path()); \ + return; \ + } \ + TQByteArray chunkDataBuffer; \ + chunkDataBuffer.setRawData(xx.text, strlen(xx.text)); \ + data(chunkDataBuffer); \ + processedSize(strlen(xx.text)); \ + chunkDataBuffer.resetRawData(xx.text, strlen(xx.text)); \ + finished(); \ + return; \ + } + + GPHOTO_TEXT_FILE(about); + GPHOTO_TEXT_FILE(manual); + GPHOTO_TEXT_FILE(summary); + +#undef GPHOTO_TEXT_FILE + // emit info message + infoMessage( i18n("Retrieving data from camera %1").arg(url.user()) ); + + // Note: There's no need to re-read directory for each get() anymore + gp_file_new(&m_file); + + // emit the total size (we must do it before sending data to allow preview) + CameraFileInfo info; + + gpr = gp_camera_file_get_info(m_camera, tocstr(fix_foldername(url.directory(false))), tocstr(url.fileName()), &info, m_context); + if (gpr != GP_OK) { + // fprintf(stderr,"Folder %s / File %s not found, gpr is %d\n",folder.latin1(), url.fileName().latin1(), gpr); + gp_file_unref(m_file); + if ((gpr == GP_ERROR_FILE_NOT_FOUND) || (gpr == GP_ERROR_DIRECTORY_NOT_FOUND)) + error(TDEIO::ERR_DOES_NOT_EXIST, url.path()); + else + error(TDEIO::ERR_UNKNOWN, gp_result_as_string(gpr)); + return; + } + + // at last, a proper API to determine whether a thumbnail was requested. + if(cameraSupportsPreview() && metaData("thumbnail") == "1") { + kdDebug(7123) << "get() retrieving the thumbnail" << endl; + fileType = GP_FILE_TYPE_PREVIEW; + if (info.preview.fields & GP_FILE_INFO_SIZE) + totalSize(info.preview.size); + if (info.preview.fields & GP_FILE_INFO_TYPE) + mimeType(info.preview.type); + } else { + kdDebug(7123) << "get() retrieving the full-scale photo" << endl; + fileType = GP_FILE_TYPE_NORMAL; + if (info.file.fields & GP_FILE_INFO_SIZE) + totalSize(info.file.size); + if (info.preview.fields & GP_FILE_INFO_TYPE) + mimeType(info.file.type); + } + + // fetch the data + m_fileSize = 0; + gpr = gp_camera_file_get(m_camera, tocstr(fix_foldername(url.directory(false))), tocstr(url.fileName()), fileType, m_file, m_context); + if ( (gpr == GP_ERROR_NOT_SUPPORTED) && + (fileType == GP_FILE_TYPE_PREVIEW) + ) { + // If we get here, the file info command information + // will either not be used, or still valid. + fileType = GP_FILE_TYPE_NORMAL; + gpr = gp_camera_file_get(m_camera, tocstr(fix_foldername(url.directory(false))), tocstr(url.fileName()), fileType, m_file, m_context); + } + switch(gpr) { + case GP_OK: + break; + case GP_ERROR_FILE_NOT_FOUND: + case GP_ERROR_DIRECTORY_NOT_FOUND: + gp_file_unref(m_file); + m_file = NULL; + error(TDEIO::ERR_DOES_NOT_EXIST, url.fileName()); + return ; + default: + gp_file_unref(m_file); + m_file = NULL; + error(TDEIO::ERR_UNKNOWN, gp_result_as_string(gpr)); + return; + } + // emit the mimetype + // NOTE: we must first get the file, so that CameraFile->name would be set + const char *fileMimeType; + gp_file_get_mime_type(m_file, &fileMimeType); + mimeType(fileMimeType); + + // We need to pass left over data here. Some camera drivers do not + // implement progress callbacks! + const char *fileData; + long unsigned int fileSize; + // This merely returns us a pointer to gphoto's internal data + // buffer -- there's no expensive memcpy + gpr = gp_file_get_data_and_size(m_file, &fileData, &fileSize); + if (gpr != GP_OK) { + kdDebug(7123) << "get():: get_data_and_size failed." << endl; + gp_file_free(m_file); + m_file = NULL; + error(TDEIO::ERR_UNKNOWN, gp_result_as_string(gpr)); + return; + } + // make sure we're not sending zero-sized chunks (=EOF) + // also make sure we send only if the progress did not send the data + // already. + if ((fileSize > 0) && (fileSize - m_fileSize)>0) { + unsigned long written = 0; + TQByteArray chunkDataBuffer; + + // We need to split it up here. Someone considered it funny + // to discard any data() larger than 16MB. + // + // So nearly any Movie will just fail.... + while (written < fileSize-m_fileSize) { + unsigned long towrite = 1024*1024; // 1MB + + if (towrite > fileSize-m_fileSize-written) + towrite = fileSize-m_fileSize-written; + chunkDataBuffer.setRawData(fileData + m_fileSize + written, towrite); + processedSize(m_fileSize + written + towrite); + data(chunkDataBuffer); + chunkDataBuffer.resetRawData(fileData + m_fileSize + written, towrite); + written += towrite; + } + m_fileSize = fileSize; + setFileSize(fileSize); + } + + finished(); + gp_file_unref(m_file); /* just unref, might be stored in fs */ + m_file = NULL; +} + +// The KIO slave "stat" function. +void KameraProtocol::stat(const KURL &url) +{ + kdDebug(7123) << "stat(\"" << url.path() << "\")" << endl; + + if (url.path() == "") { + KURL rooturl(url); + + kdDebug(7123) << "redirecting to /" << endl; + rooturl.setPath("/"); + rooturl.setHost(url.host()); + rooturl.setUser(url.user()); + redirection(rooturl); + finished(); + return; + } + + if(url.path() == "/") + statRoot(); + else + statRegular(url); +} + +// Implements stat("/") -- which always returns the same value. +void KameraProtocol::statRoot(void) +{ + UDSEntry entry; + UDSAtom atom; + + atom.m_uds = UDS_NAME; + atom.m_str = "/"; + entry.append(atom); + + atom.m_uds = UDS_FILE_TYPE; + atom.m_long = S_IFDIR; + entry.append(atom); + + atom.m_uds = UDS_ACCESS; + atom.m_long = S_IRUSR | S_IRGRP | S_IROTH | + S_IWUSR | S_IWGRP | S_IWOTH; + entry.append(atom); + + statEntry(entry); + + finished(); + + // This call happens on autodetect by kdemm. So close the camera, but + // only if no more requests are pending. + idletime = MAXIDLETIME; +} + +// Implements a regular stat() of a file / directory, returning all we know about it +void KameraProtocol::statRegular(const KURL &url) +{ + UDSEntry entry; + int gpr; + + kdDebug(7123) << "statRegular(\"" << url.path() << "\")" << endl; + if (openCamera() == false) { + error(TDEIO::ERR_DOES_NOT_EXIST, url.path()); + return; + } + + // fprintf(stderr,"statRegular(%s)\n",url.path().latin1()); + + // Is "url" a directory? + CameraList *dirList; + gp_list_new(&dirList); + kdDebug(7123) << "statRegular() Requesting directories list for " << url.directory() << endl; + + gpr = gp_camera_folder_list_folders(m_camera, tocstr(fix_foldername(url.directory(false))), dirList, m_context); + if (gpr != GP_OK) { + if ((gpr == GP_ERROR_FILE_NOT_FOUND) || (gpr == GP_ERROR_DIRECTORY_NOT_FOUND)) + error(TDEIO::ERR_DOES_NOT_EXIST, url.path()); + else + error(TDEIO::ERR_UNKNOWN, gp_result_as_string(gpr)); + gp_list_free(dirList); + return; + } + +#define GPHOTO_TEXT_FILE(xx) \ + if (!url.path().compare("/"#xx".txt")) { \ + CameraText xx; \ + gpr = gp_camera_get_about(m_camera, &xx, m_context); \ + if (gpr != GP_OK) { \ + error(TDEIO::ERR_DOES_NOT_EXIST, url.fileName()); \ + return; \ + } \ + translateTextToUDS(entry,#xx".txt",xx.text); \ + statEntry(entry); \ + finished(); \ + return; \ + } + GPHOTO_TEXT_FILE(about); + GPHOTO_TEXT_FILE(manual); + GPHOTO_TEXT_FILE(summary); +#undef GPHOTO_TEXT_FILE + + const char *name; + for(int i = 0; i < gp_list_count(dirList); i++) { + gp_list_get_name(dirList, i, &name); + if (url.fileName().compare(name) == 0) { + gp_list_free(dirList); + UDSEntry entry; + translateDirectoryToUDS(entry, url.fileName()); + statEntry(entry); + finished(); + return; + } + } + gp_list_free(dirList); + + // Is "url" a file? + CameraFileInfo info; + gpr = gp_camera_file_get_info(m_camera, tocstr(fix_foldername(url.directory(false))), tocstr(url.fileName()), &info, m_context); + if (gpr != GP_OK) { + if ((gpr == GP_ERROR_FILE_NOT_FOUND) || (gpr == GP_ERROR_DIRECTORY_NOT_FOUND)) + error(TDEIO::ERR_DOES_NOT_EXIST, url.path()); + else + error(TDEIO::ERR_UNKNOWN, gp_result_as_string(gpr)); + return; + } + translateFileToUDS(entry, info, url.fileName()); + statEntry(entry); + finished(); +} + +// The KIO slave "del" function. +void KameraProtocol::del(const KURL &url, bool isFile) +{ + kdDebug(7123) << "KameraProtocol::del(" << url.path() << ")" << endl; + + if(!openCamera()) { + error(TDEIO::ERR_CANNOT_DELETE, url.fileName()); + return; + } + if (!cameraSupportsDel()) { + error(TDEIO::ERR_CANNOT_DELETE, url.fileName()); + return; + } + if(isFile){ + CameraList *list; + gp_list_new(&list); + int ret; + + ret = gp_camera_file_delete(m_camera, tocstr(fix_foldername(url.directory(false))), tocstr(url.fileName()), m_context); + + if(ret != GP_OK) { + error(TDEIO::ERR_CANNOT_DELETE, url.fileName()); + } else { + finished(); + } + } +} + +// The KIO slave "listDir" function. +void KameraProtocol::listDir(const KURL &url) +{ + kdDebug(7123) << "KameraProtocol::listDir(" << url.path() << ")" << endl; + + if (url.host().isEmpty()) { + KURL xurl; + // List the available cameras + TQStringList groupList = m_config->groupList(); + kdDebug(7123) << "Found cameras: " << groupList.join(", ") << endl; + TQStringList::Iterator it; + UDSEntry entry; + UDSAtom atom; + + + /* + * What we do: + * - Autodetect cameras and remember them with their ports. + * - List all saved and possible offline cameras. + * - List all autodetected and not yet printed cameras. + */ + TQMap ports, names; + TQMap modelcnt; + + /* Autodetect USB cameras ... */ + GPContext *glob_context = NULL; + int i, count; + CameraList *list; + CameraAbilitiesList *al; + GPPortInfoList *il; + + gp_list_new (&list); + gp_abilities_list_new (&al); + gp_abilities_list_load (al, glob_context); + gp_port_info_list_new (&il); + gp_port_info_list_load (il); + gp_abilities_list_detect (al, il, list, glob_context); + gp_abilities_list_free (al); + gp_port_info_list_free (il); + + count = gp_list_count (list); + + for (i = 0 ; isetGroup(model); + m_config->writeEntry("Model",model); + m_config->writeEntry("Path",value); + modelcnt[model]++; + } + gp_list_free (list); + + /* Avoid duplicated entry for usb: and usb:001,042 entries. */ + if (ports.contains("usb:") && names[ports["usb:"]]!="usb:") + ports.remove("usb:"); + + for (it = groupList.begin(); it != groupList.end(); it++) { + TQString m_cfgPath; + if (*it == "") + continue; + + m_config->setGroup(*it); + m_cfgPath = m_config->readEntry("Path"); + + /* If autodetect by USB autodetect ... skip it here. + * We leave unattached USB cameras in here, because the user + * might plug them in later and does not want to press reload. + * We add them with port "usb:". + */ + if (modelcnt[*it] > 0) + continue; + + entry.clear(); + atom.m_uds = UDS_FILE_TYPE;atom.m_long = S_IFDIR;entry.append(atom); + atom.m_uds = UDS_NAME;atom.m_str = *it;entry.append(atom); + atom.m_uds = UDS_ACCESS; + atom.m_long = S_IRUSR | S_IRGRP | S_IROTH | + S_IWUSR | S_IWGRP | S_IWOTH; + entry.append(atom); + + atom.m_uds = UDS_URL; + + xurl.setProtocol("camera"); + xurl.setUser(*it); + /* Avoid setting usb:xxx,yyy. */ + if (m_cfgPath.contains("usb:")>0) { + names[*it] = "usb:"; + xurl.setHost("usb:"); + } else { + xurl.setHost(m_cfgPath); + } + xurl.setPath("/"); + atom.m_str = xurl.url(); + entry.append(atom); + + listEntry(entry, false); + } + + TQMap::iterator portsit; + + for (portsit = ports.begin(); portsit != ports.end(); portsit++) { + entry.clear(); + atom.m_uds = UDS_FILE_TYPE;atom.m_long = S_IFDIR; entry.append(atom); + atom.m_uds = UDS_NAME;atom.m_str = portsit.data();entry.append(atom); + + atom.m_uds = UDS_ACCESS; + atom.m_long = S_IRUSR | S_IRGRP | S_IROTH | + S_IWUSR | S_IWGRP | S_IWOTH; + entry.append(atom); + + atom.m_uds = UDS_URL; + xurl.setProtocol("camera"); + xurl.setHost(portsit.key()); + xurl.setUser(portsit.data()); + xurl.setPath("/"); + atom.m_str = xurl.url(); + entry.append(atom); + + listEntry(entry, false); + } + listEntry(entry, true); + + finished(); + return; + } + + if (url.path() == "") { + KURL rooturl(url); + + kdDebug(7123) << "redirecting to /" << endl; + rooturl.setPath("/"); + rooturl.setHost(url.host()); + rooturl.setUser(url.user()); + redirection(rooturl); + finished(); + return; + } + + if (!openCamera()) { + error(TDEIO::ERR_COULD_NOT_READ,url.path()); + return; + } + + CameraList *dirList; + CameraList *fileList; + CameraList *specialList; + gp_list_new(&dirList); + gp_list_new(&fileList); + gp_list_new(&specialList); + int gpr; + + if (!url.path().compare("/")) { + CameraText text; + if (GP_OK == gp_camera_get_manual(m_camera, &text, m_context)) + gp_list_append(specialList,"manual.txt",NULL); + if (GP_OK == gp_camera_get_about(m_camera, &text, m_context)) + gp_list_append(specialList,"about.txt",NULL); + if (GP_OK == gp_camera_get_summary(m_camera, &text, m_context)) + gp_list_append(specialList,"summary.txt",NULL); + } + + gpr = readCameraFolder(url.path(), dirList, fileList); + if(gpr != GP_OK) { + kdDebug(7123) << "read Camera Folder failed:" << gp_result_as_string(gpr) <getFile()) + return; + gp_file_get_data_and_size(object->getFile(), &fileData, &fileSize); + // make sure we're not sending zero-sized chunks (=EOF) + if (fileSize > 0) { + // XXX using assign() here causes segfault, prolly because + // gp_file_free is called before chunkData goes out of scope + TQByteArray chunkDataBuffer; + chunkDataBuffer.setRawData(fileData + object->getFileSize(), fileSize - object->getFileSize()); + // Note: this will fail with sizes > 16MB ... + object->data(chunkDataBuffer); + object->processedSize(fileSize); + chunkDataBuffer.resetRawData(fileData + object->getFileSize(), fileSize - object->getFileSize()); + object->setFileSize(fileSize); + } +} + +unsigned int frontendProgressStart( + GPContext * /*context*/, float totalsize, const char *format, va_list args, + void *data +) { + KameraProtocol *object = (KameraProtocol*)data; + char *status; + + /* We must copy the va_list to walk it twice, or all hell + * breaks loose on non-i386 platforms. + */ +#if defined(HAVE_VA_COPY) || defined(HAVE___VA_COPY) + va_list xvalist; +# ifdef HAVE_VA_COPY + va_copy(xvalist, args); +# elif HAVE___VA_COPY + __va_copy(xvalist, args); +# endif + int size=vsnprintf(NULL, 0, format, xvalist); + if(size<=0) + return GP_OK; // vsnprintf is broken, better don't do anything. + + status=new char[size+1]; +# ifdef HAVE_VA_COPY + va_copy(xvalist, args); +# elif HAVE___VA_COPY + __va_copy(xvalist, args); +# endif + vsnprintf(status, size+1, format, xvalist); +#else + /* We cannot copy the va_list, so make sure we + * walk it just _once_. + */ + status=new char[300]; + vsnprintf(status, 300, format, args); +#endif + + object->infoMessage(TQString::fromLocal8Bit(status)); + delete [] status; + object->totalSize((int)totalsize); // hack: call slot directly + return GP_OK; +} + +// this callback function is activated on every status message from gphoto2 +static void frontendCameraStatus(GPContext * /*context*/, const char *format, va_list args, void *data) +{ + KameraProtocol *object = (KameraProtocol*)data; + char *status; + + /* We must copy the va_list to walk it twice, or all hell + * breaks loose on non-i386 platforms. + */ +#if defined(HAVE_VA_COPY) || defined(HAVE___VA_COPY) + va_list xvalist; +# ifdef HAVE_VA_COPY + va_copy(xvalist, args); +# elif HAVE___VA_COPY + __va_copy(xvalist, args); +# endif + int size=vsnprintf(NULL, 0, format, xvalist); + if(size<=0) + return; // vsnprintf is broken, better don't do anything. + + status=new char[size+1]; +# ifdef HAVE_VA_COPY + va_copy(xvalist, args); +# elif HAVE___VA_COPY + __va_copy(xvalist, args); +# endif + vsnprintf(status, size+1, format, xvalist); +#else + /* We cannot copy the va_list, so make sure we + * walk it just _once_. + */ + status=new char[300]; + vsnprintf(status, 300, format, args); +#endif + object->infoMessage(TQString::fromLocal8Bit(status)); + delete [] status; +} diff --git a/kamera/tdeioslave/kamera.h b/kamera/tdeioslave/kamera.h new file mode 100644 index 00000000..1e015d0f --- /dev/null +++ b/kamera/tdeioslave/kamera.h @@ -0,0 +1,82 @@ +/* + + Copyright (C) 2001 The Kompany + 2001-2003 Ilya Konstantinov + 2001-2007 Marcus Meissner + + 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 of the License, 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. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ + +#ifndef __kamera_h__ +#define __kamera_h__ + +#include +#include +#include + +class KSimpleConfig; + +class KameraProtocol : public TDEIO::SlaveBase +{ +public: + KameraProtocol(const TQCString &pool, const TQCString &app); + virtual ~KameraProtocol(); + + virtual void get(const KURL &url); + virtual void stat(const KURL &url); + virtual void del(const KURL &url, bool isFile); + virtual void setHost(const TQString& host, int port, const TQString& user, const TQString& pass ); + virtual void listDir(const KURL &url); + virtual void special(const TQByteArray &data); + + CameraFile *getFile() { return m_file; } + int getFileSize() { return m_fileSize; } + void setFileSize(int newfs) { m_fileSize = newfs; } + +private: + Camera *m_camera; + CameraAbilities m_abilities; + KSimpleConfig *m_config; + + GPContext *m_context; + + void reparseConfiguration(void); + bool openCamera(TQString& str); + bool openCamera(void ) { + TQString errstr; + return openCamera(errstr); + } + void closeCamera(void); + + void statRoot(void); + void statRegular(const KURL &url); + void translateTextToUDS(TDEIO::UDSEntry &udsEntry, const TQString &info, const char *txt); + void translateFileToUDS(TDEIO::UDSEntry &udsEntry, const CameraFileInfo &info, TQString name); + void translateDirectoryToUDS(TDEIO::UDSEntry &udsEntry, const TQString &dirname); + bool cameraSupportsPreview(void); + bool cameraSupportsDel(void); + bool cameraSupportsPut(void); + int readCameraFolder(const TQString &folder, CameraList *dirList, CameraList *fileList); + + TQString m_lockfile; + int idletime; + + int m_fileSize; + CameraFile *m_file; + bool actiondone, cameraopen; + bool m_modelSpecified; +}; +#endif -- cgit v1.2.1