diff --git a/cmake/modules/FindMtp.cmake b/cmake/modules/FindMtp.cmake new file mode 100644 index 00000000..ff1624a9 --- /dev/null +++ b/cmake/modules/FindMtp.cmake @@ -0,0 +1,55 @@ +# - Try to find the libmtp library +# Once done this will define +# +# MTP_FOUND - system has libmtp +# MTP_INCLUDE_DIR - the libmtp include directory +# MTP_LIBRARIES - Link these to use libmtp +# MTP_DEFINITIONS - Compiler switches required for using libmtp +# + +if (MTP_INCLUDE_DIR AND MTP_LIBRARIES AND MTP_VERSION_OKAY) + + # in cache already + SET(MTP_FOUND TRUE) + +else (MTP_INCLUDE_DIR AND MTP_LIBRARIES AND MTP_VERSION_OKAY) + if(NOT WIN32) + # use pkg-config to get the directories and then use these values + # in the FIND_PATH() and FIND_LIBRARY() calls + INCLUDE(FindPkgConfig) + + pkg_check_modules(_MTP libmtp) + + set(MTP_DEFINITIONS ${_MTP_CFLAGS}) + endif(NOT WIN32) + FIND_PATH(MTP_INCLUDE_DIR libmtp.h + ${_MTP_INCLUDE_DIRS} + ) + + FIND_LIBRARY(MTP_LIBRARIES NAMES mtp + PATHS + ${_MTP_LIBRARY_DIRS} + ) + + exec_program(${PKG_CONFIG_EXECUTABLE} ARGS --atleast-version=1.1.2 libmtp OUTPUT_VARIABLE _pkgconfigDevNull RETURN_VALUE MTP_VERSION_OKAY) + + if (MTP_INCLUDE_DIR AND MTP_LIBRARIES AND MTP_VERSION_OKAY STREQUAL "0") + set(MTP_FOUND TRUE) + endif (MTP_INCLUDE_DIR AND MTP_LIBRARIES AND MTP_VERSION_OKAY STREQUAL "0") + + if (MTP_FOUND) + if (NOT Mtp_FIND_QUIETLY) + message(STATUS "Found MTP: ${MTP_LIBRARIES}") + endif (NOT Mtp_FIND_QUIETLY) + else (MTP_FOUND) + if (MTP_INCLUDE_DIR AND MTP_LIBRARIES AND NOT MTP_VERSION_OKAY STREQUAL "0") + message(STATUS "Found MTP but version requirements not met") + endif (MTP_INCLUDE_DIR AND MTP_LIBRARIES AND NOT MTP_VERSION_OKAY STREQUAL "0") + if (Mtp_FIND_REQUIRED) + message(FATAL_ERROR "Could NOT find MTP") + endif (Mtp_FIND_REQUIRED) + endif (MTP_FOUND) + + MARK_AS_ADVANCED(MTP_INCLUDE_DIR MTP_LIBRARIES MTP_VERSION_OKAY) + +endif (MTP_INCLUDE_DIR AND MTP_LIBRARIES AND MTP_VERSION_OKAY) diff --git a/kioslave/CMakeLists.txt b/kioslave/CMakeLists.txt index 40648284..35f96c68 100644 --- a/kioslave/CMakeLists.txt +++ b/kioslave/CMakeLists.txt @@ -16,6 +16,13 @@ set_package_properties(LibSSH PROPERTIES DESCRIPTION "the SSH library with SFTP PURPOSE "Needed to build the SFTP kioslave" ) +macro_optional_find_package(Mtp) +set_package_properties(Mtp PROPERTIES DESCRIPTION "the library implementation of the Media Transfer Protocol" + URL "http://libmtp.sourceforge.net/" + TYPE OPTIONAL + PURPOSE "Needed to build the MTP kioslave" + ) + add_subdirectory( about ) add_subdirectory( bookmarks ) add_subdirectory( cgi ) @@ -35,6 +42,9 @@ add_subdirectory( docfilter ) if (LIBSSH_FOUND) add_subdirectory(sftp) endif (LIBSSH_FOUND) +if (MTP_FOUND) + add_subdirectory(mtp) +endif (MTP_FOUND) add_subdirectory( floppy ) add_subdirectory( finger ) diff --git a/kioslave/floppy/README b/kioslave/floppy/README index 99d87bd7..6bf0624d 100644 --- a/kioslave/floppy/README +++ b/kioslave/floppy/README @@ -1,6 +1,5 @@ this is an ioslave for KDE 2/3 for accessing fat/vfat floppies without -mounting. -It is a wrapper around the mtools. +mounting. It is a wrapper around the mtools. Alex diff --git a/kioslave/mtp/CMakeLists.txt b/kioslave/mtp/CMakeLists.txt new file mode 100644 index 00000000..243728f4 --- /dev/null +++ b/kioslave/mtp/CMakeLists.txt @@ -0,0 +1,29 @@ +include(KDE4Defaults) + +#add_definitions(-DKDE_DEFAULT_DEBUG_AREA=7999) +add_definitions(-DQT_NO_CAST_FROM_ASCII) + +set( kio_mtp_PART_SRCS + devicecache.cpp + filecache.cpp + kio_mtp.cpp + kio_mtp_helpers.cpp +) + +include_directories( + ${KDE4_INCLUDES} + ${CMAKE_CURRENT_BINARY_DIR} +) + +kde4_add_plugin( kio_mtp ${kio_mtp_PART_SRCS} ) +target_link_libraries( kio_mtp ${KDE4_KIO_LIBRARY} ${MTP_LIBRARIES} ${KDE4_SOLID_LIBS} ) + +install( TARGETS kio_mtp DESTINATION ${PLUGIN_INSTALL_DIR} ) + + +########### install files ############### + +install( FILES mtp-network.desktop DESTINATION ${DATA_INSTALL_DIR}/konqueror/dirtree/remote ) +install( FILES solid_mtp.desktop DESTINATION ${DATA_INSTALL_DIR}/solid/actions ) +install( FILES mtp.protocol DESTINATION ${SERVICES_INSTALL_DIR} ) +install( FILES mtp-network.desktop DESTINATION ${DATA_INSTALL_DIR}/remoteview ) diff --git a/kioslave/mtp/COPYING b/kioslave/mtp/COPYING new file mode 100644 index 00000000..d159169d --- /dev/null +++ b/kioslave/mtp/COPYING @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/kioslave/mtp/LICENCE b/kioslave/mtp/LICENCE new file mode 100644 index 00000000..d159169d --- /dev/null +++ b/kioslave/mtp/LICENCE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/kioslave/mtp/Messages.sh b/kioslave/mtp/Messages.sh new file mode 100644 index 00000000..a48df774 --- /dev/null +++ b/kioslave/mtp/Messages.sh @@ -0,0 +1,2 @@ +#! /usr/bin/env bash +$XGETTEXT *.cpp -o $podir/kio_mtp.pot diff --git a/kioslave/mtp/README b/kioslave/mtp/README new file mode 100644 index 00000000..87263b76 --- /dev/null +++ b/kioslave/mtp/README @@ -0,0 +1,51 @@ +kio-mtp: KIO slave to access MTP devices +======================================== + +This KIO slave enables KDE applications to access +files stored on devices that provide access to them +via the MTP protocol. + +Project page: https://projects.kde.org/projects/playground/base/kio-mtp + + +Installation +------------ + +Dependencies: +* LibMTP - http://libmtp.sourceforge.net/ + Library providing convenience Access to MTP devices. + Version 1.1.3 or newer required. + +1) Install LibMTP +2) Clone from git://anongit.kde.org/kio-mtp +3) cd kio-mtp +4) mkdir build && cd build +5) cmake -DCMAKE_INSTALL_PREFIX=$( kde4-config --prefix ) -DCMAKE_BUILD_TYPE=Debug .. +6) make && su -c 'make install' + + +Usage +----- + +To list all currently connected devices, just type +mtp:/ in the addressbar of your preferred KDE filebrowser. + +Using the scheme mtp:udi= you can access the +device using their unique device identifier as provided +by Solid. + +A Device Notificator Desktop-File is also provided that +enables you to access the device directly from there. + + +Bugs +---- + +Please report all bugs to the KDE Bugzilla at http://bugs.kde.org +using the product "kio" with the component "mtp". + + +Contact +------- + +If you want to get in contact with me drop me an email: philschmidt@gmx.net diff --git a/kioslave/mtp/devicecache.cpp b/kioslave/mtp/devicecache.cpp new file mode 100644 index 00000000..a78b9da2 --- /dev/null +++ b/kioslave/mtp/devicecache.cpp @@ -0,0 +1,238 @@ +/* + Cache for recently used devices. + Copyright (C) 2012 Philipp Schmidt + + 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, see . +*/ + + +#include "devicecache.h" +#include "kio_mtp_helpers.h" + +// #include +// #include + +#include +#include +#include + +/** + * Creates a Cached Device that has a predefined lifetime (default: 10000 msec)s + * The lifetime is reset every time the device is accessed. After it expires it + * will be released. + * + * @param device The LIBMTP_mtpdevice_t pointer to cache + * @param udi The UDI of the new device to cache + */ +CachedDevice::CachedDevice ( LIBMTP_mtpdevice_t* device, LIBMTP_raw_device_t* rawdevice, const QString udi, qint32 timeout ) +{ + this->timeout = timeout; + this->mtpdevice = device; + this->rawdevice = *rawdevice; + this->udi = udi; + + char *deviceName = LIBMTP_Get_Friendlyname ( device ); + char *deviceModel = LIBMTP_Get_Modelname ( device ); + + // prefer friendly devicename over model + if ( !deviceName ) + name = QString::fromUtf8 ( deviceModel ); + else + name = QString::fromUtf8 ( deviceName ); + + kDebug ( KIO_MTP ) << "Created device " << name << " with udi=" << udi << " and timeout " << timeout; +} + +CachedDevice::~CachedDevice() +{ + LIBMTP_Release_Device ( mtpdevice ); +} + +LIBMTP_mtpdevice_t* CachedDevice::getDevice() +{ + LIBMTP_mtpdevice_t* device = mtpdevice; + if (!device->storage) + { + kDebug ( KIO_MTP ) << "reopen mtpdevice if we have no storage found"; + LIBMTP_Release_Device ( mtpdevice ); + mtpdevice = LIBMTP_Open_Raw_Device_Uncached ( &rawdevice ); + } + + return mtpdevice; +} + +const QString CachedDevice::getName() +{ + return name; +} +const QString CachedDevice::getUdi() +{ + return udi; +} + + +DeviceCache::DeviceCache ( qint32 timeout, QObject* parent ) : QEventLoop ( parent ) +{ + this->timeout = timeout; + + notifier = Solid::DeviceNotifier::instance(); + + connect( notifier, SIGNAL( deviceAdded( QString ) ), this, SLOT( deviceAdded( QString ) ) ); + connect( notifier, SIGNAL( deviceRemoved(QString) ), this, SLOT( deviceRemoved(QString) ) ); + + foreach ( Solid::Device solidDevice, Solid::Device::listFromType ( Solid::DeviceInterface::PortableMediaPlayer, QString() ) ) + { + checkDevice( solidDevice ); + } +} + +void DeviceCache::checkDevice ( Solid::Device solidDevice ) +{ + Solid::GenericInterface *iface = solidDevice.as(); + QMap properties = iface->allProperties(); + + int solidBusNum = properties.value ( QLatin1String ( "BUSNUM" ) ).toInt(); + int solidDevNum = properties.value ( QLatin1String ( "DEVNUM" ) ).toInt(); + + int isMtpDevice = LIBMTP_Check_Specific_Device( solidBusNum, solidDevNum ); + + if ( isMtpDevice == 1 && !udiCache.contains( solidDevice.udi() ) ) + { + kDebug ( KIO_MTP ) << "new device, getting raw devices"; + + LIBMTP_raw_device_t *rawdevices = 0; + int numrawdevices; + LIBMTP_error_number_t err; + + QMap devices; + + err = LIBMTP_Detect_Raw_Devices ( &rawdevices, &numrawdevices ); + switch ( err ) + { + case LIBMTP_ERROR_CONNECTING: + kError( KIO_MTP ) << "There has been an error connecting to the devices"; + break; + case LIBMTP_ERROR_MEMORY_ALLOCATION: + kError( KIO_MTP ) << "Encountered a Memory Allocation Error"; + break; + case LIBMTP_ERROR_NONE: + { + kDebug( KIO_MTP ) << "No Error, continuing"; + + for ( int i = 0; i < numrawdevices; i++ ) + { + LIBMTP_raw_device_t* rawDevice = &rawdevices[i]; + uint32_t rawBusNum = rawDevice->bus_location; + uint32_t rawDevNum = rawDevice->devnum; + + if ( rawBusNum == solidBusNum && rawDevNum == solidDevNum ) + { + kDebug( KIO_MTP ) << "Found device matching the Solid description"; + + LIBMTP_mtpdevice_t *mtpDevice = LIBMTP_Open_Raw_Device_Uncached ( rawDevice ); + + if ( udiCache.find( solidDevice.udi() ) == udiCache.end() ) + { + CachedDevice *cDev = new CachedDevice( mtpDevice, rawDevice, solidDevice.udi(), timeout ); + udiCache.insert( solidDevice.udi(), cDev ); + nameCache.insert( cDev->getName(), cDev ); + } + } + } + } + break; + case LIBMTP_ERROR_GENERAL: + default: + kError( KIO_MTP ) << "Unknown connection error"; + break; + } + free(rawdevices); + } +} + +void DeviceCache::deviceAdded ( const QString& udi ) +{ + kDebug( KIO_MTP ) << "New device attached with udi=" << udi << ". Checking if PortableMediaPlayer..."; + + Solid::Device device( udi ); + if ( device.isDeviceInterface( Solid::DeviceInterface::PortableMediaPlayer ) ) + { + kDebug ( KIO_MTP ) << "SOLID: New Device with udi=" << udi << "||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||"; + + checkDevice( device ); + } +} + +void DeviceCache::deviceRemoved ( const QString& udi ) +{ + if ( udiCache.contains( udi ) ) + { + kDebug ( KIO_MTP ) << "SOLID: Device with udi=" << udi << " removed. ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||"; + + CachedDevice *cDev = udiCache.value( udi ); + + udiCache.remove( cDev->getUdi() ); + nameCache.remove( cDev->getName() ); + delete cDev; + } +} + +DeviceCache::~DeviceCache() +{ + processEvents(); + + // Release devices + foreach ( QString udi, udiCache.keys() ) + { + deviceRemoved( udi ); + } +} + +QHash DeviceCache::getAll() +{ + kDebug ( KIO_MTP ) << "getAll()"; + + processEvents(); + + return nameCache; +} + +bool DeviceCache::contains ( QString string, bool isUdi ) +{ + processEvents(); + + if ( isUdi ) + return udiCache.find ( string ) != udiCache.end(); + else + return nameCache.find ( string ) != nameCache.end(); +} + +CachedDevice* DeviceCache::get ( const QString& string, bool isUdi ) +{ + processEvents(); + + if ( isUdi ) + return udiCache.value ( string ); + else + return nameCache.value ( string ); +} + +int DeviceCache::size() +{ + processEvents(); + + return nameCache.size(); +} + +#include "devicecache.moc" diff --git a/kioslave/mtp/devicecache.h b/kioslave/mtp/devicecache.h new file mode 100644 index 00000000..42affb64 --- /dev/null +++ b/kioslave/mtp/devicecache.h @@ -0,0 +1,94 @@ +/* + Cache for recently used devices. + Copyright (C) 2012 Philipp Schmidt + + 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, see . +*/ + + +#ifndef DEVICECACHE_H +#define DEVICECACHE_H + +#include +#include +#include +#include +#include + +#include +#include + +#include + + +class CachedDevice : public QObject +{ + Q_OBJECT + +private: + qint32 timeout; + QTimer *timer; + LIBMTP_mtpdevice_t* mtpdevice; + LIBMTP_raw_device_t rawdevice; + + QString name; + QString udi; + +public: + explicit CachedDevice(LIBMTP_mtpdevice_t* device, LIBMTP_raw_device_t* rawdevice, const QString udi, qint32 timeout); + virtual ~CachedDevice(); + + LIBMTP_mtpdevice_t* getDevice(); + const QString getName(); + const QString getUdi(); +}; + + +class DeviceCache : public QEventLoop +{ + Q_OBJECT + +private: + /** + * Fields in order: Devicename (QString), expiration Timer, pointer to device + */ + QHash< QString, CachedDevice* > nameCache, udiCache; + + Solid::DeviceNotifier *notifier; + + qint32 timeout; + +public: + DeviceCache( qint32 timeout, QObject* parent = 0 ); + virtual ~DeviceCache(); + + /* + * Functions for accessing the device + */ +private: + void checkDevice ( Solid::Device solidDevice ); + +private slots: + + void deviceAdded( const QString &udi ); + void deviceRemoved( const QString &udi ); + +public: + QHash< QString, CachedDevice* > getAll(); + CachedDevice* get ( const QString& string, bool isUdi = false ); + bool contains(QString string, bool isUdi = false); + int size(); +}; + +#endif // DEVICECACHE_H diff --git a/kioslave/mtp/filecache.cpp b/kioslave/mtp/filecache.cpp new file mode 100644 index 00000000..dfd4fe6d --- /dev/null +++ b/kioslave/mtp/filecache.cpp @@ -0,0 +1,80 @@ +/* + Cache for recent files accessed. + Copyright (C) 2012 Philipp Schmidt + + 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 "filecache.h" + +#include + +#include + +FileCache::FileCache ( QObject* parent ) : QObject ( parent ) +{ +} + +uint32_t FileCache::queryPath ( const QString& path, int timeToLive ) +{ + kDebug(KIO_MTP) << "Querying" << path; + + QPair< QDateTime, uint32_t > item = cache.value ( path ); + + if ( item.second != 0 ) + { + QDateTime dateTime = QDateTime::currentDateTime(); + + if ( item.first > dateTime ) + { + kDebug(KIO_MTP) << "Found item with ttl:" << item.first << "- now:" << dateTime; + + item.first = dateTime.addSecs ( timeToLive ); + + kDebug(KIO_MTP) << "Reset item ttl:" << item.first; + + cache.insert ( path, item ); + + return item.second; + } + else + { + kDebug(KIO_MTP) << "Item too old (" << item.first << "), removed. Current Time: " << dateTime; + + cache.remove( path ); + return 0; + } + } + + return 0; +} + +void FileCache::addPath ( const QString& path, uint32_t id, int timeToLive ) +{ + QDateTime dateTime = QDateTime::currentDateTime(); + dateTime = dateTime.addSecs ( timeToLive ); + + QPair< QDateTime, uint32_t > item ( dateTime, id ); + + cache.insert ( path, item ); +} + +void FileCache::removePath ( const QString& path ) +{ + cache.remove( path ); +} + +#include "filecache.moc" diff --git a/kioslave/mtp/filecache.h b/kioslave/mtp/filecache.h new file mode 100644 index 00000000..590e7991 --- /dev/null +++ b/kioslave/mtp/filecache.h @@ -0,0 +1,79 @@ +/* + Cache for recent files accessed. + Copyright (C) 2012 Philipp Schmidt + + 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 FILECACHE_H +#define FILECACHE_H + +#define KIO_MTP 7000 + +#include + +#include +#include +#include + +/** + * @class FileCache Implements a time based cache for file ids, mapping their path to their ID. Does _not_ store the device they are on. + */ +class FileCache : public QObject +{ + Q_OBJECT + +private: + QHash > cache; + +// private slots: +// void insertItem( const QString& path, QPair item ); +// void removeItem( const QString& path ); +// +// signals: +// void s_insertItem( const QString& path, QPair item ); +// void s_removeItem( const QString& path ); + +public: + explicit FileCache ( QObject* parent = 0 ); + + /** + * Returns the ID of the item at the given path, else 0. + * Automatically discards old items. + * + * @param path The Path to query the cache for + * @return The ID of the Item if it exists, else 0 + */ + uint32_t queryPath( const QString& path, int timeToLive = 60 ); + + /** + * Adds a Path to the Cache with the given id and ttl. + * + * @param path The path of the file/folder + * @param id The file ID on the storage + * @param timeToLive The time in seconds the entry should be valid + */ + void addPath( const QString& path, uint32_t id, int timeToLive = 60 ); + + /** + * Remove the given path from the cache, i.e. if it got deleted + * + * @param path The path that should be removed + */ + void removePath (const QString& path ); +}; + +#endif // FILECACHE_H diff --git a/kioslave/mtp/kio_mtp.cpp b/kioslave/mtp/kio_mtp.cpp new file mode 100644 index 00000000..1de49eab --- /dev/null +++ b/kioslave/mtp/kio_mtp.cpp @@ -0,0 +1,1004 @@ +/* + * Main implementation for KIO-MTP + * Copyright (C) 2012 Philipp Schmidt + * + * 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 "kio_mtp.h" +#include "kio_mtp_helpers.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + + +////////////////////////////////////////////////////////////////////////////// +///////////////////////////// Slave Implementation /////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +extern "C" +int KDE_EXPORT kdemain ( int argc, char **argv ) +{ + KComponentData instance ( "kio_mtp" ); + + KGlobal::locale(); + + QCoreApplication app( argc, argv ); + + if ( argc != 4 ) + { + fprintf ( stderr, "Usage: kio_mtp protocol domain-socket1 domain-socket2\n" ); + exit ( -1 ); + } + + MTPSlave slave ( argv[2], argv[3] ); + + slave.dispatchLoop(); + + kDebug ( KIO_MTP ) << "Slave EventLoop ended"; + + return 0; +} + +MTPSlave::MTPSlave ( const QByteArray& pool, const QByteArray& app ) + : SlaveBase ( "mtp", pool, app ) +{ + LIBMTP_Init(); + + kDebug ( KIO_MTP ) << "Slave started"; + + deviceCache = new DeviceCache( 60000 ); + fileCache = new FileCache ( this ); + + kDebug ( KIO_MTP ) << "Caches created"; +} + +MTPSlave::~MTPSlave() +{ + kDebug ( KIO_MTP ) << "Slave destroyed"; +} + +/** + * @brief Get's the correct object from the device. + * @param pathItems A QStringList containing the items of the filepath + * @return QPair with the object and its device. pair.first is a nullpointer if the object doesn't exist or for root or, depending on the pathItems size device (1), storage (2) or file (>=3) + */ +QPair MTPSlave::getPath ( const QString& path ) +{ + QStringList pathItems = path.split ( QLatin1Char ( '/' ), QString::SkipEmptyParts ); + + kDebug ( KIO_MTP ) << path << pathItems.size(); + + QPair ret; + + // Don' handle the root directory + if ( pathItems.size() <= 0 ) + { + return ret; + } + + if ( deviceCache->contains( pathItems.at ( 0 ) ) ) + { + LIBMTP_mtpdevice_t *device = deviceCache->get ( pathItems.at ( 0 ) )->getDevice(); + + // return specific device + if ( pathItems.size() == 1 ) + { + ret.first = device; + ret.second = device; + + kDebug(KIO_MTP) << "returning LIBMTP_mtpdevice_t"; + } + + if ( pathItems.size() > 2 ) + { + // Query Cache after we have the device + uint32_t c_fileID = fileCache->queryPath ( path ); + if ( c_fileID != 0 ) + { + kDebug() << "Match found in cache, checking device"; + + LIBMTP_file_t* file = LIBMTP_Get_Filemetadata ( device, c_fileID ); + if ( file ) + { + kDebug ( KIO_MTP ) << "Found file in cache"; + ret.first = file; + ret.second = device; + + kDebug(KIO_MTP) << "returning LIBMTP_file_t from cache"; + + return ret; + } + } + // Query cache for parent + else if ( pathItems.size() > 3 ) + { + QString parentPath = convertToPath ( pathItems, pathItems.size() - 1 ); + uint32_t c_parentID = fileCache->queryPath ( parentPath ); + + kDebug() << "Match for parent found in cache, checking device. Parent id = " << c_parentID; + + LIBMTP_file_t* parent = LIBMTP_Get_Filemetadata ( device, c_parentID ); + if ( parent ) + { + kDebug ( KIO_MTP ) << "Found parent in cache"; +// fileCache->addPath( parentPath, c_parentID ); + + QMap files = getFiles ( device, parent->storage_id, c_parentID ); + + for ( QMap::iterator it = files.begin(); it != files.end(); ++it ) + { + QString filePath = parentPath; + filePath.append( QString::fromUtf8("/") ).append( it.key() ); + fileCache->addPath( filePath, it.value()->item_id ); + } + + if ( files.contains ( pathItems.last() ) ) + { + LIBMTP_file_t* file = files.value( pathItems.last() ); + + ret.first = file; + ret.second = device; + + kDebug(KIO_MTP) << "returning LIBMTP_file_t from cached parent" ; + + fileCache->addPath( path, file->item_id ); + } + + return ret; + } + } + } + + QMap storages = getDevicestorages ( device ); + + if ( pathItems.size() > 1 && storages.contains ( pathItems.at ( 1 ) ) ) + { + LIBMTP_devicestorage_t *storage = storages.value ( pathItems.at ( 1 ) ); + + if ( pathItems.size() == 2 ) + { + ret.first = storage; + ret.second = device; + + kDebug(KIO_MTP) << "returning LIBMTP_devicestorage_t"; + + return ret; + } + + int currentLevel = 2, currentParent = 0xFFFFFFFF; + + QMap files; + + // traverse further while depth not reached + while ( currentLevel < pathItems.size() ) + { + files = getFiles ( device, storage->id, currentParent ); + + if ( files.contains ( pathItems.at ( currentLevel ) ) ) + { + currentParent = files.value ( pathItems.at ( currentLevel ) )->item_id; + } + else + { + + kDebug(KIO_MTP) << "returning LIBMTP_file_t using tree walk"; + + return ret; + } + currentLevel++; + } + + ret.first = LIBMTP_Get_Filemetadata ( device, currentParent ); + ret.second = device; + + fileCache->addPath ( path, currentParent ); + } + } + + return ret; +} + +int MTPSlave::checkUrl ( const KUrl& url, bool redirect ) +{ + kDebug ( KIO_MTP ) << url; + + if ( url.path().startsWith ( QLatin1String ( "udi=" ) ) && redirect ) + { + QString udi = url.path( KUrl::RemoveTrailingSlash ).remove ( 0, 4 ); + + kDebug ( KIO_MTP ) << "udi = " << udi; + + if ( deviceCache->contains( udi, true ) ) + { + KUrl newUrl; + newUrl.setProtocol ( QLatin1String ( "mtp" ) ); + newUrl.setPath ( QLatin1Char ( '/' ) + deviceCache->get( udi, true )->getName() ); + redirection ( newUrl ); + + return 1; + } + else + { + return 2; + } + } + else if ( url.path().startsWith(QLatin1Char ( '/' ) ) ) + { + return 0; + } + return -1; +} + +void MTPSlave::listDir ( const KUrl& url ) +{ + kDebug ( KIO_MTP ) << url.path(); + + int check = checkUrl( url ); + switch ( check ) + { + case 0: + break; + case 1: + finished(); + return; + case 2: + error( ERR_DOES_NOT_EXIST, url.path() ); + return; + default: + error( ERR_MALFORMED_URL, url.path() ); + return; + } + + QStringList pathItems = url.path().split ( QLatin1Char ( '/' ), QString::SkipEmptyParts ); + + UDSEntry entry; + + // list devices + if ( pathItems.size() == 0 ) + { + kDebug ( KIO_MTP ) << "Root directory, listing devices"; + totalSize ( deviceCache->size() ); + + foreach ( CachedDevice* cachedDevice, deviceCache->getAll().values() ) + { + LIBMTP_mtpdevice_t *device = cachedDevice->getDevice(); + + getEntry ( entry, device ); + + listEntry ( entry, false ); + entry.clear(); + } + + listEntry ( entry, true ); + + kDebug ( KIO_MTP ) << "[SUCCESS] :: Devices"; + finished(); + } + // traverse into device + else if ( deviceCache->contains ( pathItems.at ( 0 ) ) ) + { + QPair pair = getPath ( url.path() ); + UDSEntry entry; + + if ( pair.first ) + { + LIBMTP_mtpdevice_t *device = pair.second; + + // Device, list storages + if ( pathItems.size() == 1 ) + { + QMap storages = getDevicestorages ( device ); + + kDebug ( KIO_MTP ) << "Listing storages for device " << pathItems.at ( 0 ); + totalSize ( storages.size() ); + + if ( storages.size() > 0 ) + { + foreach ( const QString &storageName, storages.keys() ) + { + getEntry ( entry, storages.value ( storageName ) ); + + listEntry ( entry, false ); + entry.clear(); + } + + listEntry ( entry, true ); + finished(); + kDebug ( KIO_MTP ) << "[SUCCESS] :: Storages"; + } + else + { + warning( i18n("No Storages found. Maybe you need to unlock your device?") ); + } + } + // Storage, list files and folders of storage root + else + { + QMap files; + + if ( pathItems.size() == 2 ) + { + kDebug(KIO_MTP) << "Getting storage root listing"; + + LIBMTP_devicestorage_t *storage = (LIBMTP_devicestorage_t*)pair.first; + + kDebug(KIO_MTP) << "We have a storage:" << (storage == NULL); + + files = getFiles( device, storage->id ); + } + else + { + LIBMTP_file_t *parent = (LIBMTP_file_t*)pair.first; + + files = getFiles( device, parent->storage_id, parent->item_id ); + } + + for ( QMap::iterator it = files.begin(); it != files.end(); ++it ) + { + LIBMTP_file_t *file = it.value(); + + QString filePath = url.path( KUrl::AddTrailingSlash ).append( it.key() ); + fileCache->addPath( filePath, file->item_id ); + + getEntry ( entry, file ); + + listEntry ( entry, false ); + entry.clear(); + } + + listEntry ( entry, true ); + finished(); + + kDebug ( KIO_MTP ) << "[SUCCESS] Files"; + } + } + else + { + error ( ERR_CANNOT_ENTER_DIRECTORY, url.path() ); + kDebug ( KIO_MTP ) << "[ERROR]"; + } + } + else + { + error ( ERR_CANNOT_ENTER_DIRECTORY, url.path() ); + kDebug ( KIO_MTP ) << "[ERROR]"; + } +} + +void MTPSlave::stat ( const KUrl& url ) +{ + kDebug ( KIO_MTP ) << url.path(); + + int check = checkUrl( url ); + switch ( check ) + { + case 0: + break; + case 1: + finished(); + return; + case 2: + error( ERR_DOES_NOT_EXIST, url.path() ); + return; + default: + error( ERR_MALFORMED_URL, url.path() ); + return; + } + + QStringList pathItems = url.path().split ( QLatin1Char ( '/' ), QString::SkipEmptyParts ); + + QPair pair = getPath ( url.path() ); + UDSEntry entry; + + if ( pair.first ) + { + // Root + if ( pathItems.size() < 1 ) + { + entry.insert ( UDSEntry::UDS_NAME, QLatin1String ( "mtp:///" ) ); + entry.insert ( UDSEntry::UDS_FILE_TYPE, S_IFDIR ); + entry.insert ( UDSEntry::UDS_ACCESS, S_IRUSR | S_IRGRP | S_IROTH | S_IXUSR | S_IXGRP | S_IXOTH ); + entry.insert ( UDSEntry::UDS_MIME_TYPE, QLatin1String ( "inode/directory" ) ); + } + // Device + else if ( pathItems.size() < 2 ) + { + getEntry ( entry, pair.second ); + } + // Storage + else if ( pathItems.size() < 3 ) + { + getEntry ( entry, ( LIBMTP_devicestorage_t* ) pair.first ); + } + // Folder/File + else + { + getEntry ( entry, ( LIBMTP_file_t* ) pair.first ); + } + } + statEntry ( entry ); + finished(); +} + +void MTPSlave::mimetype ( const KUrl& url ) +{ + int check = checkUrl( url ); + switch ( check ) + { + case 0: + break; + case 1: + finished(); + return; + case 2: + error( ERR_DOES_NOT_EXIST, url.path() ); + return; + default: + error( ERR_MALFORMED_URL, url.path() ); + return; + } + + kDebug ( KIO_MTP ) << url.path(); + + QStringList pathItems = url.path().split ( QLatin1Char ( '/' ), QString::SkipEmptyParts ); + + QPair pair = getPath ( url.path() ); + + if ( pair.first ) + { + if ( pathItems.size() > 2 ) + mimetype ( getMimetype ( ( ( LIBMTP_file_t* ) pair.first )->filetype ) ); + else + mimetype ( QString::fromLatin1 ( "inode/directory" ) ); + } + else + { + error ( ERR_DOES_NOT_EXIST, url.path() ); + return; + } +} + +void MTPSlave::put ( const KUrl& url, int, JobFlags flags ) +{ + int check = checkUrl( url ); + switch ( check ) + { + case 0: + break; + default: + error( ERR_MALFORMED_URL, url.path() ); + return; + } + + kDebug ( KIO_MTP ) << url.path(); + + QStringList destItems = url.path().split ( QLatin1Char ( '/' ), QString::SkipEmptyParts ); + + // Can't copy to root or device, needs storage + if ( destItems.size() < 2 ) + { + error ( ERR_UNSUPPORTED_ACTION, url.path() ); + return; + } + + if ( !(flags & KIO::Overwrite) && getPath( url.path() ).first ) + { + error( ERR_FILE_ALREADY_EXIST, url.path() ); + return; + } + + destItems.takeLast(); + + QPair pair = getPath ( url.directory() ); + + if ( !pair.first ) + { + error ( ERR_DOES_NOT_EXIST, url.path() ); + return; + } + + LIBMTP_mtpdevice_t *device = pair.second; + LIBMTP_file_t *parent = ( LIBMTP_file_t* ) pair.first; + if ( parent->filetype != LIBMTP_FILETYPE_FOLDER ) + { + error ( ERR_IS_FILE, url.directory() ); + return; + } + + // We did get a total size from the application + if ( hasMetaData ( QLatin1String ( "sourceSize" ) ) ) + { + kDebug ( KIO_MTP ) << "direct put"; + + LIBMTP_file_t *file = LIBMTP_new_file_t(); + file->parent_id = parent->item_id; + file->filename = strdup ( url.fileName().toUtf8().data() ); + file->filetype = getFiletype ( url.fileName() ); + file->filesize = metaData ( QLatin1String ( "sourceSize" ) ).toULongLong(); + file->modificationdate = QDateTime::currentDateTime().toTime_t(); + file->storage_id = parent->storage_id; + + kDebug ( KIO_MTP ) << "Sending file" << file->filename; + + int ret = LIBMTP_Send_File_From_Handler ( device, &dataGet, this, file, &dataProgress, this ); + if ( ret != 0 ) + { + error ( KIO::ERR_COULD_NOT_WRITE, url.fileName() ); + LIBMTP_Dump_Errorstack ( device ); + LIBMTP_Clear_Errorstack ( device ); + return; + } + } + // We need to get the entire file first, then we can upload + else + { + kDebug ( KIO_MTP ) << "use temp file"; + + KTemporaryFile temp; + QByteArray buffer; + int len = 0; + + do + { + dataReq(); + len = readData ( buffer ); + temp.write ( buffer ); + } + while ( len > 0 ); + + QFileInfo info ( temp ); + + LIBMTP_file_t *file = LIBMTP_new_file_t(); + file->parent_id = parent->item_id; + file->filename = strdup ( url.fileName().toUtf8().data() ); + file->filetype = getFiletype ( url.fileName() ); + file->filesize = info.size(); + file->modificationdate = QDateTime::currentDateTime().toTime_t(); + file->storage_id = parent->storage_id; + + + int ret = LIBMTP_Send_File_From_File_Descriptor ( device, temp.handle(), file, NULL, NULL ); + if ( ret != 0 ) + { + error ( KIO::ERR_COULD_NOT_WRITE, url.fileName() ); + return; + } + finished(); + } +} + +void MTPSlave::get ( const KUrl& url ) +{ + int check = checkUrl( url ); + switch ( check ) + { + case 0: + break; + default: + error( ERR_MALFORMED_URL, url.path() ); + return; + } + + kDebug ( KIO_MTP ) << url.path(); + + QStringList pathItems = url.path().split ( QLatin1Char ( '/' ), QString::SkipEmptyParts ); + + // File + if ( pathItems.size() > 2 ) + { + QPair pair = getPath ( url.path() ); + + if ( pair.first ) + { + LIBMTP_file_t *file = ( LIBMTP_file_t* ) pair.first; + + mimeType ( getMimetype ( file->filetype ) ); + totalSize ( file->filesize ); + + LIBMTP_mtpdevice_t *device = pair.second; + + int ret = LIBMTP_Get_File_To_Handler ( device, file->item_id, &dataPut, this, &dataProgress, this ); + if ( ret != 0 ) + { + error ( ERR_COULD_NOT_READ, url.path() ); + return; + } + data ( QByteArray() ); + finished(); + } + else + error ( ERR_DOES_NOT_EXIST, url.path() ); + } + else + error ( ERR_UNSUPPORTED_ACTION, url.path() ); +} + +void MTPSlave::copy ( const KUrl& src, const KUrl& dest, int, JobFlags flags ) +{ + kDebug ( KIO_MTP ) << src.path() << dest.path(); + + // mtp:/// to mtp:/// + if ( src.protocol() == QLatin1String ( "mtp" ) && dest.protocol() == QLatin1String ( "mtp" ) ) + { + kDebug ( KIO_MTP ) << "Copy on device: Not supported"; + // MTP doesn't support moving files directly on the device, so we have to download and then upload... + + error ( ERR_UNSUPPORTED_ACTION, i18n( "Cannot copy/move files on the device itself" ) ); + } + // file:/// tp mtp:/// + if ( src.protocol() == QLatin1String ( "file" ) && dest.protocol() == QLatin1String ( "mtp" ) ) + { + int check = checkUrl( dest ); + switch ( check ) + { + case 0: + break; + default: + error( ERR_MALFORMED_URL, dest.path() ); + return; + } + + QStringList destItems = dest.path().split ( QLatin1Char ( '/') , QString::SkipEmptyParts ); + + // Can't copy to root or device, needs storage + if ( destItems.size() < 2 ) + { + error ( ERR_UNSUPPORTED_ACTION, dest.path() ); + return; + } + + kDebug ( KIO_MTP ) << "Copy file " << src.fileName() << "from filesystem to device" << src.directory ( KUrl::AppendTrailingSlash ) << dest.directory ( KUrl::AppendTrailingSlash ); + + if ( !(flags & KIO::Overwrite) && getPath( dest.path() ).first ) + { + error( ERR_FILE_ALREADY_EXIST, dest.path() ); + return; + } + + destItems.takeLast(); + + QPair pair = getPath ( dest.directory() ); + + if ( !pair.first ) + { + error ( ERR_DOES_NOT_EXIST, dest.directory ( KUrl::AppendTrailingSlash ) ); + return; + } + + LIBMTP_mtpdevice_t *device = pair.second; + + uint32_t parent_id = 0xFFFFFFFF, storage_id = 0; + + if ( destItems.size() == 2 ) + { + LIBMTP_devicestorage_t *storage = ( LIBMTP_devicestorage_t*) pair.first; + + storage_id = storage->id; + } + else + { + LIBMTP_file_t *parent = ( LIBMTP_file_t* ) pair.first; + + storage_id = parent->storage_id; + parent_id = parent->item_id; + + if ( parent->filetype != LIBMTP_FILETYPE_FOLDER ) + { + error ( ERR_IS_FILE, dest.directory() ); + return; + } + } + + QFileInfo source ( src.path() ); + + LIBMTP_file_t *file = LIBMTP_new_file_t(); + file->parent_id = parent_id; + file->filename = strdup ( dest.fileName().toUtf8().data() ); + file->filetype = getFiletype ( dest.fileName() ); + file->filesize = source.size(); + file->modificationdate = source.lastModified().toTime_t(); + file->storage_id = storage_id; + + kDebug ( KIO_MTP ) << "Sending file" << file->filename << "with size" << file->filesize; + + totalSize ( source.size() ); + + int ret = LIBMTP_Send_File_From_File ( device, src.path().toUtf8().data(), file, ( LIBMTP_progressfunc_t ) &dataProgress, this ); + if ( ret != 0 ) + { + error ( KIO::ERR_COULD_NOT_WRITE, dest.fileName() ); + LIBMTP_Dump_Errorstack ( device ); + LIBMTP_Clear_Errorstack ( device ); + return; + } + + kDebug ( KIO_MTP ) << "Sent file"; + } + // mtp:/// to file:/// + if ( src.protocol() == QLatin1String ( "mtp" ) && dest.protocol() == QLatin1String ( "file" ) ) + { + int check = checkUrl( src ); + switch ( check ) + { + case 0: + break; + default: + error( ERR_MALFORMED_URL, src.path() ); + return; + } + + kDebug ( KIO_MTP ) << "Copy file " << src.fileName() << "from device to filesystem" << dest.directory ( KUrl::AppendTrailingSlash ) << dest.directory ( KUrl::AppendTrailingSlash ); + + QFileInfo destination ( dest.path() ); + + if ( !(flags & KIO::Overwrite) && destination.exists() ) + { + error( ERR_FILE_ALREADY_EXIST, dest.path() ); + return; + } + + QStringList srcItems = src.path().split ( QLatin1Char ( '/' ), QString::SkipEmptyParts ); + + // Can't copy to root or device, needs storage + if ( srcItems.size() < 2 ) + { + error ( ERR_UNSUPPORTED_ACTION, src.path() ); + return; + } + + QPair pair = getPath ( src.path() ); + + LIBMTP_mtpdevice_t *device = pair.second; + LIBMTP_file_t *source = ( LIBMTP_file_t* ) pair.first; + if ( source->filetype == LIBMTP_FILETYPE_FOLDER ) + { + error ( ERR_IS_DIRECTORY, src.directory() ); + return; + } + + kDebug ( KIO_MTP ) << "Getting file" << source->filename << dest.fileName() << source->filesize; + + totalSize ( source->filesize ); + + int ret = LIBMTP_Get_File_To_File ( device, source->item_id, dest.path().toUtf8().data(), ( LIBMTP_progressfunc_t ) &dataProgress, this ); + if ( ret != 0 ) + { + error ( KIO::ERR_COULD_NOT_WRITE, dest.fileName() ); + LIBMTP_Dump_Errorstack ( device ); + LIBMTP_Clear_Errorstack ( device ); + return; + } + + struct utimbuf *times = (utimbuf*) malloc( sizeof( utimbuf ) ); + times->actime = QDateTime::currentDateTime().toTime_t(); + times->modtime = source->modificationdate; + + int result = utime( dest.path().toUtf8().data(), times ); + + free( times ); + + kDebug ( KIO_MTP ) << "Sent file"; + + } + finished(); +} + +void MTPSlave::mkdir ( const KUrl& url, int ) +{ + int check = checkUrl( url ); + switch ( check ) + { + case 0: + break; + default: + error( ERR_MALFORMED_URL, url.path() ); + return; + } + + kDebug ( KIO_MTP ) << url.path(); + + QStringList pathItems = url.path().split ( QLatin1Char ( '/' ) , QString::SkipEmptyParts ); + int pathDepth= pathItems.size(); + + if ( pathItems.size() > 2 && !getPath ( url.path() ).first ) + { + char *dirName = strdup ( pathItems.takeLast().toUtf8().data() ); + + LIBMTP_mtpdevice_t *device; + LIBMTP_file_t *file; + LIBMTP_devicestorage_t *storage; + int ret; + + QPair pair = getPath ( url.directory() ); + + if (pathDepth == 3) + {//the folder need to be created straight to a storage device + storage= ( LIBMTP_devicestorage_t* ) pair.first; + device = pair.second; + ret = LIBMTP_Create_Folder ( device, dirName, 0xFFFFFFFF, storage->id ); + } + else + if ( pair.first ) + { + file = ( LIBMTP_file_t* ) pair.first; + device = pair.second; + + if ( file && file->filetype == LIBMTP_FILETYPE_FOLDER ) + { + kDebug ( KIO_MTP ) << "Found parent" << file->item_id << file->filename; + kDebug ( KIO_MTP ) << "Attempting to create folder" << dirName; + + ret = LIBMTP_Create_Folder ( device, dirName, file->item_id, file->storage_id ); + + } + } + if ( ret != 0 ) + { + fileCache->addPath( url.path(), ret ); + finished(); + return; + } + else + { + LIBMTP_Dump_Errorstack ( device ); + LIBMTP_Clear_Errorstack ( device ); + } + } + else + { + error ( ERR_DIR_ALREADY_EXIST, url.path() ); + return; + } + + error ( ERR_COULD_NOT_MKDIR, url.path() ); +} + +void MTPSlave::del ( const KUrl& url, bool ) +{ + int check = checkUrl( url ); + switch ( check ) + { + case 0: + break; + default: + error( ERR_MALFORMED_URL, url.path() ); + return; + } + + kDebug ( KIO_MTP ) << url.path(); + + QStringList pathItems = url.path().split ( QLatin1Char ( '/' ), QString::SkipEmptyParts ); + + if ( pathItems.size() < 2 ) + { + error ( ERR_CANNOT_DELETE, url.path() ); + return; + } + + QPair pair = getPath ( url.path() ); + + LIBMTP_file_t *file = ( LIBMTP_file_t* ) pair.first; + + int ret = LIBMTP_Delete_Object ( pair.second, file->item_id ); + + LIBMTP_destroy_file_t ( file ); + + if ( ret != 0 ) + { + error ( ERR_CANNOT_DELETE, url.path() ); + return; + } + + fileCache->removePath( url.path() ); + finished(); +} + +void MTPSlave::rename ( const KUrl& src, const KUrl& dest, JobFlags flags ) +{ + int check = checkUrl( src ); + switch ( check ) + { + case 0: + break; + default: + error( ERR_MALFORMED_URL, src.path() ); + return; + } + check = checkUrl( dest ); + switch ( check ) + { + case 0: + break; + default: + error( ERR_MALFORMED_URL, dest.path() ); + return; + } + + + kDebug ( KIO_MTP ) << src.path(); + + QStringList srcItems = src.path().split ( QLatin1Char ( '/' ), QString::SkipEmptyParts ); + QPair pair = getPath ( src.path() ); + + if ( pair.first ) + { + // Rename Device + if ( srcItems.size() == 1 ) + { + LIBMTP_Set_Friendlyname ( pair.second, dest.fileName().toUtf8().data() ); + } + // Rename Storage + else if ( srcItems.size() == 2 ) + { + error ( ERR_CANNOT_RENAME, src.path() ); + return; + } + else + { + LIBMTP_file_t *destination = ( LIBMTP_file_t* ) getPath ( dest.path() ).first; + LIBMTP_file_t *source = ( LIBMTP_file_t* ) pair.first; + + if ( !(flags & KIO::Overwrite) && destination ) + { + if ( destination->filetype == LIBMTP_FILETYPE_FOLDER ) + { + error( ERR_DIR_ALREADY_EXIST, dest.path() ); + } + else + { + error( ERR_FILE_ALREADY_EXIST, dest.path() ); + } + return; + } + + int ret = LIBMTP_Set_File_Name ( pair.second, source, dest.fileName().toUtf8().data() ); + + if ( ret != 0 ) + { + error ( ERR_CANNOT_RENAME, src.path() ); + return; + } + else + { + fileCache->addPath( dest.path(), source->item_id ); + fileCache->removePath( src.path() ); + } + + LIBMTP_destroy_file_t ( source ); + } + + finished(); + } + else + { + error ( ERR_DOES_NOT_EXIST, src.path() ); + } +} + + +#include "kio_mtp.moc" + diff --git a/kioslave/mtp/kio_mtp.h b/kioslave/mtp/kio_mtp.h new file mode 100644 index 00000000..b05f09bd --- /dev/null +++ b/kioslave/mtp/kio_mtp.h @@ -0,0 +1,86 @@ +/* + * Main implementation for KIO-MTP + * Copyright (C) 2012 Philipp Schmidt + * + * 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 KIO_MTP_H +#define KIO_MTP_H + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +// #include +#include "filecache.h" +#include "devicecache.h" + +#define MAX_XFER_BUF_SIZE 16348 +#define KIO_MTP 7000 + +using namespace KIO; + + +class MTPSlave : public QObject, public KIO::SlaveBase +{ + Q_OBJECT + +private: + /** + * Check if it is a valid url or an udi. + * + * @param url The url to checkUrl + * @param redirect If udi= should be redirected or just return false + * @return 0 if valid, 1 if udi and redirected, 2 if udi but invalid device, -1 else + */ + int checkUrl( const KUrl& url, bool redirect = true ); + FileCache *fileCache; + DeviceCache *deviceCache; + QPair getPath( const QString& path ); + +// private slots: +// +// void test(); + +public: + /* + * Overwritten KIO-functions, see "kio_mtp.cpp" + */ + MTPSlave ( const QByteArray& pool, const QByteArray& app ); + virtual ~MTPSlave(); + + virtual void listDir ( const KUrl& url ); + virtual void stat ( const KUrl& url ); + virtual void mimetype ( const KUrl& url ); + virtual void get ( const KUrl& url ); + virtual void put ( const KUrl& url, int, JobFlags flags ); + virtual void copy ( const KUrl& src, const KUrl& dest, int, JobFlags flags ); + virtual void mkdir ( const KUrl& url, int ); + virtual void del ( const KUrl& url, bool ); + virtual void rename ( const KUrl& src, const KUrl& dest, JobFlags flags ); +}; + +#endif //#endif KIO_MTP_H diff --git a/kioslave/mtp/kio_mtp_helpers.cpp b/kioslave/mtp/kio_mtp_helpers.cpp new file mode 100644 index 00000000..0f9ddbce --- /dev/null +++ b/kioslave/mtp/kio_mtp_helpers.cpp @@ -0,0 +1,435 @@ +/* + * Helper implementations for KIO-MTP + * Copyright (C) 2013 Philipp Schmidt + * + * 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 "kio_mtp_helpers.h" + + +int dataProgress ( uint64_t const sent, uint64_t const, void const *const priv ) +{ + ( ( MTPSlave* ) priv )->processedSize ( sent ); + + return 0; +} + +/** + * MTPDataPutFunc callback function, "puts" data from the device somewhere else + */ +uint16_t dataPut ( void*, void *priv, uint32_t sendlen, unsigned char *data, uint32_t *putlen ) +{ + kDebug(KIO_MTP) << "transferring" << sendlen << "bytes to data()"; + + ( ( MTPSlave* ) priv )->data ( QByteArray ( ( char* ) data, ( int ) sendlen ) ); + *putlen = sendlen; + + return LIBMTP_HANDLER_RETURN_OK; +} + +/** + * MTPDataGetFunc callback function, "gets" data and puts it on the device + */ +uint16_t dataGet ( void*, void *priv, uint32_t, unsigned char *data, uint32_t *gotlen ) +{ + ( ( MTPSlave* ) priv )->dataReq(); + + QByteArray buffer; + *gotlen = ( ( MTPSlave* ) priv )->readData ( buffer ); + + kDebug(KIO_MTP) << "transferring" << *gotlen << "bytes to data()"; + + data = ( unsigned char* ) buffer.data(); + + return LIBMTP_HANDLER_RETURN_OK; +} + +QString convertToPath( const QStringList& pathItems, const int elements ) +{ + QString path; + + for ( int i = 0; i < elements && elements <= pathItems.size(); i++ ) + { + path.append( QLatin1Char ('/') ); + path.append( pathItems.at(i) ); + } + + return path; +} + +QString getMimetype ( LIBMTP_filetype_t filetype ) +{ + switch ( filetype ) + { + case LIBMTP_FILETYPE_FOLDER: + return QLatin1String ( "inode/directory" ); + + case LIBMTP_FILETYPE_WAV: + return QLatin1String ( "audio/wav" ); + case LIBMTP_FILETYPE_MP3: + return QLatin1String ( "audio/x-mp3" ); + case LIBMTP_FILETYPE_WMA: + return QLatin1String ( "audio/x-ms-wma" ); + case LIBMTP_FILETYPE_OGG: + return QLatin1String ( "audio/x-vorbis+ogg" ); + case LIBMTP_FILETYPE_AUDIBLE: + return QLatin1String ( "" ); + case LIBMTP_FILETYPE_MP4: + return QLatin1String ( "audio/mp4" ); + case LIBMTP_FILETYPE_UNDEF_AUDIO: + return QLatin1String ( "" ); + case LIBMTP_FILETYPE_WMV: + return QLatin1String ( "video/x-ms-wmv" ); + case LIBMTP_FILETYPE_AVI: + return QLatin1String ( "video/x-msvideo" ); + case LIBMTP_FILETYPE_MPEG: + return QLatin1String ( "video/mpeg" ); + case LIBMTP_FILETYPE_ASF: + return QLatin1String ( "video/x-ms-asf" ); + case LIBMTP_FILETYPE_QT: + return QLatin1String ( "video/quicktime" ); + case LIBMTP_FILETYPE_UNDEF_VIDEO: + return QLatin1String ( "" ); + case LIBMTP_FILETYPE_JPEG: + return QLatin1String ( "image/jpeg" ); + case LIBMTP_FILETYPE_JFIF: + return QLatin1String ( "" ); + case LIBMTP_FILETYPE_TIFF: + return QLatin1String ( "image/tiff" ); + case LIBMTP_FILETYPE_BMP: + return QLatin1String ( "image/bmp" ); + case LIBMTP_FILETYPE_GIF: + return QLatin1String ( "image/gif" ); + case LIBMTP_FILETYPE_PICT: + return QLatin1String ( "image/x-pict" ); + case LIBMTP_FILETYPE_PNG: + return QLatin1String ( "image/png" ); + case LIBMTP_FILETYPE_VCALENDAR1: + return QLatin1String ( "text/x-vcalendar" ); + case LIBMTP_FILETYPE_VCALENDAR2: + return QLatin1String ( "text/x-vcalendar" ); + case LIBMTP_FILETYPE_VCARD2: + return QLatin1String ( "text/x-vcard" ); + case LIBMTP_FILETYPE_VCARD3: + return QLatin1String ( "text/x-vcard" ); + case LIBMTP_FILETYPE_WINDOWSIMAGEFORMAT: + return QLatin1String ( "image/x-wmf" ); + case LIBMTP_FILETYPE_WINEXEC: + return QLatin1String ( "application/x-ms-dos-executable" ); + case LIBMTP_FILETYPE_TEXT: + return QLatin1String ( "text/plain" ); + case LIBMTP_FILETYPE_HTML: + return QLatin1String ( "text/html" ); + case LIBMTP_FILETYPE_FIRMWARE: + return QLatin1String ( "" ); + case LIBMTP_FILETYPE_AAC: + return QLatin1String ( "audio/aac" ); + case LIBMTP_FILETYPE_MEDIACARD: + return QLatin1String ( "" ); + case LIBMTP_FILETYPE_FLAC: + return QLatin1String ( "audio/flac" ); + case LIBMTP_FILETYPE_MP2: + return QLatin1String ( "video/mpeg" ); + case LIBMTP_FILETYPE_M4A: + return QLatin1String ( "audio/mp4" ); + case LIBMTP_FILETYPE_DOC: + return QLatin1String ( "application/msword" ); + case LIBMTP_FILETYPE_XML: + return QLatin1String ( "text/xml" ); + case LIBMTP_FILETYPE_XLS: + return QLatin1String ( "application/vnd.ms-excel" ); + case LIBMTP_FILETYPE_PPT: + return QLatin1String ( "application/vnd.ms-powerpoint" ); + case LIBMTP_FILETYPE_MHT: + return QLatin1String ( "" ); + case LIBMTP_FILETYPE_JP2: + return QLatin1String ( "image/jpeg2000" ); + case LIBMTP_FILETYPE_JPX: + return QLatin1String ( "application/x-jbuilder-project" ); + case LIBMTP_FILETYPE_UNKNOWN: + return QLatin1String ( "" ); + + default: + return QLatin1String ( "" ); + } +} + +LIBMTP_filetype_t getFiletype ( const QString &filename ) +{ + LIBMTP_filetype_t filetype; + + QString ptype = filename.split ( QLatin1Char ( '.' ) ).last(); + + /* This need to be kept constantly updated as new file types arrive. */ + if ( ptype == QLatin1String ( "wav" ) ) + { + filetype = LIBMTP_FILETYPE_WAV; + } + else if ( ptype == QLatin1String ( "mp3" ) ) + { + filetype = LIBMTP_FILETYPE_MP3; + } + else if ( ptype == QLatin1String ( "wma" ) ) + { + filetype = LIBMTP_FILETYPE_WMA; + } + else if ( ptype == QLatin1String ( "ogg" ) ) + { + filetype = LIBMTP_FILETYPE_OGG; + } + else if ( ptype == QLatin1String ( "mp4" ) ) + { + filetype = LIBMTP_FILETYPE_MP4; + } + else if ( ptype == QLatin1String ( "wmv" ) ) + { + filetype = LIBMTP_FILETYPE_WMV; + } + else if ( ptype == QLatin1String ( "avi" ) ) + { + filetype = LIBMTP_FILETYPE_AVI; + } + else if ( ptype == QLatin1String ( "mpeg" ) || + ptype == QLatin1String ( "mpg" ) ) + { + filetype = LIBMTP_FILETYPE_MPEG; + } + else if ( ptype == QLatin1String ( "asf" ) ) + { + filetype = LIBMTP_FILETYPE_ASF; + } + else if ( ptype == QLatin1String ( "qt" ) || + ptype == QLatin1String ( "mov" ) ) + { + filetype = LIBMTP_FILETYPE_QT; + } + else if ( ptype == QLatin1String ( "wma" ) ) + { + filetype = LIBMTP_FILETYPE_WMA; + } + else if ( ptype == QLatin1String ( "jpg" ) || + ptype == QLatin1String ( "jpeg" ) ) + { + filetype = LIBMTP_FILETYPE_JPEG; + } + else if ( ptype == QLatin1String ( "jfif" ) ) + { + filetype = LIBMTP_FILETYPE_JFIF; + } + else if ( ptype == QLatin1String ( "tif" ) || + ptype == QLatin1String ( "tiff" ) ) + { + filetype = LIBMTP_FILETYPE_TIFF; + } + else if ( ptype == QLatin1String ( "bmp" ) ) + { + filetype = LIBMTP_FILETYPE_BMP; + } + else if ( ptype == QLatin1String ( "gif" ) ) + { + filetype = LIBMTP_FILETYPE_GIF; + } + else if ( ptype == QLatin1String ( "pic" ) || + ptype == QLatin1String ( "pict" ) ) + { + filetype = LIBMTP_FILETYPE_PICT; + } + else if ( ptype == QLatin1String ( "png" ) ) + { + filetype = LIBMTP_FILETYPE_PNG; + } + else if ( ptype == QLatin1String ( "wmf" ) ) + { + filetype = LIBMTP_FILETYPE_WINDOWSIMAGEFORMAT; + } + else if ( ptype == QLatin1String ( "ics" ) ) + { + filetype = LIBMTP_FILETYPE_VCALENDAR2; + } + else if ( ptype == QLatin1String ( "exe" ) || + ptype == QLatin1String ( "com" ) || + ptype == QLatin1String ( "bat" ) || + ptype == QLatin1String ( "dll" ) || + ptype == QLatin1String ( "sys" ) ) + { + filetype = LIBMTP_FILETYPE_WINEXEC; + } + else if ( ptype == QLatin1String ( "aac" ) ) + { + filetype = LIBMTP_FILETYPE_AAC; + } + else if ( ptype == QLatin1String ( "mp2" ) ) + { + filetype = LIBMTP_FILETYPE_MP2; + } + else if ( ptype == QLatin1String ( "flac" ) ) + { + filetype = LIBMTP_FILETYPE_FLAC; + } + else if ( ptype == QLatin1String ( "m4a" ) ) + { + filetype = LIBMTP_FILETYPE_M4A; + } + else if ( ptype == QLatin1String ( "doc" ) ) + { + filetype = LIBMTP_FILETYPE_DOC; + } + else if ( ptype == QLatin1String ( "xml" ) ) + { + filetype = LIBMTP_FILETYPE_XML; + } + else if ( ptype == QLatin1String ( "xls" ) ) + { + filetype = LIBMTP_FILETYPE_XLS; + } + else if ( ptype == QLatin1String ( "ppt" ) ) + { + filetype = LIBMTP_FILETYPE_PPT; + } + else if ( ptype == QLatin1String ( "mht" ) ) + { + filetype = LIBMTP_FILETYPE_MHT; + } + else if ( ptype == QLatin1String ( "jp2" ) ) + { + filetype = LIBMTP_FILETYPE_JP2; + } + else if ( ptype == QLatin1String ( "jpx" ) ) + { + filetype = LIBMTP_FILETYPE_JPX; + } + else if ( ptype == QLatin1String ( "bin" ) ) + { + filetype = LIBMTP_FILETYPE_FIRMWARE; + } + else if ( ptype == QLatin1String ( "vcf" ) ) + { + filetype = LIBMTP_FILETYPE_VCARD3; + } + else + { + /* Tagging as unknown file type */ + filetype = LIBMTP_FILETYPE_UNKNOWN; + } + + return filetype; +} + +QMap getDevicestorages ( LIBMTP_mtpdevice_t *&device ) +{ + kDebug ( KIO_MTP ) << "[ENTER]" << ( device == 0 ); + + QMap storages; + if ( device ) + { + for ( LIBMTP_devicestorage_t* storage = device->storage; storage != NULL; storage = storage->next ) + { + // char *storageIdentifier = storage->VolumeIdentifier; + char *storageDescription = storage->StorageDescription; + + QString storagename; + // if ( !storageIdentifier ) + storagename = QString::fromUtf8 ( storageDescription ); + // else + // storagename = QString::fromUtf8 ( storageIdentifier ); + + kDebug(KIO_MTP) << "found storage" << storagename; + + storages.insert ( storagename, storage ); + } + } + + kDebug ( KIO_MTP ) << "[EXIT]" << storages.size(); + + return storages; +} + +QMap getFiles ( LIBMTP_mtpdevice_t *&device, uint32_t storage_id, uint32_t parent_id ) +{ + kDebug ( KIO_MTP ) << "getFiles() for parent" << parent_id; + + QMap fileMap; + + LIBMTP_file_t *files = LIBMTP_Get_Files_And_Folders ( device, storage_id, parent_id ), *file; + for ( file = files; file != NULL; file = file->next ) + { + fileMap.insert ( QString::fromUtf8 ( file->filename ), file ); + // kDebug(KIO_MTP) << "found file" << file->filename; + } + + kDebug ( KIO_MTP ) << "[EXIT]"; + + return fileMap; +} + +void getEntry ( UDSEntry &entry, LIBMTP_mtpdevice_t* device ) +{ + char *charName = LIBMTP_Get_Friendlyname ( device ); + char *charModel = LIBMTP_Get_Modelname ( device ); + + // prefer friendly devicename over model + QString deviceName; + if ( !charName ) + deviceName = QString::fromUtf8 ( charModel ); + else + deviceName = QString::fromUtf8 ( charName ); + + entry.insert ( UDSEntry::UDS_NAME, deviceName ); + entry.insert ( UDSEntry::UDS_ICON_NAME, QLatin1String ( "multimedia-player" ) ); + entry.insert ( UDSEntry::UDS_FILE_TYPE, S_IFDIR ); + entry.insert ( UDSEntry::UDS_ACCESS, S_IRUSR | S_IRGRP | S_IROTH | S_IXUSR | S_IXGRP | S_IXOTH ); + entry.insert ( UDSEntry::UDS_MIME_TYPE, QLatin1String ( "inode/directory" ) ); +} + +void getEntry ( UDSEntry &entry, const LIBMTP_devicestorage_t* storage ) +{ +// char *charIdentifier = storage->VolumeIdentifier; + char *charDescription = storage->StorageDescription; + + QString storageName; +// if ( !charIdentifier ) + storageName = QString::fromUtf8 ( charDescription ); +// else +// storageName = QString::fromUtf8 ( charIdentifier ); + + entry.insert ( UDSEntry::UDS_NAME, storageName ); + entry.insert ( UDSEntry::UDS_ICON_NAME, QLatin1String ( "drive-removable-media" ) ); + entry.insert ( UDSEntry::UDS_FILE_TYPE, S_IFDIR ); + entry.insert ( UDSEntry::UDS_ACCESS, S_IRUSR | S_IRGRP | S_IROTH | S_IXUSR | S_IXGRP | S_IXOTH ); + entry.insert ( UDSEntry::UDS_MIME_TYPE, QLatin1String ( "inode/directory" ) ); +} + +void getEntry ( UDSEntry &entry, const LIBMTP_file_t* file ) +{ + entry.insert ( UDSEntry::UDS_NAME, QString::fromUtf8 ( file->filename ) ); + if ( file->filetype == LIBMTP_FILETYPE_FOLDER ) + { + entry.insert ( UDSEntry::UDS_FILE_TYPE, S_IFDIR ); + entry.insert ( UDSEntry::UDS_ACCESS, S_IRWXU | S_IRWXG | S_IRWXO ); + entry.insert ( UDSEntry::UDS_MIME_TYPE, QLatin1String ( "inode/directory" ) ); + } + else + { + entry.insert ( UDSEntry::UDS_FILE_TYPE, S_IFREG ); + entry.insert ( UDSEntry::UDS_ACCESS, S_IRUSR | S_IRGRP | S_IROTH | S_IXUSR | S_IXGRP | S_IXOTH ); + entry.insert ( UDSEntry::UDS_SIZE, file->filesize ); + entry.insert ( UDSEntry::UDS_MIME_TYPE, getMimetype( file->filetype ) ); + } + entry.insert ( UDSEntry::UDS_INODE, file->item_id ); + entry.insert ( UDSEntry::UDS_ACCESS_TIME, file->modificationdate ); + entry.insert ( UDSEntry::UDS_MODIFICATION_TIME, file->modificationdate ); + entry.insert ( UDSEntry::UDS_CREATION_TIME, file->modificationdate ); +} diff --git a/kioslave/mtp/kio_mtp_helpers.h b/kioslave/mtp/kio_mtp_helpers.h new file mode 100644 index 00000000..b66adbd0 --- /dev/null +++ b/kioslave/mtp/kio_mtp_helpers.h @@ -0,0 +1,47 @@ +/* + * Helper implementations for KIO-MTP + * Copyright (C) 2013 Philipp Schmidt + * + * 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 KIO_MTP_HELPERS_H +#define KIO_MTP_HELPERS_H + + +#include "kio_mtp.h" + +#include + + +int dataProgress ( uint64_t const sent, uint64_t const, void const *const priv ); +uint16_t dataPut ( void*, void *priv, uint32_t sendlen, unsigned char *data, uint32_t *putlen ); +uint16_t dataGet ( void*, void *priv, uint32_t, unsigned char *data, uint32_t *gotlen ); + +QString convertToPath( const QStringList& pathItems, const int elements ); + +QString getMimetype ( LIBMTP_filetype_t filetype ); +LIBMTP_filetype_t getFiletype ( const QString &filename ); + +QMap getDevicestorages ( LIBMTP_mtpdevice_t *&device ); +QMap getFiles ( LIBMTP_mtpdevice_t *&device, uint32_t storage_id, uint32_t parent_id = 0xFFFFFFFF ); + +void getEntry ( UDSEntry &entry, LIBMTP_mtpdevice_t* device ); +void getEntry ( UDSEntry &entry, const LIBMTP_devicestorage_t* storage ); +void getEntry ( UDSEntry &entry, const LIBMTP_file_t* file ); + + +#endif diff --git a/kioslave/mtp/mtp-network.desktop b/kioslave/mtp/mtp-network.desktop new file mode 100644 index 00000000..45292661 --- /dev/null +++ b/kioslave/mtp/mtp-network.desktop @@ -0,0 +1,36 @@ +[Desktop Entry] +Icon=multimedia-player +Name=MTP Devices +Name[bs]=MTP Devices +Name[ca]=Dispositius MTP +Name[ca@valencia]=Dispositius MTP +Name[cs]=Zařízení MTP +Name[da]=MTP-enheder +Name[de]=MTP-Geräte +Name[el]=Συσκευές MTP +Name[es]=Dispositivos MTP +Name[et]=MTP seadmed +Name[fi]=MTP-laitteet +Name[fr]=Périphériques « MTP » +Name[ga]=Gléasanna MTP +Name[gl]=Dispositivos MTP +Name[hu]=MTP eszközök +Name[it]=Dispositivi MTP +Name[ko]=MTP 장치 +Name[lt]=MTP įrenginiai +Name[mr]=एमटीपी साधने +Name[nl]=MTP-apparaten +Name[pl]=Urządzenia MTP +Name[pt]=Dispositivos MTP +Name[pt_BR]=Dispositivos MTP +Name[ro]=Dispozitive MTP +Name[ru]=Устройства MTP +Name[sk]=Zariadenia MTP +Name[sl]=Naprave MTP +Name[sv]=MTP-enheter +Name[tr]=MTP Aygıtları +Name[uk]=Пристрої MTP +Name[x-test]=xxMTP Devicesxx +Open=false +Type=Link +URL=mtp:/ diff --git a/kioslave/mtp/mtp.protocol b/kioslave/mtp/mtp.protocol new file mode 100644 index 00000000..0fcc9351 --- /dev/null +++ b/kioslave/mtp/mtp.protocol @@ -0,0 +1,17 @@ +[Protocol] +exec=kio_mtp +protocol=mtp +input=none +output=filesystem +listing=Name,Type,Size,Access +reading=true +writing=true +makedir=true +deleting=true +opening=true +moving=false +linking=false +copyFromFile=true +copyToFile=true +Icon=network-workgroup +maxInstances=1 diff --git a/kioslave/mtp/solid_mtp.desktop b/kioslave/mtp/solid_mtp.desktop new file mode 100644 index 00000000..a4fe5a3a --- /dev/null +++ b/kioslave/mtp/solid_mtp.desktop @@ -0,0 +1,40 @@ +[Desktop Entry] +X-KDE-Solid-Predicate=PortableMediaPlayer.supportedProtocols == 'mtp' +Type=Service +Actions=open; + +[Desktop Action open] +Exec=kioclient exec mtp:udi=%i/ +Icon=system-file-manager +Name=Open with File Manager +Name[bs]=Otvori menadžerom datoteka +Name[ca]=Obre amb el gestor de fitxers +Name[ca@valencia]=Obri amb el gestor de fitxers +Name[cs]=Otevřít ve správci souborů +Name[da]=Åbn med filhåndtering +Name[de]=Mit Dateiverwaltung öffnen +Name[el]=Άνοιγμα με τον διαχειριστή αρχείων +Name[es]=Abrir con el gestor de archivos +Name[et]=Avamine failihalduriga +Name[fi]=Avaa tiedostonhallinnassa +Name[fr]=Ouvrir avec un gestionnaire de fichiers +Name[ga]=Oscail i mBainisteoir na gComhad +Name[gl]=Abrir co xestor de ficheiros +Name[hu]=Megnyitás a fájlkezelővel +Name[it]=Apri con gestore file +Name[ko]=파일 관리자로 열기 +Name[lt]=Atverti su failų tvarkykle +Name[mr]=फाईल व्यवस्थापकात उघडा +Name[nl]=Met bestandsbeheerder openen +Name[pl]=Otwórz do zarządzania plikami +Name[pt]=Abrir com o Gestor de Ficheiros +Name[pt_BR]=Abrir com o gerenciador de arquivos +Name[ro]=Deschide cu gestionarul de fișiere +Name[ru]=Открыть в диспетчере файлов +Name[sk]=Otvoriť v správcovi súborov +Name[sl]=Odpri v upravljalniku datotek +Name[sv]=Öppna med filhanterare +Name[tr]=Dosya Yöneticisi ile aç +Name[ug]=ھۆججەت باشقۇرغۇدا ئاچ +Name[uk]=Відкрити у програмі для керування файлами +Name[x-test]=xxOpen with File Managerxx