From 6f9905844f7349f97b59bbbacb8fd443d7aea969 Mon Sep 17 00:00:00 2001 From: barbieri Date: Fri, 22 Feb 2008 17:54:28 +0000 Subject: [PATCH] Deprecated lightmediascanner svn. --- lightmediascanner/AUTHORS | 9 - lightmediascanner/COPYING | 504 ----------- lightmediascanner/Doxyfile | 277 ------ lightmediascanner/INSTALL | 234 ----- lightmediascanner/Makefile.am | 23 - lightmediascanner/README | 20 +- lightmediascanner/TODO | 24 - lightmediascanner/autogen.sh | 14 - lightmediascanner/configure.ac | 126 --- lightmediascanner/lightmediascanner.pc.in | 10 - lightmediascanner/m4/Makefile.am | 4 - lightmediascanner/m4/ac-plugins.m4 | 169 ---- lightmediascanner/m4/as-expand.m4 | 43 - lightmediascanner/src/Makefile.am | 3 - lightmediascanner/src/bin/.gitignore | 1 - lightmediascanner/src/bin/Makefile.am | 12 - lightmediascanner/src/bin/test.c | 103 --- lightmediascanner/src/lib/Makefile.am | 28 - lightmediascanner/src/lib/lightmediascanner.c | 482 ----------- lightmediascanner/src/lib/lightmediascanner.h | 186 ---- .../src/lib/lightmediascanner_charset_conv.c | 460 ---------- .../src/lib/lightmediascanner_charset_conv.h | 90 -- .../src/lib/lightmediascanner_check.c | 671 --------------- lightmediascanner/src/lib/lightmediascanner_db.h | 139 --- .../src/lib/lightmediascanner_db_audio.c | 690 --------------- .../src/lib/lightmediascanner_db_common.c | 789 ----------------- .../src/lib/lightmediascanner_db_image.c | 303 ------- .../src/lib/lightmediascanner_db_playlist.c | 267 ------ .../src/lib/lightmediascanner_db_private.h | 93 -- .../src/lib/lightmediascanner_db_video.c | 279 ------ .../src/lib/lightmediascanner_plugin.h | 168 ---- .../src/lib/lightmediascanner_private.h | 89 -- .../src/lib/lightmediascanner_process.c | 904 -------------------- .../src/lib/lightmediascanner_utils.c | 177 ---- .../src/lib/lightmediascanner_utils.h | 68 -- lightmediascanner/src/plugins/Makefile.am | 70 -- lightmediascanner/src/plugins/asf/Makefile.am | 10 - lightmediascanner/src/plugins/asf/asf.c | 568 ------------ .../src/plugins/audio-dummy/Makefile.am | 10 - .../src/plugins/audio-dummy/audio-dummy.c | 129 --- lightmediascanner/src/plugins/dummy/Makefile.am | 10 - lightmediascanner/src/plugins/dummy/dummy.c | 117 --- lightmediascanner/src/plugins/flac/Makefile.am | 10 - lightmediascanner/src/plugins/flac/flac.c | 180 ---- lightmediascanner/src/plugins/id3/Makefile.am | 10 - lightmediascanner/src/plugins/id3/id3.c | 780 ----------------- lightmediascanner/src/plugins/jpeg/Makefile.am | 10 - lightmediascanner/src/plugins/jpeg/jpeg.c | 719 ---------------- lightmediascanner/src/plugins/m3u/Makefile.am | 10 - lightmediascanner/src/plugins/m3u/m3u.c | 193 ----- lightmediascanner/src/plugins/mp4/Makefile.am | 10 - lightmediascanner/src/plugins/mp4/mp4.c | 232 ----- lightmediascanner/src/plugins/ogg/Makefile.am | 10 - lightmediascanner/src/plugins/ogg/ogg.c | 325 ------- lightmediascanner/src/plugins/pls/Makefile.am | 10 - lightmediascanner/src/plugins/pls/pls.c | 375 -------- lightmediascanner/src/plugins/png/Makefile.am | 10 - lightmediascanner/src/plugins/png/png.c | 213 ----- lightmediascanner/src/plugins/rm/Makefile.am | 10 - lightmediascanner/src/plugins/rm/rm.c | 367 -------- .../src/plugins/video-dummy/Makefile.am | 10 - .../src/plugins/video-dummy/video-dummy.c | 133 --- 62 files changed, 5 insertions(+), 11985 deletions(-) delete mode 100644 lightmediascanner/AUTHORS delete mode 100644 lightmediascanner/COPYING delete mode 100644 lightmediascanner/ChangeLog delete mode 100644 lightmediascanner/Doxyfile delete mode 100644 lightmediascanner/INSTALL delete mode 100644 lightmediascanner/Makefile.am delete mode 100644 lightmediascanner/NEWS delete mode 100644 lightmediascanner/TODO delete mode 100755 lightmediascanner/autogen.sh delete mode 100644 lightmediascanner/configure.ac delete mode 100644 lightmediascanner/lightmediascanner.pc.in delete mode 100644 lightmediascanner/m4/Makefile.am delete mode 100644 lightmediascanner/m4/ac-plugins.m4 delete mode 100644 lightmediascanner/m4/as-expand.m4 delete mode 100644 lightmediascanner/src/Makefile.am delete mode 100644 lightmediascanner/src/bin/.gitignore delete mode 100644 lightmediascanner/src/bin/Makefile.am delete mode 100644 lightmediascanner/src/bin/test.c delete mode 100644 lightmediascanner/src/lib/Makefile.am delete mode 100644 lightmediascanner/src/lib/lightmediascanner.c delete mode 100644 lightmediascanner/src/lib/lightmediascanner.h delete mode 100644 lightmediascanner/src/lib/lightmediascanner_charset_conv.c delete mode 100644 lightmediascanner/src/lib/lightmediascanner_charset_conv.h delete mode 100644 lightmediascanner/src/lib/lightmediascanner_check.c delete mode 100644 lightmediascanner/src/lib/lightmediascanner_db.h delete mode 100644 lightmediascanner/src/lib/lightmediascanner_db_audio.c delete mode 100644 lightmediascanner/src/lib/lightmediascanner_db_common.c delete mode 100644 lightmediascanner/src/lib/lightmediascanner_db_image.c delete mode 100644 lightmediascanner/src/lib/lightmediascanner_db_playlist.c delete mode 100644 lightmediascanner/src/lib/lightmediascanner_db_private.h delete mode 100644 lightmediascanner/src/lib/lightmediascanner_db_video.c delete mode 100644 lightmediascanner/src/lib/lightmediascanner_plugin.h delete mode 100644 lightmediascanner/src/lib/lightmediascanner_private.h delete mode 100644 lightmediascanner/src/lib/lightmediascanner_process.c delete mode 100644 lightmediascanner/src/lib/lightmediascanner_utils.c delete mode 100644 lightmediascanner/src/lib/lightmediascanner_utils.h delete mode 100644 lightmediascanner/src/plugins/Makefile.am delete mode 100644 lightmediascanner/src/plugins/asf/Makefile.am delete mode 100644 lightmediascanner/src/plugins/asf/asf.c delete mode 100644 lightmediascanner/src/plugins/audio-dummy/Makefile.am delete mode 100644 lightmediascanner/src/plugins/audio-dummy/audio-dummy.c delete mode 100644 lightmediascanner/src/plugins/dummy/Makefile.am delete mode 100644 lightmediascanner/src/plugins/dummy/dummy.c delete mode 100644 lightmediascanner/src/plugins/flac/Makefile.am delete mode 100644 lightmediascanner/src/plugins/flac/flac.c delete mode 100644 lightmediascanner/src/plugins/id3/Makefile.am delete mode 100644 lightmediascanner/src/plugins/id3/id3.c delete mode 100644 lightmediascanner/src/plugins/jpeg/Makefile.am delete mode 100644 lightmediascanner/src/plugins/jpeg/jpeg.c delete mode 100644 lightmediascanner/src/plugins/m3u/Makefile.am delete mode 100644 lightmediascanner/src/plugins/m3u/m3u.c delete mode 100644 lightmediascanner/src/plugins/mp4/Makefile.am delete mode 100644 lightmediascanner/src/plugins/mp4/mp4.c delete mode 100644 lightmediascanner/src/plugins/ogg/Makefile.am delete mode 100644 lightmediascanner/src/plugins/ogg/ogg.c delete mode 100644 lightmediascanner/src/plugins/pls/Makefile.am delete mode 100644 lightmediascanner/src/plugins/pls/pls.c delete mode 100644 lightmediascanner/src/plugins/png/Makefile.am delete mode 100644 lightmediascanner/src/plugins/png/png.c delete mode 100644 lightmediascanner/src/plugins/rm/Makefile.am delete mode 100644 lightmediascanner/src/plugins/rm/rm.c delete mode 100644 lightmediascanner/src/plugins/video-dummy/Makefile.am delete mode 100644 lightmediascanner/src/plugins/video-dummy/video-dummy.c diff --git a/lightmediascanner/AUTHORS b/lightmediascanner/AUTHORS deleted file mode 100644 index 239824c..0000000 --- a/lightmediascanner/AUTHORS +++ /dev/null @@ -1,9 +0,0 @@ -core and some plugins: - Gustavo Sverzut Barbieri - -most plugins: - Andre Moreira Magalhaes - -ogg plugin: - Renato Chencarek - diff --git a/lightmediascanner/COPYING b/lightmediascanner/COPYING deleted file mode 100644 index 8add30a..0000000 --- a/lightmediascanner/COPYING +++ /dev/null @@ -1,504 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 2.1, February 1999 - - Copyright (C) 1991, 1999 Free Software Foundation, Inc. - 51 Franklin St, 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. - -[This is the first released version of the Lesser GPL. It also counts - as the successor of the GNU Library Public License, version 2, hence - the version number 2.1.] - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -Licenses are intended to guarantee your freedom to share and change -free software--to make sure the software is free for all its users. - - This license, the Lesser General Public License, applies to some -specially designated software packages--typically libraries--of the -Free Software Foundation and other authors who decide to use it. You -can use it too, but we suggest you first think carefully about whether -this license or the ordinary General Public License is the better -strategy to use in any particular case, based on the explanations below. - - When we speak of free software, we are referring to freedom of use, -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 and use pieces of -it in new free programs; and that you are informed that you can do -these things. - - To protect your rights, we need to make restrictions that forbid -distributors to deny you these rights or to ask you to surrender these -rights. These restrictions translate to certain responsibilities for -you if you distribute copies of the library or if you modify it. - - For example, if you distribute copies of the library, whether gratis -or for a fee, you must give the recipients all the rights that we gave -you. You must make sure that they, too, receive or can get the source -code. If you link other code with the library, you must provide -complete object files to the recipients, so that they can relink them -with the library after making changes to the library and recompiling -it. And you must show them these terms so they know their rights. - - We protect your rights with a two-step method: (1) we copyright the -library, and (2) we offer you this license, which gives you legal -permission to copy, distribute and/or modify the library. - - To protect each distributor, we want to make it very clear that -there is no warranty for the free library. Also, if the library is -modified by someone else and passed on, the recipients should know -that what they have is not the original version, so that the original -author's reputation will not be affected by problems that might be -introduced by others. - - Finally, software patents pose a constant threat to the existence of -any free program. We wish to make sure that a company cannot -effectively restrict the users of a free program by obtaining a -restrictive license from a patent holder. Therefore, we insist that -any patent license obtained for a version of the library must be -consistent with the full freedom of use specified in this license. - - Most GNU software, including some libraries, is covered by the -ordinary GNU General Public License. This license, the GNU Lesser -General Public License, applies to certain designated libraries, and -is quite different from the ordinary General Public License. We use -this license for certain libraries in order to permit linking those -libraries into non-free programs. - - When a program is linked with a library, whether statically or using -a shared library, the combination of the two is legally speaking a -combined work, a derivative of the original library. The ordinary -General Public License therefore permits such linking only if the -entire combination fits its criteria of freedom. The Lesser General -Public License permits more lax criteria for linking other code with -the library. - - We call this license the "Lesser" General Public License because it -does Less to protect the user's freedom than the ordinary General -Public License. It also provides other free software developers Less -of an advantage over competing non-free programs. These disadvantages -are the reason we use the ordinary General Public License for many -libraries. However, the Lesser license provides advantages in certain -special circumstances. - - For example, on rare occasions, there may be a special need to -encourage the widest possible use of a certain library, so that it becomes -a de-facto standard. To achieve this, non-free programs must be -allowed to use the library. A more frequent case is that a free -library does the same job as widely used non-free libraries. In this -case, there is little to gain by limiting the free library to free -software only, so we use the Lesser General Public License. - - In other cases, permission to use a particular library in non-free -programs enables a greater number of people to use a large body of -free software. For example, permission to use the GNU C Library in -non-free programs enables many more people to use the whole GNU -operating system, as well as its variant, the GNU/Linux operating -system. - - Although the Lesser General Public License is Less protective of the -users' freedom, it does ensure that the user of a program that is -linked with the Library has the freedom and the wherewithal to run -that program using a modified version of the Library. - - The precise terms and conditions for copying, distribution and -modification follow. Pay close attention to the difference between a -"work based on the library" and a "work that uses the library". The -former contains code derived from the library, whereas the latter must -be combined with the library in order to run. - - GNU LESSER GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License Agreement applies to any software library or other -program which contains a notice placed by the copyright holder or -other authorized party saying it may be distributed under the terms of -this Lesser General Public License (also called "this License"). -Each licensee is addressed as "you". - - A "library" means a collection of software functions and/or data -prepared so as to be conveniently linked with application programs -(which use some of those functions and data) to form executables. - - The "Library", below, refers to any such software library or work -which has been distributed under these terms. A "work based on the -Library" means either the Library or any derivative work under -copyright law: that is to say, a work containing the Library or a -portion of it, either verbatim or with modifications and/or translated -straightforwardly into another language. (Hereinafter, translation is -included without limitation in the term "modification".) - - "Source code" for a work means the preferred form of the work for -making modifications to it. For a library, 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 library. - - Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running a program using the Library is not restricted, and output from -such a program is covered only if its contents constitute a work based -on the Library (independent of the use of the Library in a tool for -writing it). Whether that is true depends on what the Library does -and what the program that uses the Library does. - - 1. You may copy and distribute verbatim copies of the Library's -complete 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 distribute a copy of this License along with the -Library. - - 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 Library or any portion -of it, thus forming a work based on the Library, 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) The modified work must itself be a software library. - - b) You must cause the files modified to carry prominent notices - stating that you changed the files and the date of any change. - - c) You must cause the whole of the work to be licensed at no - charge to all third parties under the terms of this License. - - d) If a facility in the modified Library refers to a function or a - table of data to be supplied by an application program that uses - the facility, other than as an argument passed when the facility - is invoked, then you must make a good faith effort to ensure that, - in the event an application does not supply such function or - table, the facility still operates, and performs whatever part of - its purpose remains meaningful. - - (For example, a function in a library to compute square roots has - a purpose that is entirely well-defined independent of the - application. Therefore, Subsection 2d requires that any - application-supplied function or table used by this function must - be optional: if the application does not supply it, the square - root function must still compute square roots.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Library, -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 Library, 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 Library. - -In addition, mere aggregation of another work not based on the Library -with the Library (or with a work based on the Library) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may opt to apply the terms of the ordinary GNU General Public -License instead of this License to a given copy of the Library. To do -this, you must alter all the notices that refer to this License, so -that they refer to the ordinary GNU General Public License, version 2, -instead of to this License. (If a newer version than version 2 of the -ordinary GNU General Public License has appeared, then you can specify -that version instead if you wish.) Do not make any other change in -these notices. - - Once this change is made in a given copy, it is irreversible for -that copy, so the ordinary GNU General Public License applies to all -subsequent copies and derivative works made from that copy. - - This option is useful when you wish to copy part of the code of -the Library into a program that is not a library. - - 4. You may copy and distribute the Library (or a portion or -derivative of it, under Section 2) in object code or executable form -under the terms of Sections 1 and 2 above provided that you 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. - - If distribution of 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 satisfies the requirement to -distribute the source code, even though third parties are not -compelled to copy the source along with the object code. - - 5. A program that contains no derivative of any portion of the -Library, but is designed to work with the Library by being compiled or -linked with it, is called a "work that uses the Library". Such a -work, in isolation, is not a derivative work of the Library, and -therefore falls outside the scope of this License. - - However, linking a "work that uses the Library" with the Library -creates an executable that is a derivative of the Library (because it -contains portions of the Library), rather than a "work that uses the -library". The executable is therefore covered by this License. -Section 6 states terms for distribution of such executables. - - When a "work that uses the Library" uses material from a header file -that is part of the Library, the object code for the work may be a -derivative work of the Library even though the source code is not. -Whether this is true is especially significant if the work can be -linked without the Library, or if the work is itself a library. The -threshold for this to be true is not precisely defined by law. - - If such an object file uses only numerical parameters, data -structure layouts and accessors, and small macros and small inline -functions (ten lines or less in length), then the use of the object -file is unrestricted, regardless of whether it is legally a derivative -work. (Executables containing this object code plus portions of the -Library will still fall under Section 6.) - - Otherwise, if the work is a derivative of the Library, you may -distribute the object code for the work under the terms of Section 6. -Any executables containing that work also fall under Section 6, -whether or not they are linked directly with the Library itself. - - 6. As an exception to the Sections above, you may also combine or -link a "work that uses the Library" with the Library to produce a -work containing portions of the Library, and distribute that work -under terms of your choice, provided that the terms permit -modification of the work for the customer's own use and reverse -engineering for debugging such modifications. - - You must give prominent notice with each copy of the work that the -Library is used in it and that the Library and its use are covered by -this License. You must supply a copy of this License. If the work -during execution displays copyright notices, you must include the -copyright notice for the Library among them, as well as a reference -directing the user to the copy of this License. Also, you must do one -of these things: - - a) Accompany the work with the complete corresponding - machine-readable source code for the Library including whatever - changes were used in the work (which must be distributed under - Sections 1 and 2 above); and, if the work is an executable linked - with the Library, with the complete machine-readable "work that - uses the Library", as object code and/or source code, so that the - user can modify the Library and then relink to produce a modified - executable containing the modified Library. (It is understood - that the user who changes the contents of definitions files in the - Library will not necessarily be able to recompile the application - to use the modified definitions.) - - b) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (1) uses at run time a - copy of the library already present on the user's computer system, - rather than copying library functions into the executable, and (2) - will operate properly with a modified version of the library, if - the user installs one, as long as the modified version is - interface-compatible with the version that the work was made with. - - c) Accompany the work with a written offer, valid for at - least three years, to give the same user the materials - specified in Subsection 6a, above, for a charge no more - than the cost of performing this distribution. - - d) If distribution of the work is made by offering access to copy - from a designated place, offer equivalent access to copy the above - specified materials from the same place. - - e) Verify that the user has already received a copy of these - materials or that you have already sent this user a copy. - - For an executable, the required form of the "work that uses the -Library" must include any data and utility programs needed for -reproducing the executable from it. However, as a special exception, -the materials to be 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. - - It may happen that this requirement contradicts the license -restrictions of other proprietary libraries that do not normally -accompany the operating system. Such a contradiction means you cannot -use both them and the Library together in an executable that you -distribute. - - 7. You may place library facilities that are a work based on the -Library side-by-side in a single library together with other library -facilities not covered by this License, and distribute such a combined -library, provided that the separate distribution of the work based on -the Library and of the other library facilities is otherwise -permitted, and provided that you do these two things: - - a) Accompany the combined library with a copy of the same work - based on the Library, uncombined with any other library - facilities. This must be distributed under the terms of the - Sections above. - - b) Give prominent notice with the combined library of the fact - that part of it is a work based on the Library, and explaining - where to find the accompanying uncombined form of the same work. - - 8. You may not copy, modify, sublicense, link with, or distribute -the Library except as expressly provided under this License. Any -attempt otherwise to copy, modify, sublicense, link with, or -distribute the Library 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. - - 9. 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 Library or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Library (or any work based on the -Library), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Library or works based on it. - - 10. Each time you redistribute the Library (or any work based on the -Library), the recipient automatically receives a license from the -original licensor to copy, distribute, link with or modify the Library -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 with -this License. - - 11. 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 Library at all. For example, if a patent -license would not permit royalty-free redistribution of the Library 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 Library. - -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. - - 12. If the distribution and/or use of the Library is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Library 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. - - 13. The Free Software Foundation may publish revised and/or new -versions of the Lesser 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 Library -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 Library does not specify a -license version number, you may choose any version ever published by -the Free Software Foundation. - - 14. If you wish to incorporate parts of the Library into other free -programs whose distribution conditions are incompatible with these, -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 - - 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO -WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. -EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR -OTHER PARTIES PROVIDE THE LIBRARY "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 -LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME -THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. 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 LIBRARY 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 -LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), 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 Libraries - - If you develop a new library, and you want it to be of the greatest -possible use to the public, we recommend making it free software that -everyone can redistribute and change. You can do so by permitting -redistribution under these terms (or, alternatively, under the terms of the -ordinary General Public License). - - To apply these terms, attach the following notices to the library. 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 library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -Also add information on how to contact you by electronic and paper mail. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the library, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the - library `Frob' (a library for tweaking knobs) written by James Random Hacker. - - , 1 April 1990 - Ty Coon, President of Vice - -That's all there is to it! - - diff --git a/lightmediascanner/ChangeLog b/lightmediascanner/ChangeLog deleted file mode 100644 index e69de29..0000000 diff --git a/lightmediascanner/Doxyfile b/lightmediascanner/Doxyfile deleted file mode 100644 index aff7892..0000000 --- a/lightmediascanner/Doxyfile +++ /dev/null @@ -1,277 +0,0 @@ -# Doxyfile 1.5.2 - -#--------------------------------------------------------------------------- -# Project related configuration options -#--------------------------------------------------------------------------- -DOXYFILE_ENCODING = UTF-8 -PROJECT_NAME = "Light Media Scanner" -PROJECT_NUMBER = 0.1 -OUTPUT_DIRECTORY = docs -CREATE_SUBDIRS = NO -OUTPUT_LANGUAGE = English -BRIEF_MEMBER_DESC = YES -REPEAT_BRIEF = YES -ABBREVIATE_BRIEF = "The $name class" \ - "The $name widget" \ - "The $name file" \ - is \ - provides \ - specifies \ - contains \ - represents \ - a \ - an \ - the -ALWAYS_DETAILED_SEC = NO -INLINE_INHERITED_MEMB = NO -FULL_PATH_NAMES = YES -STRIP_FROM_PATH = -STRIP_FROM_INC_PATH = -SHORT_NAMES = NO -JAVADOC_AUTOBRIEF = NO -MULTILINE_CPP_IS_BRIEF = NO -DETAILS_AT_TOP = NO -INHERIT_DOCS = YES -SEPARATE_MEMBER_PAGES = NO -TAB_SIZE = 8 -ALIASES = -OPTIMIZE_OUTPUT_FOR_C = YES -OPTIMIZE_OUTPUT_JAVA = NO -BUILTIN_STL_SUPPORT = NO -CPP_CLI_SUPPORT = NO -DISTRIBUTE_GROUP_DOC = NO -SUBGROUPING = YES -#--------------------------------------------------------------------------- -# Build related configuration options -#--------------------------------------------------------------------------- -EXTRACT_ALL = YES -EXTRACT_PRIVATE = NO -EXTRACT_STATIC = NO -EXTRACT_LOCAL_CLASSES = NO -EXTRACT_LOCAL_METHODS = NO -HIDE_UNDOC_MEMBERS = NO -HIDE_UNDOC_CLASSES = NO -HIDE_FRIEND_COMPOUNDS = NO -HIDE_IN_BODY_DOCS = NO -INTERNAL_DOCS = NO -CASE_SENSE_NAMES = YES -HIDE_SCOPE_NAMES = NO -SHOW_INCLUDE_FILES = YES -INLINE_INFO = YES -SORT_MEMBER_DOCS = YES -SORT_BRIEF_DOCS = NO -SORT_BY_SCOPE_NAME = NO -GENERATE_TODOLIST = YES -GENERATE_TESTLIST = YES -GENERATE_BUGLIST = YES -GENERATE_DEPRECATEDLIST= YES -ENABLED_SECTIONS = -MAX_INITIALIZER_LINES = 30 -SHOW_USED_FILES = YES -SHOW_DIRECTORIES = NO -FILE_VERSION_FILTER = -#--------------------------------------------------------------------------- -# configuration options related to warning and progress messages -#--------------------------------------------------------------------------- -QUIET = NO -WARNINGS = YES -WARN_IF_UNDOCUMENTED = YES -WARN_IF_DOC_ERROR = YES -WARN_NO_PARAMDOC = NO -WARN_FORMAT = "$file:$line: $text" -WARN_LOGFILE = -#--------------------------------------------------------------------------- -# configuration options related to the input files -#--------------------------------------------------------------------------- -INPUT = src/lib -INPUT_ENCODING = UTF-8 -FILE_PATTERNS = *.c \ - *.cc \ - *.cxx \ - *.cpp \ - *.c++ \ - *.d \ - *.java \ - *.ii \ - *.ixx \ - *.ipp \ - *.i++ \ - *.inl \ - *.h \ - *.hh \ - *.hxx \ - *.hpp \ - *.h++ \ - *.idl \ - *.odl \ - *.cs \ - *.php \ - *.php3 \ - *.inc \ - *.m \ - *.mm \ - *.dox \ - *.py \ - *.C \ - *.CC \ - *.C++ \ - *.II \ - *.I++ \ - *.H \ - *.HH \ - *.H++ \ - *.CS \ - *.PHP \ - *.PHP3 \ - *.M \ - *.MM \ - *.PY -RECURSIVE = NO -EXCLUDE = -EXCLUDE_SYMLINKS = NO -EXCLUDE_PATTERNS = -EXCLUDE_SYMBOLS = -EXAMPLE_PATH = -EXAMPLE_PATTERNS = * -EXAMPLE_RECURSIVE = NO -IMAGE_PATH = -INPUT_FILTER = -FILTER_PATTERNS = -FILTER_SOURCE_FILES = NO -#--------------------------------------------------------------------------- -# configuration options related to source browsing -#--------------------------------------------------------------------------- -SOURCE_BROWSER = YES -INLINE_SOURCES = NO -STRIP_CODE_COMMENTS = YES -REFERENCED_BY_RELATION = YES -REFERENCES_RELATION = YES -REFERENCES_LINK_SOURCE = YES -USE_HTAGS = NO -VERBATIM_HEADERS = YES -#--------------------------------------------------------------------------- -# configuration options related to the alphabetical class index -#--------------------------------------------------------------------------- -ALPHABETICAL_INDEX = YES -COLS_IN_ALPHA_INDEX = 3 -IGNORE_PREFIX = lms_ -#--------------------------------------------------------------------------- -# configuration options related to the HTML output -#--------------------------------------------------------------------------- -GENERATE_HTML = YES -HTML_OUTPUT = html -HTML_FILE_EXTENSION = .html -HTML_HEADER = -HTML_FOOTER = -HTML_STYLESHEET = -HTML_ALIGN_MEMBERS = YES -GENERATE_HTMLHELP = NO -CHM_FILE = -HHC_LOCATION = -GENERATE_CHI = NO -BINARY_TOC = NO -TOC_EXPAND = NO -DISABLE_INDEX = NO -ENUM_VALUES_PER_LINE = 4 -GENERATE_TREEVIEW = NO -TREEVIEW_WIDTH = 250 -#--------------------------------------------------------------------------- -# configuration options related to the LaTeX output -#--------------------------------------------------------------------------- -GENERATE_LATEX = NO -LATEX_OUTPUT = latex -LATEX_CMD_NAME = latex -MAKEINDEX_CMD_NAME = makeindex -COMPACT_LATEX = NO -PAPER_TYPE = a4wide -EXTRA_PACKAGES = -LATEX_HEADER = -PDF_HYPERLINKS = NO -USE_PDFLATEX = NO -LATEX_BATCHMODE = NO -LATEX_HIDE_INDICES = NO -#--------------------------------------------------------------------------- -# configuration options related to the RTF output -#--------------------------------------------------------------------------- -GENERATE_RTF = NO -RTF_OUTPUT = rtf -COMPACT_RTF = NO -RTF_HYPERLINKS = NO -RTF_STYLESHEET_FILE = -RTF_EXTENSIONS_FILE = -#--------------------------------------------------------------------------- -# configuration options related to the man page output -#--------------------------------------------------------------------------- -GENERATE_MAN = NO -MAN_OUTPUT = man -MAN_EXTENSION = .3 -MAN_LINKS = NO -#--------------------------------------------------------------------------- -# configuration options related to the XML output -#--------------------------------------------------------------------------- -GENERATE_XML = NO -XML_OUTPUT = xml -XML_SCHEMA = -XML_DTD = -XML_PROGRAMLISTING = YES -#--------------------------------------------------------------------------- -# configuration options for the AutoGen Definitions output -#--------------------------------------------------------------------------- -GENERATE_AUTOGEN_DEF = NO -#--------------------------------------------------------------------------- -# configuration options related to the Perl module output -#--------------------------------------------------------------------------- -GENERATE_PERLMOD = NO -PERLMOD_LATEX = NO -PERLMOD_PRETTY = YES -PERLMOD_MAKEVAR_PREFIX = -#--------------------------------------------------------------------------- -# Configuration options related to the preprocessor -#--------------------------------------------------------------------------- -ENABLE_PREPROCESSING = YES -MACRO_EXPANSION = NO -EXPAND_ONLY_PREDEF = NO -SEARCH_INCLUDES = YES -INCLUDE_PATH = -INCLUDE_FILE_PATTERNS = -PREDEFINED = -EXPAND_AS_DEFINED = -SKIP_FUNCTION_MACROS = YES -#--------------------------------------------------------------------------- -# Configuration::additions related to external references -#--------------------------------------------------------------------------- -TAGFILES = -GENERATE_TAGFILE = -ALLEXTERNALS = NO -EXTERNAL_GROUPS = YES -PERL_PATH = /usr/bin/perl -#--------------------------------------------------------------------------- -# Configuration options related to the dot tool -#--------------------------------------------------------------------------- -CLASS_DIAGRAMS = NO -MSCGEN_PATH = -HIDE_UNDOC_RELATIONS = YES -HAVE_DOT = YES -CLASS_GRAPH = YES -COLLABORATION_GRAPH = YES -GROUP_GRAPHS = YES -UML_LOOK = YES -TEMPLATE_RELATIONS = NO -INCLUDE_GRAPH = YES -INCLUDED_BY_GRAPH = YES -CALL_GRAPH = YES -CALLER_GRAPH = NO -GRAPHICAL_HIERARCHY = YES -DIRECTORY_GRAPH = YES -DOT_IMAGE_FORMAT = png -DOT_PATH = -DOTFILE_DIRS = -DOT_GRAPH_MAX_NODES = 50 -DOT_TRANSPARENT = YES -DOT_MULTI_TARGETS = NO -GENERATE_LEGEND = YES -DOT_CLEANUP = YES -#--------------------------------------------------------------------------- -# Configuration::additions related to the search engine -#--------------------------------------------------------------------------- -SEARCHENGINE = NO diff --git a/lightmediascanner/INSTALL b/lightmediascanner/INSTALL deleted file mode 100644 index 5458714..0000000 --- a/lightmediascanner/INSTALL +++ /dev/null @@ -1,234 +0,0 @@ -Installation Instructions -************************* - -Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005, -2006 Free Software Foundation, Inc. - -This file is free documentation; the Free Software Foundation gives -unlimited permission to copy, distribute and modify it. - -Basic Installation -================== - -Briefly, the shell commands `./configure; make; make install' should -configure, build, and install this package. The following -more-detailed instructions are generic; see the `README' file for -instructions specific to this package. - - The `configure' shell script attempts to guess correct values for -various system-dependent variables used during compilation. It uses -those values to create a `Makefile' in each directory of the package. -It may also create one or more `.h' files containing system-dependent -definitions. Finally, it creates a shell script `config.status' that -you can run in the future to recreate the current configuration, and a -file `config.log' containing compiler output (useful mainly for -debugging `configure'). - - It can also use an optional file (typically called `config.cache' -and enabled with `--cache-file=config.cache' or simply `-C') that saves -the results of its tests to speed up reconfiguring. Caching is -disabled by default to prevent problems with accidental use of stale -cache files. - - If you need to do unusual things to compile the package, please try -to figure out how `configure' could check whether to do them, and mail -diffs or instructions to the address given in the `README' so they can -be considered for the next release. If you are using the cache, and at -some point `config.cache' contains results you don't want to keep, you -may remove or edit it. - - The file `configure.ac' (or `configure.in') is used to create -`configure' by a program called `autoconf'. You need `configure.ac' if -you want to change it or regenerate `configure' using a newer version -of `autoconf'. - -The simplest way to compile this package is: - - 1. `cd' to the directory containing the package's source code and type - `./configure' to configure the package for your system. - - Running `configure' might take a while. While running, it prints - some messages telling which features it is checking for. - - 2. Type `make' to compile the package. - - 3. Optionally, type `make check' to run any self-tests that come with - the package. - - 4. Type `make install' to install the programs and any data files and - documentation. - - 5. You can remove the program binaries and object files from the - source code directory by typing `make clean'. To also remove the - files that `configure' created (so you can compile the package for - a different kind of computer), type `make distclean'. There is - also a `make maintainer-clean' target, but that is intended mainly - for the package's developers. If you use it, you may have to get - all sorts of other programs in order to regenerate files that came - with the distribution. - -Compilers and Options -===================== - -Some systems require unusual options for compilation or linking that the -`configure' script does not know about. Run `./configure --help' for -details on some of the pertinent environment variables. - - You can give `configure' initial values for configuration parameters -by setting variables in the command line or in the environment. Here -is an example: - - ./configure CC=c99 CFLAGS=-g LIBS=-lposix - - *Note Defining Variables::, for more details. - -Compiling For Multiple Architectures -==================================== - -You can compile the package for more than one kind of computer at the -same time, by placing the object files for each architecture in their -own directory. To do this, you can use GNU `make'. `cd' to the -directory where you want the object files and executables to go and run -the `configure' script. `configure' automatically checks for the -source code in the directory that `configure' is in and in `..'. - - With a non-GNU `make', it is safer to compile the package for one -architecture at a time in the source code directory. After you have -installed the package for one architecture, use `make distclean' before -reconfiguring for another architecture. - -Installation Names -================== - -By default, `make install' installs the package's commands under -`/usr/local/bin', include files under `/usr/local/include', etc. You -can specify an installation prefix other than `/usr/local' by giving -`configure' the option `--prefix=PREFIX'. - - You can specify separate installation prefixes for -architecture-specific files and architecture-independent files. If you -pass the option `--exec-prefix=PREFIX' to `configure', the package uses -PREFIX as the prefix for installing programs and libraries. -Documentation and other data files still use the regular prefix. - - In addition, if you use an unusual directory layout you can give -options like `--bindir=DIR' to specify different values for particular -kinds of files. Run `configure --help' for a list of the directories -you can set and what kinds of files go in them. - - If the package supports it, you can cause programs to be installed -with an extra prefix or suffix on their names by giving `configure' the -option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. - -Optional Features -================= - -Some packages pay attention to `--enable-FEATURE' options to -`configure', where FEATURE indicates an optional part of the package. -They may also pay attention to `--with-PACKAGE' options, where PACKAGE -is something like `gnu-as' or `x' (for the X Window System). The -`README' should mention any `--enable-' and `--with-' options that the -package recognizes. - - For packages that use the X Window System, `configure' can usually -find the X include and library files automatically, but if it doesn't, -you can use the `configure' options `--x-includes=DIR' and -`--x-libraries=DIR' to specify their locations. - -Specifying the System Type -========================== - -There may be some features `configure' cannot figure out automatically, -but needs to determine by the type of machine the package will run on. -Usually, assuming the package is built to be run on the _same_ -architectures, `configure' can figure that out, but if it prints a -message saying it cannot guess the machine type, give it the -`--build=TYPE' option. TYPE can either be a short name for the system -type, such as `sun4', or a canonical name which has the form: - - CPU-COMPANY-SYSTEM - -where SYSTEM can have one of these forms: - - OS KERNEL-OS - - See the file `config.sub' for the possible values of each field. If -`config.sub' isn't included in this package, then this package doesn't -need to know the machine type. - - If you are _building_ compiler tools for cross-compiling, you should -use the option `--target=TYPE' to select the type of system they will -produce code for. - - If you want to _use_ a cross compiler, that generates code for a -platform different from the build platform, you should specify the -"host" platform (i.e., that on which the generated programs will -eventually be run) with `--host=TYPE'. - -Sharing Defaults -================ - -If you want to set default values for `configure' scripts to share, you -can create a site shell script called `config.site' that gives default -values for variables like `CC', `cache_file', and `prefix'. -`configure' looks for `PREFIX/share/config.site' if it exists, then -`PREFIX/etc/config.site' if it exists. Or, you can set the -`CONFIG_SITE' environment variable to the location of the site script. -A warning: not all `configure' scripts look for a site script. - -Defining Variables -================== - -Variables not defined in a site shell script can be set in the -environment passed to `configure'. However, some packages may run -configure again during the build, and the customized values of these -variables may be lost. In order to avoid this problem, you should set -them in the `configure' command line, using `VAR=value'. For example: - - ./configure CC=/usr/local2/bin/gcc - -causes the specified `gcc' to be used as the C compiler (unless it is -overridden in the site shell script). - -Unfortunately, this technique does not work for `CONFIG_SHELL' due to -an Autoconf bug. Until the bug is fixed you can use this workaround: - - CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash - -`configure' Invocation -====================== - -`configure' recognizes the following options to control how it operates. - -`--help' -`-h' - Print a summary of the options to `configure', and exit. - -`--version' -`-V' - Print the version of Autoconf used to generate the `configure' - script, and exit. - -`--cache-file=FILE' - Enable the cache: use and save the results of the tests in FILE, - traditionally `config.cache'. FILE defaults to `/dev/null' to - disable caching. - -`--config-cache' -`-C' - Alias for `--cache-file=config.cache'. - -`--quiet' -`--silent' -`-q' - Do not print messages saying which checks are being made. To - suppress all normal output, redirect it to `/dev/null' (any error - messages will still be shown). - -`--srcdir=DIR' - Look for the package's source code in directory DIR. Usually - `configure' can determine that directory automatically. - -`configure' also accepts some other, not widely useful, options. Run -`configure --help' for more details. - diff --git a/lightmediascanner/Makefile.am b/lightmediascanner/Makefile.am deleted file mode 100644 index 2c5738d..0000000 --- a/lightmediascanner/Makefile.am +++ /dev/null @@ -1,23 +0,0 @@ -MAINTAINERCLEANFILES = \ - Makefile.in \ - aclocal.m4 \ - compile \ - config.guess \ - config.h.in \ - config.sub \ - configure \ - depcomp \ - install-sh \ - ltmain.sh \ - missing - -SUBDIRS = src m4 - -EXTRA_DIST = \ - README \ - AUTHORS \ - COPYING \ - Doxyfile - -pkgconfigdir = $(libdir)/pkgconfig -pkgconfig_DATA = lightmediascanner.pc diff --git a/lightmediascanner/NEWS b/lightmediascanner/NEWS deleted file mode 100644 index e69de29..0000000 diff --git a/lightmediascanner/README b/lightmediascanner/README index 524425d..32c6e60 100644 --- a/lightmediascanner/README +++ b/lightmediascanner/README @@ -1,17 +1,7 @@ - LIGHT MEDIA SCANNER - =================== +SVN IS DEPRECATED, USE GIT -Lightweight media scanner meant to be used in not-so-powerful devices, -like embedded systems or old machines. +see http://lms.garage.maemo.org/ for more info. -Provides an optimized way to recursively scan directories, handling -the parser in a child process, avoiding breaks of the main process -when parsers break (quite common with such bad libs and tags). - -Parsers are plugins in the form of shared objects, so it's easy to add -new without having to recompiling the scanner. - -The scanner will use SQLite3 to store file-mtime association, avoiding -parsing files that are already up-to-date. This SQLite connection and -the file id within the master table 'files' are handled to plugins for -relationship with other tables. +Some good repositories: + - Gustavo (creator, maintainer): http://staff.get-e.org/?p=users/barbieri/lightmediascanner.git + - Andre (plugins): http://staff.get-e.org/?p=users/andrunko/lightmediascanner.git diff --git a/lightmediascanner/TODO b/lightmediascanner/TODO deleted file mode 100644 index eb76015..0000000 --- a/lightmediascanner/TODO +++ /dev/null @@ -1,24 +0,0 @@ - * Flag to ignore symbolic links, set by default. Using symlinks may - lead user to scan the same file more than once and also scan media - outside of his library. If one uses realpath() to always have an - unique instance of the file parsed, he still will suffer from media - outside his chosen folders. If to fix this, together with the - previous fix will led to the same situation as ignore symlinks, but - without the check overhead. - - * Provide progress callback. - - * Try to address need of whole path lookup using open(), stat(), - readdir()... by using *at() variants, like openat(), fstatat(). - - * Provide single-process version of lms_process() and lms_check(). - - * Provide threaded version of lms_process() and lms_check(), this - helps in multicore setups, where one will read and cache - filesystems while the other will parse files. Study the CPU - affinity implications on this, setting better defaults. - - * Evaluate if there is a way to detect if a string is already in - UTF-8, probably it's impossible to know due the broad range of - possible values, but maybe there is a way to give hints for latin, - asian, western european charsets? diff --git a/lightmediascanner/autogen.sh b/lightmediascanner/autogen.sh deleted file mode 100755 index 5bbd4d9..0000000 --- a/lightmediascanner/autogen.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/sh - -rm -rf autom4te.cache -rm -f aclocal.m4 ltmain.sh - -echo "Running aclocal..." ; aclocal $ACLOCAL_FLAGS -I m4 || exit 1 -echo "Running autoheader..." ; autoheader || exit 1 -echo "Running autoconf..." ; autoconf || exit 1 -echo "Running libtoolize..." ; (libtoolize --copy --automake || glibtoolize --automake) || exit 1 -echo "Running automake..." ; automake --add-missing --copy --gnu || exit 1 - -if [ -z "$NOCONFIGURE" ]; then - ./configure "$@" -fi diff --git a/lightmediascanner/configure.ac b/lightmediascanner/configure.ac deleted file mode 100644 index caeb129..0000000 --- a/lightmediascanner/configure.ac +++ /dev/null @@ -1,126 +0,0 @@ -AC_INIT(lightmediascanner, 0.1.0.1, gustavo.barbieri@openbossa.org) -AC_PREREQ(2.52) -AC_CONFIG_SRCDIR(configure.ac) -AC_CANONICAL_BUILD -AC_CANONICAL_HOST -AC_ISC_POSIX - -AM_INIT_AUTOMAKE(1.6 dist-bzip2) -AM_CONFIG_HEADER(config.h) -AC_SUBST(ACLOCAL_AMFLAGS, "-I m4") -_XTERM_COLORS - -AC_PROG_CC -AM_PROG_CC_STDC -AM_PROG_CC_C_O -AC_HEADER_STDC -AC_C_CONST - -define([AC_LIBTOOL_LANG_F77_CONFIG], [:])dnl -AC_PROG_LIBTOOL - -VMAJ=`echo $PACKAGE_VERSION | awk -F. '{printf("%s", $1);}'` -VMIN=`echo $PACKAGE_VERSION | awk -F. '{printf("%s", $2);}'` -VMIC=`echo $PACKAGE_VERSION | awk -F. '{printf("%s", $3);}'` -SNAP=`echo $PACKAGE_VERSION | awk -F. '{printf("%s", $4);}'` -version_info=`expr $VMAJ + $VMIN`":$VMIC:$VMIN" -AC_SUBST(version_info) - -pluginsdir="${libdir}/lightmediascanner/plugins" - -AC_SUBST(pluginsdir) -AS_AC_EXPAND(PLUGINSDIR, $pluginsdir) -AC_DEFINE_UNQUOTED(PLUGINSDIR, ["$PLUGINSDIR"], [Where plugins are installed.]) - -AC_CHECK_FUNCS(realpath) - -# required modules -PKG_CHECK_MODULES(SQLITE3, [sqlite3 >= 3.3]) - -# plugins checks - -AM_CONDITIONAL(HAVE_VORBIS, false) -define([CHECK_MODULE_OGG], -[ - AC_LMS_CHECK_PKG(VORBIS, vorbis, [], [OGG=false]) -]) - -AM_CONDITIONAL(HAVE_MP4V2, false) -define([CHECK_MODULE_MP4], -[ - AC_CHECK_LIB(mp4v2, MP4Read, [], [MP4=false]) - MP4V2_LIBS="-lmp4v2" - AC_SUBST(MP4V2_LIBS) -]) - -AM_CONDITIONAL(HAVE_FLAC, false) -define([CHECK_MODULE_FLAC], -[ - AC_LMS_CHECK_PKG(FLAC, flac, [], [FLAC=false]) -]) - -# plugins declarations -AC_LMS_OPTIONAL_MODULE([dummy], true) -AC_LMS_OPTIONAL_MODULE([jpeg], true) -AC_LMS_OPTIONAL_MODULE([png], true) -AC_LMS_OPTIONAL_MODULE([video-dummy], true) -AC_LMS_OPTIONAL_MODULE([audio-dummy], true) -AC_LMS_OPTIONAL_MODULE([m3u], true) -AC_LMS_OPTIONAL_MODULE([ogg], true, [CHECK_MODULE_OGG]) -AC_LMS_OPTIONAL_MODULE([pls], true) -AC_LMS_OPTIONAL_MODULE([asf], true) -AC_LMS_OPTIONAL_MODULE([rm], true) -AC_LMS_OPTIONAL_MODULE([mp4], true, [CHECK_MODULE_MP4]) -AC_LMS_OPTIONAL_MODULE([id3], true) -AC_LMS_OPTIONAL_MODULE([flac], true, [CHECK_MODULE_FLAC]) - -AC_OUTPUT([ -lightmediascanner.pc -Makefile -m4/Makefile -src/Makefile -src/bin/Makefile -src/lib/Makefile -src/plugins/Makefile -src/plugins/dummy/Makefile -src/plugins/jpeg/Makefile -src/plugins/png/Makefile -src/plugins/video-dummy/Makefile -src/plugins/audio-dummy/Makefile -src/plugins/m3u/Makefile -src/plugins/ogg/Makefile -src/plugins/pls/Makefile -src/plugins/asf/Makefile -src/plugins/rm/Makefile -src/plugins/mp4/Makefile -src/plugins/id3/Makefile -src/plugins/flac/Makefile -]) - - -# report -txt_strip() { - echo "[$]@" | sed -e 's/^[[ \t]]*\([[^ \t]]*\)[[ \t]]*$/\1/g' -} - -MODS="" -for mod in $OPTIONAL_MODULES; do - MODS="$MODS ${COLOR_HGREEN}+$mod${COLOR_END}" -done -MODS=$(txt_strip $MODS) - -UNUSED_MODS="" -for mod in $UNUSED_OPTIONAL_MODULES; do - UNUSED_MODS="$UNUSED_MODS ${COLOR_HRED}-$mod${COLOR_END}" -done -UNUSED_MODS=$(txt_strip $UNUSED_MODS) - -cat << SUMMARY_EOF - -Summary: - * project........: $PACKAGE $VERSION - * prefix.........: $(txt_strip $prefix) - * CFLAGS.........: $(txt_strip $CFLAGS) -SUMMARY_EOF - -echo -e " * modules........: $MODS $UNUSED_MODS" diff --git a/lightmediascanner/lightmediascanner.pc.in b/lightmediascanner/lightmediascanner.pc.in deleted file mode 100644 index 9dad103..0000000 --- a/lightmediascanner/lightmediascanner.pc.in +++ /dev/null @@ -1,10 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@ - -Name: lightmediascanner -Description: Lightweight Media Scanner -Version: @VERSION@ -Libs: -L${libdir} -llightmediascanner -lsqlite3 -Cflags: -I${includedir} diff --git a/lightmediascanner/m4/Makefile.am b/lightmediascanner/m4/Makefile.am deleted file mode 100644 index c187774..0000000 --- a/lightmediascanner/m4/Makefile.am +++ /dev/null @@ -1,4 +0,0 @@ -MAINTAINERCLEANFILES = Makefile.in -EXTRA_DIST = \ - as-expand.m4 \ - ac-plugins.m4 diff --git a/lightmediascanner/m4/ac-plugins.m4 b/lightmediascanner/m4/ac-plugins.m4 deleted file mode 100644 index dd4f6a9..0000000 --- a/lightmediascanner/m4/ac-plugins.m4 +++ /dev/null @@ -1,169 +0,0 @@ -dnl _XTERM_COLORS -define([_XTERM_COLORS], -[ - # Check for XTerm and define some colors - if test "x$TERM" = "xxterm"; then - COLOR_PREF="\0033\0133" - COLOR_H="${COLOR_PREF}1m" - COLOR_HGREEN="${COLOR_PREF}1;32m" - COLOR_HRED="${COLOR_PREF}1;31m" - COLOR_GREEN="${COLOR_PREF}32m" - COLOR_RED="${COLOR_PREF}31m" - COLOR_YELLOW="${COLOR_PREF}1;33m" - COLOR_END="${COLOR_PREF}0m" - else - COLOR_H="" - COLOR_HGREEN="" - COLOR_HRED="" - COLOR_GREEN="" - COLOR_RED="" - COLOR_YELLOW="" - COLOR_END="" - fi -]) - -dnl AC_LMS_CHECK_PKG(name, lib [>= version], [action-if, [action-not]]) -dnl improved version of PKG_CHECK_MODULES, it does the same checking -dnl and defines HAVE_[name]=yes/no and also exports -dnl [name]_CFLAGS and [name]_LIBS. -dnl -dnl if action-not isn't provided, AC_MSG_ERROR will be used. -dnl -dnl Checks: -dnl lib >= version -dnl -dnl Provides: -dnl - HAVE_[name]=yes|no -dnl - [name]_CFLAGS: if HAVE_[name]=yes -dnl - [name]_LIBS: if HAVE_[name]=yes -dnl - [name]_VERSION: if HAVE_[name]=yes -dnl -AC_DEFUN([AC_LMS_CHECK_PKG], -[ -# ---------------------------------------------------------------------- -# BEGIN: Check library with pkg-config: $1 (pkg-config=$2) -# - - PKG_CHECK_MODULES([$1], [$2], - [ - HAVE_[$1]=yes - [pkg_name]=$(echo "[$2]" | cut -d\ -f1) - [$1]_VERSION=$($PKG_CONFIG --modversion $pkg_name) - AC_SUBST([$1]_VERSION) - AC_SUBST([$1]_CFLAGS) - AC_SUBST([$1]_LIBS) - ifelse([$3], , :, [$3]) - ], - [ - HAVE_[$1]=no - ifelse([$4], , AC_MSG_ERROR(you need [$2] development installed!), AC_MSG_RESULT(no); [$4]) - ]) - AM_CONDITIONAL(HAVE_[$1], test x$HAVE_[$1] = xyes) - AC_SUBST(HAVE_[$1]) - if test x$HAVE_[$1] = xyes; then - AC_DEFINE_UNQUOTED(HAVE_[$1], 1, Package [$1] ($2) found.) - fi - -# -# END: Check library with pkg-config: $1 (pkg-config=$2) -# ---------------------------------------------------------------------- -]) - -dnl AC_LMS_OPTIONAL_MODULE(name, [initial-status, [check-if-enabled]]) -dnl Defines configure argument ---[name] to enable an -dnl optional module called 'name'. -dnl -dnl If initial-status is true, then it's enabled by default and option -dnl will be called --disable-[name], otherwise it's disabled and option -dnl is --enable-[name]. -dnl -dnl If module is enabled, then check-if-enabled will be executed. This -dnl may change the contents of shell variable NAME (uppercase version of -dnl name, with underscores instead of dashed) to something different than -dnl "true" to disable module. -dnl -dnl Parameters: -dnl - name: module name to use. It will be converted to have dashes (-) -dnl instead of underscores, and will be in lowercase. -dnl - initial-status: true or false, states if module is enabled or -dnl disabled by default. -dnl - check-if-enabled: macro to be expanded inside check for enabled -dnl module. -dnl -dnl Provides: -dnl - USE_MODULE_[name]=true|false [make, shell] -dnl - USE_MODULE_[name]=1 if enabled [config.h] -dnl -AC_DEFUN([AC_LMS_OPTIONAL_MODULE], -[ -# ---------------------------------------------------------------------- -# BEGIN: Check for optional module: $1 (default: $2) -# - m4_pushdef([MODNAME], [m4_bpatsubst(m4_toupper([$1]), -, _)])dnl - m4_pushdef([modname_opt], [m4_bpatsubst(m4_tolower([$1]), _, -)]) - m4_pushdef([INITVAL], [m4_default([$2], [false])])dnl - m4_pushdef([ENABLE_HELP], AS_HELP_STRING([--enable-modname_opt], - [enable optional module modname_opt. Default is disabled.]) - )dnl - m4_pushdef([DISABLE_HELP], AS_HELP_STRING([--disable-modname_opt], - [disable optional module modname_opt. Default is enabled.]) - )dnl - m4_pushdef([HELP_STR], m4_if(INITVAL, [true], [DISABLE_HELP], [ENABLE_HELP]))dnl - m4_pushdef([NOT_INITVAL], m4_if(INITVAL, [true], [false], [true]))dnl - - USING_MODULES=1 - - MODNAME=INITVAL - AC_ARG_ENABLE(modname_opt, HELP_STR, [MODNAME=${enableval:-NOT_INITVAL}]) - if test x[$]MODNAME = xyes || test x[$]MODNAME = x1; then - MODNAME=true - fi - if test x[$]MODNAME = xno || test x[$]MODNAME = x0; then - MODNAME=false - fi - - USE_MODULE_[]MODNAME=[$]MODNAME - - _XTERM_COLORS - - # Check list for optional module $1 - if test x[$]MODNAME = xtrue; then - ifelse([$3], , , [ -echo -echo "checking optional module modname_opt:" -# BEGIN: User checks -$3 -# END: User checks -if test x[$]MODNAME = xfalse; then - echo -e "optional module modname_opt ${COLOR_HRED}failed${COLOR_END} checks." -else - echo -e "optional module modname_opt passed checks." -fi -echo -]) - - if test x[$]MODNAME = xfalse; then - echo -e "${COLOR_YELLOW}Warning:${COLOR_END} optional module ${COLOR_H}modname_opt${COLOR_END} disabled by extra checks." - fi - fi - - # Check if user checks succeeded - if test x[$]MODNAME = xtrue; then - [OPTIONAL_MODULES]="$[OPTIONAL_MODULES] modname_opt" - AC_DEFINE_UNQUOTED(USE_MODULE_[]MODNAME, 1, Use module modname_opt) - else - [UNUSED_OPTIONAL_MODULES]="$[UNUSED_OPTIONAL_MODULES] modname_opt" - fi - - AM_CONDITIONAL(USE_MODULE_[]MODNAME, test x[$]MODNAME = xtrue) - AC_SUBST(USE_MODULE_[]MODNAME) - - m4_popdef([HELP_STR])dnl - m4_popdef([DISABLE_HELP])dnl - m4_popdef([ENABLE_HELP])dnl - m4_popdef([INITVAL])dnl - m4_popdef([MODNAME]) -# -# END: Check for optional module: $1 ($2) -# ---------------------------------------------------------------------- -]) diff --git a/lightmediascanner/m4/as-expand.m4 b/lightmediascanner/m4/as-expand.m4 deleted file mode 100644 index 7b7e4a8..0000000 --- a/lightmediascanner/m4/as-expand.m4 +++ /dev/null @@ -1,43 +0,0 @@ -dnl AS_AC_EXPAND(VAR, CONFIGURE_VAR) -dnl -dnl example -dnl AS_AC_EXPAND(SYSCONFDIR, $sysconfdir) -dnl will set SYSCONFDIR to /usr/local/etc if prefix=/usr/local - -AC_DEFUN([AS_AC_EXPAND], -[ - EXP_VAR=[$1] - FROM_VAR=[$2] - - dnl first expand prefix and exec_prefix if necessary - prefix_save=$prefix - exec_prefix_save=$exec_prefix - - dnl if no prefix given, then use /usr/local, the default prefix - if test "x$prefix" = "xNONE"; then - prefix=$ac_default_prefix - fi - dnl if no exec_prefix given, then use prefix - if test "x$exec_prefix" = "xNONE"; then - exec_prefix=$prefix - fi - - full_var="$FROM_VAR" - dnl loop until it doesn't change anymore - while true; do - new_full_var="`eval echo $full_var`" - dnl if test "x$new_full_var" = "x$full_var"; then - if test "x${new_full_var:0:1}" != "x\$"; then - break; - fi - full_var=$new_full_var - done - - dnl clean up - full_var=$new_full_var - AC_SUBST([$1], "$full_var") - - dnl restore prefix and exec_prefix - prefix=$prefix_save - exec_prefix=$exec_prefix_save -]) diff --git a/lightmediascanner/src/Makefile.am b/lightmediascanner/src/Makefile.am deleted file mode 100644 index e55545e..0000000 --- a/lightmediascanner/src/Makefile.am +++ /dev/null @@ -1,3 +0,0 @@ -MAINTAINERCLEANFILES = Makefile.in - -SUBDIRS = lib bin plugins diff --git a/lightmediascanner/src/bin/.gitignore b/lightmediascanner/src/bin/.gitignore deleted file mode 100644 index 9daeafb..0000000 --- a/lightmediascanner/src/bin/.gitignore +++ /dev/null @@ -1 +0,0 @@ -test diff --git a/lightmediascanner/src/bin/Makefile.am b/lightmediascanner/src/bin/Makefile.am deleted file mode 100644 index d6b7e4f..0000000 --- a/lightmediascanner/src/bin/Makefile.am +++ /dev/null @@ -1,12 +0,0 @@ -MAINTAINERCLEANFILES = Makefile.in - -AM_CPPFLAGS = \ - -I$(top_srcdir)/src/lib - -noinst_PROGRAMS = \ - test - - -test_SOURCES = test.c -test_LDADD = $(top_builddir)/src/lib/liblightmediascanner.la @SQLITE3_LIBS@ -test_DEPENDENCIES = $(top_builddir)/src/lib/liblightmediascanner.la diff --git a/lightmediascanner/src/bin/test.c b/lightmediascanner/src/bin/test.c deleted file mode 100644 index f6ae564..0000000 --- a/lightmediascanner/src/bin/test.c +++ /dev/null @@ -1,103 +0,0 @@ -/** - * Copyright (C) 2007 by INdT - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser 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 Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * @author Gustavo Sverzut Barbieri - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include - -void -usage(const char *prgname) -{ - fprintf(stderr, - "Usage:\n" - "\t%s " - " \n" - "\n", - prgname); -} - -int -main(int argc, char *argv[]) -{ - char *db_path, *parser_name, *charset, *scan_path; - lms_t *lms; - lms_plugin_t *parser; - int commit_interval, slave_timeout; - - if (argc < 6) { - usage(argv[0]); - return 1; - } - - commit_interval = atoi(argv[1]); - slave_timeout = atoi(argv[2]); - db_path = argv[3]; - parser_name = argv[4]; - charset = argv[5]; - scan_path = argv[6]; - - lms = lms_new(db_path); - if (!lms) { - fprintf(stderr, - "ERROR: could not create light media scanner for DB \"%s\".\n", - db_path); - return -1; - } - - lms_set_commit_interval(lms, commit_interval); - lms_set_slave_timeout(lms, slave_timeout); - - parser = lms_parser_find_and_add(lms, parser_name); - if (!parser) { - fprintf(stderr, "ERROR: could not create parser \"%s\".\n", - parser_name); - lms_free(lms); - return -2; - } - - if (lms_charset_add(lms, charset) != 0) { - fprintf(stderr, "ERROR: could not add charset '%s'\n", charset); - lms_free(lms); - return -3; - } - - if (lms_check(lms, scan_path) != 0) { - fprintf(stderr, "ERROR: checking \"%s\".\n", scan_path); - lms_free(lms); - return -4; - } - - if (lms_process(lms, scan_path) != 0) { - fprintf(stderr, "ERROR: processing \"%s\".\n", scan_path); - lms_free(lms); - return -5; - } - - if (lms_free(lms) != 0) { - fprintf(stderr, "ERROR: could not close light media scanner.\n"); - return -6; - } - - return 0; -} diff --git a/lightmediascanner/src/lib/Makefile.am b/lightmediascanner/src/lib/Makefile.am deleted file mode 100644 index 6c30db5..0000000 --- a/lightmediascanner/src/lib/Makefile.am +++ /dev/null @@ -1,28 +0,0 @@ -MAINTAINERCLEANFILES = Makefile.in - -AM_CPPFLAGS = -I$(top_srcdir)/src/lib - -include_HEADERS = \ - lightmediascanner.h \ - lightmediascanner_plugin.h \ - lightmediascanner_utils.h \ - lightmediascanner_db.h \ - lightmediascanner_charset_conv.h -noinst_HEADERS = lightmediascanner_private.h lightmediascanner_db_private.h - -lib_LTLIBRARIES = liblightmediascanner.la - -liblightmediascanner_la_SOURCES = \ - lightmediascanner.c \ - lightmediascanner_utils.c \ - lightmediascanner_charset_conv.c \ - lightmediascanner_process.c \ - lightmediascanner_check.c \ - lightmediascanner_db_common.c \ - lightmediascanner_db_image.c \ - lightmediascanner_db_audio.c \ - lightmediascanner_db_video.c \ - lightmediascanner_db_playlist.c - -liblightmediascanner_la_LIBADD = -ldl @SQLITE3_LIBS@ -liblightmediascanner_la_LDFLAGS = -version-info @version_info@ diff --git a/lightmediascanner/src/lib/lightmediascanner.c b/lightmediascanner/src/lib/lightmediascanner.c deleted file mode 100644 index 108ce0d..0000000 --- a/lightmediascanner/src/lib/lightmediascanner.c +++ /dev/null @@ -1,482 +0,0 @@ -/** - * Copyright (C) 2007 by INdT - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser 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 Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * @author Gustavo Sverzut Barbieri - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include -#include - -#include "lightmediascanner.h" -#include "lightmediascanner_private.h" -#include "lightmediascanner_plugin.h" - -#define DEFAULT_SLAVE_TIMEOUT 1000 -#define DEFAULT_COMMIT_INTERVAL 100 - -static int -_parser_load(struct parser *p, const char *so_path) -{ - lms_plugin_t *(*plugin_open)(void); - char *errmsg; - - memset(p, 0, sizeof(*p)); - - p->dl_handle = dlopen(so_path, RTLD_NOW | RTLD_LOCAL); - errmsg = dlerror(); - if (errmsg) { - fprintf(stderr, "ERROR: could not dlopen() %s\n", errmsg); - return -1; - } - - plugin_open = dlsym(p->dl_handle, "lms_plugin_open"); - errmsg = dlerror(); - if (errmsg) { - fprintf(stderr, "ERROR: could not find plugin entry point %s\n", - errmsg); - return -2; - } - - p->so_path = strdup(so_path); - if (!p->so_path) { - perror("strdup"); - return -3; - } - - p->plugin = plugin_open(); - if (!p->plugin) { - fprintf(stderr, "ERROR: plugin \"%s\" failed to init.\n", so_path); - return -4; - } - - return 0; -} - -static int -_parser_unload(struct parser *p) -{ - int r; - - r = 0; - if (p->plugin) { - if (p->plugin->close(p->plugin) != 0) { - fprintf(stderr, "ERROR: plugin \"%s\" failed to deinit.\n", - p->so_path); - r -= 1; - } - } - - if (p->dl_handle) { - char *errmsg; - - dlclose(p->dl_handle); - errmsg = dlerror(); - if (errmsg) { - fprintf(stderr, "ERROR: could not dlclose() plugin \"%s\": %s\n", - errmsg, p->so_path); - r -= 1; - } - } - - if (p->so_path) - free(p->so_path); - - return r; -} - - -/*********************************************************************** - * Public API. - ***********************************************************************/ -/** - * Create new Light Media Scanner instance. - * - * @param db_path path to database file. - * @return allocated data on success or NULL on failure. - * @ingroup LMS_API - */ -lms_t * -lms_new(const char *db_path) -{ - lms_t *lms; - - lms = calloc(1, sizeof(lms_t)); - if (!lms) { - perror("calloc"); - return NULL; - } - - lms->cs_conv = lms_charset_conv_new(); - if (!lms->cs_conv) { - free(lms); - return NULL; - } - - lms->commit_interval = DEFAULT_COMMIT_INTERVAL; - lms->slave_timeout = DEFAULT_SLAVE_TIMEOUT; - lms->db_path = strdup(db_path); - if (!lms->db_path) { - perror("strdup"); - lms_charset_conv_free(lms->cs_conv); - free(lms); - return NULL; - } - - return lms; -} - -/** - * Free existing Light Media Scanner instance. - * - * @param lms previously allocated Light Media Scanner instance. - * - * @return On success 0 is returned. - * @ingroup LMS_API - */ -int -lms_free(lms_t *lms) -{ - int i; - - if (!lms) - return 0; - - if (lms->is_processing) - return -1; - - if (lms->parsers) { - for (i = 0; i < lms->n_parsers; i++) - _parser_unload(lms->parsers + i); - - free(lms->parsers); - } - - free(lms->db_path); - lms_charset_conv_free(lms->cs_conv); - free(lms); - return 0; -} - -/** - * Add parser plugin given it's shared object path. - * - * @param lms previously allocated Light Media Scanner instance. - * @param so_path path to shared object (usable by dlopen(3)). - * - * @return On success the LMS handle to plugin is returned, NULL on error. - * @ingroup LMS_API - */ -lms_plugin_t * -lms_parser_add(lms_t *lms, const char *so_path) -{ - struct parser *parser; - - if (!lms) - return NULL; - - if (!so_path) - return NULL; - - if (lms->is_processing) { - fprintf(stderr, "ERROR: do not add parsers while it's processing.\n"); - return NULL; - } - - lms->parsers = realloc(lms->parsers, - (lms->n_parsers + 1) * sizeof(struct parser)); - if (!lms->parsers) { - perror("realloc"); - return NULL; - } - - parser = lms->parsers + lms->n_parsers; - if (_parser_load(parser, so_path) != 0) { - _parser_unload(parser); - return NULL; - } - - lms->n_parsers++; - return parser->plugin; -} - -/** - * Add parser plugin given it's name. - * - * This will look at default plugin path by the file named @p name (plus - * the required shared object extension). - * - * @param lms previously allocated Light Media Scanner instance. - * @param name plugin name. - * - * @return On success the LMS handle to plugin is returned, NULL on error. - * @ingroup LMS_API - */ -lms_plugin_t * -lms_parser_find_and_add(lms_t *lms, const char *name) -{ - char so_path[PATH_MAX]; - - if (!lms) - return NULL; - if (!name) - return NULL; - - snprintf(so_path, sizeof(so_path), "%s/%s.so", PLUGINSDIR, name); - return lms_parser_add(lms, so_path); -} - -int -lms_parser_del_int(lms_t *lms, int i) -{ - struct parser *parser; - - parser = lms->parsers + i; - _parser_unload(parser); - lms->n_parsers--; - - if (lms->n_parsers == 0) { - free(lms->parsers); - lms->parsers = NULL; - return 0; - } else { - int dif; - - dif = lms->n_parsers - i; - if (dif) - lms->parsers = memmove(parser, parser + 1, - dif * sizeof(struct parser)); - - lms->parsers = realloc(lms->parsers, - lms->n_parsers * sizeof(struct parser)); - if (!lms->parsers) { - lms->n_parsers = 0; - return -1; - } - - return 0; - } -} - -/** - * Delete previously added parser, making it unavailable for future operations. - * - * @param lms previously allocated Light Media Scanner instance. - * - * @return On success 0 is returned. - * @ingroup LMS_API - */ -int -lms_parser_del(lms_t *lms, lms_plugin_t *handle) -{ - int i; - - if (!lms) - return -1; - if (!handle) - return -2; - if (!lms->parsers) - return -3; - if (lms->is_processing) { - fprintf(stderr, "ERROR: do not del parsers while it's processing.\n"); - return -4; - } - - for (i = 0; i < lms->n_parsers; i++) - if (lms->parsers[i].plugin == handle) - return lms_parser_del_int(lms, i); - - return -3; -} - -/** - * Checks if Light Media Scanner is being used in a processing operation lile - * lms_process() or lms_check(). - * - * @param lms previously allocated Light Media Scanner instance. - * - * @return 1 if it is processing, 0 if it's not, -1 on error. - * @ingroup LMS_API - */ -int -lms_is_processing(const lms_t *lms) -{ - if (!lms) { - fprintf(stderr, "ERROR: lms_is_processing(NULL)\n"); - return -1; - } - - return lms->is_processing; -} - -/** - * Get the database path given at creation time. - * - * @param lms previously allocated Light Media Scanner instance. - * - * @return path to database. - * @ingroup LMS_API - */ -const char * -lms_get_db_path(const lms_t *lms) -{ - if (!lms) { - fprintf(stderr, "ERROR: lms_get_db_path(NULL)\n"); - return NULL; - } - - return lms->db_path; -} - -/** - * Get the maximum amount of milliseconds the slave can take to serve one file. - * - * If a slave takes more than this amount of milliseconds, it will be killed - * and the scanner will continue with the next file. - * - * @param lms previously allocated Light Media Scanner instance. - * - * @return -1 on error or time in milliseconds otherwise. - * @ingroup LMS_API - */ -int -lms_get_slave_timeout(const lms_t *lms) -{ - if (!lms) { - fprintf(stderr, "ERROR: lms_get_slave_timeout(NULL)\n"); - return -1; - } - - return lms->slave_timeout; -} - -/** - * Set the maximum amount of milliseconds the slave can take to serve one file. - * - * If a slave takes more than this amount of milliseconds, it will be killed - * and the scanner will continue with the next file. - * - * @param lms previously allocated Light Media Scanner instance. - * @param ms time in milliseconds. - * @ingroup LMS_API - */ -void lms_set_slave_timeout(lms_t *lms, int ms) -{ - if (!lms) { - fprintf(stderr, "ERROR: lms_set_slave_timeout(NULL, %d)\n", ms); - return; - } - - lms->slave_timeout = ms; -} - -/** - * Get the number of files served between database transactions. - * - * This is used as an optimization to database access: doing database commits - * take some time and can slow things down too much, so you can choose to just - * commit after some number of files are processed, this is the commit_interval. - * - * @param lms previously allocated Light Media Scanner instance. - * @return (unsigned int)-1 on error, value otherwise. - * @ingroup LMS_API - */ -unsigned int -lms_get_commit_interval(const lms_t *lms) -{ - if (!lms) { - fprintf(stderr, "ERROR: lms_get_commit_interval(NULL)\n"); - return (unsigned int)-1; - } - - return lms->commit_interval; -} - -/** - * Set the number of files served between database transactions. - * - * This is used as an optimization to database access: doing database commits - * take some time and can slow things down too much, so you can choose to just - * commit after @p transactions files are processed. - * - * @param lms previously allocated Light Media Scanner instance. - * @param transactions number of files (transactions) to process between - * commits. - * @ingroup LMS_API - */ -void -lms_set_commit_interval(lms_t *lms, unsigned int transactions) -{ - if (!lms) { - fprintf(stderr, "ERROR: lms_set_commit_interval(NULL, %u)\n", - transactions); - return; - } - - lms->commit_interval = transactions; -} - -/** - * Register a new charset encoding to be used. - * - * All database text strings are in UTF-8, so one needs to register new - * encodings in order to convert to it. - * - * @param lms previously allocated Light Media Scanner instance. - * @param charset charset name as understood by iconv_open(3). - * - * @return On success 0 is returned. - * @ingroup LMS_API - */ -int -lms_charset_add(lms_t *lms, const char *charset) -{ - if (!lms) { - fprintf(stderr, "ERROR: lms_charset_add(NULL)\n"); - return -1; - } - - return lms_charset_conv_add(lms->cs_conv, charset); -} - -/** - * Forget about registered charset encoding. - * - * All database text strings are in UTF-8, so one needs to register new - * encodings in order to convert to it. - * - * @param lms previously allocated Light Media Scanner instance. - * @param charset charset name as understood by iconv_open(3). - * - * @return On success 0 is returned. - * @ingroup LMS_API - */ -int -lms_charset_del(lms_t *lms, const char *charset) -{ - if (!lms) { - fprintf(stderr, "ERROR: lms_charset_del(NULL)\n"); - return -1; - } - - return lms_charset_conv_del(lms->cs_conv, charset); -} diff --git a/lightmediascanner/src/lib/lightmediascanner.h b/lightmediascanner/src/lib/lightmediascanner.h deleted file mode 100644 index bd11060..0000000 --- a/lightmediascanner/src/lib/lightmediascanner.h +++ /dev/null @@ -1,186 +0,0 @@ -/** - * Copyright (C) 2007 by INdT - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser 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 Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * @author Gustavo Sverzut Barbieri - */ - -/** - * @mainpage - * - * The architecture is based on 2 processes that cooperate, the first is - * the driver, that controls the behavior of the worker/slave process, - * that does the hard work. This slave process is meant to make the - * software more robust since some parser libraries and even - * user-provided media is not reliable, so if for some reason the worker - * process freezes, it's killed and then restarted with the next item. - * - * User API is quite simple, with means to add new charsets to be tried - * and new parsers to handle media. The most important functions are (see - * lightmediascanner.h): - * - * - int lms_process(lms_t *lms, const char *top_path) - * - int lms_check(lms_t *lms, const char *top_path) - * - * @note The whole library follows libC standard of "0 (zero) means success", - * unless explicitly stated (usually boolean queries where no error is - * possible/interesting). - * - * The first will walk all the files and children directories of - * top_path, check if files are handled by some parser and if they're, - * they'll be parsed and registered in the data base. - * - * The second will get all already registered media in data base that is - * located at top_path and see if they're still up to date, deleted or - * changed. If they were deleted, a flag is set on data base with current - * time, so it can be expired at some point. If they were marked as - * deleted, but are not present again, check if the state is still valid - * (mtime, size), so we can avoid re-parse of removable media. If the - * file was present and is still present, just check if its properties - * (mtime, size) are still the same, if not trigger re-parse. - * - * Parsers are handled as shared object plugins, they can be added - * without modification to the core, see the plugins API later in this - * document. Since the core have no control over plugins, they can - * register data as they want, but since some utilities are provided, we - * expect that the given data base tables are used: - * - * - @b files: known files. - * - id: identification inside LMS/DB. - * - path: file path. - * - mtime: modification time, in seconds from UNIX epoch. - * - dtime: modification time, in seconds from UNIX epoch. - * - size: in bytes. - * - @b audios: audio files. - * - id: same as files.id - * - title: audio title. - * - album_id: same as audio_albums.id. - * - genre_id: same as audio_genres.id. - * - trackno: track number. - * - rating: rating. - * - playcnt: play count. - * - @b audio_artists: audio artists. - * - id: identification inside LMS/DB. - * - name: artist name. - * - @b audio_albums: audio albums. - * - id: identification inside LMS/DB. - * - artist_id: same as audio_artists.id. - * - name: album name. - * - @b audio_genres: audio genres. - * - id: identification inside LMS/DB. - * - name: genre name. - * - @b playlists: playlists. - * - id: identification inside LMS/DB. - * - title: playlists title. - * - n_entries: number of entries in this playlist. - * - @b images: image files. - * - id: identification inside LMS/DB. - * - title: image title. - * - artist: image creator or artirst or photographer or ... - * - date: image taken date or creation date or ... - * - width: image width. - * - height: image height. - * - orientation: image orientation. - * - gps_lat: GPS latitude. - * - gps_long: GPS longitude. - * - gps_alt: GPS altitude. - * - @b videos: video files. - * - id: identification inside LMS/DB. - * - title: video title. - * - artist: video artist or creator or producer or ... - */ - - -#ifndef _LIGHTMEDIASCANNER_H_ -#define _LIGHTMEDIASCANNER_H_ 1 - -#ifdef API -#undef API -#endif - -#ifdef __GNUC__ -# if __GNUC__ >= 4 -# define API __attribute__ ((visibility("default"))) -# define GNUC_NULL_TERMINATED __attribute__((__sentinel__)) -# else -# define API -# define GNUC_NULL_TERMINATED -# endif -# if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96) -# define GNUC_PURE __attribute__((__pure__)) -# define GNUC_MALLOC __attribute__((__malloc__)) -# define GNUC_CONST __attribute__((__const__)) -# define GNUC_UNUSED __attribute__((__unused__)) -# else -# define GNUC_PURE -# define GNUC_MALLOC -# define GNUC_NORETURN -# define GNUC_CONST -# define GNUC_UNUSED -# endif -# if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) -# define GNUC_WARN_UNUSED_RESULT __attribute__((warn_unused_result)) -# define GNUC_NON_NULL(...) __attribute__((nonnull(__VA_ARGS__))) -# else -# define GNUC_WARN_UNUSED_RESULT -# define GNUC_NON_NULL(...) -# endif -#else -# define API -# define GNUC_NULL_TERMINATED -# define GNUC_PURE -# define GNUC_MALLOC -# define GNUC_CONST -# define GNUC_UNUSED -# define GNUC_WARN_UNUSED_RESULT -# define GNUC_NON_NULL(...) -#endif - -#ifdef __cplusplus -extern "C" { -#endif - /** - * @defgroup LMS_API User-API - * - * Functions for library users. - */ - - typedef struct lms lms_t; - typedef struct lms_plugin lms_plugin_t; - - API lms_t *lms_new(const char *db_path) GNUC_MALLOC GNUC_WARN_UNUSED_RESULT; - API int lms_free(lms_t *lms) GNUC_NON_NULL(1); - API int lms_process(lms_t *lms, const char *top_path) GNUC_NON_NULL(1, 2); - API int lms_check(lms_t *lms, const char *top_path) GNUC_NON_NULL(1, 2); - API void lms_stop_processing(lms_t *lms) GNUC_NON_NULL(1); - API const char *lms_get_db_path(const lms_t *lms) GNUC_NON_NULL(1); - API int lms_is_processing(const lms_t *lms) GNUC_PURE GNUC_NON_NULL(1); - API int lms_get_slave_timeout(const lms_t *lms) GNUC_NON_NULL(1); - API void lms_set_slave_timeout(lms_t *lms, int ms) GNUC_NON_NULL(1); - API unsigned int lms_get_commit_interval(const lms_t *lms) GNUC_NON_NULL(1); - API void lms_set_commit_interval(lms_t *lms, unsigned int transactions) GNUC_NON_NULL(1); - - API lms_plugin_t *lms_parser_add(lms_t *lms, const char *so_path) GNUC_NON_NULL(1, 2); - API lms_plugin_t *lms_parser_find_and_add(lms_t *lms, const char *name) GNUC_NON_NULL(1, 2); - API int lms_parser_del(lms_t *lms, lms_plugin_t *handle) GNUC_NON_NULL(1, 2); - - API int lms_charset_add(lms_t *lms, const char *charset) GNUC_NON_NULL(1, 2); - API int lms_charset_del(lms_t *lms, const char *charset) GNUC_NON_NULL(1, 2); - -#ifdef __cplusplus -} -#endif -#endif /* _LIGHTMEDIASCANNER_H_ */ diff --git a/lightmediascanner/src/lib/lightmediascanner_charset_conv.c b/lightmediascanner/src/lib/lightmediascanner_charset_conv.c deleted file mode 100644 index 370b2eb..0000000 --- a/lightmediascanner/src/lib/lightmediascanner_charset_conv.c +++ /dev/null @@ -1,460 +0,0 @@ -/** - * Copyright (C) 2007 by INdT - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser 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 Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * @author Gustavo Sverzut Barbieri - */ - -#include "lightmediascanner_charset_conv.h" -#include -#include -#include -#include -#include -#include - -struct lms_charset_conv { - iconv_t check; - iconv_t fallback; - unsigned int size; - iconv_t *convs; - char **names; -}; - -/** - * Create a new charset conversion tool controlling its behavior. - * - * Conversion tool will try to convert provided strings to UTF-8, just need - * to register known charsets with lms_charset_conv_add() and then call - * lms_charset_conv(). - * - * @return newly allocated conversion tool or NULL on error. - */ -lms_charset_conv_t * -lms_charset_conv_new_full(int use_check, int use_fallback) -{ - lms_charset_conv_t *lcc; - - lcc = malloc(sizeof(*lcc)); - if (!lcc) { - perror("malloc"); - return NULL; - } - - if (!use_check) - lcc->check = (iconv_t)-1; - else { - lcc->check = iconv_open("UTF-8", "UTF-8"); - if (lcc->check == (iconv_t)-1) { - perror("ERROR: could not create conversion checker"); - goto error_check; - } - } - - if (!use_fallback) - lcc->fallback = (iconv_t)-1; - else { - lcc->fallback = iconv_open("UTF-8//IGNORE", "UTF-8"); - if (lcc->fallback == (iconv_t)-1) { - perror("ERROR: could not create conversion fallback"); - goto error_fallback; - } - } - - lcc->size = 0; - lcc->convs = NULL; - lcc->names = NULL; - return lcc; - - error_fallback: - if (lcc->check != (iconv_t)-1) - iconv_close(lcc->check); - error_check: - free(lcc); - - return NULL; -} - -/** - * Create a new charset conversion tool. - * - * Conversion tool will try to convert provided strings to UTF-8, just need - * to register known charsets with lms_charset_conv_add() and then call - * lms_charset_conv(). - * - * @return newly allocated conversion tool or NULL on error. - */ -lms_charset_conv_t * -lms_charset_conv_new(void) -{ - return lms_charset_conv_new_full(1, 1); -} - -/** - * Free existing charset conversion tool. - * - * @param lcc existing Light Media Scanner charset conversion. - */ -void -lms_charset_conv_free(lms_charset_conv_t *lcc) -{ - int i; - - if (!lcc) - return; - - if (lcc->check != (iconv_t)-1) - iconv_close(lcc->check); - if (lcc->fallback != (iconv_t)-1) - iconv_close(lcc->fallback); - - for (i = 0; i < lcc->size; i++) { - iconv_close(lcc->convs[i]); - free(lcc->names[i]); - } - - if (lcc->convs) - free(lcc->convs); - if (lcc->names) - free(lcc->names); - free(lcc); -} - -/** - * Register new charset to conversion tool. - * - * @param lcc existing Light Media Scanner charset conversion. - * @param charset charset name as understood by iconv_open(3). - * - * @return On success 0 is returned. - */ -int -lms_charset_conv_add(lms_charset_conv_t *lcc, const char *charset) -{ - iconv_t cd, *convs; - char **names; - int idx, ns; - - if (!lcc) - return -1; - - if (!charset) - return -2; - - cd = iconv_open("UTF-8", charset); - if (cd == (iconv_t)-1) { - fprintf(stderr, "ERROR: could not add conversion charset '%s': %s\n", - charset, strerror(errno)); - return -3; - } - - idx = lcc->size; - ns = lcc->size + 1; - - convs = realloc(lcc->convs, ns * sizeof(*convs)); - if (!convs) - goto realloc_error; - lcc->convs = convs; - lcc->convs[idx] = cd; - - names = realloc(lcc->names, ns * sizeof(*names)); - if (!names) - goto realloc_error; - lcc->names = names; - lcc->names[idx] = strdup(charset); - if (!lcc->names[idx]) - goto realloc_error; - - lcc->size = ns; - return 0; - - realloc_error: - perror("realloc"); - iconv_close(cd); - return -4; -} - -static int -_find(const lms_charset_conv_t *lcc, const char *charset) -{ - int i; - - for (i = 0; i < lcc->size; i++) - if (strcmp(lcc->names[i], charset) == 0) - return i; - - return -1; -} - -/** - * Forget about previously registered charset in conversion tool. - * - * @param lcc existing Light Media Scanner charset conversion. - * @param charset charset name. - * - * @return On success 0 is returned. - */ -int -lms_charset_conv_del(lms_charset_conv_t *lcc, const char *charset) -{ - iconv_t *convs; - char **names; - int idx; - - if (!lcc) - return -1; - - if (!charset) - return -2; - - idx = _find(lcc, charset); - if (idx < 0) { - fprintf(stderr, "ERROR: could not find charset '%s'\n", charset); - return -3; - } - - iconv_close(lcc->convs[idx]); - free(lcc->names[idx]); - - lcc->size--; - for (; idx < lcc->size; idx++) { - lcc->convs[idx] = lcc->convs[idx + 1]; - lcc->names[idx] = lcc->names[idx + 1]; - } - - convs = realloc(lcc->convs, lcc->size * sizeof(*convs)); - if (convs) - lcc->convs = convs; - else - perror("could not realloc 'convs'"); - - names = realloc(lcc->names, lcc->size * sizeof(*names)); - if (names) - lcc->names = names; - else - perror("could not realloc 'names'"); - - return 0; -} - -static int -_check(lms_charset_conv_t *lcc, const char *istr, unsigned int ilen, char *ostr, unsigned int olen) -{ - char *inbuf, *outbuf; - size_t r, inlen, outlen; - - if (lcc->check == (iconv_t)-1) - return -1; - - inbuf = (char *)istr; - inlen = ilen; - outbuf = ostr; - outlen = olen; - - iconv(lcc->check, NULL, NULL, NULL, NULL); - r = iconv(lcc->check, &inbuf, &inlen, &outbuf, &outlen); - if (r == (size_t)-1) - return -1; - else - return 0; -} - -static int -_conv(iconv_t cd, char **p_str, unsigned int *p_len, char *ostr, unsigned int olen) -{ - char *inbuf, *outbuf; - size_t r, inlen, outlen; - - inbuf = *p_str; - inlen = *p_len; - outbuf = ostr; - outlen = olen; - - iconv(cd, NULL, NULL, NULL, NULL); - r = iconv(cd, &inbuf, &inlen, &outbuf, &outlen); - if (r == (size_t)-1) - return -1; - - *p_len = olen - outlen; - free(*p_str); - *p_str = ostr; - - outbuf = realloc(*p_str, *p_len + 1); - if (!outbuf) - perror("realloc"); - else - *p_str = outbuf; - - (*p_str)[*p_len] = '\0'; - - return 0; -} - -static void -_fix_non_ascii(char *s, int len) -{ - for (; len > 0; len--, s++) - if (!isprint(*s)) - *s = '?'; -} - -/** - * If required, do charset conversion to UTF-8. - * - * @param lcc existing Light Media Scanner charset conversion. - * @param p_str string to be converted. - * @param p_len string size. - * - * @note the check for string being already UTF-8 is not reliable, - * some cases might show false positives (UTF-16 is considered UTF-8). - * @see lms_charset_conv_check() - * - * @return On success 0 is returned. - */ -int -lms_charset_conv(lms_charset_conv_t *lcc, char **p_str, unsigned int *p_len) -{ - char *outstr; - int i, outlen; - - if (!lcc) - return -1; - if (!p_str) - return -2; - if (!p_len) - return -3; - if (!*p_str || !*p_len) - return 0; - - outlen = 2 * *p_len; - outstr = malloc(outlen + 1); - if (!outstr) { - perror("malloc"); - return -4; - } - - if (_check(lcc, *p_str, *p_len, outstr, outlen) == 0) { - free(outstr); - return 0; - } - - for (i = 0; i < lcc->size; i++) - if (_conv(lcc->convs[i], p_str, p_len, outstr, outlen) == 0) - return 0; - - if (lcc->fallback == (iconv_t)-1) - return -5; - - fprintf(stderr, - "WARNING: could not convert '%*s' to any charset, use fallback\n", - *p_len, *p_str); - i = _conv(lcc->fallback, p_str, p_len, outstr, outlen); - if (i < 0) { - _fix_non_ascii(*p_str, *p_len); - free(outstr); - } - return i; -} - -/** - * Forcefully do charset conversion to UTF-8. - * - * @param lcc existing Light Media Scanner charset conversion. - * @param p_str string to be converted. - * @param p_len string size. - * - * @note This function does not check for the string being in UTF-8 before - * doing the conversion, use it if you are sure about the charset. - * In this case you'll usually have just one charset added. - * - * @return On success 0 is returned. - */ -int -lms_charset_conv_force(lms_charset_conv_t *lcc, char **p_str, unsigned int *p_len) -{ - char *outstr; - int i, outlen; - - if (!lcc) - return -1; - if (!p_str) - return -2; - if (!p_len) - return -3; - if (!*p_str || !*p_len) - return 0; - - outlen = 2 * *p_len; - outstr = malloc(outlen + 1); - if (!outstr) { - perror("malloc"); - return -4; - } - - for (i = 0; i < lcc->size; i++) - if (_conv(lcc->convs[i], p_str, p_len, outstr, outlen) == 0) - return 0; - - if (lcc->fallback == (iconv_t)-1) - return -5; - - fprintf(stderr, - "WARNING: could not convert '%*s' to any charset, use fallback\n", - *p_len, *p_str); - i = _conv(lcc->fallback, p_str, p_len, outstr, outlen); - if (i < 0) { - _fix_non_ascii(*p_str, *p_len); - free(outstr); - } - return i; -} - -/** - * Check if strings is not UTF-8 and conversion is required. - * - * @param lcc existing Light Media Scanner charset conversion. - * @param str string to be analysed. - * @param len string size. - * - * @note current implementation is not reliable, it tries to convert from - * UTF-8 to UTF-8. Some cases, like ISO-8859-1 will work, but some like - * UTF-16 to UTF-8 will say it's already in the correct charset, - * even if it's not. - * - * @return 0 if string is already UTF-8. - */ -int -lms_charset_conv_check(lms_charset_conv_t *lcc, const char *str, unsigned int len) -{ - char *outstr; - int r, outlen; - - if (!lcc) - return -1; - if (!str || !len) - return 0; - - outlen = 2 * len; - outstr = malloc(outlen); - if (!outstr) { - perror("malloc"); - return -2; - } - - r = _check(lcc, str, len, outstr, outlen); - free(outstr); - return r; -} diff --git a/lightmediascanner/src/lib/lightmediascanner_charset_conv.h b/lightmediascanner/src/lib/lightmediascanner_charset_conv.h deleted file mode 100644 index 09af11b..0000000 --- a/lightmediascanner/src/lib/lightmediascanner_charset_conv.h +++ /dev/null @@ -1,90 +0,0 @@ -/** - * Copyright (C) 2007 by INdT - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser 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 Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * @author Gustavo Sverzut Barbieri - */ - -#ifndef _LIGHTMEDIASCANNER_CHARSET_CONV_H_ -#define _LIGHTMEDIASCANNER_CHARSET_CONV_H_ 1 - -#ifdef GNUC_MALLOC -#undef GNUC_MALLOC -#endif -#ifdef GNUC_WARN_UNUSED_RESULT -#undef GNUC_WARN_UNUSED_RESULT -#endif -#ifdef GNUC_NON_NULL -#undef GNUC_NON_NULL -#endif -#ifdef API -#undef API -#endif - -#ifdef __GNUC__ -# if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96) -# define GNUC_MALLOC __attribute__((__malloc__)) -# else -# define GNUC_MALLOC -# endif -# if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) -# define GNUC_WARN_UNUSED_RESULT __attribute__((warn_unused_result)) -# define GNUC_NON_NULL(...) __attribute__((nonnull(__VA_ARGS__))) -# else -# define GNUC_WARN_UNUSED_RESULT -# define GNUC_NON_NULL(...) -# endif -# if __GNUC__ >= 4 -# define API __attribute__ ((visibility("default"))) -# else -# define API -# endif -#else -# define GNUC_MALLOC -# define GNUC_WARN_UNUSED_RESULT -# define GNUC_NON_NULL(...) -# define API -#endif - -#ifdef __cplusplus -extern "C" { -#endif -/** - * @defgroup LMS_CHARSET Charset Conversion - * - * Utilities to convert strings to UTF-8, the charset used in database. - * @{ - */ - - typedef struct lms_charset_conv lms_charset_conv_t; - - API lms_charset_conv_t *lms_charset_conv_new_full(int use_check, int use_fallback) GNUC_MALLOC GNUC_WARN_UNUSED_RESULT; - API lms_charset_conv_t *lms_charset_conv_new(void) GNUC_MALLOC GNUC_WARN_UNUSED_RESULT; - API void lms_charset_conv_free(lms_charset_conv_t *lcc) GNUC_NON_NULL(1); - API int lms_charset_conv_add(lms_charset_conv_t *lcc, const char *charset) GNUC_NON_NULL(1, 2); - API int lms_charset_conv_del(lms_charset_conv_t *lcc, const char *charset) GNUC_NON_NULL(1, 2); - - API int lms_charset_conv(lms_charset_conv_t *lcc, char **p_str, unsigned int *p_len) GNUC_NON_NULL(1, 2, 3); - API int lms_charset_conv_force(lms_charset_conv_t *lcc, char **p_str, unsigned int *p_len) GNUC_NON_NULL(1, 2, 3); - API int lms_charset_conv_check(lms_charset_conv_t *lcc, const char *str, unsigned int len) GNUC_NON_NULL(1, 2); - -/** - * @} - */ -#ifdef __cplusplus -} -#endif -#endif /* _LIGHTMEDIASCANNER_CHARSET_CONV_H_ */ diff --git a/lightmediascanner/src/lib/lightmediascanner_check.c b/lightmediascanner/src/lib/lightmediascanner_check.c deleted file mode 100644 index 1865c45..0000000 --- a/lightmediascanner/src/lib/lightmediascanner_check.c +++ /dev/null @@ -1,671 +0,0 @@ -/** - * Copyright (C) 2007 by INdT - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser 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 Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * @author Gustavo Sverzut Barbieri - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#define _GNU_SOURCE -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "lightmediascanner.h" -#include "lightmediascanner_private.h" -#include "lightmediascanner_db_private.h" - -struct master_db { - sqlite3 *handle; - sqlite3_stmt *get_files; -}; - -struct slave_db { - sqlite3 *handle; - sqlite3_stmt *transaction_begin; - sqlite3_stmt *transaction_commit; - sqlite3_stmt *delete_file_info; - sqlite3_stmt *update_file_info; -}; - - -/*********************************************************************** - * Master-Slave communication. - ***********************************************************************/ - -struct comm_finfo { - int path_len; - int base; - int64_t id; - time_t mtime; - time_t dtime; - size_t size; - unsigned int flags; -#define COMM_FINFO_FLAG_OUTDATED 1 -}; - -static int -_master_send_file(const struct fds *master, const struct lms_file_info finfo, unsigned int flags) -{ - struct comm_finfo ci; - - ci.path_len = finfo.path_len; - ci.base = finfo.base; - ci.id = finfo.id; - ci.mtime = finfo.mtime; - ci.dtime = finfo.dtime; - ci.size = finfo.size; - ci.flags = flags; - - if (write(master->w, &ci, sizeof(ci)) < 0) { - perror("write"); - return -1; - } - - if (write(master->w, finfo.path, finfo.path_len) < 0) { - perror("write"); - return -1; - } - - return 0; -} - -static int -_master_send_finish(const struct fds *master) -{ - struct comm_finfo ci = {-1, -1, -1, -1, -1, -1, 0}; - - if (write(master->w, &ci, sizeof(ci)) < 0) { - perror("write"); - return -1; - } - - return 0; -} - -static int -_master_recv_reply(const struct fds *master, struct pollfd *pfd, int *reply, int timeout) -{ - int r; - - r = poll(pfd, 1, timeout); - if (r < 0) { - perror("poll"); - return -1; - } - - if (r == 0) - return 1; - - if (read(master->r, reply, sizeof(*reply)) != sizeof(*reply)) { - perror("read"); - return -2; - } - - return 0; -} - -static int -_slave_send_reply(const struct fds *slave, int reply) -{ - if (write(slave->w, &reply, sizeof(reply)) == 0) { - perror("write"); - return -1; - } - return 0; -} - -static int -_slave_recv_file(const struct fds *slave, struct lms_file_info *finfo, unsigned int *flags) -{ - struct comm_finfo ci; - static char path[PATH_SIZE + 1]; - int r; - - r = read(slave->r, &ci, sizeof(ci)); - if (r != sizeof(ci)) { - perror("read"); - return -1; - } - - finfo->path_len = ci.path_len; - finfo->base = ci.base; - finfo->id = ci.id; - finfo->mtime = ci.mtime; - finfo->dtime = ci.dtime; - finfo->size = ci.size; - finfo->path = NULL; - *flags = ci.flags; - - if (ci.path_len == -1) - return 0; - - if (ci.path_len > PATH_SIZE) { - fprintf(stderr, "ERROR: path too long (%d/%d)\n", - ci.path_len, PATH_SIZE); - return -2; - } - - r = read(slave->r, path, ci.path_len); - if (r != ci.path_len) { - fprintf(stderr, "ERROR: could not read whole path %d/%d\n", - r, ci.path_len); - return -3; - } - - path[ci.path_len] = 0; - finfo->path = path; - return 0; -} - - -/*********************************************************************** - * Slave-side. - ***********************************************************************/ - -static int -_slave_db_compile_all_stmts(struct slave_db *db) -{ - sqlite3 *handle; - - handle = db->handle; - - db->transaction_begin = lms_db_compile_stmt_begin_transaction(handle); - if (!db->transaction_begin) - return -1; - - db->transaction_commit = lms_db_compile_stmt_end_transaction(handle); - if (!db->transaction_commit) - return -2; - - db->delete_file_info = lms_db_compile_stmt_delete_file_info(handle); - if (!db->delete_file_info) - return -3; - - db->update_file_info = lms_db_compile_stmt_update_file_info(handle); - if (!db->update_file_info) - return -4; - - return 0; -} - -static struct slave_db * -_slave_db_open(const char *db_path) -{ - struct slave_db *db; - - db = calloc(1, sizeof(*db)); - if (!db) { - perror("calloc"); - return NULL; - } - - if (sqlite3_open(db_path, &db->handle) != SQLITE_OK) { - fprintf(stderr, "ERROR: could not open DB \"%s\": %s\n", - db_path, sqlite3_errmsg(db->handle)); - goto error; - } - - return db; - - error: - sqlite3_close(db->handle); - free(db); - return NULL; -} - -static int -_slave_db_close(struct slave_db *db) -{ - if (db->transaction_begin) - lms_db_finalize_stmt(db->transaction_begin, "transaction_begin"); - - if (db->transaction_commit) - lms_db_finalize_stmt(db->transaction_commit, "transaction_commit"); - - if (db->delete_file_info) - lms_db_finalize_stmt(db->delete_file_info, "delete_file_info"); - - if (db->update_file_info) - lms_db_finalize_stmt(db->update_file_info, "update_file_info"); - - if (sqlite3_close(db->handle) != SQLITE_OK) { - fprintf(stderr, "ERROR: clould not close DB (slave): %s\n", - sqlite3_errmsg(db->handle)); - return -1; - } - free(db); - - return 0; -} - -static int -_init_sync_send(struct fds *fds) -{ - return _slave_send_reply(fds, 0); -} - -static int -_slave_work_int(lms_t *lms, struct fds *fds, struct slave_db *db) -{ - struct lms_file_info finfo; - void **parser_match; - unsigned int counter, flags; - int r; - - parser_match = malloc(lms->n_parsers * sizeof(*parser_match)); - if (!parser_match) { - perror("malloc"); - return -6; - } - - _init_sync_send(fds); - - counter = 0; - lms_db_begin_transaction(db->transaction_begin); - - while (((r = _slave_recv_file(fds, &finfo, &flags)) == 0) && - finfo.path_len > 0) { - r = lms_db_update_file_info(db->update_file_info, &finfo); - if (r < 0) - fprintf(stderr, "ERROR: could not update path in DB\n"); - else if (flags & COMM_FINFO_FLAG_OUTDATED) { - int used; - - used = lms_parsers_check_using(lms, parser_match, &finfo); - if (!used) - r = 0; - else { - r = lms_parsers_run(lms, db->handle, parser_match, &finfo); - if (r < 0) { - fprintf(stderr, "ERROR: pid=%d failed to parse \"%s\".\n", - getpid(), finfo.path); - lms_db_delete_file_info(db->delete_file_info, &finfo); - } - } - } - - _slave_send_reply(fds, r); - counter++; - if (counter > lms->commit_interval) { - lms_db_end_transaction(db->transaction_commit); - lms_db_begin_transaction(db->transaction_begin); - counter = 0; - } - } - - free(parser_match); - lms_db_end_transaction(db->transaction_commit); - - return r; -} - -static int -_slave_work(lms_t *lms, struct fds *fds) -{ - struct slave_db *db; - int r; - - db = _slave_db_open(lms->db_path); - if (!db) - return -1; - - if (lms_parsers_setup(lms, db->handle) != 0) { - fprintf(stderr, "ERROR: could not setup parsers.\n"); - r = -2; - goto end; - } - - if (_slave_db_compile_all_stmts(db) != 0) { - fprintf(stderr, "ERROR: could not compile statements.\n"); - r = -3; - goto end; - } - - if (lms_parsers_start(lms, db->handle) != 0) { - fprintf(stderr, "ERROR: could not start parsers.\n"); - r = -4; - goto end; - } - if (lms->n_parsers < 1) { - fprintf(stderr, "ERROR: no parser could be started, exit.\n"); - r = -5; - goto end; - } - - r = _slave_work_int(lms, fds, db); - - end: - lms_parsers_finish(lms, db->handle); - _slave_db_close(db); - _init_sync_send(fds); - - return r; -} - - -/*********************************************************************** - * Master-side. - ***********************************************************************/ - -static int -_master_db_compile_all_stmts(struct master_db *db) -{ - sqlite3 *handle; - - handle = db->handle; - - db->get_files = lms_db_compile_stmt_get_files(handle); - if (!db->get_files) - return -1; - - return 0; -} - -static struct master_db * -_master_db_open(const char *db_path) -{ - struct master_db *db; - - db = calloc(1, sizeof(*db)); - if (!db) { - perror("calloc"); - return NULL; - } - - if (sqlite3_open(db_path, &db->handle) != SQLITE_OK) { - fprintf(stderr, "ERROR: could not open DB \"%s\": %s\n", - db_path, sqlite3_errmsg(db->handle)); - goto error; - } - - if (lms_db_create_core_tables_if_required(db->handle) != 0) { - fprintf(stderr, "ERROR: could not setup tables and indexes.\n"); - goto error; - } - - if (_master_db_compile_all_stmts(db) != 0) { - fprintf(stderr, "ERROR: could not compile statements.\n"); - goto error; - } - - return db; - - error: - sqlite3_close(db->handle); - free(db); - return NULL; -} - -static int -_master_db_close(struct master_db *db) -{ - if (db->get_files) - lms_db_finalize_stmt(db->get_files, "get_files"); - - if (sqlite3_close(db->handle) != SQLITE_OK) { - fprintf(stderr, "ERROR: clould not close DB (master): %s\n", - sqlite3_errmsg(db->handle)); - return -1; - } - free(db); - - return 0; -} - -static void -_calc_base(struct lms_file_info *finfo) -{ - int i; - - for (i = finfo->path_len - 1; i >= 0; i--) - if (finfo->path[i] == '/') { - finfo->base = i; - return; - } -} - -static inline void -_update_finfo_from_stmt(struct lms_file_info *finfo, sqlite3_stmt *stmt) -{ - finfo->id = sqlite3_column_int64(stmt, 0); - finfo->path = sqlite3_column_blob(stmt, 1); - finfo->path_len = sqlite3_column_bytes(stmt, 1); - finfo->base = 0; - finfo->mtime = sqlite3_column_int(stmt, 2); - finfo->dtime = sqlite3_column_int(stmt, 3); - finfo->size = sqlite3_column_int(stmt, 4); -} - -static inline void -_update_finfo_from_stat(struct lms_file_info *finfo, const struct stat *st) -{ - finfo->mtime = st->st_mtime; - finfo->size = st->st_size; - finfo->dtime = 0; -} - -static int -_check_row(struct master_db *db, struct pinfo *pinfo) -{ - struct lms_file_info finfo; - struct stat st; - unsigned int flags; - int r, reply; - - _update_finfo_from_stmt(&finfo, db->get_files); - - flags = 0; - if (stat(finfo.path, &st) == 0) { - if (st.st_mtime == finfo.mtime && st.st_size == finfo.size) { - if (finfo.dtime == 0) - return 0; - else - finfo.dtime = 0; - } else { - _update_finfo_from_stat(&finfo, &st); - flags |= COMM_FINFO_FLAG_OUTDATED; - } - } else { - if (finfo.dtime) - return 0; - else - finfo.dtime = time(NULL); - } - - _calc_base(&finfo); - - if (_master_send_file(&pinfo->master, finfo, flags) != 0) - return -1; - - r = _master_recv_reply(&pinfo->master, &pinfo->poll, &reply, - pinfo->lms->slave_timeout); - if (r < 0) - return -2; - else if (r == 1) { - fprintf(stderr, "ERROR: slave took too long, restart %d\n", - pinfo->child); - if (lms_restart_slave(pinfo, _slave_work) != 0) - return -3; - return 1; - } else { - if (reply < 0) { - /* XXX callback library users to inform error. */ - fprintf(stderr, "ERROR: pid=%d failed to parse \"%s\".\n", - getpid(), finfo.path); - return (-reply) << 8; - } else - return reply; - } -} - -static int -_init_sync_wait(struct pinfo *pinfo, int restart) -{ - int r, reply; - - do { - r = _master_recv_reply(&pinfo->master, &pinfo->poll, &reply, - pinfo->lms->slave_timeout); - if (r < 0) - return -1; - else if (r == 1 && restart) { - fprintf(stderr, "ERROR: slave took too long, restart %d\n", - pinfo->child); - if (lms_restart_slave(pinfo, _slave_work) != 0) - return -2; - } - } while (r != 0 && restart); - - return r; -} - -static int -_master_dummy_send_finish(const struct fds *master) -{ - return 0; -} - -static int -_check(struct pinfo *pinfo, int len, char *path) -{ - char query[PATH_SIZE + 2]; - struct master_db *db; - lms_t *lms; - int r, ret; - - db = _master_db_open(pinfo->lms->db_path); - if (!db) - return -1; - - memcpy(query, path, len); - query[len] = '%'; - query[len + 1] = '\0'; - ret = lms_db_get_files(db->get_files, query, len + 1); - if (ret != 0) - goto end; - - if (lms_create_slave(pinfo, _slave_work) != 0) { - ret = -2; - goto end; - } - _init_sync_wait(pinfo, 1); - lms = pinfo->lms; - - do { - r = sqlite3_step(db->get_files); - if (r == SQLITE_ROW) { - if (_check_row(db, pinfo) < 0) { - fprintf(stderr, "ERROR: could not check row.\n"); - ret = -1; - goto finish_slave; - } - } else if (r != SQLITE_DONE) { - fprintf(stderr, "ERROR: could not begin transaction: %s\n", - sqlite3_errmsg(db->handle)); - ret = -2; - goto finish_slave; - } - } while (r != SQLITE_DONE && !lms->stop_processing); - ret = 0; - - finish_slave: - _master_send_finish(&pinfo->master); - _init_sync_wait(pinfo, 0); - lms_finish_slave(pinfo, _master_dummy_send_finish); - - end: - lms_db_reset_stmt(db->get_files); - _master_db_close(db); - - return ret; -} - -/** - * Check consistency of given directory. - * - * This will update media in the given directory or its children. If files - * are missing, they'll be marked as deleted (dtime is set), if they were - * marked as deleted and are now present, they are unmarked (dtime is unset). - * - * @param lms previously allocated Light Media Scanner instance. - * @param top_path top directory to scan. - * - * @return On success 0 is returned. - */ -int -lms_check(lms_t *lms, const char *top_path) -{ - struct pinfo pinfo; - int r; - char path[PATH_SIZE]; - - if (!lms) { - r = -1; - goto end; - } - - if (!top_path) { - r = -2; - goto end; - } - - if (lms->is_processing) { - fprintf(stderr, "ERROR: is already processing.\n"); - r = -3; - goto end; - } - - if (!lms->parsers) { - fprintf(stderr, "ERROR: no plugins registered.\n"); - r = -4; - goto end; - } - - pinfo.lms = lms; - - if (lms_create_pipes(&pinfo) != 0) { - r = -5; - goto end; - } - - if (realpath(top_path, path) == NULL) { - perror("realpath"); - r = -6; - goto close_pipes; - } - - lms->is_processing = 1; - lms->stop_processing = 0; - r = _check(&pinfo, strlen(path), path); - lms->is_processing = 0; - lms->stop_processing = 0; - - close_pipes: - lms_close_pipes(&pinfo); - end: - return r; -} diff --git a/lightmediascanner/src/lib/lightmediascanner_db.h b/lightmediascanner/src/lib/lightmediascanner_db.h deleted file mode 100644 index 9752308..0000000 --- a/lightmediascanner/src/lib/lightmediascanner_db.h +++ /dev/null @@ -1,139 +0,0 @@ -/** - * Copyright (C) 2007 by INdT - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser 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 Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * @author Gustavo Sverzut Barbieri - */ - -#ifndef _LIGHTMEDIASCANNER_DB_H_ -#define _LIGHTMEDIASCANNER_DB_H_ 1 - -#ifdef API -#undef API -#endif - -#ifdef __GNUC__ -# if __GNUC__ >= 4 -# define API __attribute__ ((visibility("default"))) -# else -# define API -# endif -# if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) -# define GNUC_NON_NULL(...) __attribute__((nonnull(__VA_ARGS__))) -# else -# define GNUC_NON_NULL(...) -# endif -#else -# define API -# define GNUC_NON_NULL(...) -#endif - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif -/** - * @defgroup LMS_DB DataBase-API - * - * Although Light Media Scanner uses SQLite3 and doesn't try to hide it from - * plugins/parsers, it does provide some utilities to make development easier - * and less error prone. - * - * @{ - */ - - /* Image Records */ - struct lms_gps_info { - double latitude; - double longitude; - double altitude; - }; - - struct lms_image_info { - int64_t id; - struct lms_string_size title; - struct lms_string_size artist; - unsigned int date; - unsigned short width; - unsigned short height; - unsigned short orientation; - struct lms_gps_info gps; - }; - - typedef struct lms_db_image lms_db_image_t; - - API lms_db_image_t *lms_db_image_new(sqlite3 *db) GNUC_NON_NULL(1); - API int lms_db_image_start(lms_db_image_t *ldi) GNUC_NON_NULL(1); - API int lms_db_image_free(lms_db_image_t *ldi) GNUC_NON_NULL(1); - API int lms_db_image_add(lms_db_image_t *ldi, struct lms_image_info *info) GNUC_NON_NULL(1, 2); - - /* Audio Records */ - struct lms_audio_info { - int64_t id; - struct lms_string_size title; - struct lms_string_size artist; - struct lms_string_size album; - struct lms_string_size genre; - unsigned int playcnt; - unsigned char trackno; - unsigned char rating; - }; - - typedef struct lms_db_audio lms_db_audio_t; - - API lms_db_audio_t *lms_db_audio_new(sqlite3 *db) GNUC_NON_NULL(1); - API int lms_db_audio_start(lms_db_audio_t *lda) GNUC_NON_NULL(1); - API int lms_db_audio_free(lms_db_audio_t *lda) GNUC_NON_NULL(1); - API int lms_db_audio_add(lms_db_audio_t *lda, struct lms_audio_info *info) GNUC_NON_NULL(1, 2); - - /* Video Records */ - struct lms_video_info { - int64_t id; - struct lms_string_size title; - struct lms_string_size artist; - }; - - typedef struct lms_db_video lms_db_video_t; - - API lms_db_video_t *lms_db_video_new(sqlite3 *db) GNUC_NON_NULL(1); - API int lms_db_video_start(lms_db_video_t *ldv) GNUC_NON_NULL(1); - API int lms_db_video_free(lms_db_video_t *ldv) GNUC_NON_NULL(1); - API int lms_db_video_add(lms_db_video_t *ldv, struct lms_video_info *info) GNUC_NON_NULL(1, 2); - - /* Playlist Records */ - struct lms_playlist_info { - int64_t id; - struct lms_string_size title; - unsigned int n_entries; - }; - - typedef struct lms_db_playlist lms_db_playlist_t; - - API lms_db_playlist_t *lms_db_playlist_new(sqlite3 *db) GNUC_NON_NULL(1); - API int lms_db_playlist_start(lms_db_playlist_t *ldp) GNUC_NON_NULL(1); - API int lms_db_playlist_free(lms_db_playlist_t *ldp) GNUC_NON_NULL(1); - API int lms_db_playlist_add(lms_db_playlist_t *ldp, struct lms_playlist_info *info) GNUC_NON_NULL(1, 2); - -/** - * @} - */ - -#ifdef __cplusplus -} -#endif -#endif /* _LIGHTMEDIASCANNER_DB_H_ */ diff --git a/lightmediascanner/src/lib/lightmediascanner_db_audio.c b/lightmediascanner/src/lib/lightmediascanner_db_audio.c deleted file mode 100644 index 66f4db2..0000000 --- a/lightmediascanner/src/lib/lightmediascanner_db_audio.c +++ /dev/null @@ -1,690 +0,0 @@ -/** - * Copyright (C) 2007 by INdT - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser 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 Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * @author Gustavo Sverzut Barbieri - */ -#include -#include "lightmediascanner_db_private.h" -#include -#include - -struct lms_db_audio { - sqlite3 *db; - sqlite3_stmt *insert_audio; - sqlite3_stmt *insert_artist; - sqlite3_stmt *insert_album; - sqlite3_stmt *insert_genre; - sqlite3_stmt *get_artist; - sqlite3_stmt *get_album; - sqlite3_stmt *get_genre; - unsigned int _references; - unsigned int _is_started:1; -}; - -static struct lms_db_cache _cache = {0, NULL}; - -static int -_db_create(sqlite3 *db, const char *name, const char *sql) -{ - char *err; - int r; - - r = sqlite3_exec(db, sql, NULL, NULL, &err); - if (r != SQLITE_OK) { - fprintf(stderr, "ERROR: could not create \"%s\": %s\n", name, err); - sqlite3_free(err); - return -1; - } - - return 0; -} - -static int -_db_table_updater_audios_0(sqlite3 *db, const char *table, unsigned int current_version, int is_last_run) { - int ret; - - ret = _db_create(db, "audios", - "CREATE TABLE IF NOT EXISTS audios (" - "id INTEGER PRIMARY KEY, " - "title TEXT, " - "album_id INTEGER, " - "genre_id INTEGER, " - "trackno INTEGER, " - "rating INTEGER, " - "playcnt INTEGER" - ")"); - if (ret != 0) - goto done; - - ret = _db_create(db, "audios_title_idx", - "CREATE INDEX IF NOT EXISTS " - "audios_title_idx ON audios (title)"); - if (ret != 0) - goto done; - - ret = _db_create(db, "audios_album_idx", - "CREATE INDEX IF NOT EXISTS " - "audios_album_idx ON audios (album_id)"); - if (ret != 0) - goto done; - - ret = _db_create(db, "audios_genre_idx", - "CREATE INDEX IF NOT EXISTS " - "audios_genre_idx ON audios (genre_id)"); - if (ret != 0) - goto done; - - ret = _db_create(db, "audios_trackno_idx", - "CREATE INDEX IF NOT EXISTS " - "audios_trackno_idx ON audios (trackno)"); - if (ret != 0) - goto done; - - ret = _db_create(db, "audios_playcnt_idx", - "CREATE INDEX IF NOT EXISTS " - "audios_playcnt_idx ON audios (playcnt)"); - if (ret != 0) - goto done; - - ret = lms_db_create_trigger_if_not_exists(db, - "delete_audios_on_files_deleted " - "DELETE ON files FOR EACH ROW BEGIN" - " DELETE FROM audios WHERE id = OLD.id; END;"); - if (ret != 0) - goto done; - - ret = lms_db_create_trigger_if_not_exists(db, - "delete_files_on_audios_deleted " - "DELETE ON audios FOR EACH ROW BEGIN" - " DELETE FROM files WHERE id = OLD.id; END;"); - - done: - return ret; -} - -static lms_db_table_updater_t _db_table_updater_audios[] = { - _db_table_updater_audios_0 -}; - -static int -_db_table_updater_audio_artists_0(sqlite3 *db, const char *table, unsigned int current_version, int is_last_run) { - int ret; - - ret = _db_create(db, "audio_artists", - "CREATE TABLE IF NOT EXISTS audio_artists (" - "id INTEGER PRIMARY KEY, " - "name TEXT UNIQUE" - ")"); - if (ret != 0) - goto done; - - ret = _db_create(db, "audio_artists_name_idx", - "CREATE INDEX IF NOT EXISTS " - "audio_artists_name_idx ON audio_artists (name)"); - - done: - return ret; -} - -static lms_db_table_updater_t _db_table_updater_audio_artists[] = { - _db_table_updater_audio_artists_0 -}; - -static int -_db_table_updater_audio_albums_0(sqlite3 *db, const char *table, unsigned int current_version, int is_last_run) { - int ret; - - ret = _db_create(db, "audio_albums", - "CREATE TABLE IF NOT EXISTS audio_albums (" - "id INTEGER PRIMARY KEY, " - "artist_id INTEGER, " - "name TEXT" - ")"); - if (ret != 0) - goto done; - - ret = _db_create(db, "audio_albums_name_idx", - "CREATE INDEX IF NOT EXISTS " - "audio_albums_name_idx ON audio_albums (name)"); - if (ret != 0) - goto done; - - ret = _db_create(db, "audio_albums_artist_idx", - "CREATE INDEX IF NOT EXISTS " - "audio_albums_artist_idx ON audio_albums (artist_id)"); - if (ret != 0) - goto done; - - ret = lms_db_create_trigger_if_not_exists(db, - "delete_audios_on_albums_deleted " - "DELETE ON audio_albums FOR EACH ROW BEGIN" - " DELETE FROM audios WHERE album_id = OLD.id; END;"); - if (ret != 0) - goto done; - - ret = lms_db_create_trigger_if_not_exists(db, - "delete_audio_albums_on_artists_deleted " - "DELETE ON audio_artists FOR EACH ROW BEGIN" - " DELETE FROM audio_albums WHERE artist_id = OLD.id; END;"); - - done: - return ret; -} - -static lms_db_table_updater_t _db_table_updater_audio_albums[] = { - _db_table_updater_audio_albums_0 -}; - -static int -_db_table_updater_audio_genres_0(sqlite3 *db, const char *table, unsigned int current_version, int is_last_run) { - int ret; - - ret = _db_create(db, "audio_genres", - "CREATE TABLE IF NOT EXISTS audio_genres (" - "id INTEGER PRIMARY KEY, " - "name TEXT UNIQUE" - ")"); - if (ret != 0) - goto done; - - ret = _db_create(db, "audio_genres_name_idx", - "CREATE INDEX IF NOT EXISTS " - "audio_albums_name_idx ON audio_albums (name)"); - if (ret != 0) - goto done; - - ret = lms_db_create_trigger_if_not_exists(db, - "delete_audios_on_genres_deleted " - "DELETE ON audio_genres FOR EACH ROW BEGIN" - " DELETE FROM audios WHERE genre_id = OLD.id; END;"); - - done: - return ret; -} - -static lms_db_table_updater_t _db_table_updater_audio_genres[] = { - _db_table_updater_audio_genres_0 -}; - -#define _DB_T_UPDATE(db, name, array) \ - lms_db_table_update_if_required(db, name, LMS_ARRAY_SIZE(array), array) - -static int -_db_create_tables_if_required(sqlite3 *db) -{ - int ret; - - ret = _DB_T_UPDATE(db, "audios", _db_table_updater_audios); - if (ret != 0) - goto done; - - ret = _DB_T_UPDATE(db, "audio_artists", _db_table_updater_audio_artists); - if (ret != 0) - goto done; - - ret = _DB_T_UPDATE(db, "audio_albums", _db_table_updater_audio_albums); - if (ret != 0) - goto done; - - ret = _DB_T_UPDATE(db, "audio_genres", _db_table_updater_audio_genres); - - done: - return ret; -} - -#undef _DB_T_UPDATE - -/** - * Create audio DB access tool. - * - * Creates or get a reference to tools to access 'audios' table in an - * optimized and easy way. - * - * This is usually called from plugin's @b setup() callback with the @p db - * got from @c ctxt. - * - * @param db database connection. - * - * @return DB access tool handle. - * @ingroup LMS_Plugins - */ -lms_db_audio_t * -lms_db_audio_new(sqlite3 *db) -{ - lms_db_audio_t *lda; - void *p; - - if (lms_db_cache_get(&_cache, db, &p) == 0) { - lda = p; - lda->_references++; - return lda; - } - - if (!db) - return NULL; - - if (_db_create_tables_if_required(db) != 0) { - fprintf(stderr, "ERROR: could not create tables.\n"); - return NULL; - } - - lda = calloc(1, sizeof(lms_db_audio_t)); - lda->_references = 1; - lda->db = db; - - if (lms_db_cache_add(&_cache, db, lda) != 0) { - lms_db_audio_free(lda); - return NULL; - } - - return lda; -} - -/** - * Start audio DB access tool. - * - * Compile SQL statements and other initialization functions. - * - * This is usually called from plugin's @b start() callback. - * - * @param lda handle returned by lms_db_audio_new(). - * - * @return On success 0 is returned. - * @ingroup LMS_Plugins - */ -int -lms_db_audio_start(lms_db_audio_t *lda) -{ - if (!lda) - return -1; - if (lda->_is_started) - return 0; - - lda->insert_audio = lms_db_compile_stmt(lda->db, - "INSERT OR REPLACE INTO audios " - "(id, title, album_id, genre_id, trackno, rating, playcnt) " - "VALUES (?, ?, ?, ?, ?, ?, ?)"); - if (!lda->insert_audio) - return -2; - - lda->insert_artist = lms_db_compile_stmt(lda->db, - "INSERT INTO audio_artists (name) VALUES (?)"); - if (!lda->insert_artist) - return -3; - - lda->insert_album = lms_db_compile_stmt(lda->db, - "INSERT INTO audio_albums (artist_id, name) VALUES (?, ?)"); - if (!lda->insert_album) - return -4; - - lda->insert_genre = lms_db_compile_stmt(lda->db, - "INSERT INTO audio_genres (name) VALUES (?)"); - if (!lda->insert_genre) - return -5; - - lda->get_artist = lms_db_compile_stmt(lda->db, - "SELECT id FROM audio_artists WHERE name = ? LIMIT 1"); - if (!lda->get_artist) - return -6; - - lda->get_album = lms_db_compile_stmt(lda->db, - "SELECT id FROM audio_albums WHERE name = ? AND artist_id = ? LIMIT 1"); - if (!lda->get_album) - return -7; - - lda->get_genre = lms_db_compile_stmt(lda->db, - "SELECT id FROM audio_genres WHERE name = ? LIMIT 1"); - if (!lda->get_genre) - return -8; - - lda->_is_started = 1; - return 0; -} - -/** - * Free audio DB access tool. - * - * Unreference and possible free resources allocated to access tool. - * - * This is usually called from plugin's @b finish() callback. - * - * @param lda handle returned by lms_db_audio_new(). - * - * @return On success 0 is returned. - * @ingroup LMS_Plugins - */ -int -lms_db_audio_free(lms_db_audio_t *lda) -{ - int r; - - if (!lda) - return -1; - if (lda->_references == 0) { - fprintf(stderr, "ERROR: over-called lms_db_audio_free(%p)\n", lda); - return -1; - } - - lda->_references--; - if (lda->_references > 0) - return 0; - - if (lda->insert_audio) - lms_db_finalize_stmt(lda->insert_audio, "insert_audio"); - - if (lda->insert_artist) - lms_db_finalize_stmt(lda->insert_artist, "insert_artist"); - - if (lda->insert_album) - lms_db_finalize_stmt(lda->insert_album, "insert_album"); - - if (lda->insert_genre) - lms_db_finalize_stmt(lda->insert_genre, "insert_genre"); - - if (lda->get_artist) - lms_db_finalize_stmt(lda->get_artist, "get_artist"); - - if (lda->get_album) - lms_db_finalize_stmt(lda->get_album, "get_album"); - - if (lda->get_genre) - lms_db_finalize_stmt(lda->get_genre, "get_genre"); - - r = lms_db_cache_del(&_cache, lda->db, lda); - free(lda); - - return r; -} - -static int -_db_get_id_by_name(sqlite3_stmt *stmt, const struct lms_string_size *name, int64_t *id) -{ - int r, ret; - - ret = lms_db_bind_text(stmt, 1, name->str, name->len); - if (ret != 0) - goto done; - - r = sqlite3_step(stmt); - if (r == SQLITE_DONE) { - ret = 1; - goto done; - } - - if (r != SQLITE_ROW) { - fprintf(stderr, "ERROR: could not get id by name: %s\n", - sqlite3_errmsg(sqlite3_db_handle(stmt))); - ret = -2; - goto done; - } - - *id = sqlite3_column_int64(stmt, 0); - ret = 0; - - done: - lms_db_reset_stmt(stmt); - - return ret; - -} -static int -_db_insert_name(sqlite3_stmt *stmt, const struct lms_string_size *name, int64_t *id) -{ - int r, ret; - - ret = lms_db_bind_text(stmt, 1, name->str, name->len); - if (ret != 0) - goto done; - - r = sqlite3_step(stmt); - if (r != SQLITE_DONE) { - fprintf(stderr, "ERROR: could not insert name: %s\n", - sqlite3_errmsg(sqlite3_db_handle(stmt))); - ret = -2; - goto done; - } - - *id = sqlite3_last_insert_rowid(sqlite3_db_handle(stmt)); - ret = 0; - - done: - lms_db_reset_stmt(stmt); - - return ret; -} - -static int -_db_get_artist(lms_db_audio_t *lda, const struct lms_audio_info *info, int64_t *artist_id) -{ - return _db_get_id_by_name(lda->get_artist, &info->artist, artist_id); -} - -static int -_db_insert_artist(lms_db_audio_t *lda, const struct lms_audio_info *info, int64_t *artist_id) -{ - int r; - - if (!info->artist.str) /* fast path for unknown artist */ - return 1; - - r =_db_get_artist(lda, info, artist_id); - if (r == 0) - return 0; - else if (r < 0) - return -1; - - return _db_insert_name(lda->insert_artist, &info->artist, artist_id); -} - -static int -_db_get_album(lms_db_audio_t *lda, const struct lms_audio_info *info, int64_t *artist_id, int64_t *album_id) -{ - sqlite3_stmt *stmt; - int r, ret; - - stmt = lda->get_album; - - ret = lms_db_bind_text(stmt, 1, info->album.str, info->album.len); - if (ret != 0) - goto done; - - ret = lms_db_bind_int64_or_null(stmt, 2, artist_id); - if (ret != 0) - goto done; - - r = sqlite3_step(stmt); - if (r == SQLITE_DONE) { - ret = 1; - goto done; - } - - if (r != SQLITE_ROW) { - fprintf(stderr, "ERROR: could not get album from table: %s\n", - sqlite3_errmsg(lda->db)); - ret = -2; - goto done; - } - - *album_id = sqlite3_column_int64(stmt, 0); - ret = 0; - - done: - lms_db_reset_stmt(stmt); - - return ret; - -} - -static int -_db_insert_album(lms_db_audio_t *lda, const struct lms_audio_info *info, int64_t *album_id) -{ - int r, ret, ret_artist; - int64_t artist_id; - sqlite3_stmt *stmt; - - if (!info->album.str) /* fast path for unknown album */ - return 1; - - ret_artist = _db_insert_artist(lda, info, &artist_id); - if (ret_artist < 0) - return -1; - - r =_db_get_album(lda, info, - (ret_artist == 0) ? &artist_id : NULL, - album_id); - if (r == 0) - return 0; - else if (r < 0) - return -1; - - stmt = lda->insert_album; - ret = lms_db_bind_int64_or_null(stmt, 1, - (ret_artist == 0) ? &artist_id : NULL); - if (ret != 0) - goto done; - - ret = lms_db_bind_text(stmt, 2, info->album.str, info->album.len); - if (ret != 0) - goto done; - - r = sqlite3_step(stmt); - if (r != SQLITE_DONE) { - fprintf(stderr, "ERROR: could not insert audio album: %s\n", - sqlite3_errmsg(lda->db)); - ret = -3; - goto done; - } - - *album_id = sqlite3_last_insert_rowid(lda->db); - ret = 0; - - done: - lms_db_reset_stmt(stmt); - - return ret; -} - -static int -_db_get_genre(lms_db_audio_t *lda, const struct lms_audio_info *info, int64_t *genre_id) -{ - return _db_get_id_by_name(lda->get_genre, &info->genre, genre_id); -} - -static int -_db_insert_genre(lms_db_audio_t *lda, const struct lms_audio_info *info, int64_t *genre_id) -{ - int r; - - if (!info->genre.str) /* fast path for unknown genre */ - return 1; - - r =_db_get_genre(lda, info, genre_id); - if (r == 0) - return 0; - else if (r < 0) - return -1; - - return _db_insert_name(lda->insert_genre, &info->genre, genre_id); -} - -static int -_db_insert_audio(lms_db_audio_t *lda, const struct lms_audio_info *info, int64_t *album_id, int64_t *genre_id) -{ - sqlite3_stmt *stmt; - int r, ret; - - stmt = lda->insert_audio; - ret = lms_db_bind_int64(stmt, 1, info->id); - if (ret != 0) - goto done; - - ret = lms_db_bind_text(stmt, 2, info->title.str, info->title.len); - if (ret != 0) - goto done; - - ret = lms_db_bind_int64_or_null(stmt, 3, album_id); - if (ret != 0) - goto done; - - ret = lms_db_bind_int64_or_null(stmt, 4, genre_id); - if (ret != 0) - goto done; - - ret = lms_db_bind_int(stmt, 5, info->trackno); - if (ret != 0) - goto done; - - ret = lms_db_bind_int(stmt, 6, info->rating); - if (ret != 0) - goto done; - - ret = lms_db_bind_int(stmt, 7, info->playcnt); - if (ret != 0) - goto done; - - r = sqlite3_step(stmt); - if (r != SQLITE_DONE) { - fprintf(stderr, "ERROR: could not insert audio info: %s\n", - sqlite3_errmsg(lda->db)); - ret = -8; - goto done; - } - - ret = 0; - - done: - lms_db_reset_stmt(stmt); - - return ret; -} - -/** - * Add audio file to DB. - * - * This is usually called from plugin's @b parse() callback. - * - * @param lda handle returned by lms_db_audio_new(). - * @param info audio information to store. - * - * @return On success 0 is returned. - * @ingroup LMS_Plugins - */ -int -lms_db_audio_add(lms_db_audio_t *lda, struct lms_audio_info *info) -{ - int64_t album_id, genre_id; - int ret_album, ret_genre; - - if (!lda) - return -1; - if (!info) - return -2; - if (info->id < 1) - return -3; - - ret_album = _db_insert_album(lda, info, &album_id); - if (ret_album < 0) - return -4; - - ret_genre = _db_insert_genre(lda, info, &genre_id); - if (ret_genre < 0) - return -5; - - return _db_insert_audio(lda, info, - (ret_album == 0) ? &album_id : NULL, - (ret_genre == 0) ? &genre_id : NULL); -} diff --git a/lightmediascanner/src/lib/lightmediascanner_db_common.c b/lightmediascanner/src/lib/lightmediascanner_db_common.c deleted file mode 100644 index f95611c..0000000 --- a/lightmediascanner/src/lib/lightmediascanner_db_common.c +++ /dev/null @@ -1,789 +0,0 @@ -/** - * Copyright (C) 2007 by INdT - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser 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 Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * @author Gustavo Sverzut Barbieri - */ - -#include "lightmediascanner_db_private.h" -#include -#include -#include - -#if SQLITE_VERSION_NUMBER < 3003009 -int -sqlite3_prepare_v2(sqlite3 *db, const char *sql, int len, sqlite3_stmt **stmt, const char **tail) -{ - return sqlite3_prepare(db, sql, len, stmt, tail); -} -#endif /* SQLITE_VERSION_NUMBER < 3003009 */ - -#if SQLITE_VERSION_NUMBER < 3003007 -int -sqlite3_clear_bindings(sqlite3_stmt *stmt) -{ - int i, last; - int rc; - - rc = SQLITE_OK; - last = sqlite3_bind_parameter_count(stmt); - for(i = 1; rc == SQLITE_OK && i <= last; i++) { - rc = sqlite3_bind_null(stmt, i); - } - return rc; -} -#endif /* SQLITE_VERSION_NUMBER < 3003007 */ - -#if SQLITE_VERSION_NUMBER < 3003008 -/* Until 3.3.8 it doesn't support CREATE TRIGGER IF NOT EXISTS, so - * just ignore errors :-( - */ -int -lms_db_create_trigger_if_not_exists(sqlite3 *db, const char *sql) -{ - char *errmsg, *query; - int r, sql_len, prefix_len; - - prefix_len = sizeof("CREATE TRIGGER ") - 1; - sql_len = strlen(sql); - query = malloc((prefix_len + sql_len + 1) * sizeof(char)); - if (!query) - return -1; - - memcpy(query, "CREATE TRIGGER ", prefix_len); - memcpy(query + prefix_len, sql, sql_len + 1); - r = sqlite3_exec(db, query, NULL, NULL, &errmsg); - free(query); - if (r != SQLITE_OK) - sqlite3_free(errmsg); - return 0; -} -#else /* SQLITE_VERSION_NUMBER < 3003008 */ -int -lms_db_create_trigger_if_not_exists(sqlite3 *db, const char *sql) -{ - char *errmsg, *query; - int r, sql_len, prefix_len; - - prefix_len = sizeof("CREATE TRIGGER IF NOT EXISTS ") - 1; - sql_len = strlen(sql); - query = malloc((prefix_len + sql_len + 1) * sizeof(char)); - if (!query) - return -1; - - memcpy(query, "CREATE TRIGGER IF NOT EXISTS ", prefix_len); - memcpy(query + prefix_len, sql, sql_len + 1); - r = sqlite3_exec(db, query, NULL, NULL, &errmsg); - free(query); - if (r != SQLITE_OK) { - fprintf(stderr, "ERROR: could not create trigger: %s\n", errmsg); - sqlite3_free(errmsg); - return -2; - } - return 0; -} -#endif /* SQLITE_VERSION_NUMBER < 3003008 */ - -sqlite3_stmt * -lms_db_compile_stmt(sqlite3 *db, const char *sql) -{ - sqlite3_stmt *stmt; - - if (sqlite3_prepare_v2(db, sql, -1, &stmt, NULL) != SQLITE_OK) - fprintf(stderr, "ERROR: could not prepare \"%s\": %s\n", sql, - sqlite3_errmsg(db)); - - return stmt; -} - -int -lms_db_finalize_stmt(sqlite3_stmt *stmt, const char *name) -{ - int r; - - r = sqlite3_finalize(stmt); - if (r != SQLITE_OK) { - fprintf(stderr, "ERROR: could not finalize %s statement: #%d\n", - name, r); - return -1; - } - - return 0; -} - -int -lms_db_reset_stmt(sqlite3_stmt *stmt) -{ - int r, ret; - - ret = r = sqlite3_reset(stmt); - if (r != SQLITE_OK) - fprintf(stderr, "ERROR: could not reset SQL statement: #%d\n", r); - - r = sqlite3_clear_bindings(stmt); - ret += r; - if (r != SQLITE_OK) - fprintf(stderr, "ERROR: could not clear SQL: #%d\n", r); - - return ret; -} - -int -lms_db_bind_text(sqlite3_stmt *stmt, int col, const char *text, int len) -{ - int r; - - if (text) - r = sqlite3_bind_text(stmt, col, text, len, SQLITE_STATIC); - else - r = sqlite3_bind_null(stmt, col); - - if (r == SQLITE_OK) - return 0; - else { - sqlite3 *db; - const char *err; - - db = sqlite3_db_handle(stmt); - err = sqlite3_errmsg(db); - fprintf(stderr, "ERROR: could not bind SQL value %d: %s\n", col, err); - return -col; - } -} - -int -lms_db_bind_blob(sqlite3_stmt *stmt, int col, const void *blob, int len) -{ - int r; - - if (blob) - r = sqlite3_bind_blob(stmt, col, blob, len, SQLITE_STATIC); - else - r = sqlite3_bind_null(stmt, col); - - if (r == SQLITE_OK) - return 0; - else { - sqlite3 *db; - const char *err; - - db = sqlite3_db_handle(stmt); - err = sqlite3_errmsg(db); - fprintf(stderr, "ERROR: could not bind SQL value %d: %s\n", col, err); - return -col; - } -} - -int -lms_db_bind_int64(sqlite3_stmt *stmt, int col, int64_t value) -{ - int r; - - r = sqlite3_bind_int64(stmt, col, value); - if (r == SQLITE_OK) - return 0; - else { - sqlite3 *db; - const char *err; - - db = sqlite3_db_handle(stmt); - err = sqlite3_errmsg(db); - fprintf(stderr, "ERROR: could not bind SQL value %d: %s\n", col, err); - return -col; - } -} - -int -lms_db_bind_int64_or_null(sqlite3_stmt *stmt, int col, int64_t *p_value) -{ - int r; - - if (p_value) - r = sqlite3_bind_int64(stmt, col, *p_value); - else - r = sqlite3_bind_null(stmt, col); - if (r == SQLITE_OK) - return 0; - else { - sqlite3 *db; - const char *err; - - db = sqlite3_db_handle(stmt); - err = sqlite3_errmsg(db); - fprintf(stderr, "ERROR: could not bind SQL value %d: %s\n", col, err); - return -col; - } -} - -int -lms_db_bind_int(sqlite3_stmt *stmt, int col, int value) -{ - int r; - - r = sqlite3_bind_int(stmt, col, value); - if (r == SQLITE_OK) - return 0; - else { - sqlite3 *db; - const char *err; - - db = sqlite3_db_handle(stmt); - err = sqlite3_errmsg(db); - fprintf(stderr, "ERROR: could not bind SQL value %d: %s\n", col, err); - return -col; - } -} - -int -lms_db_bind_double(sqlite3_stmt *stmt, int col, double value) -{ - int r; - - r = sqlite3_bind_double(stmt, col, value); - if (r == SQLITE_OK) - return 0; - else { - sqlite3 *db; - const char *err; - - db = sqlite3_db_handle(stmt); - err = sqlite3_errmsg(db); - fprintf(stderr, "ERROR: could not bind SQL value %d: %s\n", col, err); - return -col; - } -} - -int -lms_db_table_version_get(sqlite3 *db, const char *table) -{ - int r, version; - sqlite3_stmt *stmt; - - stmt = lms_db_compile_stmt(db, - "SELECT version FROM lms_internal WHERE tab = ?"); - if (!stmt) - return -1; - - if (lms_db_bind_text(stmt, 1, table, -1) != 0) { - version = -1; - goto done; - } - - r = sqlite3_step(stmt); - if (r == SQLITE_DONE) - version = 0; - else if (r == SQLITE_ROW) - version = sqlite3_column_int(stmt, 1); - else { - version = -1; - fprintf(stderr, "ERROR: could not get table '%s' version: %s\n", - table, sqlite3_errmsg(db)); - } - - done: - lms_db_reset_stmt(stmt); - lms_db_finalize_stmt(stmt, "table_version_get"); - - return version; -} - -int -lms_db_table_version_set(sqlite3 *db, const char *table, unsigned int version) -{ - int r, ret; - sqlite3_stmt *stmt; - - stmt = lms_db_compile_stmt(db, - "INSERT OR REPLACE INTO lms_internal (tab, version) VALUES (?, ?)"); - if (!stmt) - return -1; - - ret = lms_db_bind_text(stmt, 1, table, -1); - if (ret != 0) - goto done; - - ret = lms_db_bind_int(stmt, 2, version); - if (ret != 0) - goto done; - - r = sqlite3_step(stmt); - if (r != SQLITE_DONE) { - ret = -1; - fprintf(stderr, "ERROR: could not set table '%s' version: %s\n", - table, sqlite3_errmsg(db)); - } - - done: - lms_db_reset_stmt(stmt); - lms_db_finalize_stmt(stmt, "table_version_set"); - - return ret; -} - -int -lms_db_table_update(sqlite3 *db, const char *table, unsigned int current_version, unsigned int last_version, const lms_db_table_updater_t *updaters) -{ - if (current_version == last_version) - return 0; - else if (current_version > last_version) { - fprintf(stderr, - "WARNING: current version (%d) of table '%s' is greater than " - "last known version (%d), no updates will be made.\n", - current_version, table, last_version); - return 0; - } - - for (; current_version < last_version; current_version++) { - int r, is_last_run; - - is_last_run = current_version == (last_version - 1); - r = updaters[current_version](db, table, current_version, is_last_run); - if (r != 0) { - fprintf(stderr, - "ERROR: could not update table '%s' from version %d->%d\n", - table, current_version, current_version + 1); - return r; - } - lms_db_table_version_set(db, table, current_version + 1); - } - - return 0; -} - -int -lms_db_table_update_if_required(sqlite3 *db, const char *table, unsigned int last_version, lms_db_table_updater_t *updaters) -{ - int current_version; - - current_version = lms_db_table_version_get(db, table); - if (current_version < 0) - return -1; - else - return lms_db_table_update(db, table, current_version, last_version, - updaters); -} - -static int -lms_db_cache_find_db(const struct lms_db_cache *cache, const sqlite3 *db) -{ - int i; - - for (i = 0; i < cache->size; i++) - if (cache->entries[i].db == db) - return i; - - return -1; -} - -static int -lms_db_cache_resize(struct lms_db_cache *cache, int new_size) -{ - cache->size = new_size; - cache->entries = realloc(cache->entries, - cache->size * sizeof(*cache->entries)); - if (cache->size && !cache->entries) { - perror("realloc"); - cache->size = 0; - return -1; - } - - return 0; -} - -int -lms_db_cache_add(struct lms_db_cache *cache, const sqlite3 *db, void *data) -{ - struct lms_db_cache_entry *e; - int idx; - - idx = lms_db_cache_find_db(cache, db); - if (idx >= 0) { - e = cache->entries + idx; - if (e->data == data) - return 0; - else { - fprintf(stderr, - "ERROR: cache %p for db %p has another data registered" - ": %p (current is %p)\n", cache, db, e->data, data); - return -1; - } - } - - idx = cache->size; - if (lms_db_cache_resize(cache, cache->size + 1) != 0) { - return -2; - } - - e = cache->entries + idx; - e->db = db; - e->data = data; - return 0; -} - -int -lms_db_cache_del(struct lms_db_cache *cache, const sqlite3 *db, void *data) -{ - int idx; - struct lms_db_cache_entry *e; - - idx = lms_db_cache_find_db(cache, db); - if (idx < 0) { - fprintf(stderr, "ERROR: no db %p found in cache %p\n", db, cache); - return -1; - } - - e = cache->entries + idx; - if (e->data != data) { - fprintf(stderr, "ERROR: data mismatch in request to delete from cache: " - "want %p, has %p, cache %p, db %p\n", data, e->data, cache, db); - return -2; - } - - for (; idx < cache->size - 1; idx++) - cache->entries[idx] = cache->entries[idx + 1]; - - return lms_db_cache_resize(cache, cache->size - 1); -} - -int -lms_db_cache_get(struct lms_db_cache *cache, const sqlite3 *db, void **pdata) -{ - int idx; - - idx = lms_db_cache_find_db(cache, db); - if (idx < 0) - return -1; - - *pdata = cache->entries[idx].data; - return 0; -} - -int -lms_db_create_core_tables_if_required(sqlite3 *db) -{ - char *errmsg; - int r; - - errmsg = NULL; - r = sqlite3_exec(db, - "CREATE TABLE IF NOT EXISTS lms_internal (" - "tab TEXT NOT NULL UNIQUE, " - "version INTEGER NOT NULL" - ")", - NULL, NULL, &errmsg); - if (r != SQLITE_OK) { - fprintf(stderr, "ERROR: could not create 'lms_internal' table: %s\n", - errmsg); - sqlite3_free(errmsg); - return -1; - } - - r = sqlite3_exec(db, - "CREATE TABLE IF NOT EXISTS files (" - "id INTEGER PRIMARY KEY AUTOINCREMENT, " - "path BLOB NOT NULL UNIQUE, " - "mtime INTEGER NOT NULL, " - "dtime INTEGER NOT NULL, " - "size INTEGER NOT NULL" - ")", - NULL, NULL, &errmsg); - if (r != SQLITE_OK) { - fprintf(stderr, "ERROR: could not create 'files' table: %s\n", errmsg); - sqlite3_free(errmsg); - return -2; - } - - r = sqlite3_exec(db, - "CREATE INDEX IF NOT EXISTS files_path_idx ON files (" - "path" - ")", - NULL, NULL, &errmsg); - if (r != SQLITE_OK) { - fprintf(stderr, "ERROR: could not create 'files_path_idx' index: %s\n", - errmsg); - sqlite3_free(errmsg); - return -3; - } - - return 0; -} - - -sqlite3_stmt * -lms_db_compile_stmt_begin_transaction(sqlite3 *db) -{ - return lms_db_compile_stmt(db, "BEGIN TRANSACTION"); -} - -int -lms_db_begin_transaction(sqlite3_stmt *stmt) -{ - int r, ret; - - ret = 0; - r = sqlite3_step(stmt); - if (r != SQLITE_DONE) { - fprintf(stderr, "ERROR: could not begin transaction: %s\n", - sqlite3_errmsg(sqlite3_db_handle(stmt))); - ret = -1; - } - - r = sqlite3_reset(stmt); - if (r != SQLITE_OK) - fprintf(stderr, "ERROR: could not reset SQL statement: %s\n", - sqlite3_errmsg(sqlite3_db_handle(stmt))); - - return ret; -} - -sqlite3_stmt * -lms_db_compile_stmt_end_transaction(sqlite3 *db) -{ - return lms_db_compile_stmt(db, "COMMIT"); -} - -int -lms_db_end_transaction(sqlite3_stmt *stmt) -{ - int r, ret; - - ret = 0; - r = sqlite3_step(stmt); - if (r != SQLITE_DONE) { - fprintf(stderr, "ERROR: could not end transaction: %s\n", - sqlite3_errmsg(sqlite3_db_handle(stmt))); - ret = -1; - } - - r = sqlite3_reset(stmt); - if (r != SQLITE_OK) - fprintf(stderr, "ERROR: could not reset SQL statement: %s\n", - sqlite3_errmsg(sqlite3_db_handle(stmt))); - - return ret; -} - -sqlite3_stmt * -lms_db_compile_stmt_get_file_info(sqlite3 *db) -{ - return lms_db_compile_stmt(db, - "SELECT id, mtime, dtime, size FROM files WHERE path = ?"); -} - -int -lms_db_get_file_info(sqlite3_stmt *stmt, struct lms_file_info *finfo) -{ - int r, ret; - - ret = lms_db_bind_blob(stmt, 1, finfo->path, finfo->path_len); - if (ret != 0) - goto done; - - r = sqlite3_step(stmt); - if (r == SQLITE_DONE) { - ret = 1; - finfo->id = -1; - goto done; - } - - if (r != SQLITE_ROW) { - fprintf(stderr, "ERROR: could not get file info from table: %s\n", - sqlite3_errmsg(sqlite3_db_handle(stmt))); - ret = -2; - goto done; - } - - finfo->id = sqlite3_column_int64(stmt, 0); - finfo->mtime = sqlite3_column_int(stmt, 1); - finfo->dtime = sqlite3_column_int(stmt, 2); - finfo->size = sqlite3_column_int(stmt, 3); - ret = 0; - - done: - lms_db_reset_stmt(stmt); - - return ret; -} - -sqlite3_stmt * -lms_db_compile_stmt_update_file_info(sqlite3 *db) -{ - return lms_db_compile_stmt(db, - "UPDATE files SET mtime = ?, dtime = ?, size = ? WHERE id = ?"); -} - -int -lms_db_update_file_info(sqlite3_stmt *stmt, const struct lms_file_info *finfo) -{ - int r, ret; - - ret = lms_db_bind_int(stmt, 1, finfo->mtime); - if (ret != 0) - goto done; - - ret = lms_db_bind_int(stmt, 2, finfo->dtime); - if (ret != 0) - goto done; - - ret = lms_db_bind_int(stmt, 3, finfo->size); - if (ret != 0) - goto done; - - ret = lms_db_bind_int(stmt, 4, finfo->id); - if (ret != 0) - goto done; - - r = sqlite3_step(stmt); - if (r != SQLITE_DONE) { - fprintf(stderr, "ERROR: could not update file info: %s\n", - sqlite3_errmsg(sqlite3_db_handle(stmt))); - ret = -5; - goto done; - } - - ret = 0; - - done: - lms_db_reset_stmt(stmt); - - return ret; -} - -sqlite3_stmt * -lms_db_compile_stmt_insert_file_info(sqlite3 *db) -{ - return lms_db_compile_stmt(db, - "INSERT INTO files (path, mtime, dtime, size) VALUES(?, ?, ?, ?)"); -} - -int -lms_db_insert_file_info(sqlite3_stmt *stmt, struct lms_file_info *finfo) -{ - int r, ret; - - ret = lms_db_bind_blob(stmt, 1, finfo->path, finfo->path_len); - if (ret != 0) - goto done; - - ret = lms_db_bind_int(stmt, 2, finfo->mtime); - if (ret != 0) - goto done; - - ret = lms_db_bind_int(stmt, 3, finfo->dtime); - if (ret != 0) - goto done; - - ret = lms_db_bind_int(stmt, 4, finfo->size); - if (ret != 0) - goto done; - - r = sqlite3_step(stmt); - if (r != SQLITE_DONE) { - fprintf(stderr, "ERROR: could not insert file info: %s\n", - sqlite3_errmsg(sqlite3_db_handle(stmt))); - ret = -5; - goto done; - } - - finfo->id = sqlite3_last_insert_rowid(sqlite3_db_handle(stmt)); - ret = 0; - - done: - lms_db_reset_stmt(stmt); - - return ret; -} - -sqlite3_stmt * -lms_db_compile_stmt_delete_file_info(sqlite3 *db) -{ - return lms_db_compile_stmt(db, "DELETE FROM files WHERE id = ?"); -} - -int -lms_db_delete_file_info(sqlite3_stmt *stmt, const struct lms_file_info *finfo) -{ - int r, ret; - - ret = lms_db_bind_int64(stmt, 1, finfo->id); - if (ret != 0) - goto done; - - r = sqlite3_step(stmt); - if (r != SQLITE_DONE) { - fprintf(stderr, "ERROR: could not delete file info: %s\n", - sqlite3_errmsg(sqlite3_db_handle(stmt))); - ret = -2; - goto done; - } - ret = 0; - - done: - lms_db_reset_stmt(stmt); - - return ret; -} - -sqlite3_stmt * -lms_db_compile_stmt_set_file_dtime(sqlite3 *db) -{ - return lms_db_compile_stmt(db, "UPDATE files SET dtime = ? WHERE id = ?"); -} - -int -lms_db_set_file_dtime(sqlite3_stmt *stmt, const struct lms_file_info *finfo) -{ - int r, ret; - - ret = lms_db_bind_int(stmt, 1, finfo->dtime); - if (ret != 0) - goto done; - - ret = lms_db_bind_int64(stmt, 1, finfo->id); - if (ret != 0) - goto done; - - r = sqlite3_step(stmt); - if (r != SQLITE_DONE) { - fprintf(stderr, "ERROR: could not set file dtime: %s\n", - sqlite3_errmsg(sqlite3_db_handle(stmt))); - ret = -3; - goto done; - } - - ret = 0; - - done: - lms_db_reset_stmt(stmt); - - return ret; -} - -sqlite3_stmt * -lms_db_compile_stmt_get_files(sqlite3 *db) -{ - return lms_db_compile_stmt(db, - "SELECT id, path, mtime, dtime, size FROM files WHERE path LIKE ?"); -} - -int -lms_db_get_files(sqlite3_stmt *stmt, const char *path, int len) -{ - int ret; - - ret = lms_db_bind_blob(stmt, 1, path, len); - return ret; -} diff --git a/lightmediascanner/src/lib/lightmediascanner_db_image.c b/lightmediascanner/src/lib/lightmediascanner_db_image.c deleted file mode 100644 index 3f6bcae..0000000 --- a/lightmediascanner/src/lib/lightmediascanner_db_image.c +++ /dev/null @@ -1,303 +0,0 @@ -/** - * Copyright (C) 2007 by INdT - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser 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 Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * @author Gustavo Sverzut Barbieri - */ - -#include -#include "lightmediascanner_db_private.h" -#include -#include - -struct lms_db_image { - sqlite3 *db; - sqlite3_stmt *insert; - unsigned int _references; - unsigned int _is_started:1; -}; - -static struct lms_db_cache _cache = {0, NULL}; - -static int -_db_table_updater_images_0(sqlite3 *db, const char *table, unsigned int current_version, int is_last_run) { - char *errmsg; - int r, ret; - - errmsg = NULL; - r = sqlite3_exec(db, - "CREATE TABLE IF NOT EXISTS images (" - "id INTEGER PRIMARY KEY, " - "title TEXT, " - "artist TEXT, " - "date INTEGER NOT NULL, " - "width INTEGER NOT NULL, " - "height INTEGER NOT NULL, " - "orientation INTEGER NOT NULL, " - "gps_lat REAL DEFAULT 0.0, " - "gps_long REAL DEFAULT 0.0, " - "gps_alt REAL DEFAULT 0.0" - ")", - NULL, NULL, &errmsg); - if (r != SQLITE_OK) { - fprintf(stderr, "ERROR: could not create 'images' table: %s\n", errmsg); - sqlite3_free(errmsg); - return -1; - } - - r = sqlite3_exec(db, - "CREATE INDEX IF NOT EXISTS images_date_idx ON images (" - "date" - ")", - NULL, NULL, &errmsg); - if (r != SQLITE_OK) { - fprintf(stderr, "ERROR: could not create 'images_date_idx' index: %s\n", - errmsg); - sqlite3_free(errmsg); - return -2; - } - - ret = lms_db_create_trigger_if_not_exists(db, - "delete_images_on_files_deleted " - "DELETE ON files FOR EACH ROW BEGIN " - " DELETE FROM images WHERE id = OLD.id; END;"); - if (ret != 0) - goto done; - - ret = lms_db_create_trigger_if_not_exists(db, - "delete_files_on_images_deleted " - "DELETE ON images FOR EACH ROW BEGIN " - " DELETE FROM files WHERE id = OLD.id; END;"); - - done: - return ret; -} - -static lms_db_table_updater_t _db_table_updater_images[] = { - _db_table_updater_images_0 -}; - - -static int -_db_create_table_if_required(sqlite3 *db) -{ - return lms_db_table_update_if_required(db, "images", - LMS_ARRAY_SIZE(_db_table_updater_images), - _db_table_updater_images); -} - -/** - * Create image DB access tool. - * - * Creates or get a reference to tools to access 'images' table in an - * optimized and easy way. - * - * This is usually called from plugin's @b setup() callback with the @p db - * got from @c ctxt. - * - * @param db database connection. - * - * @return DB access tool handle. - * @ingroup LMS_Plugins - */ -lms_db_image_t * -lms_db_image_new(sqlite3 *db) -{ - lms_db_image_t *ldi; - void *p; - - if (lms_db_cache_get(&_cache, db, &p) == 0) { - ldi = p; - ldi->_references++; - return ldi; - } - - if (!db) - return NULL; - - if (_db_create_table_if_required(db) != 0) { - fprintf(stderr, "ERROR: could not create table.\n"); - return NULL; - } - - ldi = calloc(1, sizeof(lms_db_image_t)); - ldi->_references = 1; - ldi->db = db; - - if (lms_db_cache_add(&_cache, db, ldi) != 0) { - lms_db_image_free(ldi); - return NULL; - } - - return ldi; -} - -/** - * Start image DB access tool. - * - * Compile SQL statements and other initialization functions. - * - * This is usually called from plugin's @b start() callback. - * - * @param ldi handle returned by lms_db_image_new(). - * - * @return On success 0 is returned. - * @ingroup LMS_Plugins - */ -int -lms_db_image_start(lms_db_image_t *ldi) -{ - if (!ldi) - return -1; - if (ldi->_is_started) - return 0; - - ldi->insert = lms_db_compile_stmt(ldi->db, - "INSERT OR REPLACE INTO images (" - "id, title, artist, date, width, height, orientation, " - "gps_lat, gps_long, gps_alt) VALUES (" - "?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); - if (!ldi->insert) - return -2; - - ldi->_is_started = 1; - return 0; -} - -/** - * Free image DB access tool. - * - * Unreference and possible free resources allocated to access tool. - * - * This is usually called from plugin's @b finish() callback. - * - * @param ldi handle returned by lms_db_image_new(). - * - * @return On success 0 is returned. - * @ingroup LMS_Plugins - */ -int -lms_db_image_free(lms_db_image_t *ldi) -{ - int r; - - if (!ldi) - return -1; - if (ldi->_references == 0) { - fprintf(stderr, "ERROR: over-called lms_db_image_free(%p)\n", ldi); - return -1; - } - - ldi->_references--; - if (ldi->_references > 0) - return 0; - - if (ldi->insert) - lms_db_finalize_stmt(ldi->insert, "insert"); - - r = lms_db_cache_del(&_cache, ldi->db, ldi); - free(ldi); - - return r; -} - -static int -_db_insert(lms_db_image_t *ldi, const struct lms_image_info *info) -{ - sqlite3_stmt *stmt; - int r, ret; - - stmt = ldi->insert; - - ret = lms_db_bind_int64(stmt, 1, info->id); - if (ret != 0) - goto done; - - ret = lms_db_bind_text(stmt, 2, info->title.str, info->title.len); - if (ret != 0) - goto done; - - ret = lms_db_bind_text(stmt, 3, info->artist.str, info->artist.len); - if (ret != 0) - goto done; - - ret = lms_db_bind_int(stmt, 4, info->date); - if (ret != 0) - goto done; - - ret = lms_db_bind_int(stmt, 5, info->width); - if (ret != 0) - goto done; - - ret = lms_db_bind_int(stmt, 6, info->height); - if (ret != 0) - goto done; - - ret = lms_db_bind_int(stmt, 7, info->orientation); - if (ret != 0) - goto done; - - ret = lms_db_bind_double(stmt, 8, info->gps.latitude); - if (ret != 0) - goto done; - - ret = lms_db_bind_double(stmt, 9, info->gps.longitude); - if (ret != 0) - goto done; - - ret = lms_db_bind_double(stmt, 10, info->gps.altitude); - if (ret != 0) - goto done; - - r = sqlite3_step(stmt); - if (r != SQLITE_DONE) { - fprintf(stderr, "ERROR: could not insert image info: %s\n", - sqlite3_errmsg(ldi->db)); - ret = -11; - goto done; - } - - ret = 0; - - done: - lms_db_reset_stmt(stmt); - - return ret; -} - -/** - * Add image file to DB. - * - * This is usually called from plugin's @b parse() callback. - * - * @param ldi handle returned by lms_db_image_new(). - * @param info image information to store. - * - * @return On success 0 is returned. - * @ingroup LMS_Plugins - */ -int -lms_db_image_add(lms_db_image_t *ldi, struct lms_image_info *info) -{ - if (!ldi) - return -1; - if (!info) - return -2; - if (info->id < 1) - return -3; - - return _db_insert(ldi, info); -} diff --git a/lightmediascanner/src/lib/lightmediascanner_db_playlist.c b/lightmediascanner/src/lib/lightmediascanner_db_playlist.c deleted file mode 100644 index 54c4581..0000000 --- a/lightmediascanner/src/lib/lightmediascanner_db_playlist.c +++ /dev/null @@ -1,267 +0,0 @@ -/** - * Copyright (C) 2007 by INdT - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser 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 Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * @author Gustavo Sverzut Barbieri - */ - -#include -#include "lightmediascanner_db_private.h" -#include -#include - -struct lms_db_playlist { - sqlite3 *db; - sqlite3_stmt *insert; - unsigned int _references; - unsigned int _is_started:1; -}; - -static struct lms_db_cache _cache = {0, NULL}; - -static int -_db_table_updater_playlists_0(sqlite3 *db, const char *table, unsigned int current_version, int is_last_run) { - char *errmsg; - int r, ret; - - errmsg = NULL; - r = sqlite3_exec(db, - "CREATE TABLE IF NOT EXISTS playlists (" - "id INTEGER PRIMARY KEY, " - "title TEXT, " - "n_entries INTEGER NOT NULL" - ")", - NULL, NULL, &errmsg); - if (r != SQLITE_OK) { - fprintf(stderr, "ERROR: could not create 'playlists' table: %s\n", - errmsg); - sqlite3_free(errmsg); - return -1; - } - - r = sqlite3_exec(db, - "CREATE INDEX IF NOT EXISTS playlists_title_idx ON " - "playlists (title)", - NULL, NULL, &errmsg); - if (r != SQLITE_OK) { - fprintf(stderr, - "ERROR: could not create 'playlists_title_idx' index: %s\n", - errmsg); - sqlite3_free(errmsg); - return -2; - } - - ret = lms_db_create_trigger_if_not_exists(db, - "delete_playlists_on_files_deleted " - "DELETE ON files FOR EACH ROW BEGIN " - " DELETE FROM playlists WHERE id = OLD.id; END;"); - if (ret != 0) - goto done; - - ret = lms_db_create_trigger_if_not_exists(db, - "delete_files_on_playlists_deleted " - "DELETE ON playlists FOR EACH ROW BEGIN " - " DELETE FROM files WHERE id = OLD.id; END;"); - - done: - return ret; -} - -static lms_db_table_updater_t _db_table_updater_playlists[] = { - _db_table_updater_playlists_0 -}; - - -static int -_db_create_table_if_required(sqlite3 *db) -{ - return lms_db_table_update_if_required(db, "playlists", - LMS_ARRAY_SIZE(_db_table_updater_playlists), - _db_table_updater_playlists); -} - -/** - * Create playlist DB access tool. - * - * Creates or get a reference to tools to access 'playlists' table in an - * optimized and easy way. - * - * This is usually called from plugin's @b setup() callback with the @p db - * got from @c ctxt. - * - * @param db database connection. - * - * @return DB access tool handle. - * @ingroup LMS_Plugins - */ -lms_db_playlist_t * -lms_db_playlist_new(sqlite3 *db) -{ - lms_db_playlist_t *ldp; - void *p; - - if (lms_db_cache_get(&_cache, db, &p) == 0) { - ldp = p; - ldp->_references++; - return ldp; - } - - if (!db) - return NULL; - - if (_db_create_table_if_required(db) != 0) { - fprintf(stderr, "ERROR: could not create table.\n"); - return NULL; - } - - ldp = calloc(1, sizeof(lms_db_playlist_t)); - ldp->_references = 1; - ldp->db = db; - - if (lms_db_cache_add(&_cache, db, ldp) != 0) { - lms_db_playlist_free(ldp); - return NULL; - } - - return ldp; -} - -/** - * Start playlist DB access tool. - * - * Compile SQL statements and other initialization functions. - * - * This is usually called from plugin's @b start() callback. - * - * @param ldp handle returned by lms_db_playlist_new(). - * - * @return On success 0 is returned. - * @ingroup LMS_Plugins - */ -int -lms_db_playlist_start(lms_db_playlist_t *ldp) -{ - if (!ldp) - return -1; - if (ldp->_is_started) - return 0; - - ldp->insert = lms_db_compile_stmt(ldp->db, - "INSERT OR REPLACE INTO playlists (id, title, n_entries) " - "VALUES (?, ?, ?)"); - if (!ldp->insert) - return -2; - - ldp->_is_started = 1; - return 0; -} - -/** - * Free playlist DB access tool. - * - * Unreference and possible free resources allocated to access tool. - * - * This is usually called from plugin's @b finish() callback. - * - * @param ldp handle returned by lms_db_playlist_new(). - * - * @return On success 0 is returned. - * @ingroup LMS_Plugins - */ -int -lms_db_playlist_free(lms_db_playlist_t *ldp) -{ - int r; - - if (!ldp) - return -1; - if (ldp->_references == 0) { - fprintf(stderr, "ERROR: over-called lms_db_playlist_free(%p)\n", ldp); - return -1; - } - - ldp->_references--; - if (ldp->_references > 0) - return 0; - - if (ldp->insert) - lms_db_finalize_stmt(ldp->insert, "insert"); - - r = lms_db_cache_del(&_cache, ldp->db, ldp); - free(ldp); - - return r; -} - -static int -_db_insert(lms_db_playlist_t *ldp, const struct lms_playlist_info *info) -{ - sqlite3_stmt *stmt; - int r, ret; - - stmt = ldp->insert; - - ret = lms_db_bind_int64(stmt, 1, info->id); - if (ret != 0) - goto done; - - ret = lms_db_bind_text(stmt, 2, info->title.str, info->title.len); - if (ret != 0) - goto done; - - ret = lms_db_bind_int(stmt, 3, info->n_entries); - if (ret != 0) - goto done; - - r = sqlite3_step(stmt); - if (r != SQLITE_DONE) { - fprintf(stderr, "ERROR: could not insert playlist info: %s\n", - sqlite3_errmsg(ldp->db)); - ret = -4; - goto done; - } - - ret = 0; - - done: - lms_db_reset_stmt(stmt); - - return ret; -} - -/** - * Add playlist file to DB. - * - * This is usually called from plugin's @b parse() callback. - * - * @param ldp handle returned by lms_db_playlist_new(). - * @param info playlist information to store. - * - * @return On success 0 is returned. - * @ingroup LMS_Plugins - */ -int -lms_db_playlist_add(lms_db_playlist_t *ldp, struct lms_playlist_info *info) -{ - if (!ldp) - return -1; - if (!info) - return -2; - if (info->id < 1) - return -3; - - return _db_insert(ldp, info); -} diff --git a/lightmediascanner/src/lib/lightmediascanner_db_private.h b/lightmediascanner/src/lib/lightmediascanner_db_private.h deleted file mode 100644 index 4ef6df3..0000000 --- a/lightmediascanner/src/lib/lightmediascanner_db_private.h +++ /dev/null @@ -1,93 +0,0 @@ -/** - * Copyright (C) 2007 by INdT - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser 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 Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * @author Gustavo Sverzut Barbieri - */ - -#ifndef _LIGHTMEDIASCANNER_DB_PRIVATE_H_ -#define _LIGHTMEDIASCANNER_DB_PRIVATE_H_ 1 - -#ifdef __GNUC__ -# if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) -# define GNUC_NON_NULL(...) __attribute__((nonnull(__VA_ARGS__))) -# else -# define GNUC_NON_NULL(...) -# endif -#else -# define GNUC_NON_NULL(...) -#endif - -#include -#include -#include "lightmediascanner_plugin.h" - -sqlite3_stmt *lms_db_compile_stmt(sqlite3 *db, const char *sql) GNUC_NON_NULL(1, 2); -int lms_db_finalize_stmt(sqlite3_stmt *stmt, const char *name) GNUC_NON_NULL(1, 2); -int lms_db_reset_stmt(sqlite3_stmt *stmt) GNUC_NON_NULL(1); -int lms_db_bind_text(sqlite3_stmt *stmt, int col, const char *text, int len) GNUC_NON_NULL(1); -int lms_db_bind_blob(sqlite3_stmt *stmt, int col, const void *blob, int len) GNUC_NON_NULL(1); -int lms_db_bind_int64(sqlite3_stmt *stmt, int col, int64_t value) GNUC_NON_NULL(1); -int lms_db_bind_int64_or_null(sqlite3_stmt *stmt, int col, int64_t *p_value) GNUC_NON_NULL(1); -int lms_db_bind_int(sqlite3_stmt *stmt, int col, int value) GNUC_NON_NULL(1); -int lms_db_bind_double(sqlite3_stmt *stmt, int col, double value) GNUC_NON_NULL(1); -int lms_db_create_trigger_if_not_exists(sqlite3 *db, const char *sql) GNUC_NON_NULL(1, 2); - -int lms_db_table_version_get(sqlite3 *db, const char *table) GNUC_NON_NULL(1, 2); -int lms_db_table_version_set(sqlite3 *db, const char *table, unsigned int version) GNUC_NON_NULL(1, 2); - -typedef int (*lms_db_table_updater_t)(sqlite3 *db, const char *table, unsigned int current_version, int is_last_run); - -int lms_db_table_update(sqlite3 *db, const char *table, unsigned int current_version, unsigned int last_version, const lms_db_table_updater_t *updaters) GNUC_NON_NULL(1, 2, 5); -int lms_db_table_update_if_required(sqlite3 *db, const char *table, unsigned int last_version, lms_db_table_updater_t *updaters) GNUC_NON_NULL(1, 2, 4); - -struct lms_db_cache_entry { - const sqlite3 *db; - void *data; -}; - -struct lms_db_cache { - int size; - struct lms_db_cache_entry *entries; -}; - -int lms_db_cache_add(struct lms_db_cache *cache, const sqlite3 *db, void *data) GNUC_NON_NULL(1, 2, 3); -int lms_db_cache_del(struct lms_db_cache *cache, const sqlite3 *db, void *data) GNUC_NON_NULL(1, 2, 3); -int lms_db_cache_get(struct lms_db_cache *cache, const sqlite3 *db, void **pdata) GNUC_NON_NULL(1, 2, 3); - -int lms_db_create_core_tables_if_required(sqlite3 *db) GNUC_NON_NULL(1); - -sqlite3_stmt *lms_db_compile_stmt_begin_transaction(sqlite3 *db) GNUC_NON_NULL(1); -sqlite3_stmt *lms_db_compile_stmt_end_transaction(sqlite3 *db) GNUC_NON_NULL(1); -sqlite3_stmt *lms_db_compile_stmt_get_file_info(sqlite3 *db) GNUC_NON_NULL(1); -sqlite3_stmt *lms_db_compile_stmt_insert_file_info(sqlite3 *db) GNUC_NON_NULL(1); -sqlite3_stmt *lms_db_compile_stmt_update_file_info(sqlite3 *db) GNUC_NON_NULL(1); -sqlite3_stmt *lms_db_compile_stmt_delete_file_info(sqlite3 *db) GNUC_NON_NULL(1); -sqlite3_stmt *lms_db_compile_stmt_set_file_dtime(sqlite3 *db) GNUC_NON_NULL(1); -sqlite3_stmt *lms_db_compile_stmt_get_files(sqlite3 *db) GNUC_NON_NULL(1); - -int lms_db_begin_transaction(sqlite3_stmt *stmt) GNUC_NON_NULL(1); -int lms_db_end_transaction(sqlite3_stmt *stmt) GNUC_NON_NULL(1); -int lms_db_update_file_info(sqlite3_stmt *stmt, const struct lms_file_info *finfo) GNUC_NON_NULL(1, 2); -int lms_db_get_file_info(sqlite3_stmt *stmt, struct lms_file_info *finfo) GNUC_NON_NULL(1, 2); -int lms_db_insert_file_info(sqlite3_stmt *stmt, struct lms_file_info *finfo) GNUC_NON_NULL(1, 2); -int lms_db_delete_file_info(sqlite3_stmt *stmt, const struct lms_file_info *finfo) GNUC_NON_NULL(1, 2); -int lms_db_set_file_dtime(sqlite3_stmt *stmt, const struct lms_file_info *finfo) GNUC_NON_NULL(1, 2); -int lms_db_get_files(sqlite3_stmt *stmt, const char *path, int len) GNUC_NON_NULL(1, 2); - - - -#endif /* _LIGHTMEDIASCANNER_DB_PRIVATE_H_ */ diff --git a/lightmediascanner/src/lib/lightmediascanner_db_video.c b/lightmediascanner/src/lib/lightmediascanner_db_video.c deleted file mode 100644 index bb6e3d6..0000000 --- a/lightmediascanner/src/lib/lightmediascanner_db_video.c +++ /dev/null @@ -1,279 +0,0 @@ -/** - * Copyright (C) 2007 by INdT - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser 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 Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * @author Gustavo Sverzut Barbieri - */ - -#include -#include "lightmediascanner_db_private.h" -#include -#include - -struct lms_db_video { - sqlite3 *db; - sqlite3_stmt *insert; - unsigned int _references; - unsigned int _is_started:1; -}; - -static struct lms_db_cache _cache = {0, NULL}; - -static int -_db_table_updater_videos_0(sqlite3 *db, const char *table, unsigned int current_version, int is_last_run) { - char *errmsg; - int r, ret; - - errmsg = NULL; - r = sqlite3_exec(db, - "CREATE TABLE IF NOT EXISTS videos (" - "id INTEGER PRIMARY KEY, " - "title TEXT, " - "artist TEXT" - ")", - NULL, NULL, &errmsg); - if (r != SQLITE_OK) { - fprintf(stderr, "ERROR: could not create 'videos' table: %s\n", errmsg); - sqlite3_free(errmsg); - return -1; - } - - r = sqlite3_exec(db, - "CREATE INDEX IF NOT EXISTS videos_title_idx ON videos (" - "title" - ")", - NULL, NULL, &errmsg); - if (r != SQLITE_OK) { - fprintf(stderr, - "ERROR: could not create 'videos_title_idx' index: %s\n", - errmsg); - sqlite3_free(errmsg); - return -2; - } - - r = sqlite3_exec(db, - "CREATE INDEX IF NOT EXISTS videos_artist_idx ON videos (" - "artist" - ")", - NULL, NULL, &errmsg); - if (r != SQLITE_OK) { - fprintf(stderr, - "ERROR: could not create 'videos_artist_idx' index: %s\n", - errmsg); - sqlite3_free(errmsg); - return -3; - } - - ret = lms_db_create_trigger_if_not_exists(db, - "delete_videos_on_files_deleted " - "DELETE ON files FOR EACH ROW BEGIN " - " DELETE FROM videos WHERE id = OLD.id; END;"); - if (ret != 0) - goto done; - - ret = lms_db_create_trigger_if_not_exists(db, - "delete_files_on_videos_deleted " - "DELETE ON videos FOR EACH ROW BEGIN " - " DELETE FROM files WHERE id = OLD.id; END;"); - - done: - return ret; -} - -static lms_db_table_updater_t _db_table_updater_videos[] = { - _db_table_updater_videos_0 -}; - - -static int -_db_create_table_if_required(sqlite3 *db) -{ - return lms_db_table_update_if_required(db, "videos", - LMS_ARRAY_SIZE(_db_table_updater_videos), - _db_table_updater_videos); -} - -/** - * Create video DB access tool. - * - * Creates or get a reference to tools to access 'videos' table in an - * optimized and easy way. - * - * This is usually called from plugin's @b setup() callback with the @p db - * got from @c ctxt. - * - * @param db database connection. - * - * @return DB access tool handle. - * @ingroup LMS_Plugins - */ -lms_db_video_t * -lms_db_video_new(sqlite3 *db) -{ - lms_db_video_t *ldv; - void *p; - - if (lms_db_cache_get(&_cache, db, &p) == 0) { - ldv = p; - ldv->_references++; - return ldv; - } - - if (!db) - return NULL; - - if (_db_create_table_if_required(db) != 0) { - fprintf(stderr, "ERROR: could not create table.\n"); - return NULL; - } - - ldv = calloc(1, sizeof(lms_db_video_t)); - ldv->_references = 1; - ldv->db = db; - - if (lms_db_cache_add(&_cache, db, ldv) != 0) { - lms_db_video_free(ldv); - return NULL; - } - - return ldv; -} - -/** - * Start video DB access tool. - * - * Compile SQL statements and other initialization functions. - * - * This is usually called from plugin's @b start() callback. - * - * @param ldv handle returned by lms_db_video_new(). - * - * @return On success 0 is returned. - * @ingroup LMS_Plugins - */ -int -lms_db_video_start(lms_db_video_t *ldv) -{ - if (!ldv) - return -1; - if (ldv->_is_started) - return 0; - - ldv->insert = lms_db_compile_stmt(ldv->db, - "INSERT OR REPLACE INTO videos (id, title, artist) VALUES (?, ?, ?)"); - if (!ldv->insert) - return -2; - - ldv->_is_started = 1; - return 0; -} - -/** - * Free video DB access tool. - * - * Unreference and possible free resources allocated to access tool. - * - * This is usually called from plugin's @b finish() callback. - * - * @param ldv handle returned by lms_db_video_new(). - * - * @return On success 0 is returned. - * @ingroup LMS_Plugins - */ -int -lms_db_video_free(lms_db_video_t *ldv) -{ - int r; - - if (!ldv) - return -1; - if (ldv->_references == 0) { - fprintf(stderr, "ERROR: over-called lms_db_video_free(%p)\n", ldv); - return -1; - } - - ldv->_references--; - if (ldv->_references > 0) - return 0; - - if (ldv->insert) - lms_db_finalize_stmt(ldv->insert, "insert"); - - r = lms_db_cache_del(&_cache, ldv->db, ldv); - free(ldv); - - return r; -} - -static int -_db_insert(lms_db_video_t *ldv, const struct lms_video_info *info) -{ - sqlite3_stmt *stmt; - int r, ret; - - stmt = ldv->insert; - - ret = lms_db_bind_int64(stmt, 1, info->id); - if (ret != 0) - goto done; - - ret = lms_db_bind_text(stmt, 2, info->title.str, info->title.len); - if (ret != 0) - goto done; - - ret = lms_db_bind_text(stmt, 3, info->artist.str, info->artist.len); - if (ret != 0) - goto done; - - r = sqlite3_step(stmt); - if (r != SQLITE_DONE) { - fprintf(stderr, "ERROR: could not insert video info: %s\n", - sqlite3_errmsg(ldv->db)); - ret = -4; - goto done; - } - - ret = 0; - - done: - lms_db_reset_stmt(stmt); - - return ret; -} - -/** - * Add video file to DB. - * - * This is usually called from plugin's @b parse() callback. - * - * @param ldv handle returned by lms_db_video_new(). - * @param info video information to store. - * - * @return On success 0 is returned. - * @ingroup LMS_Plugins - */ -int -lms_db_video_add(lms_db_video_t *ldv, struct lms_video_info *info) -{ - if (!ldv) - return -1; - if (!info) - return -2; - if (info->id < 1) - return -3; - - return _db_insert(ldv, info); -} diff --git a/lightmediascanner/src/lib/lightmediascanner_plugin.h b/lightmediascanner/src/lib/lightmediascanner_plugin.h deleted file mode 100644 index c2f49a0..0000000 --- a/lightmediascanner/src/lib/lightmediascanner_plugin.h +++ /dev/null @@ -1,168 +0,0 @@ -/** - * Copyright (C) 2007 by INdT - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser 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 Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * @author Gustavo Sverzut Barbieri - */ - -/** - * @defgroup LMS_Plugin Plugins-API - * - * - * Plugins should implement the following call that provides required - * callbacks (see lightmediascanner_plugin.h): - * - * @code - * struct lms_plugin *lms_plugin_open(void) - * @endcode - * - * where: - * - * @code - * struct lms_plugin { - * const char *name; - * lms_plugin_match_fn_t match; - * lms_plugin_parse_fn_t parse; - * lms_plugin_close_fn_t close; - * lms_plugin_setup_fn_t setup; - * lms_plugin_start_fn_t start; - * lms_plugin_finish_fn_t finish; - * }; - * @endcode - * - * Users can add their own data to the end of this data - * structure. Callbacks and their meanings are: - * - * @code - * void *match(lms_plugin_t *p, - * const char *path, - * int len, - * int base) - * @endcode - * - * Given the file 'path' of 'len' bytes, with base name starting at - * 'base' bytes offset inside 'path', return a match. Non-NULL - * values means it matched, and this return will be given to - * parse() function so any match-time analysis can be reused. - * This function will be used in the slave process. - * - * - * @code - * int parse(lms_plugin_t *p, - * struct lms_context *ctxt, - * const struct lms_file_info *finfo, - * void *match) - * @endcode - * - * Given the parsing context 'ctxt' (contains DB connection, - * charset conversion pointers and possible more), parse the file - * information 'finfo' using the previously matched data - * 'match'. This should return 0 on success or other value for - * errors. This will be used in the slave process. - * - * - * @code - * int close(lms_plugin_t *p) - * @endcode - * - * Closes the plugin returned by lms_plugin_open(), this will run - * on the master process. - * - * - * @code - * int setup(lms_plugin_t *p, struct lms_context *ctxt) - * @endcode - * - * Prepare parser to be executed. This is the first phase of plugin - * initialization on the slave process, it should create database - * tables and like, after this function is called, no database - * schema changes are allowed! - * - * - * @code - * int start(lms_plugin_t *p, struct lms_context *ctxt) - * @endcode - * - * This is the second phase of plugin initialization on the slave - * process. At this point, all database tables should exist and - * database schema will not be changed anymore, so one can use this - * phase to compile SQL statements for future use. - * - * - * @code - * int finish(lms_plugin_t *p, struct lms_context *ctxt) - * @endcode - * - * Finishes the plugin on slave process. - * - * - * Although LMS doesn't place any restrictions on what plugins can do and - * how they store information, it's good to have standard tables and easy - * way to store data on them. For this task we provide - * lightmediascanner_db.h with functions to add audios, images, videos, - * playlists and possible more. Use should be pretty straightforward, see - * existing plugins to see usage examples. - * - */ - -#ifndef _LIGHTMEDIASCANNER_PLUGIN_H_ -#define _LIGHTMEDIASCANNER_PLUGIN_H_ 1 - -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - - struct lms_file_info { - const char *path; /**< file path */ - int path_len; /**< path length */ - int base; /**< index of basename inside path */ - int64_t id; /**< database id */ - time_t mtime; /**< in-disk modification time */ - time_t dtime; /**< deletion time */ - size_t size; /**< file size in bytes */ - }; - - struct lms_context { - sqlite3 *db; /**< database instance */ - lms_charset_conv_t *cs_conv; /**< charset conversion tool */ - }; - - typedef void *(*lms_plugin_match_fn_t)(lms_plugin_t *p, const char *path, int len, int base); - typedef int (*lms_plugin_parse_fn_t)(lms_plugin_t *p, struct lms_context *ctxt, const struct lms_file_info *finfo, void *match); - typedef int (*lms_plugin_close_fn_t)(lms_plugin_t *p); - typedef int (*lms_plugin_setup_fn_t)(lms_plugin_t *p, struct lms_context *ctxt); - typedef int (*lms_plugin_start_fn_t)(lms_plugin_t *p, struct lms_context *ctxt); - typedef int (*lms_plugin_finish_fn_t)(lms_plugin_t *p, struct lms_context *ctxt); - - struct lms_plugin { - const char *name; /**< plugin name */ - lms_plugin_match_fn_t match; /**< check match */ - lms_plugin_parse_fn_t parse; /**< parse matched file */ - lms_plugin_close_fn_t close; /**< close plugin */ - lms_plugin_setup_fn_t setup; /**< setup (1st phase init) */ - lms_plugin_start_fn_t start; /**< start (2nd phase init) */ - lms_plugin_finish_fn_t finish; /**< finish plugin */ - }; - -#ifdef __cplusplus -} -#endif -#endif /* _LIGHTMEDIASCANNER_PLUGIN_H_ */ diff --git a/lightmediascanner/src/lib/lightmediascanner_private.h b/lightmediascanner/src/lib/lightmediascanner_private.h deleted file mode 100644 index e92d6e3..0000000 --- a/lightmediascanner/src/lib/lightmediascanner_private.h +++ /dev/null @@ -1,89 +0,0 @@ -/** - * Copyright (C) 2007 by INdT - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser 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 Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * @author Gustavo Sverzut Barbieri - */ - -#ifndef _LIGHTMEDIASCANNER_PRIVATE_H_ -#define _LIGHTMEDIASCANNER_PRIVATE_H_ 1 - -#ifdef __GNUC__ -# if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) -# define GNUC_NON_NULL(...) __attribute__((nonnull(__VA_ARGS__))) -# else -# define GNUC_NON_NULL(...) -# endif -#else -# define GNUC_NON_NULL(...) -#endif - -#include "lightmediascanner.h" -#include "lightmediascanner_plugin.h" -#include "lightmediascanner_charset_conv.h" -#include -#include -#include -#include - -#define PATH_SIZE PATH_MAX - -struct fds { - int r; - int w; -}; - -/* info to be carried along lms_process() and lms_check() */ -struct pinfo { - struct fds master; - struct fds slave; - struct pollfd poll; - lms_t *lms; - pid_t child; -}; - -struct parser { - lms_plugin_t *plugin; - void *dl_handle; - char *so_path; -}; - -struct lms { - struct parser *parsers; - int n_parsers; - lms_charset_conv_t *cs_conv; - char *db_path; - int slave_timeout; - unsigned int commit_interval; - unsigned int is_processing:1; - unsigned int stop_processing:1; -}; - -int lms_parser_del_int(lms_t *lms, int i) GNUC_NON_NULL(1); -int lms_create_pipes(struct pinfo *pinfo) GNUC_NON_NULL(1); -int lms_close_pipes(struct pinfo *pinfo) GNUC_NON_NULL(1); -int lms_create_slave(struct pinfo *pinfo, int (*work)(lms_t *lms, struct fds *fds)) GNUC_NON_NULL(1, 2); -int lms_restart_slave(struct pinfo *pinfo, int (*work)(lms_t *lms, struct fds *fds)) GNUC_NON_NULL(1, 2); -int lms_finish_slave(struct pinfo *pinfo, int (*finish)(const struct fds *fds)) GNUC_NON_NULL(1, 2); - -int lms_parsers_setup(lms_t *lms, sqlite3 *db) GNUC_NON_NULL(1, 2); -int lms_parsers_start(lms_t *lms, sqlite3 *db) GNUC_NON_NULL(1, 2); -int lms_parsers_finish(lms_t *lms, sqlite3 *db) GNUC_NON_NULL(1, 2); -int lms_parsers_check_using(lms_t *lms, void **parser_match, struct lms_file_info *finfo) GNUC_NON_NULL(1, 2, 3); -int lms_parsers_run(lms_t *lms, sqlite3 *db, void **parser_match, struct lms_file_info *finfo) GNUC_NON_NULL(1, 2, 3, 4); - - -#endif /* _LIGHTMEDIASCANNER_PRIVATE_H_ */ diff --git a/lightmediascanner/src/lib/lightmediascanner_process.c b/lightmediascanner/src/lib/lightmediascanner_process.c deleted file mode 100644 index 80a1cbd..0000000 --- a/lightmediascanner/src/lib/lightmediascanner_process.c +++ /dev/null @@ -1,904 +0,0 @@ -/** - * Copyright (C) 2007 by INdT - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser 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 Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * @author Gustavo Sverzut Barbieri - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#define _GNU_SOURCE -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "lightmediascanner.h" -#include "lightmediascanner_private.h" -#include "lightmediascanner_db_private.h" - -struct db { - sqlite3 *handle; - sqlite3_stmt *transaction_begin; - sqlite3_stmt *transaction_commit; - sqlite3_stmt *get_file_info; - sqlite3_stmt *insert_file_info; - sqlite3_stmt *update_file_info; - sqlite3_stmt *delete_file_info; - sqlite3_stmt *set_file_dtime; -}; - -/*********************************************************************** - * Master-Slave communication. - ***********************************************************************/ - -static int -_master_send_path(const struct fds *master, int plen, int dlen, const char *p) -{ - int lengths[2]; - - lengths[0] = plen; - lengths[1] = dlen; - - if (write(master->w, lengths, sizeof(lengths)) < 0) { - perror("write"); - return -1; - } - - if (write(master->w, p, plen) < 0) { - perror("write"); - return -1; - } - - return 0; -} - -static int -_master_send_finish(const struct fds *master) -{ - const int lengths[2] = {-1, -1}; - - if (write(master->w, lengths, sizeof(lengths)) < 0) { - perror("write"); - return -1; - } - return 0; -} - -static int -_master_recv_reply(const struct fds *master, struct pollfd *pfd, int *reply, int timeout) -{ - int r; - - r = poll(pfd, 1, timeout); - if (r < 0) { - perror("poll"); - return -1; - } - - if (r == 0) - return 1; - - if (read(master->r, reply, sizeof(*reply)) != sizeof(*reply)) { - perror("read"); - return -2; - } - - return 0; -} - -static int -_slave_send_reply(const struct fds *slave, int reply) -{ - if (write(slave->w, &reply, sizeof(reply)) == 0) { - perror("write"); - return -1; - } - return 0; -} - -static int -_slave_recv_path(const struct fds *slave, int *plen, int *dlen, char *path) -{ - int lengths[2], r; - - r = read(slave->r, lengths, sizeof(lengths)); - if (r != sizeof(lengths)) { - perror("read"); - return -1; - } - *plen = lengths[0]; - *dlen = lengths[1]; - - if (*plen == -1) - return 0; - - if (*plen > PATH_SIZE) { - fprintf(stderr, "ERROR: path too long (%d/%d)\n", *plen, PATH_SIZE); - return -2; - } - - r = read(slave->r, path, *plen); - if (r != *plen) { - fprintf(stderr, "ERROR: could not read whole path %d/%d\n", r, *plen); - return -3; - } - - path[*plen] = 0; - return 0; -} - - -/*********************************************************************** - * Slave-side. - ***********************************************************************/ - -static int -_db_compile_all_stmts(struct db *db) -{ - sqlite3 *handle; - - handle = db->handle; - db->transaction_begin = lms_db_compile_stmt_begin_transaction(handle); - if (!db->transaction_begin) - return -1; - - db->transaction_commit = lms_db_compile_stmt_end_transaction(handle); - if (!db->transaction_commit) - return -2; - - db->get_file_info = lms_db_compile_stmt_get_file_info(handle); - if (!db->get_file_info) - return -4; - - db->insert_file_info = lms_db_compile_stmt_insert_file_info(handle); - if (!db->insert_file_info) - return -5; - - db->update_file_info = lms_db_compile_stmt_update_file_info(handle); - if (!db->update_file_info) - return -6; - - db->delete_file_info = lms_db_compile_stmt_delete_file_info(handle); - if (!db->delete_file_info) - return -6; - - db->set_file_dtime = lms_db_compile_stmt_set_file_dtime(handle); - if (!db->set_file_dtime) - return -7; - - return 0; -} - -static struct db * -_db_open(const char *db_path) -{ - struct db *db; - - db = calloc(1, sizeof(*db)); - if (!db) { - perror("calloc"); - return NULL; - } - - if (sqlite3_open(db_path, &db->handle) != SQLITE_OK) { - fprintf(stderr, "ERROR: could not open DB \"%s\": %s\n", - db_path, sqlite3_errmsg(db->handle)); - goto error; - } - - if (lms_db_create_core_tables_if_required(db->handle) != 0) { - fprintf(stderr, "ERROR: could not setup tables and indexes.\n"); - goto error; - } - - return db; - - error: - sqlite3_close(db->handle); - free(db); - return NULL; -} - -static int -_db_close(struct db *db) -{ - if (db->transaction_begin) - lms_db_finalize_stmt(db->transaction_begin, "transaction_begin"); - - if (db->transaction_commit) - lms_db_finalize_stmt(db->transaction_commit, "transaction_commit"); - - if (db->get_file_info) - lms_db_finalize_stmt(db->get_file_info, "get_file_info"); - - if (db->insert_file_info) - lms_db_finalize_stmt(db->insert_file_info, "insert_file_info"); - - if (db->update_file_info) - lms_db_finalize_stmt(db->update_file_info, "update_file_info"); - - if (db->delete_file_info) - lms_db_finalize_stmt(db->delete_file_info, "delete_file_info"); - - if (db->set_file_dtime) - lms_db_finalize_stmt(db->set_file_dtime, "set_file_dtime"); - - if (sqlite3_close(db->handle) != SQLITE_OK) { - fprintf(stderr, "ERROR: clould not close DB: %s\n", - sqlite3_errmsg(db->handle)); - return -1; - } - free(db); - - return 0; -} - -static int -_retrieve_file_status(struct db *db, struct lms_file_info *finfo) -{ - struct stat st; - int r; - - if (stat(finfo->path, &st) != 0) { - perror("stat"); - return -1; - } - - r = lms_db_get_file_info(db->get_file_info, finfo); - if (r == 0) { - if (st.st_mtime <= finfo->mtime && finfo->size == st.st_size) - return 0; - else { - finfo->mtime = st.st_mtime; - finfo->size = st.st_size; - return 1; - } - } else if (r == 1) { - finfo->mtime = st.st_mtime; - finfo->size = st.st_size; - return 1; - } else - return -2; -} - -static void -_ctxt_init(struct lms_context *ctxt, const lms_t *lms, sqlite3 *db) -{ - ctxt->cs_conv = lms->cs_conv; - ctxt->db = db; -} - -int -lms_parsers_setup(lms_t *lms, sqlite3 *db) -{ - struct lms_context ctxt; - int i; - - _ctxt_init(&ctxt, lms, db); - - for (i = 0; i < lms->n_parsers; i++) { - lms_plugin_t *plugin; - int r; - - plugin = lms->parsers[i].plugin; - r = plugin->setup(plugin, &ctxt); - if (r != 0) { - fprintf(stderr, "ERROR: parser \"%s\" failed to setup: %d.\n", - plugin->name, r); - plugin->finish(plugin, &ctxt); - lms_parser_del_int(lms, i); - i--; /* cancel i++ */ - } - } - - return 0; -} - -int -lms_parsers_start(lms_t *lms, sqlite3 *db) -{ - struct lms_context ctxt; - int i; - - _ctxt_init(&ctxt, lms, db); - - for (i = 0; i < lms->n_parsers; i++) { - lms_plugin_t *plugin; - int r; - - plugin = lms->parsers[i].plugin; - r = plugin->start(plugin, &ctxt); - if (r != 0) { - fprintf(stderr, "ERROR: parser \"%s\" failed to start: %d.\n", - plugin->name, r); - plugin->finish(plugin, &ctxt); - lms_parser_del_int(lms, i); - i--; /* cancel i++ */ - } - } - - return 0; -} - -int -lms_parsers_finish(lms_t *lms, sqlite3 *db) -{ - struct lms_context ctxt; - int i; - - _ctxt_init(&ctxt, lms, db); - - for (i = 0; i < lms->n_parsers; i++) { - lms_plugin_t *plugin; - int r; - - plugin = lms->parsers[i].plugin; - r = plugin->finish(plugin, &ctxt); - if (r != 0) - fprintf(stderr, "ERROR: parser \"%s\" failed to finish: %d.\n", - plugin->name, r); - } - - return 0; -} - -int -lms_parsers_check_using(lms_t *lms, void **parser_match, struct lms_file_info *finfo) -{ - int used, i; - - used = 0; - for (i = 0; i < lms->n_parsers; i++) { - lms_plugin_t *plugin; - void *r; - - plugin = lms->parsers[i].plugin; - r = plugin->match(plugin, finfo->path, finfo->path_len, finfo->base); - parser_match[i] = r; - if (r) - used = 1; - } - - return used; -} - -int -lms_parsers_run(lms_t *lms, sqlite3 *db, void **parser_match, struct lms_file_info *finfo) -{ - struct lms_context ctxt; - int i, failed, available; - - _ctxt_init(&ctxt, lms, db); - - failed = 0; - available = 0; - for (i = 0; i < lms->n_parsers; i++) { - lms_plugin_t *plugin; - - plugin = lms->parsers[i].plugin; - if (parser_match[i]) { - int r; - - available++; - r = plugin->parse(plugin, &ctxt, finfo, parser_match[i]); - if (r != 0) - failed++; - } - } - - if (!failed) - return 0; - else if (failed == available) - return -1; - else - return 1; /* non critical */ -} - -static int -_slave_work(lms_t *lms, struct fds *fds) -{ - int r, len, base, counter; - char path[PATH_SIZE]; - void **parser_match; - struct db *db; - - db = _db_open(lms->db_path); - if (!db) - return -1; - - if (lms_parsers_setup(lms, db->handle) != 0) { - fprintf(stderr, "ERROR: could not setup parsers.\n"); - r = -2; - goto end; - } - - if (_db_compile_all_stmts(db) != 0) { - fprintf(stderr, "ERROR: could not compile statements.\n"); - r = -3; - goto end; - } - - if (lms_parsers_start(lms, db->handle) != 0) { - fprintf(stderr, "ERROR: could not start parsers.\n"); - r = -4; - goto end; - } - if (lms->n_parsers < 1) { - fprintf(stderr, "ERROR: no parser could be started, exit.\n"); - r = -5; - goto end; - } - - parser_match = malloc(lms->n_parsers * sizeof(*parser_match)); - if (!parser_match) { - perror("malloc"); - r = -6; - goto end; - } - - counter = 0; - lms_db_begin_transaction(db->transaction_begin); - - while (((r = _slave_recv_path(fds, &len, &base, path)) == 0) && len > 0) { - struct lms_file_info finfo; - int used, r; - - finfo.path = path; - finfo.path_len = len; - finfo.base = base; - - r = _retrieve_file_status(db, &finfo); - if (r == 0) { - if (finfo.dtime) { - finfo.dtime = 0; - lms_db_set_file_dtime(db->set_file_dtime, &finfo); - } - goto inform_end; - } else if (r < 0) { - fprintf(stderr, "ERROR: could not detect file status.\n"); - goto inform_end; - } - - used = lms_parsers_check_using(lms, parser_match, &finfo); - if (!used) - goto inform_end; - - finfo.dtime = 0; - if (finfo.id > 0) - r = lms_db_update_file_info(db->update_file_info, &finfo); - else - r = lms_db_insert_file_info(db->insert_file_info, &finfo); - if (r < 0) { - fprintf(stderr, "ERROR: could not register path in DB\n"); - goto inform_end; - } - - r = lms_parsers_run(lms, db->handle, parser_match, &finfo); - if (r < 0) { - fprintf(stderr, "ERROR: pid=%d failed to parse \"%s\".\n", - getpid(), finfo.path); - lms_db_delete_file_info(db->delete_file_info, &finfo); - } - - inform_end: - _slave_send_reply(fds, r); - counter++; - if (counter > lms->commit_interval) { - lms_db_end_transaction(db->transaction_commit); - lms_db_begin_transaction(db->transaction_begin); - counter = 0; - } - } - - free(parser_match); - lms_db_end_transaction(db->transaction_commit); - end: - lms_parsers_finish(lms, db->handle); - _db_close(db); - - return r; -} - - -/*********************************************************************** - * Master-side. - ***********************************************************************/ - -static int -_consume_garbage(struct pollfd *pfd) -{ - int r; - - while ((r = poll(pfd, 1, 0)) > 0) { - if (pfd->revents & (POLLERR | POLLHUP | POLLNVAL)) - return 0; - else if (pfd->revents & POLLIN) { - char c; - - read(pfd->fd, &c, sizeof(c)); - } - } - - return r; -} - -static int -_close_fds(struct fds *fds) -{ - int r; - - r = 0; - if (close(fds->r) != 0) { - r--; - perror("close"); - } - - if (close(fds->w) != 0) { - r--; - perror("close"); - } - - return r; -} - -int -lms_close_pipes(struct pinfo *pinfo) -{ - int r; - - r = _close_fds(&pinfo->master); - r += _close_fds(&pinfo->slave); - - return r; -} - -int -lms_create_pipes(struct pinfo *pinfo) -{ - int fds[2]; - - if (pipe(fds) != 0) { - perror("pipe"); - return -1; - } - pinfo->master.r = fds[0]; - pinfo->slave.w = fds[1]; - - if (pipe(fds) != 0) { - perror("pipe"); - close(pinfo->master.r); - close(pinfo->slave.w); - return -1; - } - pinfo->slave.r = fds[0]; - pinfo->master.w = fds[1]; - - pinfo->poll.fd = pinfo->master.r; - pinfo->poll.events = POLLIN; - - return 0; -} - -int -lms_create_slave(struct pinfo *pinfo, int (*work)(lms_t *lms, struct fds *fds)) -{ - int r; - - pinfo->child = fork(); - if (pinfo->child == -1) { - perror("fork"); - return -1; - } - - if (pinfo->child > 0) - return 0; - - _close_fds(&pinfo->master); - nice(19); - r = work(pinfo->lms, &pinfo->slave); - lms_free(pinfo->lms); - _exit(r); - return r; /* shouldn't reach anyway... */ -} - -static int -_waitpid(pid_t pid) -{ - int status; - pid_t r; - - r = waitpid(pid, &status, 0); - if (r > -1) - return 0; - else - perror("waitpid"); - - return r; -} - -int -lms_finish_slave(struct pinfo *pinfo, int (*finish)(const struct fds *fds)) -{ - int r; - - if (pinfo->child <= 0) - return 0; - - r = finish(&pinfo->master); - if (r == 0) - r = _waitpid(pinfo->child); - else { - r = kill(pinfo->child, SIGKILL); - if (r < 0) - perror("kill"); - else - r =_waitpid(pinfo->child); - } - pinfo->child = 0; - - return r; -} - -int -lms_restart_slave(struct pinfo *pinfo, int (*work)(lms_t *lms, struct fds *fds)) -{ - int status; - - if (waitpid(pinfo->child, &status, WNOHANG) > 0) { - if (WIFEXITED(status)) { - int code; - - code = WEXITSTATUS(status); - if (code != 0) { - fprintf(stderr, "ERROR: slave returned %d, exit.\n", code); - pinfo->child = 0; - return -1; - } - } else { - if (WIFSIGNALED(status)) { - int code; - - code = WTERMSIG(status); - fprintf(stderr, "ERROR: slave was terminated by signal %d.\n", - code); - } - pinfo->child = 0; - return -1; - } - } - - if (kill(pinfo->child, SIGKILL)) - perror("kill"); - - if (waitpid(pinfo->child, &status, 0) < 0) - perror("waitpid"); - - _consume_garbage(&pinfo->poll); - return lms_create_slave(pinfo, work); -} - -static int -_strcat(int base, char *path, const char *name) -{ - int new_len, name_len; - - name_len = strlen(name); - new_len = base + name_len; - - if (new_len >= PATH_SIZE) { - path[base] = '\0'; - fprintf(stderr, - "ERROR: path concatenation too long %d of %d " - "available: \"%s\" + \"%s\"\n", new_len, PATH_SIZE, - path, name); - return -1; - } - - memcpy(path + base, name, name_len + 1); - - return new_len; -} - -static int -_process_file(struct pinfo *pinfo, int base, char *path, const char *name) -{ - int new_len, reply, r; - - new_len = _strcat(base, path, name); - if (new_len < 0) - return -1; - - if (_master_send_path(&pinfo->master, new_len, base, path) != 0) - return -2; - - r = _master_recv_reply(&pinfo->master, &pinfo->poll, &reply, - pinfo->lms->slave_timeout); - if (r < 0) - return -3; - else if (r == 1) { - fprintf(stderr, "ERROR: slave took too long, restart %d\n", - pinfo->child); - if (lms_restart_slave(pinfo, _slave_work) != 0) - return -4; - return 1; - } else { - if (reply < 0) { - /* XXX callback library users to inform error. */ - fprintf(stderr, "ERROR: pid=%d failed to parse \"%s\".\n", - getpid(), path); - return (-reply) << 8; - } else - return reply; - } -} - -static int -_process_dir(struct pinfo *pinfo, int base, char *path, const char *name) -{ - DIR *dir; - struct dirent *de; - lms_t *lms; - int new_len, r; - - new_len = _strcat(base, path, name); - if (new_len < 0) - return -1; - else if (new_len + 1 >= PATH_SIZE) { - fprintf(stderr, "ERROR: path too long\n"); - return 2; - } - - dir = opendir(path); - if (dir == NULL) { - perror("opendir"); - return 3; - } - - path[new_len] = '/'; - new_len++; - - r = 0; - lms = pinfo->lms; - while ((de = readdir(dir)) != NULL && !lms->stop_processing) { - if (de->d_name[0] == '.') - continue; - if (de->d_type == DT_REG) { - if (_process_file(pinfo, new_len, path, de->d_name) < 0) { - fprintf(stderr, - "ERROR: unrecoverable error parsing file, " - "exit \"%s\".\n", path); - path[new_len - 1] = '\0'; - r = -4; - goto end; - } - } else if (de->d_type == DT_DIR || de->d_type == DT_UNKNOWN) { - if (_process_dir(pinfo, new_len, path, de->d_name) < 0) { - fprintf(stderr, - "ERROR: unrecoverable error parsing dir, " - "exit \"%s\".\n", path); - path[new_len - 1] = '\0'; - r = -5; - goto end; - } - } - } - - end: - closedir(dir); - return r; -} - -/** - * Process the given directory. - * - * This will add or update media found in the given directory or its children. - * - * @param lms previously allocated Light Media Scanner instance. - * @param top_path top directory to scan. - * - * @return On success 0 is returned. - */ -int -lms_process(lms_t *lms, const char *top_path) -{ - struct pinfo pinfo; - int r, len; - char path[PATH_SIZE], *bname; - - if (!lms) { - r = -1; - goto end; - } - - if (!top_path) { - r = -2; - goto end; - } - - if (lms->is_processing) { - fprintf(stderr, "ERROR: is already processing.\n"); - r = -3; - goto end; - } - - if (!lms->parsers) { - fprintf(stderr, "ERROR: no plugins registered.\n"); - r = -4; - goto end; - } - - pinfo.lms = lms; - - if (lms_create_pipes(&pinfo) != 0) { - r = -5; - goto end; - } - - if (lms_create_slave(&pinfo, _slave_work) != 0) { - r = -6; - goto close_pipes; - } - - if (realpath(top_path, path) == NULL) { - perror("realpath"); - r = -7; - goto finish_slave; - } - - /* search '/' backwards, split dirname and basename, note realpath usage */ - len = strlen(path); - for (; len >= 0 && path[len] != '/'; len--); - len++; - bname = strdup(path + len); - if (bname == NULL) { - perror("strdup"); - r = -8; - goto finish_slave; - } - - lms->is_processing = 1; - lms->stop_processing = 0; - r = _process_dir(&pinfo, len, path, bname); - lms->is_processing = 0; - lms->stop_processing = 0; - free(bname); - - finish_slave: - lms_finish_slave(&pinfo, _master_send_finish); - close_pipes: - lms_close_pipes(&pinfo); - end: - return r; -} - -void -lms_stop_processing(lms_t *lms) -{ - if (!lms) - return; - if (!lms->is_processing) - return; - - lms->stop_processing = 1; -} diff --git a/lightmediascanner/src/lib/lightmediascanner_utils.c b/lightmediascanner/src/lib/lightmediascanner_utils.c deleted file mode 100644 index c33dca4..0000000 --- a/lightmediascanner/src/lib/lightmediascanner_utils.c +++ /dev/null @@ -1,177 +0,0 @@ -/** - * Copyright (C) 2007 by INdT - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser 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 Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * @author Gustavo Sverzut Barbieri - */ - -#include -#include -#include -#include - -/** - * Strips string, in place. - * - * @param str string to be stripped. - * @param p_len string length to analyse, also the place where the final size - * is stored. - */ -void -lms_strstrip(char *str, unsigned int *p_len) -{ - int i, len; - char *p; - - len = *p_len; - - if (len == 0) - return; - - if (*str == '\0') { - *p_len = 0; - return; - } - - p = str + len - 1; - for (i = len - 1; i >= 0; i--) { - if (isspace(*p) || *p == '\0') { - *p = '\0'; - len--; - p--; - } else - break; - } - if (len == 0) { - *p_len = 0; - return; - } - - p = str; - for (i = 0; i < len; i++) { - if (isspace(*p)) - p++; - else - break; - } - len -= i; - if (len == 0) { - *str = '\0'; - *p_len = 0; - return; - } - - *p_len = len; - - if (str < p) - for (; len >= 0; len--, str++, p++) - *str = *p; -} - -/** - * If string exists, strips it, in place, free if *p_len = 0 - * - * @param p_str pointer to string to be stripped. - * @param p_len string length to analyse, also the place where the final size - * is stored. - * - * @note this will call free() on *p_str if it becomes empty. - */ -void -lms_strstrip_and_free(char **p_str, unsigned int *p_len) -{ - if (!*p_str) - return; - - lms_strstrip(*p_str, p_len); - if (*p_len == 0) { - free(*p_str); - *p_str = NULL; - } -} - -/** - * lms_string_size version of lms_strstrip_and_free(). - * - * @param *p pointer to lms_string_size to be stripped. - * - * @note this will call free() on lms_string_size->str if it becomes empty. - */ -void -lms_string_size_strip_and_free(struct lms_string_size *p) -{ - if (!p->str) - return; - - lms_strstrip(p->str, &p->len); - if (p->len == 0) { - free(p->str); - p->str = NULL; - } -} - - -/** - * Find out which of the given extensions matches the given name. - * - * @param name string to analyse. - * @param name_len string length. - * @param exts array of extensions to be checked. - * @param exts_len number of items in array @p exts - * - * @return index in @p exts or -1 if it doesn't match none. - */ -int -lms_which_extension(const char *name, unsigned int name_len, const struct lms_string_size *exts, unsigned int exts_len) { - int i; - unsigned int *exts_pos; - const char *s; - - exts_pos = alloca(exts_len * sizeof(*exts_pos)); - for (i = 0; i < exts_len; i++) - exts_pos[i] = exts[i].len; - - for (s = name + name_len - 1; s >= name; s--) { - int i, match; - char c1, c2; - - c1 = *s; - if (c1 >= 'a') - c2 = c1; - else - c2 = 'a' + c1 - 'A'; - - match = 0; - for (i = 0; i < exts_len; i++) { - if (exts_pos[i] > 0) { - char ce; - - ce = exts[i].str[exts_pos[i] - 1]; - if (ce == c1 || ce == c2) { - if (exts_pos[i] == 1) - return i; - exts_pos[i]--; - match = 1; - } else - exts_pos[i] = 0; - } - } - if (!match) - return -1; - } - - return -1; -} diff --git a/lightmediascanner/src/lib/lightmediascanner_utils.h b/lightmediascanner/src/lib/lightmediascanner_utils.h deleted file mode 100644 index dc0c773..0000000 --- a/lightmediascanner/src/lib/lightmediascanner_utils.h +++ /dev/null @@ -1,68 +0,0 @@ -/** - * Copyright (C) 2007 by INdT - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser 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 Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * @author Gustavo Sverzut Barbieri - */ - -#ifndef _LIGHTMEDIASCANNER_UTILS_H_ -#define _LIGHTMEDIASCANNER_UTILS_H_ 1 - -#ifdef API -#undef API -#endif - -#ifdef __GNUC__ -# if __GNUC__ >= 4 -# define API __attribute__ ((visibility("default"))) -# else -# define API -# endif -# if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) -# define GNUC_NON_NULL(...) __attribute__((nonnull(__VA_ARGS__))) -# else -# define GNUC_NON_NULL(...) -# endif -#else -# define API -# define GNUC_NON_NULL(...) -#endif - -#ifdef __cplusplus -extern "C" { -#endif - - - struct lms_string_size { - char *str; - unsigned int len; - }; - -#define LMS_STATIC_STRING_SIZE(s) {s, sizeof(s) - 1} -#define LMS_ARRAY_SIZE(a) (sizeof(a) / sizeof(*a)) - - - API void lms_strstrip(char *str, unsigned int *p_len) GNUC_NON_NULL(1, 2); - API void lms_strstrip_and_free(char **p_str, unsigned int *p_len) GNUC_NON_NULL(1, 2); - API void lms_string_size_strip_and_free(struct lms_string_size *p) GNUC_NON_NULL(1); - API int lms_which_extension(const char *name, unsigned int name_len, const struct lms_string_size *exts, unsigned int exts_len) GNUC_NON_NULL(1, 3); - - - -#ifdef __cplusplus -} -#endif -#endif /* _LIGHTMEDIASCANNER_UTILS_H_ */ diff --git a/lightmediascanner/src/plugins/Makefile.am b/lightmediascanner/src/plugins/Makefile.am deleted file mode 100644 index bb22f06..0000000 --- a/lightmediascanner/src/plugins/Makefile.am +++ /dev/null @@ -1,70 +0,0 @@ -MAINTAINERCLEANFILES = Makefile.in - -SUBDIRS = - -if USE_MODULE_DUMMY -SUBDIRS += dummy -endif - -if USE_MODULE_JPEG -SUBDIRS += jpeg -endif - -if USE_MODULE_PNG -SUBDIRS += png -endif - -if USE_MODULE_VIDEO_DUMMY -SUBDIRS += video-dummy -endif - -if USE_MODULE_AUDIO_DUMMY -SUBDIRS += audio-dummy -endif - -if USE_MODULE_M3U -SUBDIRS += m3u -endif - -if USE_MODULE_PLS -SUBDIRS += pls -endif - -if USE_MODULE_OGG -SUBDIRS += ogg -endif - -if USE_MODULE_ASF -SUBDIRS += asf -endif - -if USE_MODULE_RM -SUBDIRS += rm -endif - -if USE_MODULE_MP4 -SUBDIRS += mp4 -endif - -if USE_MODULE_ID3 -SUBDIRS += id3 -endif - -if USE_MODULE_FLAC -SUBDIRS += flac -endif - -DIST_SUBDIRS = \ - dummy \ - jpeg \ - png \ - video-dummy \ - audio-dummy \ - m3u \ - ogg \ - pls \ - asf \ - rm \ - mp4 \ - id3 \ - flac diff --git a/lightmediascanner/src/plugins/asf/Makefile.am b/lightmediascanner/src/plugins/asf/Makefile.am deleted file mode 100644 index f4e784c..0000000 --- a/lightmediascanner/src/plugins/asf/Makefile.am +++ /dev/null @@ -1,10 +0,0 @@ -MAINTAINERCLEANFILES = Makefile.in - -AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_srcdir)/src/plugins/asf - -pkgdir = $(pluginsdir) -pkg_LTLIBRARIES = asf.la -asf_la_SOURCES = asf.c -asf_la_DEPENDENCIES = $(top_builddir)/config.h -asf_la_LIBADD = $(top_builddir)/src/lib/liblightmediascanner.la -asf_la_LDFLAGS = -module -avoid-version diff --git a/lightmediascanner/src/plugins/asf/asf.c b/lightmediascanner/src/plugins/asf/asf.c deleted file mode 100644 index ae828df..0000000 --- a/lightmediascanner/src/plugins/asf/asf.c +++ /dev/null @@ -1,568 +0,0 @@ -/** - * Copyright (C) 2008 by INdT - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser 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 Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * @author Andre Moreira Magalhaes - */ - -/** - * @brief - * - * asf/wma file parser. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#define _XOPEN_SOURCE 600 -#include -#include -#include -#include -#include -#include -#include -#include -#include - -enum StreamTypes { - STREAM_TYPE_UNKNOWN = 0, - STREAM_TYPE_AUDIO, - STREAM_TYPE_VIDEO -}; - -enum AttributeTypes { - ATTR_TYPE_UNICODE = 0, - ATTR_TYPE_BYTES, - ATTR_TYPE_BOOL, - ATTR_TYPE_DWORD, - ATTR_TYPE_QWORD, - ATTR_TYPE_WORD, - ATTR_TYPE_GUID -}; - -struct asf_info { - struct lms_string_size title; - struct lms_string_size artist; - struct lms_string_size album; - struct lms_string_size genre; - unsigned char trackno; -}; - -struct plugin { - struct lms_plugin plugin; - lms_db_audio_t *audio_db; - lms_db_video_t *video_db; - lms_charset_conv_t *cs_conv; -}; - -static const char _name[] = "asf"; -static const struct lms_string_size _exts[] = { - LMS_STATIC_STRING_SIZE(".wma"), - LMS_STATIC_STRING_SIZE(".wmv"), - LMS_STATIC_STRING_SIZE(".asf") -}; - -/* ASF GUIDs - * - * Microsoft defines these 16-byte (128-bit) GUIDs as: - * first 8 bytes are in little-endian order - * next 8 bytes are in big-endian order - * - * Eg.: AaBbCcDd-EeFf-GgHh-IiJj-KkLlMmNnOoPp: - * - * to convert to byte string do as follow: - * - * $Dd $Cc $Bb $Aa $Ff $Ee $Hh $Gg $Ii $Jj $Kk $Ll $Mm $Nn $Oo $Pp - * - * See http://www.microsoft.com/windows/windowsmedia/forpros/format/asfspec.aspx - */ -static const char header_guid[16] = "\x30\x26\xB2\x75\x8E\x66\xCF\x11\xA6\xD9\x00\xAA\x00\x62\xCE\x6C"; -static const char file_properties_guid[16] = "\xA1\xDC\xAB\x8C\x47\xA9\xCF\x11\x8E\xE4\x00\xC0\x0C\x20\x53\x65"; -static const char stream_properties_guid[16] = "\x91\x07\xDC\xB7\xB7\xA9\xCF\x11\x8E\xE6\x00\xC0\x0C\x20\x53\x65"; -static const char stream_type_audio_guid[16] = "\x40\x9E\x69\xF8\x4D\x5B\xCF\x11\xA8\xFD\x00\x80\x5F\x5C\x44\x2B"; -static const char stream_type_video_guid[16] = "\xC0\xEF\x19\xBC\x4D\x5B\xCF\x11\xA8\xFD\x00\x80\x5F\x5C\x44\x2B"; -static const char content_description_guid[16] = "\x33\x26\xB2\x75\x8E\x66\xCF\x11\xA6\xD9\x00\xAA\x00\x62\xCE\x6C"; -static const char extended_content_description_guid[16] = "\x40\xA4\xD0\xD2\x07\xE3\xD2\x11\x97\xF0\x00\xA0\xC9\x5E\xA8\x50"; -static const char header_extension_guid[16] = "\xb5\x03\xbf_.\xa9\xcf\x11\x8e\xe3\x00\xc0\x0c Se"; -static const char metadata_guid[16] = "\xEA\xCB\xF8\xC5\xAF[wH\204g\xAA\214D\xFAL\xCA"; -static const char metadata_library_guid[16] = "\224\034#D\230\224\321I\241A\x1d\x13NEpT"; -static const char content_encryption_object_guid[16] = "\xFB\xB3\x11\x22\x23\xBD\xD2\x11\xB4\xB7\x00\xA0\xC9\x55\xFC\x6E"; -static const char extended_content_encryption_object_guid[16] = "\x14\xE6\x8A\x29\x22\x26\x17\x4C\xB9\x35\xDA\xE0\x7E\xE9\x28\x9C"; - -static const char attr_name_wm_album_title[26] = "\x57\x00\x4d\x00\x2f\x00\x41\x00\x6c\x00\x62\x00\x75\x00\x6d\x00\x54\x00\x69\x00\x74\x00\x6c\x00\x65\x00"; -static const char attr_name_wm_genre[16] = "\x57\x00\x4d\x00\x2f\x00\x47\x00\x65\x00\x6e\x00\x72\x00\x65\x00"; -static const char attr_name_wm_track_number[28] = "\x57\x00\x4d\x00\x2f\x00\x54\x00\x72\x00\x61\x00\x63\x00\x6b\x00\x4e\x00\x75\x00\x6d\x00\x62\x00\x65\x00\x72\x00"; - -static long long -_to_number(const char *data, unsigned int type_size, unsigned int data_size) -{ - long long sum = 0; - unsigned int last, i; - - last = data_size > type_size ? type_size : data_size; - - for (i = 0; i < last; i++) - sum |= (unsigned char) (data[i]) << (i * 8); - - return sum; -} - -static short -_read_word(int fd) -{ - char v[2]; - if (read(fd, &v, 2) != 2) - return 0; - return (short) _to_number(v, sizeof(unsigned short), 2); -} - -static unsigned int -_read_dword(int fd) -{ - char v[4]; - if (read(fd, &v, 4) != 4) - return 0; - return (unsigned int) _to_number(v, sizeof(unsigned int), 4); -} - -static long long -_read_qword(int fd) -{ - char v[8]; - if (read(fd, &v, 8) != 8) - return 0; - return _to_number(v, sizeof(unsigned long long), 8); -} - -static int -_read_string(int fd, size_t count, char **str, size_t *len) -{ - char *data; - size_t data_size, size; - - if (!str) { - lseek(fd, count, SEEK_CUR); - return 0; - } - - data = malloc(sizeof(char) * count); - data_size = read(fd, data, count); - if (data_size == -1) { - free(data); - return -1; - } - - size = data_size; - while (size >= 2) { - if (data[size - 1] != '\0' || data[size - 2] != '\0') - break; - size -= 2; - } - - *str = data; - *len = size; - - return 0; -} - -static void -_parse_content_description(lms_charset_conv_t *cs_conv, int fd, struct asf_info *info) -{ - int title_length = _read_word(fd); - int artist_length = _read_word(fd); - int copyright_length = _read_word(fd); - int comment_length = _read_word(fd); - int rating_length = _read_word(fd); - - _read_string(fd, title_length, &info->title.str, &info->title.len); - lms_charset_conv_force(cs_conv, &info->title.str, &info->title.len); - _read_string(fd, artist_length, &info->artist.str, &info->artist.len); - lms_charset_conv_force(cs_conv, &info->artist.str, &info->artist.len); - /* ignore copyright, comment and rating */ - lseek(fd, copyright_length + comment_length + rating_length, SEEK_CUR); -} - -static void -_parse_attribute_name(int fd, - int kind, - char **attr_name, - size_t *attr_name_len, - int *attr_type, - int *attr_size) -{ - int attr_name_length; - - /* extended content descriptor */ - if (kind == 0) { - attr_name_length = _read_word(fd); - _read_string(fd, attr_name_length, attr_name, attr_name_len); - *attr_type = _read_word(fd); - *attr_size = _read_word(fd); - } - /* metadata & metadata library */ - else { - lseek(fd, 2 + 2, SEEK_CUR); /* language and stream */ - attr_name_length = _read_word(fd); - *attr_type = _read_word(fd); - *attr_size = _read_dword(fd); - _read_string(fd, attr_name_length, attr_name, attr_name_len); - } -} - -static void -_parse_attribute_string_data(lms_charset_conv_t *cs_conv, - int fd, - int attr_size, - char **attr_data, - size_t *attr_data_len) -{ - _read_string(fd, attr_size, attr_data, attr_data_len); - lms_charset_conv_force(cs_conv, attr_data, attr_data_len); -} - -static void -_skip_attribute_data(int fd, int kind, int attr_type, int attr_size) -{ - switch (attr_type) { - case ATTR_TYPE_WORD: - lseek(fd, 2, SEEK_CUR); - break; - - case ATTR_TYPE_BOOL: - if (kind == 0) - lseek(fd, 4, SEEK_CUR); - else - lseek(fd, 2, SEEK_CUR); - break; - - case ATTR_TYPE_DWORD: - lseek(fd, 4, SEEK_CUR); - break; - - case ATTR_TYPE_QWORD: - lseek(fd, 8, SEEK_CUR); - break; - - case ATTR_TYPE_UNICODE: - case ATTR_TYPE_BYTES: - case ATTR_TYPE_GUID: - lseek(fd, attr_size, SEEK_CUR); - break; - - default: - break; - } -} - -static void -_skip_attribute(int fd, int kind) -{ - int attr_type, attr_size; - _parse_attribute_name(fd, kind, NULL, NULL, &attr_type, &attr_size); - _skip_attribute_data(fd, kind, attr_type, attr_size); -} - -static void -_parse_extended_content_description_object(lms_charset_conv_t *cs_conv, int fd, struct asf_info *info) -{ - int count = _read_word(fd); - char *attr_name; - size_t attr_name_len; - int attr_type, attr_size; - while (count--) { - attr_name = NULL; - _parse_attribute_name(fd, 0, - &attr_name, &attr_name_len, - &attr_type, &attr_size); - if (attr_type == ATTR_TYPE_UNICODE) { - if (memcmp(attr_name, attr_name_wm_album_title, attr_name_len) == 0) - _parse_attribute_string_data(cs_conv, - fd, attr_size, - &info->album.str, - &info->album.len); - else if (memcmp(attr_name, attr_name_wm_genre, attr_name_len) == 0) - _parse_attribute_string_data(cs_conv, - fd, attr_size, - &info->genre.str, - &info->genre.len); - else if (memcmp(attr_name, attr_name_wm_track_number, attr_name_len) == 0) { - char *trackno; - size_t trackno_len; - _parse_attribute_string_data(cs_conv, - fd, attr_size, - &trackno, - &trackno_len); - if (trackno) { - info->trackno = atoi(trackno); - free(trackno); - } - } - else - _skip_attribute_data(fd, 0, attr_type, attr_size); - } - else - _skip_attribute_data(fd, 0, attr_type, attr_size); - if (attr_name) - free(attr_name); - } -} - -static void -_skip_metadata(int fd) -{ - int count = _read_word(fd); - while (count--) - _skip_attribute(fd, 1); -} - -static void -_skip_metadata_library(int fd) -{ - int count = _read_word(fd); - while (count--) - _skip_attribute(fd, 2); -} - -static void -_skip_header_extension(int fd) -{ - char guid[16]; - long long size, data_size, data_pos; - - lseek(fd, 18, SEEK_CUR); - data_size = _read_dword(fd); - data_pos = 0; - while (data_pos < data_size) { - read(fd, &guid, 16); - size = _read_qword(fd); - if (size == 0) - break; - if (memcmp(guid, metadata_guid, 16) == 0) - _skip_metadata(fd); - else if (memcmp(guid, metadata_library_guid, 16) == 0) - _skip_metadata_library(fd); - else - lseek(fd, size - 24, SEEK_CUR); - data_pos += size; - } -} - -static void * -_match(struct plugin *p, const char *path, int len, int base) -{ - int i; - - i = lms_which_extension(path, len, _exts, LMS_ARRAY_SIZE(_exts)); - if (i < 0) - return NULL; - else - return (void*)(i + 1); -} - -static int -_parse(struct plugin *plugin, struct lms_context *ctxt, const struct lms_file_info *finfo, void *match) -{ - struct asf_info info = {{0}, {0}, {0}, {0}, 0}; - struct lms_audio_info audio_info = {0}; - struct lms_video_info video_info = {0}; - int r, fd, num_objects, i; - char guid[16]; - unsigned int size; - int stream_type = STREAM_TYPE_UNKNOWN; - - fd = open(finfo->path, O_RDONLY); - if (fd < 0) { - perror("open"); - return -1; - } - - if (read(fd, &guid, 16) != 16) { - perror("read"); - r = -2; - goto done; - } - if (memcmp(guid, header_guid, 16) != 0) { - fprintf(stderr, "ERROR: invalid header (%s).\n", finfo->path); - r = -3; - goto done; - } - - size = _read_qword(fd); - num_objects = _read_dword(fd); - - lseek(fd, 2, SEEK_CUR); - - for (i = 0; i < num_objects; ++i) { - read(fd, &guid, 16); - size = _read_qword(fd); - - if (memcmp(guid, file_properties_guid, 16) == 0) - lseek(fd, size - 24, SEEK_CUR); - else if (memcmp(guid, stream_properties_guid, 16) == 0) { - read(fd, &guid, 16); - if (memcmp(guid, stream_type_audio_guid, 16) == 0) - stream_type = STREAM_TYPE_AUDIO; - else if (memcmp(guid, stream_type_video_guid, 16) == 0) - stream_type = STREAM_TYPE_VIDEO; - lseek(fd, size - 40, SEEK_CUR); - } - else if (memcmp(guid, content_description_guid, 16) == 0) - _parse_content_description(plugin->cs_conv, fd, &info); - else if (memcmp(guid, extended_content_description_guid, 16) == 0) - _parse_extended_content_description_object(plugin->cs_conv, fd, &info); - else if (memcmp(guid, header_extension_guid, 16) == 0) - _skip_header_extension(fd); - else if (memcmp(guid, content_encryption_object_guid, 16) == 0 || - memcmp(guid, extended_content_encryption_object_guid, 16) == 0) { - /* ignore DRM'd files */ - fprintf(stderr, "ERROR: ignoring DRM'd file %s\n", finfo->path); - r = -4; - goto done; - } - else - lseek(fd, size - 24, SEEK_CUR); - } - - /* try to define stream type by extension */ - if (stream_type == STREAM_TYPE_UNKNOWN) { - int ext_idx = ((int)match) - 1; - if (strcmp(_exts[ext_idx].str, ".wma") == 0) - stream_type = STREAM_TYPE_AUDIO; - /* consider wmv and asf as video */ - else - stream_type = STREAM_TYPE_VIDEO; - } - - lms_string_size_strip_and_free(&info.title); - lms_string_size_strip_and_free(&info.artist); - lms_string_size_strip_and_free(&info.album); - lms_string_size_strip_and_free(&info.genre); - - if (!info.title.str) { - int ext_idx; - ext_idx = ((int)match) - 1; - info.title.len = finfo->path_len - finfo->base - _exts[ext_idx].len; - info.title.str = malloc((info.title.len + 1) * sizeof(char)); - memcpy(info.title.str, finfo->path + finfo->base, info.title.len); - info.title.str[info.title.len] = '\0'; - lms_charset_conv(ctxt->cs_conv, &info.title.str, &info.title.len); - } - -#if 0 - fprintf(stderr, "file %s info\n", finfo->path); - fprintf(stderr, "\ttitle='%s'\n", info.title.str); - fprintf(stderr, "\tartist='%s'\n", info.artist.str); - fprintf(stderr, "\talbum='%s'\n", info.album.str); - fprintf(stderr, "\tgenre='%s'\n", info.genre.str); - fprintf(stderr, "\ttrackno=%d\n", info.trackno); -#endif - - if (stream_type == STREAM_TYPE_AUDIO) { - audio_info.id = finfo->id; - audio_info.title = info.title; - audio_info.artist = info.artist; - audio_info.album = info.album; - audio_info.genre = info.genre; - audio_info.trackno = info.trackno; - r = lms_db_audio_add(plugin->audio_db, &audio_info); - } - else { - video_info.id = finfo->id; - video_info.title = info.title; - video_info.artist = info.artist; - r = lms_db_video_add(plugin->video_db, &video_info); - } - - done: - if (info.title.str) - free(info.title.str); - if (info.artist.str) - free(info.artist.str); - if (info.album.str) - free(info.album.str); - if (info.genre.str) - free(info.genre.str); - - posix_fadvise(fd, 0, 0, POSIX_FADV_DONTNEED); - close(fd); - - return r; -} - -static int -_setup(struct plugin *plugin, struct lms_context *ctxt) -{ - plugin->audio_db = lms_db_audio_new(ctxt->db); - if (!plugin->audio_db) - return -1; - plugin->video_db = lms_db_video_new(ctxt->db); - if (!plugin->video_db) - return -1; - plugin->cs_conv = lms_charset_conv_new(); - if (!plugin->cs_conv) - return -1; - lms_charset_conv_add(plugin->cs_conv, "UTF-16LE"); - - return 0; -} - -static int -_start(struct plugin *plugin, struct lms_context *ctxt) -{ - int r; - r = lms_db_audio_start(plugin->audio_db); - r |= lms_db_video_start(plugin->video_db); - return r; -} - -static int -_finish(struct plugin *plugin, struct lms_context *ctxt) -{ - if (plugin->audio_db) - lms_db_audio_free(plugin->audio_db); - if (plugin->video_db) - lms_db_video_free(plugin->video_db); - if (plugin->cs_conv) - lms_charset_conv_free(plugin->cs_conv); - - return 0; -} - -static int -_close(struct plugin *plugin) -{ - free(plugin); - return 0; -} - -API struct lms_plugin * -lms_plugin_open(void) -{ - struct plugin *plugin; - - plugin = (struct plugin *)malloc(sizeof(*plugin)); - plugin->plugin.name = _name; - plugin->plugin.match = (lms_plugin_match_fn_t)_match; - plugin->plugin.parse = (lms_plugin_parse_fn_t)_parse; - plugin->plugin.close = (lms_plugin_close_fn_t)_close; - plugin->plugin.setup = (lms_plugin_setup_fn_t)_setup; - plugin->plugin.start = (lms_plugin_start_fn_t)_start; - plugin->plugin.finish = (lms_plugin_finish_fn_t)_finish; - - return (struct lms_plugin *)plugin; -} diff --git a/lightmediascanner/src/plugins/audio-dummy/Makefile.am b/lightmediascanner/src/plugins/audio-dummy/Makefile.am deleted file mode 100644 index 23667ce..0000000 --- a/lightmediascanner/src/plugins/audio-dummy/Makefile.am +++ /dev/null @@ -1,10 +0,0 @@ -MAINTAINERCLEANFILES = Makefile.in - -AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_srcdir)/src/plugins/audio-dummy - -pkgdir = $(pluginsdir) -pkg_LTLIBRARIES = audio-dummy.la -audio_dummy_la_SOURCES = audio-dummy.c -audio_dummy_la_DEPENDENCIES = $(top_builddir)/config.h -audio_dummy_la_LIBADD = $(top_builddir)/src/lib/liblightmediascanner.la -audio_dummy_la_LDFLAGS = -module -avoid-version diff --git a/lightmediascanner/src/plugins/audio-dummy/audio-dummy.c b/lightmediascanner/src/plugins/audio-dummy/audio-dummy.c deleted file mode 100644 index 5e036cc..0000000 --- a/lightmediascanner/src/plugins/audio-dummy/audio-dummy.c +++ /dev/null @@ -1,129 +0,0 @@ -/** - * Copyright (C) 2007 by INdT - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser 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 Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * @author Gustavo Sverzut Barbieri - */ - -/** - * @brief - * - * Audio Dummy plugin, just register matched extensions in audios DB. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#define _XOPEN_SOURCE 600 -#include -#include -#include -#include -#include - -static const char _name[] = "audio-dummy"; -static const struct lms_string_size _exts[] = { - LMS_STATIC_STRING_SIZE(".wav") -}; - -struct plugin { - struct lms_plugin plugin; - lms_db_audio_t *audio_db; -}; - -static void * -_match(struct plugin *p, const char *path, int len, int base) -{ - int i; - - i = lms_which_extension(path, len, _exts, LMS_ARRAY_SIZE(_exts)); - if (i < 0) - return NULL; - else - return (void*)(i + 1); -} - -static int -_parse(struct plugin *plugin, struct lms_context *ctxt, const struct lms_file_info *finfo, void *match) -{ - struct lms_audio_info info = {0}; - int r, ext_idx; - - ext_idx = ((int)match) - 1; - info.title.len = finfo->path_len - finfo->base - _exts[ext_idx].len; - info.title.str = malloc((info.title.len + 1) * sizeof(char)); - memcpy(info.title.str, finfo->path + finfo->base, info.title.len); - info.title.str[info.title.len] = '\0'; - lms_charset_conv(ctxt->cs_conv, &info.title.str, &info.title.len); - - info.id = finfo->id; - r = lms_db_audio_add(plugin->audio_db, &info); - - free(info.title.str); - - return r; -} - -static int -_setup(struct plugin *plugin, struct lms_context *ctxt) -{ - plugin->audio_db = lms_db_audio_new(ctxt->db); - if (!plugin->audio_db) - return -1; - - return 0; -} - -static int -_start(struct plugin *plugin, struct lms_context *ctxt) -{ - return lms_db_audio_start(plugin->audio_db); -} - -static int -_finish(struct plugin *plugin, struct lms_context *ctxt) -{ - if (plugin->audio_db) - return lms_db_audio_free(plugin->audio_db); - - return 0; -} - - -static int -_close(struct plugin *plugin) -{ - free(plugin); - return 0; -} - -API struct lms_plugin * -lms_plugin_open(void) -{ - struct plugin *plugin; - - plugin = malloc(sizeof(*plugin)); - plugin->plugin.name = _name; - plugin->plugin.match = (lms_plugin_match_fn_t)_match; - plugin->plugin.parse = (lms_plugin_parse_fn_t)_parse; - plugin->plugin.close = (lms_plugin_close_fn_t)_close; - plugin->plugin.setup = (lms_plugin_setup_fn_t)_setup; - plugin->plugin.start = (lms_plugin_start_fn_t)_start; - plugin->plugin.finish = (lms_plugin_finish_fn_t)_finish; - - return (struct lms_plugin *)plugin; -} diff --git a/lightmediascanner/src/plugins/dummy/Makefile.am b/lightmediascanner/src/plugins/dummy/Makefile.am deleted file mode 100644 index 7af4e97..0000000 --- a/lightmediascanner/src/plugins/dummy/Makefile.am +++ /dev/null @@ -1,10 +0,0 @@ -MAINTAINERCLEANFILES = Makefile.in - -AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_srcdir)/src/plugins/dummy - -pkgdir = $(pluginsdir) -pkg_LTLIBRARIES = dummy.la -dummy_la_SOURCES = dummy.c -dummy_la_DEPENDENCIES = $(top_builddir)/config.h -dummy_la_LIBADD = $(top_builddir)/src/lib/liblightmediascanner.la -dummy_la_LDFLAGS = -module -avoid-version diff --git a/lightmediascanner/src/plugins/dummy/dummy.c b/lightmediascanner/src/plugins/dummy/dummy.c deleted file mode 100644 index 8d3f7be..0000000 --- a/lightmediascanner/src/plugins/dummy/dummy.c +++ /dev/null @@ -1,117 +0,0 @@ -/** - * Copyright (C) 2007 by INdT - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser 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 Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * @author Gustavo Sverzut Barbieri - */ - -/** - * @brief - * - * Dummy plugin demonstrating the basic lightmediascanner_plugin API, - * it just write paths to /tmp/dummy.log. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#define _XOPEN_SOURCE 600 -#include -#include -#include -#include -#include -#include -#include -#include - -static const char _name[] = "dummy"; - -struct plugin { - struct lms_plugin plugin; - int fd; -}; - -static void * -_match(struct plugin *p, const char *path, int len, int base) -{ - return (void*)1; -} - -static int -_parse(struct plugin *plugin, struct lms_context *ctxt, const struct lms_file_info *finfo, void *match) -{ - write(plugin->fd, finfo->path, finfo->path_len); - write(plugin->fd, "\n", 1); - return 0; -} - -static int -_close(struct plugin *plugin) -{ - free(plugin); - return 0; -} - -static int -_setup(struct plugin *plugin, struct lms_context *ctxt) -{ - return 0; -} - -static int -_start(struct plugin *plugin, struct lms_context *ctxt) -{ - char logfile[PATH_MAX]; - - snprintf(logfile, sizeof(logfile), "/tmp/dummy-%d.log", getuid()); - plugin->fd = open(logfile, O_WRONLY | O_CREAT, 0600); - if (plugin->fd < 0) { - perror("open"); - return -1; - } - - return 0; -} - -static int -_finish(struct plugin *plugin, struct lms_context *ctxt) -{ - if (close(plugin->fd) != 0) - perror("close"); - - plugin->fd = 0; - - return 0; -} - -API struct lms_plugin * -lms_plugin_open(void) -{ - struct plugin *plugin; - - plugin = malloc(sizeof(*plugin)); - plugin->plugin.name = _name; - plugin->plugin.match = (lms_plugin_match_fn_t)_match; - plugin->plugin.parse = (lms_plugin_parse_fn_t)_parse; - plugin->plugin.close = (lms_plugin_close_fn_t)_close; - plugin->plugin.setup = (lms_plugin_setup_fn_t)_setup; - plugin->plugin.start = (lms_plugin_start_fn_t)_start; - plugin->plugin.finish = (lms_plugin_finish_fn_t)_finish; - - return (struct lms_plugin *)plugin; -} diff --git a/lightmediascanner/src/plugins/flac/Makefile.am b/lightmediascanner/src/plugins/flac/Makefile.am deleted file mode 100644 index 6c3d568..0000000 --- a/lightmediascanner/src/plugins/flac/Makefile.am +++ /dev/null @@ -1,10 +0,0 @@ -MAINTAINERCLEANFILES = Makefile.in - -AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_srcdir)/src/plugins/flac @FLAC_CFLAGS@ - -pkgdir = $(pluginsdir) -pkg_LTLIBRARIES = flac.la -flac_la_SOURCES = flac.c -flac_la_DEPENDENCIES = $(top_builddir)/config.h -flac_la_LIBADD = $(top_builddir)/src/lib/liblightmediascanner.la @FLAC_LIBS@ -flac_la_LDFLAGS = -module -avoid-version diff --git a/lightmediascanner/src/plugins/flac/flac.c b/lightmediascanner/src/plugins/flac/flac.c deleted file mode 100644 index a8ba8e0..0000000 --- a/lightmediascanner/src/plugins/flac/flac.c +++ /dev/null @@ -1,180 +0,0 @@ -/** - * Copyright (C) 2008 by INdT - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser 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 Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * @author Andre Moreira Magalhaes - */ - -/** - * @brief - * - * flac file parser. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include -#include -#include -#include - -struct plugin { - struct lms_plugin plugin; - lms_db_audio_t *audio_db; -}; - -static const char _name[] = "flac"; -static const struct lms_string_size _exts[] = { - LMS_STATIC_STRING_SIZE(".flac") -}; - -static void * -_match(struct plugin *p, const char *path, int len, int base) -{ - int i; - - i = lms_which_extension(path, len, _exts, LMS_ARRAY_SIZE(_exts)); - if (i < 0) - return NULL; - else - return (void*)(i + 1); -} - -static int -_parse(struct plugin *plugin, struct lms_context *ctxt, const struct lms_file_info *finfo, void *match) -{ - struct lms_audio_info info = {0, {0}, {0}, {0}, {0}, 0, 0, 0}; - FLAC__StreamMetadata *tags = 0; - char *str; - int i, len, r; - - if (!FLAC__metadata_get_tags(finfo->path, &tags)) { - fprintf(stderr, "ERROR: cannot retrieve file %s tags\n", finfo->path); - return -1; - } - - for (i = 0; i < tags->data.vorbis_comment.num_comments; i++) { - str = (char *) tags->data.vorbis_comment.comments[i].entry; - len = tags->data.vorbis_comment.comments[i].length; - if (strncmp(str, "TITLE=", 6) == 0) { - info.title.str = str + 6; - info.title.len = len; - } - else if (strncmp(str, "ARTIST=", 7) == 0) { - info.artist.str = str + 7; - info.artist.len = len; - } - else if (strncmp(str, "ALBUM=", 6) == 0) { - info.album.str = str + 6; - info.album.len = len; - } - else if (strncmp(str, "GENRE=", 6) == 0) { - info.genre.str = str + 6; - info.genre.len = len; - } - else if (strncmp(str, "TRACKNUMBER=", 12) == 0) - info.trackno = atoi(str + 12); - } - - lms_string_size_strip_and_free(&info.title); - lms_string_size_strip_and_free(&info.artist); - lms_string_size_strip_and_free(&info.album); - lms_string_size_strip_and_free(&info.genre); - - if (!info.title.str) { - int ext_idx; - ext_idx = ((int)match) - 1; - info.title.len = finfo->path_len - finfo->base - _exts[ext_idx].len; - info.title.str = malloc((info.title.len + 1) * sizeof(char)); - memcpy(info.title.str, finfo->path + finfo->base, info.title.len); - info.title.str[info.title.len] = '\0'; - } - lms_charset_conv(ctxt->cs_conv, &info.title.str, &info.title.len); - - if (info.artist.str) - lms_charset_conv(ctxt->cs_conv, &info.artist.str, &info.artist.len); - if (info.album.str) - lms_charset_conv(ctxt->cs_conv, &info.album.str, &info.album.len); - if (info.genre.str) - lms_charset_conv(ctxt->cs_conv, &info.genre.str, &info.genre.len); - -#if 0 - fprintf(stderr, "file %s info\n", finfo->path); - fprintf(stderr, "\ttitle='%s'\n", info.title.str); - fprintf(stderr, "\tartist='%s'\n", info.artist.str); - fprintf(stderr, "\talbum='%s'\n", info.album.str); - fprintf(stderr, "\tgenre='%s'\n", info.genre.str); - fprintf(stderr, "\ttrack number='%d'\n", info.trackno); -#endif - - info.id = finfo->id; - r = lms_db_audio_add(plugin->audio_db, &info); - - FLAC__metadata_object_delete(tags); - - return r; -} - -static int -_setup(struct plugin *plugin, struct lms_context *ctxt) -{ - plugin->audio_db = lms_db_audio_new(ctxt->db); - if (!plugin->audio_db) - return -1; - return 0; -} - -static int -_start(struct plugin *plugin, struct lms_context *ctxt) -{ - return lms_db_audio_start(plugin->audio_db); -} - -static int -_finish(struct plugin *plugin, struct lms_context *ctxt) -{ - if (plugin->audio_db) - lms_db_audio_free(plugin->audio_db); - return 0; -} - -static int -_close(struct plugin *plugin) -{ - free(plugin); - return 0; -} - -API struct lms_plugin * -lms_plugin_open(void) -{ - struct plugin *plugin; - - plugin = (struct plugin *)malloc(sizeof(*plugin)); - plugin->plugin.name = _name; - plugin->plugin.match = (lms_plugin_match_fn_t)_match; - plugin->plugin.parse = (lms_plugin_parse_fn_t)_parse; - plugin->plugin.close = (lms_plugin_close_fn_t)_close; - plugin->plugin.setup = (lms_plugin_setup_fn_t)_setup; - plugin->plugin.start = (lms_plugin_start_fn_t)_start; - plugin->plugin.finish = (lms_plugin_finish_fn_t)_finish; - - return (struct lms_plugin *)plugin; -} diff --git a/lightmediascanner/src/plugins/id3/Makefile.am b/lightmediascanner/src/plugins/id3/Makefile.am deleted file mode 100644 index ede48f5..0000000 --- a/lightmediascanner/src/plugins/id3/Makefile.am +++ /dev/null @@ -1,10 +0,0 @@ -MAINTAINERCLEANFILES = Makefile.in - -AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_srcdir)/src/plugins/id3 - -pkgdir = $(pluginsdir) -pkg_LTLIBRARIES = id3.la -id3_la_SOURCES = id3.c -id3_la_DEPENDENCIES = $(top_builddir)/config.h -id3_la_LIBADD = $(top_builddir)/src/lib/liblightmediascanner.la -id3_la_LDFLAGS = -module -avoid-version diff --git a/lightmediascanner/src/plugins/id3/id3.c b/lightmediascanner/src/plugins/id3/id3.c deleted file mode 100644 index 0c12d01..0000000 --- a/lightmediascanner/src/plugins/id3/id3.c +++ /dev/null @@ -1,780 +0,0 @@ -/** - * Copyright (C) 2008 by INdT - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser 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 Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * @author Andre Moreira Magalhaes - */ - -/** - * @brief - * - * id3 file parser. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#define _GNU_SOURCE -#define _XOPEN_SOURCE 600 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define ID3V2_HEADER_SIZE 10 -#define ID3V2_FOOTER_SIZE 10 - -#define ID3V1_NUM_GENRES 148 - -#define ID3_NUM_ENCODINGS 5 - -enum ID3Encodings { - ID3_ENCODING_LATIN1 = 0, - ID3_ENCODING_UTF16, - ID3_ENCODING_UTF16BE, - ID3_ENCODING_UTF8, - ID3_ENCODING_UTF16LE -}; - -static const char *id3v1_genres[ID3V1_NUM_GENRES] = { - "Blues", - "Classic Rock", - "Country", - "Dance", - "Disco", - "Funk", - "Grunge", - "Hip-Hop", - "Jazz", - "Metal", - "New Age", - "Oldies", - "Other", - "Pop", - "R&B", - "Rap", - "Reggae", - "Rock", - "Techno", - "Industrial", - "Alternative", - "Ska", - "Death Metal", - "Pranks", - "Soundtrack", - "Euro-Techno", - "Ambient", - "Trip-Hop", - "Vocal", - "Jazz+Funk", - "Fusion", - "Trance", - "Classical", - "Instrumental", - "Acid", - "House", - "Game", - "Sound Clip", - "Gospel", - "Noise", - "Alternative Rock", - "Bass", - "Soul", - "Punk", - "Space", - "Meditative", - "Instrumental Pop", - "Instrumental Rock", - "Ethnic", - "Gothic", - "Darkwave", - "Techno-Industrial", - "Electronic", - "Pop-Folk", - "Eurodance", - "Dream", - "Southern Rock", - "Comedy", - "Cult", - "Gangsta", - "Top 40", - "Christian Rap", - "Pop/Funk", - "Jungle", - "Native American", - "Cabaret", - "New Wave", - "Psychedelic", - "Rave", - "Showtunes", - "Trailer", - "Lo-Fi", - "Tribal", - "Acid Punk", - "Acid Jazz", - "Polka", - "Retro", - "Musical", - "Rock & Roll", - "Hard Rock", - "Folk", - "Folk/Rock", - "National Folk", - "Swing", - "Fusion", - "Bebob", - "Latin", - "Revival", - "Celtic", - "Bluegrass", - "Avantgarde", - "Gothic Rock", - "Progressive Rock", - "Psychedelic Rock", - "Symphonic Rock", - "Slow Rock", - "Big Band", - "Chorus", - "Easy Listening", - "Acoustic", - "Humour", - "Speech", - "Chanson", - "Opera", - "Chamber Music", - "Sonata", - "Symphony", - "Booty Bass", - "Primus", - "Porn Groove", - "Satire", - "Slow Jam", - "Club", - "Tango", - "Samba", - "Folklore", - "Ballad", - "Power Ballad", - "Rhythmic Soul", - "Freestyle", - "Duet", - "Punk Rock", - "Drum Solo", - "A Cappella", - "Euro-House", - "Dance Hall", - "Goa", - "Drum & Bass", - "Club-House", - "Hardcore", - "Terror", - "Indie", - "BritPop", - "Negerpunk", - "Polsk Punk", - "Beat", - "Christian Gangsta Rap", - "Heavy Metal", - "Black Metal", - "Crossover", - "Contemporary Christian", - "Christian Rock", - "Merengue", - "Salsa", - "Thrash Metal", - "Anime", - "Jpop", - "Synthpop" -}; - -struct id3v2_frame_header { - char frame_id[4]; - unsigned int frame_size; - int compression; - int data_length_indicator; -}; - -struct id3v1_tag { - char title[30]; - char artist[30]; - char album[30]; - char year[4]; - char comments[30]; - char genre; -} __attribute__((packed)); - -struct plugin { - struct lms_plugin plugin; - lms_db_audio_t *audio_db; - lms_charset_conv_t *cs_convs[ID3_NUM_ENCODINGS]; -}; - -static const char _name[] = "id3"; -static const struct lms_string_size _exts[] = { - LMS_STATIC_STRING_SIZE(".mp3"), - LMS_STATIC_STRING_SIZE(".aac") -}; - -static unsigned int -_to_uint(const char *data, int data_size) -{ - unsigned int sum = 0; - unsigned int last, i; - - last = data_size > 4 ? 3 : data_size - 1; - - for (i = 0; i <= last; i++) - sum |= ((unsigned char) data[i]) << ((last - i) * 8); - - return sum; -} - -static inline int -_is_id3v2_second_synch_byte(unsigned char byte) -{ - if (byte == 0xff) - return 0; - if ((byte & 0xE0) == 0xE0) - return 1; - return 0; -} - -static long -_find_id3v2(int fd) -{ - long buffer_offset = 0; - char buffer[3], *p; - int buffer_size = sizeof(buffer); - const char pattern[] = "ID3"; - ssize_t nread; - - /* These variables are used to keep track of a partial match that happens at - * the end of a buffer. */ - int previous_partial_match = -1; - int previous_partial_synch_match = 0; - int first_synch_byte; - - /* Start the search at the beginning of the file. */ - lseek(fd, 0, SEEK_SET); - - if ((nread = read(fd, &buffer, buffer_size)) != buffer_size) - return -1; - - /* check if pattern is in the beggining of the file */ - if (memcmp(buffer, pattern, 3) == 0) - return 0; - - /* This loop is the crux of the find method. There are three cases that we - * want to account for: - * (1) The previously searched buffer contained a partial match of the search - * pattern and we want to see if the next one starts with the remainder of - * that pattern. - * - * (2) The search pattern is wholly contained within the current buffer. - * - * (3) The current buffer ends with a partial match of the pattern. We will - * note this for use in the next iteration, where we will check for the rest - * of the pattern. */ - while (1) { - /* (1) previous partial match */ - if (previous_partial_synch_match && _is_id3v2_second_synch_byte(buffer[0])) - return -1; - - if (previous_partial_match >= 0 && previous_partial_match < buffer_size) { - const int pattern_offset = buffer_size - previous_partial_match; - - if (memcmp(buffer, pattern + pattern_offset, 3 - pattern_offset) == 0) - return buffer_offset - buffer_size + previous_partial_match; - } - - /* (2) pattern contained in current buffer */ - p = buffer; - while ((p = memchr(p, 'I', buffer_size))) { - if (memcmp(p, pattern, 3) == 0) - return buffer_offset + (p - buffer); - p += 1; - } - - p = memchr(buffer, 255, buffer_size); - if (p) - first_synch_byte = p - buffer; - else - first_synch_byte = -1; - - /* Here we have to loop because there could be several of the first - * (11111111) byte, and we want to check all such instances until we find - * a full match (11111111 111) or hit the end of the buffer. */ - while (first_synch_byte >= 0) { - /* if this *is not* at the end of the buffer */ - if (first_synch_byte < buffer_size - 1) { - if(_is_id3v2_second_synch_byte(buffer[first_synch_byte + 1])) - /* We've found the frame synch pattern. */ - return -1; - else - /* We found 11111111 at the end of the current buffer indicating a - * partial match of the synch pattern. The find() below should - * return -1 and break out of the loop. */ - previous_partial_synch_match = 1; - } - - /* Check in the rest of the buffer. */ - p = memchr(p + 1, 255, buffer_size); - if (p) - first_synch_byte = p - buffer; - else - first_synch_byte = -1; - } - - /* (3) partial match */ - if (buffer[nread - 1] == pattern[1]) - previous_partial_match = nread - 1; - else if (memcmp(&buffer[nread - 2], pattern, 2) == 0) - previous_partial_match = nread - 2; - buffer_offset += buffer_size; - - if ((nread = read(fd, &buffer, sizeof(buffer))) == -1) - return -1; - } - - return -1; -} - -static unsigned int -_get_id3v2_frame_header_size(unsigned int version) -{ - switch (version) { - case 0: - case 1: - case 2: - return 6; - case 3: - case 4: - default: - return 10; - } -} - -static void -_parse_id3v2_frame_header(char *data, unsigned int version, struct id3v2_frame_header *fh) -{ - switch (version) { - case 0: - case 1: - case 2: - memcpy(fh->frame_id, data, 3); - fh->frame_id[3] = 0; - fh->frame_size = _to_uint(data + 3, 3); - fh->compression = 0; - fh->data_length_indicator = 0; - break; - case 3: - memcpy(fh->frame_id, data, 4); - fh->frame_size = _to_uint(data + 4, 4); - fh->compression = data[9] & 0x40; - fh->data_length_indicator = 0; - break; - case 4: - default: - memcpy(fh->frame_id, data, 4); - fh->frame_size = _to_uint(data + 4, 4); - fh->compression = data[9] & 0x4; - fh->data_length_indicator = data[9] & 0x1; - break; - } -} - -static inline void -_get_id3v2_frame_info(const char *frame_data, unsigned int frame_size, struct lms_string_size *s, lms_charset_conv_t *cs_conv) -{ - s->str = malloc(sizeof(char) * (frame_size + 1)); - memcpy(s->str, frame_data, frame_size); - s->str[frame_size] = '\0'; - s->len = frame_size; - if (cs_conv) - lms_charset_conv(cs_conv, &s->str, &s->len); -} - -static void -_parse_id3v2_frame(struct id3v2_frame_header *fh, const char *frame_data, struct lms_audio_info *info, lms_charset_conv_t **cs_convs) -{ - lms_charset_conv_t *cs_conv = NULL; - unsigned int text_encoding, frame_size; - -#if 0 - fprintf(stderr, "text encoding = %d\n", frame_data[0]); -#endif - - /* Latin1 = 0 - * UTF16 = 1 - * UTF16BE = 2 - * UTF8 = 3 - * UTF16LE = 4 - */ - text_encoding = frame_data[0]; - if (text_encoding >= 0 && text_encoding < ID3_NUM_ENCODINGS) - cs_conv = cs_convs[text_encoding]; - - /* skip first byte - text encoding */ - frame_data += 1; - frame_size = fh->frame_size - 1; - - /* ID3v2.2 used 3 bytes for the frame id, so let's check it */ - if (memcmp(fh->frame_id, "TIT2", 4) == 0 || - memcmp(fh->frame_id, "TT2", 3) == 0) - _get_id3v2_frame_info(frame_data, frame_size, &info->title, cs_conv); - else if (memcmp(fh->frame_id, "TPE1", 4) == 0 || - memcmp(fh->frame_id, "TP1", 3) == 0) - _get_id3v2_frame_info(frame_data, frame_size, &info->artist, cs_conv); - /* TALB, TAL */ - else if (memcmp(fh->frame_id, "TAL", 3) == 0) - _get_id3v2_frame_info(frame_data, frame_size, &info->album, cs_conv); - /* TCON, TCO */ - else if (memcmp(fh->frame_id, "TCO", 3) == 0) { - /* TODO handle multiple genres */ - int i, is_number; - - _get_id3v2_frame_info(frame_data, frame_size, &info->genre, cs_conv); - - is_number = 1; - for (i = 0; i < info->genre.len; ++i) { - if (!isdigit(info->genre.str[i])) - is_number = 0; - } - - if ((is_number) && - (info->genre.str) && - (info->genre.len > 0)) { - int genre = atoi(info->genre.str); - if (genre >= 0 && genre < ID3V1_NUM_GENRES) { - free(info->genre.str); - info->genre.str = strdup(id3v1_genres[(int) genre]); - info->genre.len = strlen(info->genre.str); - } - else { - /* ignore other genres */ - free(info->genre.str); - info->genre.str = NULL; - info->genre.len = 0; - } - } - } - else if (memcmp(fh->frame_id, "TRCK", 4) == 0 || - memcmp(fh->frame_id, "TRK", 3) == 0) { - struct lms_string_size trackno; - _get_id3v2_frame_info(frame_data, frame_size, &trackno, cs_conv); - info->trackno = atoi(trackno.str); - free(trackno.str); - } -} - -static int -_parse_id3v2(int fd, long id3v2_offset, struct lms_audio_info *info, lms_charset_conv_t **cs_convs) -{ - char header_data[10], frame_header_data[10]; - unsigned int tag_size, major_version, frame_data_pos, frame_data_length, frame_header_size; - int extended_header, footer_present; - struct id3v2_frame_header fh; - - lseek(fd, id3v2_offset, SEEK_SET); - - /* parse header */ - if (read(fd, header_data, ID3V2_HEADER_SIZE) != ID3V2_HEADER_SIZE) - return -1; - - tag_size = _to_uint(header_data + 6, 4); - if (tag_size == 0) - return -1; - - /* parse frames */ - major_version = header_data[3]; - - frame_data_pos = 0; - frame_data_length = tag_size; - - /* check for extended header */ - extended_header = header_data[5] & 0x20; /* bit 6 */ - if (extended_header) { - /* skip extended header */ - unsigned int extended_header_size; - char extended_header_data[4]; - - if (read(fd, extended_header_data, 4) != 4) - return -1; - extended_header_size = _to_uint(extended_header_data, 4); - lseek(fd, extended_header_size - 4, SEEK_CUR); - frame_data_pos += extended_header_size; - frame_data_length -= extended_header_size; - } - - footer_present = header_data[5] & 0x8; /* bit 4 */ - if (footer_present && frame_data_length > ID3V2_FOOTER_SIZE) - frame_data_length -= ID3V2_FOOTER_SIZE; - - frame_header_size = _get_id3v2_frame_header_size(major_version); - while (frame_data_pos < frame_data_length - frame_header_size) { - if (read(fd, frame_header_data, frame_header_size) != frame_header_size) - return -1; - - if (frame_header_data[0] == 0) - break; - - _parse_id3v2_frame_header(frame_header_data, major_version, &fh); - - if (!fh.compression && - fh.frame_id[0] == 'T' && - memcmp(fh.frame_id, "TXXX", 4) != 0) { - char *frame_data; - - if (fh.data_length_indicator) - lseek(fd, 4, SEEK_CUR); - - frame_data = malloc(sizeof(char) * fh.frame_size); - if (read(fd, frame_data, fh.frame_size) != fh.frame_size) { - free(frame_data); - return -1; - } - - _parse_id3v2_frame(&fh, frame_data, info, cs_convs); - free(frame_data); - } - else { - if (fh.data_length_indicator) - lseek(fd, fh.frame_size + 4, SEEK_CUR); - else - lseek(fd, fh.frame_size, SEEK_CUR); - } - - frame_data_pos += fh.frame_size + frame_header_size; - } - - return 0; -} - -static int -_parse_id3v1(int fd, struct lms_audio_info *info, lms_charset_conv_t *cs_conv) -{ - struct id3v1_tag tag; - if (read(fd, &tag, sizeof(struct id3v1_tag)) == -1) - return -1; - - info->title.str = strndup(tag.title, 30); - info->title.len = strlen(info->title.str); - lms_charset_conv(cs_conv, &info->title.str, &info->title.len); - info->artist.str = strndup(tag.artist, 30); - info->artist.len = strlen(info->artist.str); - lms_charset_conv(cs_conv, &info->artist.str, &info->artist.len); - info->album.str = strndup(tag.album, 30); - info->album.len = strlen(info->album.str); - lms_charset_conv(cs_conv, &info->album.str, &info->album.len); - if ((unsigned char) tag.genre < ID3V1_NUM_GENRES) { - info->genre.str = strdup(id3v1_genres[(unsigned char) tag.genre]); - info->genre.len = strlen(info->genre.str); - } - if (tag.comments[28] == 0 && tag.comments[29] != 0) - info->trackno = (unsigned char) tag.comments[29]; - - return 0; -} - -static void * -_match(struct plugin *p, const char *path, int len, int base) -{ - int i; - - i = lms_which_extension(path, len, _exts, LMS_ARRAY_SIZE(_exts)); - if (i < 0) - return NULL; - else - return (void*)(i + 1); -} - -static int -_parse(struct plugin *plugin, struct lms_context *ctxt, const struct lms_file_info *finfo, void *match) -{ - struct lms_audio_info info = {0, {0}, {0}, {0}, {0}, 0, 0, 0}; - int r, fd; - long id3v2_offset; - - fd = open(finfo->path, O_RDONLY); - if (fd < 0) { - perror("open"); - return -1; - } - - id3v2_offset = _find_id3v2(fd); - if (id3v2_offset >= 0) { -#if 0 - fprintf(stderr, "id3v2 tag found in file %s with offset %ld\n", - finfo->path, id3v2_offset); -#endif - if (_parse_id3v2(fd, id3v2_offset, &info, plugin->cs_convs) != 0) { - r = -2; - goto done; - } - } - else { - char tag[3]; -#if 0 - fprintf(stderr, "id3v2 tag not found in file %s. trying id3v1\n", finfo->path); -#endif - /* check for id3v1 tag */ - if (lseek(fd, -128, SEEK_END) == -1) { - r = -3; - goto done; - } - - if (read(fd, &tag, 3) == -1) { - r = -4; - goto done; - } - - if (memcmp(tag, "TAG", 3) == 0) { -#if 0 - fprintf(stderr, "id3v1 tag found in file %s\n", finfo->path); -#endif - if (_parse_id3v1(fd, &info, ctxt->cs_conv) != 0) { - r = -5; - goto done; - } - } - } - - lms_string_size_strip_and_free(&info.title); - lms_string_size_strip_and_free(&info.artist); - lms_string_size_strip_and_free(&info.album); - lms_string_size_strip_and_free(&info.genre); - - if (!info.title.str) { - int ext_idx; - ext_idx = ((int)match) - 1; - info.title.len = finfo->path_len - finfo->base - _exts[ext_idx].len; - info.title.str = malloc((info.title.len + 1) * sizeof(char)); - memcpy(info.title.str, finfo->path + finfo->base, info.title.len); - info.title.str[info.title.len] = '\0'; - lms_charset_conv(ctxt->cs_conv, &info.title.str, &info.title.len); - } - -#if 0 - fprintf(stderr, "file %s info\n", finfo->path); - fprintf(stderr, "\ttitle='%s'\n", info.title.str); - fprintf(stderr, "\tartist='%s'\n", info.artist.str); - fprintf(stderr, "\talbum='%s'\n", info.album.str); - fprintf(stderr, "\tgenre='%s'\n", info.genre.str); - fprintf(stderr, "\ttrack number='%d'\n", info.trackno); -#endif - - info.id = finfo->id; - r = lms_db_audio_add(plugin->audio_db, &info); - - done: - close(fd); - - if (info.title.str) - free(info.title.str); - if (info.artist.str) - free(info.artist.str); - if (info.album.str) - free(info.album.str); - if (info.genre.str) - free(info.genre.str); - - return r; -} - -static int -_setup(struct plugin *plugin, struct lms_context *ctxt) -{ - int i; - const char *id3v2_encodings[ID3_NUM_ENCODINGS] = { - "Latin1", - "UTF-16", - "UTF-16BE", - NULL, /* UTF-8 */ - "UTF-16LE", - }; - - plugin->audio_db = lms_db_audio_new(ctxt->db); - if (!plugin->audio_db) - return -1; - - for (i = 0; i < ID3_NUM_ENCODINGS; ++i) { - /* do not create charset conv for UTF-8 encoding */ - if (i == ID3_ENCODING_UTF8) { - plugin->cs_convs[i] = NULL; - continue; - } - plugin->cs_convs[i] = lms_charset_conv_new_full(0, 0); - if (!plugin->cs_convs[i]) - return -1; - lms_charset_conv_add(plugin->cs_convs[i], id3v2_encodings[i]); - } - - return 0; -} - -static int -_start(struct plugin *plugin, struct lms_context *ctxt) -{ - return lms_db_audio_start(plugin->audio_db); -} - -static int -_finish(struct plugin *plugin, struct lms_context *ctxt) -{ - int i; - - if (plugin->audio_db) - lms_db_audio_free(plugin->audio_db); - - for (i = 0; i < ID3_NUM_ENCODINGS; ++i) { - if (plugin->cs_convs[i]) - lms_charset_conv_free(plugin->cs_convs[i]); - } - - return 0; -} - -static int -_close(struct plugin *plugin) -{ - free(plugin); - return 0; -} - -API struct lms_plugin * -lms_plugin_open(void) -{ - struct plugin *plugin; - - plugin = (struct plugin *)malloc(sizeof(*plugin)); - plugin->plugin.name = _name; - plugin->plugin.match = (lms_plugin_match_fn_t)_match; - plugin->plugin.parse = (lms_plugin_parse_fn_t)_parse; - plugin->plugin.close = (lms_plugin_close_fn_t)_close; - plugin->plugin.setup = (lms_plugin_setup_fn_t)_setup; - plugin->plugin.start = (lms_plugin_start_fn_t)_start; - plugin->plugin.finish = (lms_plugin_finish_fn_t)_finish; - - return (struct lms_plugin *)plugin; -} diff --git a/lightmediascanner/src/plugins/jpeg/Makefile.am b/lightmediascanner/src/plugins/jpeg/Makefile.am deleted file mode 100644 index 6ec341a..0000000 --- a/lightmediascanner/src/plugins/jpeg/Makefile.am +++ /dev/null @@ -1,10 +0,0 @@ -MAINTAINERCLEANFILES = Makefile.in - -AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_srcdir)/src/plugins/jpeg - -pkgdir = $(pluginsdir) -pkg_LTLIBRARIES = jpeg.la -jpeg_la_SOURCES = jpeg.c -jpeg_la_DEPENDENCIES = $(top_builddir)/config.h -jpeg_la_LIBADD = $(top_builddir)/src/lib/liblightmediascanner.la -jpeg_la_LDFLAGS = -module -avoid-version diff --git a/lightmediascanner/src/plugins/jpeg/jpeg.c b/lightmediascanner/src/plugins/jpeg/jpeg.c deleted file mode 100644 index 92c60b9..0000000 --- a/lightmediascanner/src/plugins/jpeg/jpeg.c +++ /dev/null @@ -1,719 +0,0 @@ -/** - * Copyright (C) 2007 by INdT - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser 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 Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * @author Gustavo Sverzut Barbieri - */ - -/** - * @brief - * - * Reads EXIF tags from images. - * - * @todo: get GPS data. - * @todo: check if worth using mmap(). - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#define _XOPEN_SOURCE 600 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -enum { - JPEG_MARKER_SOI = 0xd8, - JPEG_MARKER_DQT = 0xdb, - JPEG_MARKER_JFIF = 0xe0, - JPEG_MARKER_EXIF = 0xe1, - JPEG_MARKER_COMM = 0xfe, - JPEG_MARKER_SOF0 = 0xc0, - JPEG_MARKER_SOF1 = 0xc1, - JPEG_MARKER_SOF2 = 0xc2, - JPEG_MARKER_SOF9 = 0xc9, - JPEG_MARKER_SOF10 = 0xca, - JPEG_MARKER_SOS = 0xda -}; - -/** - * Process SOF JPEG, this contains width and height. - */ -static int -_jpeg_sof_process(int fd, unsigned short *width, unsigned short *height) -{ - unsigned char buf[6]; - - if (read(fd, buf, 6) != 6) { - perror("could not read() SOF data"); - return -1; - } - - *height = (buf[1] << 8) | buf[2]; - *width = (buf[3] << 8) | buf[4]; - - return 0; -} - -/** - * Process COM JPEG, this contains user comment. - */ -static int -_jpeg_com_process(int fd, int len, struct lms_string_size *comment) -{ - if (len < 1) { - comment->str = NULL; - comment->len = 0; - return 0; - } - - comment->str = malloc(len + 1); - if (!comment->str) { - perror("malloc"); - return -1; - } - if (read(fd, comment->str, len) != len) { - perror("read"); - free(comment->str); - comment->str = NULL; - comment->len = 0; - return -2; - } - if (comment->str[len - 1] == '\0') - len--; - else - comment->str[len] = '\0'; - comment->len = len; - - lms_string_size_strip_and_free(comment); - - return 0; -} - -/** - * Walk JPEG markers in order to get useful information. - */ -static int -_jpeg_info_get(int fd, int len, struct lms_image_info *info) -{ - unsigned char buf[4]; - int found; - off_t offset; - - found = info->title.str ? 1 : 0; - offset = lseek(fd, len - 2, SEEK_CUR); - len = 0; - while (found < 2) { - offset = lseek(fd, offset + len, SEEK_SET); - if (offset == -1) { - perror("lseek"); - return -1; - } - - if (read(fd, buf, 4) != 4) { - perror("read"); - return -2; - } - - len = ((buf[2] << 8) | buf[3]) - 2; - - if (buf[0] != 0xff) { - fprintf(stderr, "ERROR: expected 0xff marker, got %#x\n", buf[0]); - return -3; - } - - if (buf[1] == JPEG_MARKER_SOF0 || - buf[1] == JPEG_MARKER_SOF1 || - buf[1] == JPEG_MARKER_SOF2 || - buf[1] == JPEG_MARKER_SOF9 || - buf[1] == JPEG_MARKER_SOF10) { - if (_jpeg_sof_process(fd, &info->width, &info->height) != 0) - return -4; - found++; - } else if (buf[1] == JPEG_MARKER_COMM && !info->title.str) { - if (_jpeg_com_process(fd, len, &info->title) != 0) - return -5; - found++; - } else if (buf[1] == JPEG_MARKER_SOS) - break; - - len += 4; /* add read size */ - } - - return 0; -} - -/** - * Read JPEG file start (0xffd8 marker) and return the next - * marker type and its length. - */ -static int -_jpeg_data_get(int fd, int *type, int *len) -{ - unsigned char buf[6]; - - if (lseek(fd, 0, SEEK_SET) != 0) { - perror("lseek"); - return -1; - } - - if (read(fd, buf, 6) != 6) { - perror("read"); - return -2; - } - - if (buf[0] != 0xff || buf[1] != JPEG_MARKER_SOI || buf[2] != 0xff) { - fprintf(stderr, "ERROR: not JPEG file (magic=%#x %#x %#x)\n", - buf[0], buf[1], buf[2]); - return -3; - } - - *type = buf[3]; - *len = (buf[4] << 8) | buf[5]; - - return 0; -} - -#define LE_4BYTE(a) ((a)[0] | ((a)[1] << 8) | ((a)[2] << 16) | ((a)[3] << 24)) -#define BE_4BYTE(a) (((a)[0] << 24) | ((a)[1] << 16) | ((a)[2] << 8) | (a)[3]) - -#define LE_2BYTE(a) ((a)[0] | ((a)[1] << 8)) -#define BE_2BYTE(a) (((a)[0] << 8) | (a)[1]) - -#define E_2BTYE(little_endian, a) ((little_endian) ? LE_2BYTE(a) : BE_2BYTE(a)) -#define E_4BTYE(little_endian, a) ((little_endian) ? LE_4BYTE(a) : BE_4BYTE(a)) - -enum { - EXIF_TYPE_BYTE = 1, /* 8 bit unsigned */ - EXIF_TYPE_ASCII = 2, /* 8 bit byte with 7-bit ASCII code, NULL terminated */ - EXIF_TYPE_SHORT = 3, /* 2-byte unsigned integer */ - EXIF_TYPE_LONG = 4, /* 4-byte unsigned integer */ - EXIF_TYPE_RATIONAL = 5, /* 2 4-byte unsigned integer, 1st = numerator */ - EXIF_TYPE_UNDEFINED = 7, /* 8-bit byte */ - EXIF_TYPE_SLONG = 9, /* 4-byte signed integer (2'complement) */ - EXIF_TYPE_SRATIONAL = 10 /* 2 4-byte signed integer, 1st = numerator */ -}; - -enum { - EXIF_TAG_ORIENTATION = 0x0112, - EXIF_TAG_ARTIST = 0x013b, - EXIF_TAG_USER_COMMENT = 0x9286, - EXIF_TAG_IMAGE_DESCRIPTION = 0x010e, - EXIF_TAG_DATE_TIME = 0x0132, - EXIF_TAG_DATE_TIME_ORIGINAL = 0x9003, - EXIF_TAG_DATE_TIME_DIGITIZED = 0x9004, - EXIF_TAG_EXIF_IFD_POINTER = 0x8769 -}; - - -struct exif_ifd { - unsigned short tag; - unsigned short type; - unsigned int count; - unsigned int offset; -}; - -/** - * Read IFD from stream. - */ -static int -_exif_ifd_get(int fd, int little_endian, struct exif_ifd *ifd) -{ - unsigned char buf[12]; - - if (read(fd, buf, 12) != 12) { - perror("read"); - return -1; - } - - if (little_endian) { - ifd->tag = LE_2BYTE(buf); - ifd->type = LE_2BYTE(buf + 2); - ifd->count = LE_4BYTE(buf + 4); - ifd->offset = LE_4BYTE(buf + 8); - } else { - ifd->tag = BE_2BYTE(buf); - ifd->type = BE_2BYTE(buf + 2); - ifd->count = BE_4BYTE(buf + 4); - ifd->offset = BE_4BYTE(buf + 8); - } - return 0; -} - -/** - * Get non-exif data based on Exif tag offset. - * - * This will setup the file description position and call _jpeg_info_get(). - */ -static int -_exif_extra_get(int fd, int abs_offset, int len, struct lms_image_info *info) -{ - if (lseek(fd, abs_offset, SEEK_SET) == -1) { - perror("lseek"); - return -1; - } - - if (_jpeg_info_get(fd, len, info) != 0) { - fprintf(stderr, "ERROR: could not get image size.\n"); - return -2; - } - return 0; -} - -static int -_exif_text_encoding_get(int fd, unsigned int count, int offset, struct lms_string_size *s) -{ - if (count <= 8) - return -1; - - count -= 8; /* XXX don't just ignore character code, handle it. */ - offset += 8; - - if (lseek(fd, offset, SEEK_SET) == -1) { - perror("lseek"); - return -2; - } - - s->str = malloc(count + 1); - - if (read(fd, s->str, count) != count) { - perror("read"); - free(s->str); - s->str = NULL; - s->len = 0; - return -3; - } - s->str[count] = '\0'; - s->len = count; - - lms_string_size_strip_and_free(s); - - return 0; -} - -static int -_exif_text_ascii_get(int fd, unsigned int count, int offset, struct lms_string_size *s) -{ - if (count < 1) { - s->str = NULL; - s->len = 0; - return 0; - } - - if (lseek(fd, offset, SEEK_SET) == -1) { - perror("lseek"); - return -1; - } - - s->str = malloc(count); - - if (read(fd, s->str, count) != count) { - perror("read"); - free(s->str); - s->str = NULL; - s->len = 0; - return -1; - } - s->str[count - 1] = '\0'; - s->len = count - 1; - - lms_string_size_strip_and_free(s); - - return 0; -} - -static unsigned int -_exif_datetime_get(int fd, int offset) -{ - char buf[20]; - struct tm tm = {0}; - - if (lseek(fd, offset, SEEK_SET) == -1) { - perror("lseek"); - return 0; - } - - if (read(fd, buf, 20) != 20) { - perror("read"); - return 0; - } - - buf[19] = '\0'; - if (strptime(buf, "%Y:%m:%d %H:%M:%S", &tm)) { - return mktime(&tm); - } - return 0; -} - -static int _exif_private_ifd_get(int fd, int base_offset, int offset, int little_endian, struct lms_image_info *info); - -/** - * Process IFD contents. - */ -static int -_exif_ifd_process(int fd, int count, int ifd_offset, int tiff_base, int little_endian, struct lms_image_info *info) -{ - int i, torig, tdig, tlast; - - torig = tdig = tlast = 0; - - for (i = 0; i < count; i++) { - struct exif_ifd ifd; - - lseek(fd, tiff_base + ifd_offset + i * 12, SEEK_SET); - if (_exif_ifd_get(fd, little_endian, &ifd) != 0) { - fprintf(stderr, "ERROR: could not read Exif IFD.\n"); - return -8; - } - - switch (ifd.tag) { - case EXIF_TAG_ORIENTATION: - info->orientation = ifd.offset >> 16; - break; - case EXIF_TAG_ARTIST: - if (!info->artist.str) - _exif_text_ascii_get(fd, ifd.count, tiff_base + ifd.offset, - &info->artist); - break; - case EXIF_TAG_USER_COMMENT: - if (!info->title.str) - _exif_text_encoding_get(fd, ifd.count, tiff_base + ifd.offset, - &info->title); - break; - case EXIF_TAG_IMAGE_DESCRIPTION: - if (!info->title.str) - _exif_text_ascii_get(fd, ifd.count, tiff_base + ifd.offset, - &info->title); - break; - case EXIF_TAG_DATE_TIME: - if (torig == 0 && info->date == 0) - tlast = _exif_datetime_get(fd, tiff_base + ifd.offset); - break; - case EXIF_TAG_DATE_TIME_ORIGINAL: - if (torig == 0 && info->date == 0) - torig = _exif_datetime_get(fd, tiff_base + ifd.offset); - break; - case EXIF_TAG_DATE_TIME_DIGITIZED: - if (torig == 0 && info->date == 0) - tdig = _exif_datetime_get(fd, tiff_base + ifd.offset); - break; - case EXIF_TAG_EXIF_IFD_POINTER: - if (ifd.count == 1 && ifd.type == EXIF_TYPE_LONG) - _exif_private_ifd_get(fd, ifd.offset, tiff_base, - little_endian, info); - break; - default: - /* ignore */ - break; - } - } - - if (info->date == 0) { - if (torig) - info->date = torig; - else if (tdig) - info->date = tdig; - else - info->date = tlast; - } - - return 0; -} - -/** - * Process Exif IFD (Exif Private Tag), with more specific info. - */ -static int -_exif_private_ifd_get(int fd, int ifd_offset, int tiff_base, int little_endian, struct lms_image_info *info) -{ - char buf[2]; - unsigned int count; - - if (lseek(fd, tiff_base + ifd_offset, SEEK_SET) == -1) { - perror("lseek"); - return -1; - } - - if (read(fd, buf, 2) != 2) { - perror("read"); - return -1; - } - - count = E_2BTYE(little_endian, buf); - return _exif_ifd_process(fd, count, ifd_offset + 2, tiff_base, - little_endian, info); -} - -/** - * Process file as it being Exif, will extract Exif as well as other - * JPEG markers (comment, size). - */ -static int -_exif_data_get(int fd, int len, struct lms_image_info *info) -{ - const unsigned char exif_hdr[6] = "Exif\0"; - unsigned char buf[8]; - unsigned int little_endian, offset, count; - off_t abs_offset, tiff_base; - - abs_offset = lseek(fd, 0, SEEK_CUR); - if (abs_offset == -1) { - perror("lseek"); - return -1; - } - - if (read(fd, buf, 6) != 6) { - perror("read"); - return -2; - } - - memset(info, 0, sizeof(*info)); - info->orientation = 1; - - if (memcmp(buf, exif_hdr, 6) != 0) - return _exif_extra_get(fd, abs_offset, len, info); - - if (read(fd, buf, 8) != 8) { - perror("read"); - return -4; - } - - if (buf[0] == 'I' && buf[1] == 'I') { - little_endian = 1; - offset = LE_4BYTE(buf + 4); - } else if (buf[0] == 'M' && buf[1] == 'M') { - little_endian = 0; - offset = BE_4BYTE(buf + 4); - } else { - fprintf(stderr, "ERROR: undefined byte sex \"%2.2s\".\n", buf); - return -5; - } - - offset -= 8; - if (offset > 0 && lseek(fd, offset, SEEK_CUR) == -1) { - perror("lseek"); - return -6; - } - - tiff_base = abs_offset + 6; /* offsets are relative to TIFF base */ - - if (read(fd, buf, 2) != 2) { - perror("read"); - return -7; - } - count = E_2BTYE(little_endian, buf); - - _exif_ifd_process(fd, count, 8 + 2, tiff_base, - little_endian, info); - - return _exif_extra_get(fd, abs_offset, len, info); -} - -/** - * Process file as it being JFIF - */ -static int -_jfif_data_get(int fd, int len, struct lms_image_info *info) -{ - unsigned char buf[4]; - int new_len; - - memset(info, 0, sizeof(*info)); - info->orientation = 1; - - /* JFIF provides no useful information, try to find out Exif */ - if (lseek(fd, len - 2, SEEK_CUR) == -1) { - perror("lseek"); - return -1; - } - - if (read(fd, buf, 4) != 4) { - perror("read"); - return -2; - } - - new_len = ((buf[2] << 8) | buf[3]); - if (buf[0] != 0xff) { - fprintf(stderr, "ERROR: expected 0xff marker, got %#x\n", buf[0]); - return -3; - } - - if (buf[1] == JPEG_MARKER_EXIF) - return _exif_data_get(fd, new_len, info); - else { - /* rollback to avoid losing initial frame */ - if (lseek(fd, - len - 2, SEEK_CUR) == -1) { - perror("lseek"); - return -1; - } - return _jpeg_info_get(fd, len, info); - } -} - -static const char _name[] = "jpeg"; -static const struct lms_string_size _exts[] = { - LMS_STATIC_STRING_SIZE(".jpg"), - LMS_STATIC_STRING_SIZE(".jpeg"), - LMS_STATIC_STRING_SIZE(".jpe") -}; - -struct plugin { - struct lms_plugin plugin; - lms_db_image_t *img_db; -}; - -static void * -_match(struct plugin *p, const char *path, int len, int base) -{ - int i; - - i = lms_which_extension(path, len, _exts, LMS_ARRAY_SIZE(_exts)); - if (i < 0) - return NULL; - else - return (void*)(i + 1); -} - -static int -_parse(struct plugin *plugin, struct lms_context *ctxt, const struct lms_file_info *finfo, void *match) -{ - struct lms_image_info info = {0}; - int fd, type, len, r; - - fd = open(finfo->path, O_RDONLY); - if (fd < 0) { - perror("open"); - return -1; - } - - if (_jpeg_data_get(fd, &type, &len) != 0) { - r = -2; - goto done; - } - - if (type == JPEG_MARKER_EXIF) { - if (_exif_data_get(fd, len, &info) != 0) { - fprintf(stderr, "ERROR: could not get EXIF info (%s).\n", - finfo->path); - r = -3; - goto done; - } - } else if (type == JPEG_MARKER_JFIF || type == JPEG_MARKER_DQT) { - if (_jfif_data_get(fd, len, &info) != 0) { - fprintf(stderr, "ERROR: could not get JPEG size (%s).\n", - finfo->path); - r = -4; - goto done; - } - } else { - fprintf(stderr, "ERROR: unsupported JPEG marker %#x (%s)\n", type, - finfo->path); - r = -6; - goto done; - } - - if (info.date == 0) - info.date = finfo->mtime; - - if (!info.title.str) { - int ext_idx; - - ext_idx = ((int)match) - 1; - info.title.len = finfo->path_len - finfo->base - _exts[ext_idx].len; - info.title.str = malloc((info.title.len + 1) * sizeof(char)); - memcpy(info.title.str, finfo->path + finfo->base, info.title.len); - info.title.str[info.title.len] = '\0'; - } - - if (info.title.str) - lms_charset_conv(ctxt->cs_conv, &info.title.str, &info.title.len); - if (info.artist.str) - lms_charset_conv(ctxt->cs_conv, &info.artist.str, &info.artist.len); - - info.id = finfo->id; - r = lms_db_image_add(plugin->img_db, &info); - - done: - if (info.title.str) - free(info.title.str); - if (info.artist.str) - free(info.artist.str); - - posix_fadvise(fd, 0, 0, POSIX_FADV_DONTNEED); - close(fd); - - return r; -} - -static int -_setup(struct plugin *plugin, struct lms_context *ctxt) -{ - plugin->img_db = lms_db_image_new(ctxt->db); - if (!plugin->img_db) - return -1; - - return 0; -} - -static int -_start(struct plugin *plugin, struct lms_context *ctxt) -{ - return lms_db_image_start(plugin->img_db); -} - -static int -_finish(struct plugin *plugin, struct lms_context *ctxt) -{ - if (plugin->img_db) - return lms_db_image_free(plugin->img_db); - - return 0; -} - - -static int -_close(struct plugin *plugin) -{ - free(plugin); - return 0; -} - -API struct lms_plugin * -lms_plugin_open(void) -{ - struct plugin *plugin; - - plugin = malloc(sizeof(*plugin)); - plugin->plugin.name = _name; - plugin->plugin.match = (lms_plugin_match_fn_t)_match; - plugin->plugin.parse = (lms_plugin_parse_fn_t)_parse; - plugin->plugin.close = (lms_plugin_close_fn_t)_close; - plugin->plugin.setup = (lms_plugin_setup_fn_t)_setup; - plugin->plugin.start = (lms_plugin_start_fn_t)_start; - plugin->plugin.finish = (lms_plugin_finish_fn_t)_finish; - - return (struct lms_plugin *)plugin; -} diff --git a/lightmediascanner/src/plugins/m3u/Makefile.am b/lightmediascanner/src/plugins/m3u/Makefile.am deleted file mode 100644 index b2332cf..0000000 --- a/lightmediascanner/src/plugins/m3u/Makefile.am +++ /dev/null @@ -1,10 +0,0 @@ -MAINTAINERCLEANFILES = Makefile.in - -AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_srcdir)/src/plugins/m3u - -pkgdir = $(pluginsdir) -pkg_LTLIBRARIES = m3u.la -m3u_la_SOURCES = m3u.c -m3u_la_DEPENDENCIES = $(top_builddir)/config.h -m3u_la_LIBADD = $(top_builddir)/src/lib/liblightmediascanner.la -m3u_la_LDFLAGS = -module -avoid-version diff --git a/lightmediascanner/src/plugins/m3u/m3u.c b/lightmediascanner/src/plugins/m3u/m3u.c deleted file mode 100644 index d5c907e..0000000 --- a/lightmediascanner/src/plugins/m3u/m3u.c +++ /dev/null @@ -1,193 +0,0 @@ -/** - * Copyright (C) 2007 by INdT - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser 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 Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * @author Gustavo Sverzut Barbieri - */ - -/** - * @brief - * - * m3u playlist parser. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#define _XOPEN_SOURCE 600 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static int -_m3u_get_n_entries(int fd, struct lms_playlist_info *info) -{ - char buf[1024]; - enum { - IS_EMPTY, - IS_ENTRY, - IS_COMMENT - } state; - - state = IS_EMPTY; - do { - ssize_t r; - int i; - - r = read(fd, buf, sizeof(buf)); - if (r < 0) { - perror("read"); - return -1; - } else if (r == 0) - goto done; - - for (i = 0; i < r; i++) { - char c; - - c = buf[i]; - if (c == '\n') { - if (state == IS_ENTRY) - info->n_entries++; - state = IS_EMPTY; - } else if (state == IS_EMPTY) { - if (c == '#') - state = IS_COMMENT; - else if (!isspace(c)) - state = IS_ENTRY; - } - } - } while (1); - - done: - if (state == IS_ENTRY) - info->n_entries++; - return 0; -} - -static const char _name[] = "m3u"; -static const struct lms_string_size _exts[] = { - LMS_STATIC_STRING_SIZE(".m3u") -}; - -struct plugin { - struct lms_plugin plugin; - lms_db_playlist_t *playlist_db; -}; - -static void * -_match(struct plugin *p, const char *path, int len, int base) -{ - int i; - - i = lms_which_extension(path, len, _exts, LMS_ARRAY_SIZE(_exts)); - if (i < 0) - return NULL; - else - return (void*)(i + 1); -} - -static int -_parse(struct plugin *plugin, struct lms_context *ctxt, const struct lms_file_info *finfo, void *match) -{ - struct lms_playlist_info info = {0}; - int fd, r, ext_idx; - - fd = open(finfo->path, O_RDONLY); - if (fd < 0) { - perror("open"); - return -1; - } - - if (_m3u_get_n_entries(fd, &info) != 0) - fprintf(stderr, - "WARNING: could not get number of entries in playlist '%s'.\n", - finfo->path); - - ext_idx = ((int)match) - 1; - info.title.len = finfo->path_len - finfo->base - _exts[ext_idx].len; - info.title.str = malloc((info.title.len + 1) * sizeof(char)); - memcpy(info.title.str, finfo->path + finfo->base, info.title.len); - info.title.str[info.title.len] = '\0'; - lms_charset_conv(ctxt->cs_conv, &info.title.str, &info.title.len); - - info.id = finfo->id; - r = lms_db_playlist_add(plugin->playlist_db, &info); - - if (info.title.str) - free(info.title.str); - posix_fadvise(fd, 0, 0, POSIX_FADV_DONTNEED); - close(fd); - - return r; -} - -static int -_setup(struct plugin *plugin, struct lms_context *ctxt) -{ - plugin->playlist_db = lms_db_playlist_new(ctxt->db); - if (!plugin->playlist_db) - return -1; - - return 0; -} - -static int -_start(struct plugin *plugin, struct lms_context *ctxt) -{ - return lms_db_playlist_start(plugin->playlist_db); -} - -static int -_finish(struct plugin *plugin, struct lms_context *ctxt) -{ - if (plugin->playlist_db) - return lms_db_playlist_free(plugin->playlist_db); - - return 0; -} - - -static int -_close(struct plugin *plugin) -{ - free(plugin); - return 0; -} - -API struct lms_plugin * -lms_plugin_open(void) -{ - struct plugin *plugin; - - plugin = malloc(sizeof(*plugin)); - plugin->plugin.name = _name; - plugin->plugin.match = (lms_plugin_match_fn_t)_match; - plugin->plugin.parse = (lms_plugin_parse_fn_t)_parse; - plugin->plugin.close = (lms_plugin_close_fn_t)_close; - plugin->plugin.setup = (lms_plugin_setup_fn_t)_setup; - plugin->plugin.start = (lms_plugin_start_fn_t)_start; - plugin->plugin.finish = (lms_plugin_finish_fn_t)_finish; - - return (struct lms_plugin *)plugin; -} diff --git a/lightmediascanner/src/plugins/mp4/Makefile.am b/lightmediascanner/src/plugins/mp4/Makefile.am deleted file mode 100644 index 340eea5..0000000 --- a/lightmediascanner/src/plugins/mp4/Makefile.am +++ /dev/null @@ -1,10 +0,0 @@ -MAINTAINERCLEANFILES = Makefile.in - -AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_srcdir)/src/plugins/mp4 - -pkgdir = $(pluginsdir) -pkg_LTLIBRARIES = mp4.la -mp4_la_SOURCES = mp4.c -mp4_la_DEPENDENCIES = $(top_builddir)/config.h -mp4_la_LIBADD = $(top_builddir)/src/lib/liblightmediascanner.la @MP4V2_LIBS@ -mp4_la_LDFLAGS = -module -avoid-version diff --git a/lightmediascanner/src/plugins/mp4/mp4.c b/lightmediascanner/src/plugins/mp4/mp4.c deleted file mode 100644 index b556fe4..0000000 --- a/lightmediascanner/src/plugins/mp4/mp4.c +++ /dev/null @@ -1,232 +0,0 @@ -/** - * Copyright (C) 2008 by INdT - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser 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 Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * @author Andre Moreira Magalhaes - */ - -/** - * @brief - * - * mp4 file parser. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include - -enum StreamTypes { - STREAM_TYPE_UNKNOWN = 0, - STREAM_TYPE_AUDIO, - STREAM_TYPE_VIDEO -}; - -struct mp4_info { - struct lms_string_size title; - struct lms_string_size artist; - struct lms_string_size album; - struct lms_string_size genre; - u_int16_t trackno; -}; - -struct plugin { - struct lms_plugin plugin; - lms_db_audio_t *audio_db; - lms_db_video_t *video_db; -}; - -static const char _name[] = "mp4"; -static const struct lms_string_size _exts[] = { - LMS_STATIC_STRING_SIZE(".mp4"), - LMS_STATIC_STRING_SIZE(".m4a"), - LMS_STATIC_STRING_SIZE(".mov"), - LMS_STATIC_STRING_SIZE(".qt"), - LMS_STATIC_STRING_SIZE(".3gp") -}; - -static void * -_match(struct plugin *p, const char *path, int len, int base) -{ - int i; - - i = lms_which_extension(path, len, _exts, LMS_ARRAY_SIZE(_exts)); - if (i < 0) - return NULL; - else - return (void*)(i + 1); -} - -static int -_parse(struct plugin *plugin, struct lms_context *ctxt, const struct lms_file_info *finfo, void *match) -{ - struct mp4_info info = {{0}, {0}, {0}, {0}}; - struct lms_audio_info audio_info = {0, {0}, {0}, {0}, {0}, 0, 0, 0}; - struct lms_video_info video_info = {0, {0}, {0}}; - int r, stream_type = STREAM_TYPE_AUDIO; - MP4FileHandle mp4_fh; - u_int32_t num_tracks; - - mp4_fh = MP4Read(finfo->path, 0); - if (mp4_fh == MP4_INVALID_FILE_HANDLE) { - fprintf(stderr, "ERROR: cannot read mp4 file %s\n", finfo->path); - return -1; - } - - /* check if the file contains a video track */ - num_tracks = MP4GetNumberOfTracks(mp4_fh, MP4_VIDEO_TRACK_TYPE, 0); - if (num_tracks > 0) - stream_type = STREAM_TYPE_VIDEO; - - MP4GetMetadataName(mp4_fh, &info.title.str); - if (info.title.str) - info.title.len = strlen(info.title.str); - MP4GetMetadataArtist(mp4_fh, &info.artist.str); - if (info.artist.str) - info.artist.len = strlen(info.artist.str); - - if (stream_type == STREAM_TYPE_AUDIO) { - u_int16_t total_tracks; - - MP4GetMetadataAlbum(mp4_fh, &info.album.str); - if (info.album.str) - info.album.len = strlen(info.album.str); - MP4GetMetadataGenre(mp4_fh, &info.genre.str); - if (info.genre.str) - info.genre.len = strlen(info.genre.str); - - MP4GetMetadataTrack(mp4_fh, &info.trackno, &total_tracks); - } - - lms_string_size_strip_and_free(&info.title); - lms_string_size_strip_and_free(&info.artist); - lms_string_size_strip_and_free(&info.album); - lms_string_size_strip_and_free(&info.genre); - - if (!info.title.str) { - int ext_idx; - ext_idx = ((int)match) - 1; - info.title.len = finfo->path_len - finfo->base - _exts[ext_idx].len; - info.title.str = malloc((info.title.len + 1) * sizeof(char)); - memcpy(info.title.str, finfo->path + finfo->base, info.title.len); - info.title.str[info.title.len] = '\0'; - } - lms_charset_conv(ctxt->cs_conv, &info.title.str, &info.title.len); - - if (info.artist.str) - lms_charset_conv(ctxt->cs_conv, &info.artist.str, &info.artist.len); - if (info.album.str) - lms_charset_conv(ctxt->cs_conv, &info.album.str, &info.album.len); - if (info.genre.str) - lms_charset_conv(ctxt->cs_conv, &info.genre.str, &info.genre.len); - -#if 0 - fprintf(stderr, "file %s info\n", finfo->path); - fprintf(stderr, "\ttitle='%s'\n", info.title.str); - fprintf(stderr, "\tartist='%s'\n", info.artist.str); - fprintf(stderr, "\talbum='%s'\n", info.album.str); - fprintf(stderr, "\tgenre='%s'\n", info.genre.str); -#endif - - if (stream_type == STREAM_TYPE_AUDIO) { - audio_info.id = finfo->id; - audio_info.title = info.title; - audio_info.artist = info.artist; - audio_info.album = info.album; - audio_info.genre = info.genre; - audio_info.trackno = info.trackno; - r = lms_db_audio_add(plugin->audio_db, &audio_info); - } - else { - video_info.id = finfo->id; - video_info.title = info.title; - video_info.artist = info.artist; - r = lms_db_video_add(plugin->video_db, &video_info); - } - - MP4Close(mp4_fh); - - if (info.title.str) - free(info.title.str); - if (info.artist.str) - free(info.artist.str); - if (info.album.str) - free(info.album.str); - if (info.genre.str) - free(info.genre.str); - - return r; -} - -static int -_setup(struct plugin *plugin, struct lms_context *ctxt) -{ - plugin->audio_db = lms_db_audio_new(ctxt->db); - if (!plugin->audio_db) - return -1; - plugin->video_db = lms_db_video_new(ctxt->db); - if (!plugin->video_db) - return -1; - - return 0; -} - -static int -_start(struct plugin *plugin, struct lms_context *ctxt) -{ - int r; - r = lms_db_audio_start(plugin->audio_db); - r |= lms_db_video_start(plugin->video_db); - return r; -} - -static int -_finish(struct plugin *plugin, struct lms_context *ctxt) -{ - if (plugin->audio_db) - lms_db_audio_free(plugin->audio_db); - if (plugin->video_db) - lms_db_video_free(plugin->video_db); - - return 0; -} - -static int -_close(struct plugin *plugin) -{ - free(plugin); - return 0; -} - -API struct lms_plugin * -lms_plugin_open(void) -{ - struct plugin *plugin; - - plugin = (struct plugin *)malloc(sizeof(*plugin)); - plugin->plugin.name = _name; - plugin->plugin.match = (lms_plugin_match_fn_t)_match; - plugin->plugin.parse = (lms_plugin_parse_fn_t)_parse; - plugin->plugin.close = (lms_plugin_close_fn_t)_close; - plugin->plugin.setup = (lms_plugin_setup_fn_t)_setup; - plugin->plugin.start = (lms_plugin_start_fn_t)_start; - plugin->plugin.finish = (lms_plugin_finish_fn_t)_finish; - - return (struct lms_plugin *)plugin; -} diff --git a/lightmediascanner/src/plugins/ogg/Makefile.am b/lightmediascanner/src/plugins/ogg/Makefile.am deleted file mode 100644 index 26d414d..0000000 --- a/lightmediascanner/src/plugins/ogg/Makefile.am +++ /dev/null @@ -1,10 +0,0 @@ -MAINTAINERCLEANFILES = Makefile.in - -AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_srcdir)/src/plugins/ogg @VORBIS_CFLAGS@ - -pkgdir = $(pluginsdir) -pkg_LTLIBRARIES = ogg.la -ogg_la_SOURCES = ogg.c -ogg_la_DEPENDENCIES = $(top_builddir)/config.h -ogg_la_LIBADD = $(top_builddir)/src/lib/liblightmediascanner.la @VORBIS_LIBS@ -ogg_la_LDFLAGS = -module -avoid-version diff --git a/lightmediascanner/src/plugins/ogg/ogg.c b/lightmediascanner/src/plugins/ogg/ogg.c deleted file mode 100644 index f4beaef..0000000 --- a/lightmediascanner/src/plugins/ogg/ogg.c +++ /dev/null @@ -1,325 +0,0 @@ -/** - * Copyright (C) 2007 by INdT - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser 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 Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * @author Renato Chencarek - */ - -/** - * @brief - * - * ogg file parser. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include -#include -#include -#include - -static long int -_id3_tag_size(FILE *file) -{ - unsigned char tmp[4]; - long int size; - - if (fread(tmp, 1, 4, file) == 4) { - if (tmp[0] == 'I' && tmp[1] == 'D' && - tmp[2] == '3' && tmp[3] < 0xFF) { - fseek(file, 2, SEEK_CUR); - if (fread(tmp, 1, 4, file) == 4) { - size = 10 + ( (long)(tmp[3]) - | ((long)(tmp[2]) << 7) - | ((long)(tmp[1]) << 14) - | ((long)(tmp[0]) << 21) ); - - return size; - } - } - } - return 0L; -} - - -static int -_get_vorbis_comment(FILE *file, vorbis_comment *vc) -{ - char *buffer; - int bytes, i, chunks = 0; - ogg_packet header; - - ogg_page og; - ogg_sync_state osync; - ogg_stream_state os; - vorbis_info vi; - - int serial; - int CHUNKSIZE = 4096; - int nheaders = 0; - - ogg_sync_init(&osync); - - while (1) { - buffer = ogg_sync_buffer(&osync, CHUNKSIZE); - bytes = fread(buffer, 1, CHUNKSIZE, file); - - ogg_sync_wrote(&osync, bytes); - - if (ogg_sync_pageout(&osync, &og) == 1) - break; - - if (chunks++ >= 10) - return -1; - } - - serial = ogg_page_serialno(&og); - - ogg_stream_init(&os, serial); - vorbis_info_init(&vi); - vorbis_comment_init(vc); - - if (ogg_stream_pagein(&os, &og) < 0) - return -1; - if (ogg_stream_packetout(&os, &header) != 1) - return -1; - if (vorbis_synthesis_headerin(&vi, vc, &header) != 0) - return -1; - - i = 1; - nheaders = 3; - while (i < nheaders) { - while (i < nheaders) { - int result = ogg_sync_pageout(&osync, &og); - if (result == 0) - break; - else if (result == 1) { - ogg_stream_pagein(&os, &og); - while (i < nheaders) { - result = ogg_stream_packetout(&os, &header); - if (result == 0) - break; - if (result == -1) - return -1; - - vorbis_synthesis_headerin(&vi, vc, &header); - i++; - } - } - } - - buffer = ogg_sync_buffer(&osync, CHUNKSIZE); - bytes = fread(buffer, 1, CHUNKSIZE, file); - - if (bytes == 0 && i < 2) - return -1; - - ogg_sync_wrote(&osync, bytes); - } - - ogg_stream_clear(&os); - ogg_sync_clear(&osync); - vorbis_info_clear(&vi); - - return 0; -} - -static int -_parse_ogg(const char *filename, struct lms_audio_info *info) -{ - vorbis_comment vc; - FILE *file; - const char *tag; - int size; - - if (!filename) - return -1; - - file = fopen(filename, "rb"); - if (file == NULL) - return -1; - - fseek(file, _id3_tag_size(file), SEEK_SET); - - if (_get_vorbis_comment(file, &vc) != 0) - return -1; - - tag = vorbis_comment_query(&vc, "TITLE", 0); - size = strlen(tag); - if (tag && size > 0) { - info->title.len = size; - info->title.str = malloc(size * sizeof(char)); - memcpy(info->title.str, tag, size); - lms_string_size_strip_and_free(&info->title); - } - - tag = vorbis_comment_query(&vc, "ARTIST", 0); - size = strlen(tag); - if (tag && size > 0) { - info->artist.len = size; - info->artist.str = malloc(size * sizeof(char)); - memcpy(info->artist.str, tag, size); - lms_string_size_strip_and_free(&info->artist); - } - - tag = vorbis_comment_query(&vc, "ALBUM", 0); - size = strlen(tag); - if (tag && size > 0) { - info->album.len = size; - info->album.str = malloc(size * sizeof(char)); - memcpy(info->album.str, tag, size); - lms_string_size_strip_and_free(&info->album); - } - - tag = vorbis_comment_query(&vc, "TRACKNUMBER", 0); - if (tag) - info->trackno = atoi(tag); - - tag = vorbis_comment_query(&vc, "GENRE", 0); - size = strlen(tag); - if (tag && size > 0) { - info->genre.len = size; - info->genre.str = malloc(size * sizeof(char)); - memcpy(info->genre.str, tag, size); - lms_string_size_strip_and_free(&info->genre); - } - - fclose(file); - vorbis_comment_clear(&vc); - - return 0; -} - - -static const char _name[] = "ogg"; -static const struct lms_string_size _exts[] = { - LMS_STATIC_STRING_SIZE(".ogg") -}; - -struct plugin { - struct lms_plugin plugin; - lms_db_audio_t *audio_db; -}; - -static void * -_match(struct plugin *p, const char *path, int len, int base) -{ - int i; - - i = lms_which_extension(path, len, _exts, LMS_ARRAY_SIZE(_exts)); - if (i < 0) - return NULL; - else - return (void*)(i + 1); -} - -static int -_parse(struct plugin *plugin, struct lms_context *ctxt, const struct lms_file_info *finfo, void *match) -{ - struct lms_audio_info info = {0}; - int r; - - r = _parse_ogg(finfo->path, &info); - if (r != 0) - goto done; - - if (!info.title.str) { - int ext_idx; - - ext_idx = ((int)match) - 1; - info.title.len = finfo->path_len - finfo->base - _exts[ext_idx].len; - info.title.str = (char *)malloc((info.title.len + 1) * sizeof(char)); - memcpy(info.title.str, finfo->path + finfo->base, info.title.len); - info.title.str[info.title.len] = '\0'; - } - - if (info.title.str) - lms_charset_conv(ctxt->cs_conv, &info.title.str, &info.title.len); - if (info.artist.str) - lms_charset_conv(ctxt->cs_conv, &info.artist.str, &info.artist.len); - if (info.album.str) - lms_charset_conv(ctxt->cs_conv, &info.album.str, &info.album.len); - if (info.genre.str) - lms_charset_conv(ctxt->cs_conv, &info.genre.str, &info.genre.len); - - info.id = finfo->id; - r = lms_db_audio_add(plugin->audio_db, &info); - - done: - if (info.title.str) - free(info.title.str); - if (info.artist.str) - free(info.artist.str); - if (info.album.str) - free(info.album.str); - if (info.genre.str) - free(info.genre.str); - - return r; -} - -static int -_setup(struct plugin *plugin, struct lms_context *ctxt) -{ - plugin->audio_db = lms_db_audio_new(ctxt->db); - if (!plugin->audio_db) - return -1; - - return 0; -} - -static int -_start(struct plugin *plugin, struct lms_context *ctxt) -{ - return lms_db_audio_start(plugin->audio_db); -} - -static int -_finish(struct plugin *plugin, struct lms_context *ctxt) -{ - if (plugin->audio_db) - return lms_db_audio_free(plugin->audio_db); - - return 0; -} - -static int -_close(struct plugin *plugin) -{ - free(plugin); - return 0; -} - -API struct lms_plugin * -lms_plugin_open(void) -{ - struct plugin *plugin; - - plugin = (struct plugin *)malloc(sizeof(*plugin)); - plugin->plugin.name = _name; - plugin->plugin.match = (lms_plugin_match_fn_t)_match; - plugin->plugin.parse = (lms_plugin_parse_fn_t)_parse; - plugin->plugin.close = (lms_plugin_close_fn_t)_close; - plugin->plugin.setup = (lms_plugin_setup_fn_t)_setup; - plugin->plugin.start = (lms_plugin_start_fn_t)_start; - plugin->plugin.finish = (lms_plugin_finish_fn_t)_finish; - - return (struct lms_plugin *)plugin; -} diff --git a/lightmediascanner/src/plugins/pls/Makefile.am b/lightmediascanner/src/plugins/pls/Makefile.am deleted file mode 100644 index f85b557..0000000 --- a/lightmediascanner/src/plugins/pls/Makefile.am +++ /dev/null @@ -1,10 +0,0 @@ -MAINTAINERCLEANFILES = Makefile.in - -AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_srcdir)/src/plugins/pls - -pkgdir = $(pluginsdir) -pkg_LTLIBRARIES = pls.la -pls_la_SOURCES = pls.c -pls_la_DEPENDENCIES = $(top_builddir)/config.h -pls_la_LIBADD = $(top_builddir)/src/lib/liblightmediascanner.la -pls_la_LDFLAGS = -module -avoid-version diff --git a/lightmediascanner/src/plugins/pls/pls.c b/lightmediascanner/src/plugins/pls/pls.c deleted file mode 100644 index 08533ab..0000000 --- a/lightmediascanner/src/plugins/pls/pls.c +++ /dev/null @@ -1,375 +0,0 @@ -/** - * Copyright (C) 2007 by INdT - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser 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 Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * @author Gustavo Sverzut Barbieri - */ - -/** - * @brief - * - * pls playlist parser. - * - * This parser doesn't actually parse the whole file, instead it just checks - * for the header [playlist], then search the beginning and ending of the file - * (at most PLS_MAX_N_ENTRIES_BYTES_LOOKUP bytes) in order to find out - * NumberOfEntries=XXX line. If there are too many bogus (ie: empty) lines or - * this line is inside the data declaration, then it will fail the parse. - * In theory this should not happen, so let's wait for bug reports. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#define _XOPEN_SOURCE 600 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define PLS_MAX_N_ENTRIES_BYTES_LOOKUP 64 - -static int -_pls_find_header(int fd) -{ - const char header[] = "[playlist]"; - char buf[sizeof(header) - 1]; - ssize_t r; - - /* skip out white spaces */ - do { - r = read(fd, buf, 1); - if (r < 0) { - perror("read"); - return -1; - } else if (r == 0) { - fprintf(stderr, "ERROR: premature end of file.\n"); - return -2; - } - - if (!isspace(buf[0])) - break; - } while (1); - - if (buf[0] != header[0]) - return -3; - - /* try to read rest (from the second on) of the header */ - r = read(fd, buf + 1, sizeof(buf) - 1); - if (r < 0) { - perror("read"); - return -4; - } else if (r != sizeof(buf) - 1) { - fprintf(stderr, "ERROR: premature end of file: read %d of %d bytes.\n", - r, sizeof(buf) - 1); - return -5; - } - - if (memcmp(buf + 1, header + 1, sizeof(buf) - 1) != 0) { - fprintf(stderr, "ERROR: invalid pls header '%.*s'\n", - sizeof(buf) - 1, buf); - return -6; - } - - /* find '\n' */ - do { - r = read(fd, buf, 1); - if (r < 0) { - perror("read"); - return -7; - } else if (r == 0) - return -8; - - if (buf[0] == '\n') - return 0; - } while (1); - - return -1; -} - -static int -_pls_find_n_entries_start(int fd, struct lms_playlist_info *info) -{ - char buf[PLS_MAX_N_ENTRIES_BYTES_LOOKUP]; - const char n_entries[] = "NumberOfEntries="; - ssize_t r; - int i; - off_t off; - - off = lseek(fd, 0, SEEK_CUR); - if (off < 0) { - perror("lseek"); - return -1; - } - - r = read(fd, buf, sizeof(buf)); - if (r < 0) { - perror("read"); - return -2; - } else if (r == 0) - return -3; - - for (i = 0; i < r; i++) { - char c; - - c = buf[i]; - if (c == n_entries[0]) { - const char *p; - i++; - if (memcmp(buf + i, n_entries + 1, sizeof(n_entries) - 2) != 0) { - off += i + sizeof(n_entries) - 2; - goto done; - } - - i += sizeof(n_entries) - 2; - p = buf + i; - for (; i < r; i++) - if (buf[i] == '\n') - break; - - if (i == r) { - fprintf(stderr, "WARNING: missing end of line\n"); - i = r - 1; - } - buf[i] = '\0'; - info->n_entries = atoi(p); - return 0; - } else if (c == 'V') { - /* skip possible 'Version=XX' */ - for (i++; i < r; i++) - if (buf[i] == '\n') - break; - } else if (isspace(c)) - continue; - else { - off += i; - goto done; - } - } - - done: - /* not at the file beginning, reset offset */ - if (lseek(fd, off, SEEK_SET) < 0) { - perror("lseek"); - return -1; - } - - return 1; -} - -static int -_pls_parse_entries_line(int fd, struct lms_playlist_info *info, char *buf, int len) -{ - const char n_entries[] = "NumberOfEntries="; - int i; - - for (i = 0; i < len; i++, buf++) - if (!isspace(*buf)) - break; - - if (i == len) - return 1; - len -= i; - - if (memcmp(buf, n_entries, sizeof(n_entries) - 1) != 0) - return 1; - - buf += sizeof(n_entries) - 1; - len -= sizeof(n_entries) - 1; - buf[len] = '\0'; - - info->n_entries = atoi(buf); - return 0; -} - -static int -_pls_find_n_entries_end(int fd, const struct lms_file_info *finfo, struct lms_playlist_info *info) -{ - char buf[PLS_MAX_N_ENTRIES_BYTES_LOOKUP]; - ssize_t r; - int i, last_nl; - - if (finfo->size > sizeof(buf)) - if (lseek(fd, finfo->size - sizeof(buf), SEEK_SET) < 0) { - perror("lseek"); - return -1; - } - - r = read(fd, buf, sizeof(buf)); - if (r < 0) { - perror("read"); - return -1; - } else if (r == 0) - return -2; - - last_nl = -1; - for (i = r - 1; i >= 0; i--) { - if (buf[i] == '\n') { - if (last_nl >= 0) { - int len; - - len = last_nl - i - 1; - if (len > 0) { - int ret; - - ret = _pls_parse_entries_line(fd, info, buf + i + 1, len); - if (ret <= 0) - return ret; - } - } - last_nl = i; - } - } - - return 1; -} - -static int -_pls_parse(int fd, const struct lms_file_info *finfo, struct lms_playlist_info *info) -{ - int r; - - r = _pls_find_header(fd); - if (r != 0) { - fprintf(stderr, "ERROR: could not find pls header. code=%d\n", r); - return -1; - } - - r = _pls_find_n_entries_start(fd, info); - if (r <= 0) - return r; - - r = _pls_find_n_entries_end(fd, finfo, info); - if (r != 0) - fprintf(stderr, "ERROR: could not find pls NumberOfEntries=\n"); - - return r; -} - -static const char _name[] = "pls"; -static const struct lms_string_size _exts[] = { - LMS_STATIC_STRING_SIZE(".pls") -}; - -struct plugin { - struct lms_plugin plugin; - lms_db_playlist_t *playlist_db; -}; - -static void * -_match(struct plugin *p, const char *path, int len, int base) -{ - int i; - - i = lms_which_extension(path, len, _exts, LMS_ARRAY_SIZE(_exts)); - if (i < 0) - return NULL; - else - return (void*)(i + 1); -} - -static int -_parse(struct plugin *plugin, struct lms_context *ctxt, const struct lms_file_info *finfo, void *match) -{ - struct lms_playlist_info info = {0}; - int fd, r, ext_idx; - - fd = open(finfo->path, O_RDONLY); - if (fd < 0) { - perror("open"); - return -1; - } - - if (_pls_parse(fd, finfo, &info) != 0) { - fprintf(stderr, - "WARNING: could not parse playlist '%s'.\n", finfo->path); - return -1; - } - - ext_idx = ((int)match) - 1; - info.title.len = finfo->path_len - finfo->base - _exts[ext_idx].len; - info.title.str = malloc((info.title.len + 1) * sizeof(char)); - memcpy(info.title.str, finfo->path + finfo->base, info.title.len); - info.title.str[info.title.len] = '\0'; - lms_charset_conv(ctxt->cs_conv, &info.title.str, &info.title.len); - - info.id = finfo->id; - r = lms_db_playlist_add(plugin->playlist_db, &info); - - if (info.title.str) - free(info.title.str); - posix_fadvise(fd, 0, 0, POSIX_FADV_DONTNEED); - close(fd); - - return r; -} - -static int -_setup(struct plugin *plugin, struct lms_context *ctxt) -{ - plugin->playlist_db = lms_db_playlist_new(ctxt->db); - if (!plugin->playlist_db) - return -1; - - return 0; -} - -static int -_start(struct plugin *plugin, struct lms_context *ctxt) -{ - return lms_db_playlist_start(plugin->playlist_db); -} - -static int -_finish(struct plugin *plugin, struct lms_context *ctxt) -{ - if (plugin->playlist_db) - return lms_db_playlist_free(plugin->playlist_db); - - return 0; -} - - -static int -_close(struct plugin *plugin) -{ - free(plugin); - return 0; -} - -API struct lms_plugin * -lms_plugin_open(void) -{ - struct plugin *plugin; - - plugin = malloc(sizeof(*plugin)); - plugin->plugin.name = _name; - plugin->plugin.match = (lms_plugin_match_fn_t)_match; - plugin->plugin.parse = (lms_plugin_parse_fn_t)_parse; - plugin->plugin.close = (lms_plugin_close_fn_t)_close; - plugin->plugin.setup = (lms_plugin_setup_fn_t)_setup; - plugin->plugin.start = (lms_plugin_start_fn_t)_start; - plugin->plugin.finish = (lms_plugin_finish_fn_t)_finish; - - return (struct lms_plugin *)plugin; -} diff --git a/lightmediascanner/src/plugins/png/Makefile.am b/lightmediascanner/src/plugins/png/Makefile.am deleted file mode 100644 index 65f9a06..0000000 --- a/lightmediascanner/src/plugins/png/Makefile.am +++ /dev/null @@ -1,10 +0,0 @@ -MAINTAINERCLEANFILES = Makefile.in - -AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_srcdir)/src/plugins/png - -pkgdir = $(pluginsdir) -pkg_LTLIBRARIES = png.la -png_la_SOURCES = png.c -png_la_DEPENDENCIES = $(top_builddir)/config.h -png_la_LIBADD = $(top_builddir)/src/lib/liblightmediascanner.la -png_la_LDFLAGS = -module -avoid-version diff --git a/lightmediascanner/src/plugins/png/png.c b/lightmediascanner/src/plugins/png/png.c deleted file mode 100644 index 16b1567..0000000 --- a/lightmediascanner/src/plugins/png/png.c +++ /dev/null @@ -1,213 +0,0 @@ -/** - * Copyright (C) 2007 by INdT - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser 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 Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * @author Gustavo Sverzut Barbieri - */ - -/** - * @brief - * - * Reads PNG images. - * - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#define _XOPEN_SOURCE 600 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static inline unsigned int -_chunk_to_uint(unsigned char *buf) -{ - return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; -} - -static int -_png_data_get(int fd, struct lms_image_info *info) -{ - unsigned char buf[16], *p; - const unsigned char sig[8] = {0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa}; - const unsigned char ihdr[4] = {'I', 'H', 'D', 'R'}; - unsigned int length; - - if (read(fd, buf, sizeof(buf)) != sizeof(buf)) { - perror("read"); - return -1; - } - - if (memcmp(buf, sig, sizeof(sig)) != 0) { - fprintf(stderr, "ERROR: invalid PNG signature.\n"); - return -2; - } - - p = buf + sizeof(sig) + 4; - if (memcmp(p, ihdr, sizeof(ihdr)) != 0) { - fprintf(stderr, "ERROR: invalid first chunk: %4.4s.\n", p); - return -3; - } - - p = buf + sizeof(sig); - length = _chunk_to_uint(p); - if (length < 13) { - fprintf(stderr, "ERROR: IHDR chunk size is too small: %d.\n", length); - return -4; - } - - if (read(fd, buf, 8) != 8) { - perror("read"); - return -5; - } - info->width = _chunk_to_uint(buf); - info->height = _chunk_to_uint(buf + 4); - - return 0; -} - -static const char _name[] = "png"; -static const struct lms_string_size _exts[] = { - LMS_STATIC_STRING_SIZE(".png") -}; - -struct plugin { - struct lms_plugin plugin; - lms_db_image_t *img_db; -}; - -static void * -_match(struct plugin *p, const char *path, int len, int base) -{ - int i; - - i = lms_which_extension(path, len, _exts, LMS_ARRAY_SIZE(_exts)); - if (i < 0) - return NULL; - else - return (void*)(i + 1); -} - -static int -_parse(struct plugin *plugin, struct lms_context *ctxt, const struct lms_file_info *finfo, void *match) -{ - struct lms_image_info info = {0}; - int fd, r; - - fd = open(finfo->path, O_RDONLY); - if (fd < 0) { - perror("open"); - return -1; - } - - if (_png_data_get(fd, &info) != 0) { - r = -2; - goto done; - } - - if (info.date == 0) - info.date = finfo->mtime; - - if (!info.title.str) { - int ext_idx; - - ext_idx = ((int)match) - 1; - info.title.len = finfo->path_len - finfo->base - _exts[ext_idx].len; - info.title.str = malloc((info.title.len + 1) * sizeof(char)); - memcpy(info.title.str, finfo->path + finfo->base, info.title.len); - info.title.str[info.title.len] = '\0'; - } - - if (info.title.str) - lms_charset_conv(ctxt->cs_conv, &info.title.str, &info.title.len); - if (info.artist.str) - lms_charset_conv(ctxt->cs_conv, &info.artist.str, &info.artist.len); - - info.id = finfo->id; - r = lms_db_image_add(plugin->img_db, &info); - - done: - if (info.title.str) - free(info.title.str); - if (info.artist.str) - free(info.artist.str); - - posix_fadvise(fd, 0, 0, POSIX_FADV_DONTNEED); - close(fd); - - return r; -} - -static int -_setup(struct plugin *plugin, struct lms_context *ctxt) -{ - plugin->img_db = lms_db_image_new(ctxt->db); - if (!plugin->img_db) - return -1; - - return 0; -} - -static int -_start(struct plugin *plugin, struct lms_context *ctxt) -{ - return lms_db_image_start(plugin->img_db); -} - -static int -_finish(struct plugin *plugin, struct lms_context *ctxt) -{ - if (plugin->img_db) - return lms_db_image_free(plugin->img_db); - - return 0; -} - - -static int -_close(struct plugin *plugin) -{ - free(plugin); - return 0; -} - -API struct lms_plugin * -lms_plugin_open(void) -{ - struct plugin *plugin; - - plugin = malloc(sizeof(*plugin)); - plugin->plugin.name = _name; - plugin->plugin.match = (lms_plugin_match_fn_t)_match; - plugin->plugin.parse = (lms_plugin_parse_fn_t)_parse; - plugin->plugin.close = (lms_plugin_close_fn_t)_close; - plugin->plugin.setup = (lms_plugin_setup_fn_t)_setup; - plugin->plugin.start = (lms_plugin_start_fn_t)_start; - plugin->plugin.finish = (lms_plugin_finish_fn_t)_finish; - - return (struct lms_plugin *)plugin; -} diff --git a/lightmediascanner/src/plugins/rm/Makefile.am b/lightmediascanner/src/plugins/rm/Makefile.am deleted file mode 100644 index 9070c4e..0000000 --- a/lightmediascanner/src/plugins/rm/Makefile.am +++ /dev/null @@ -1,10 +0,0 @@ -MAINTAINERCLEANFILES = Makefile.in - -AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_srcdir)/src/plugins/rm - -pkgdir = $(pluginsdir) -pkg_LTLIBRARIES = rm.la -rm_la_SOURCES = rm.c -rm_la_DEPENDENCIES = $(top_builddir)/config.h -rm_la_LIBADD = $(top_builddir)/src/lib/liblightmediascanner.la -rm_la_LDFLAGS = -module -avoid-version diff --git a/lightmediascanner/src/plugins/rm/rm.c b/lightmediascanner/src/plugins/rm/rm.c deleted file mode 100644 index 871baf8..0000000 --- a/lightmediascanner/src/plugins/rm/rm.c +++ /dev/null @@ -1,367 +0,0 @@ -/** - * Copyright (C) 2008 by INdT - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser 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 Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * @author Andre Moreira Magalhaes - */ - -/** - * @brief - * - * real media file parser. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#define _XOPEN_SOURCE 600 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define BE_4BYTE(a) ((((unsigned char*)a)[0] << 24) | \ - (((unsigned char*)a)[1] << 16) | \ - (((unsigned char*)a)[2] << 8) | \ - ((unsigned char*)a)[3]) -#define BE_2BYTE(a) ((((unsigned char*)a)[0] << 8) | ((unsigned char*)a)[1]) - -enum StreamTypes { - STREAM_TYPE_UNKNOWN = 0, - STREAM_TYPE_AUDIO, - STREAM_TYPE_VIDEO -}; - -struct rm_info { - struct lms_string_size title; - struct lms_string_size artist; -}; - -struct rm_file_header { - char type[4]; - uint32_t size; - uint16_t version; -} __attribute__((packed)); - -struct plugin { - struct lms_plugin plugin; - lms_db_audio_t *audio_db; - lms_db_video_t *video_db; -}; - -static const char _name[] = "rm"; -static const struct lms_string_size _exts[] = { - LMS_STATIC_STRING_SIZE(".ra"), - LMS_STATIC_STRING_SIZE(".rv"), - LMS_STATIC_STRING_SIZE(".rm"), - LMS_STATIC_STRING_SIZE(".rmj"), - LMS_STATIC_STRING_SIZE(".rmvb") -}; - -/* - * A real media file header has the following format: - * dword chunk type ('.RMF') - * dword chunk size (typically 0x12) - * word chunk version - * dword file version - * dword number of headers - */ -static int -_parse_file_header(int fd, struct rm_file_header *file_header) -{ - if (read(fd, file_header, sizeof(struct rm_file_header)) == -1) { - fprintf(stderr, "ERROR: could not read file header\n"); - return -1; - } - - if (memcmp(file_header->type, ".RMF", 4) != 0) { - fprintf(stderr, "ERROR: invalid header type\n"); - return -1; - } - - /* convert to host byte order */ - file_header->size = BE_4BYTE(&file_header->size); - -#if 0 - fprintf(stderr, "file_header type=%.*s\n", 4, file_header->type); - fprintf(stderr, "file_header size=%d\n", file_header->size); - fprintf(stderr, "file_header version=%d\n", file_header->version); -#endif - - /* TODO we should ignore these fields just when version is 0 or 1, - * but using the test files, if we don't ignore them for version 256 - * it fails */ - /* ignore file header extra fields - * file version and number of headers */ - lseek(fd, 8, SEEK_CUR); - - return 0; -} - -static int -_read_header_type_and_size(int fd, char *type, uint32_t *size) -{ - if (read(fd, type, 4) != 4) - return -1; - - if (read(fd, size, 4) != 4) - return -1; - - *size = BE_4BYTE(size); - -#if 0 - fprintf(stderr, "header type=%.*s\n", 4, type); - fprintf(stderr, "header size=%d\n", *size); -#endif - - return 0; -} - -static int -_read_string(int fd, char **out, unsigned int *out_len) -{ - char *s; - uint16_t len; - - if (read(fd, &len, 2) == -1) - return -1; - - len = BE_2BYTE(&len); - - if (out) { - if (len > 0) { - s = malloc(sizeof(char) * (len + 1)); - if (read(fd, s, len) == -1) { - free(s); - return -1; - } - s[len] = '\0'; - *out = s; - } else - *out = NULL; - - *out_len = len; - } else - lseek(fd, len, SEEK_CUR); - - return 0; -} - -/* - * A CONT header has the following format - * dword Chunk type ('CONT') - * dword Chunk size - * word Chunk version (always 0, for every known file) - * word Title string length - * byte[] Title string - * word Author string length - * byte[] Author string - * word Copyright string length - * byte[] Copyright string - * word Comment string length - * byte[] Comment string - */ -static void -_parse_cont_header(int fd, struct rm_info *info) -{ - /* Ps.: type and size were already read */ - - /* ignore version */ - lseek(fd, 2, SEEK_CUR); - - _read_string(fd, &info->title.str, &info->title.len); - _read_string(fd, &info->artist.str, &info->artist.len); - _read_string(fd, NULL, NULL); /* copyright */ - _read_string(fd, NULL, NULL); /* comment */ -} - -static void * -_match(struct plugin *p, const char *path, int len, int base) -{ - int i; - - i = lms_which_extension(path, len, _exts, LMS_ARRAY_SIZE(_exts)); - if (i < 0) - return NULL; - else - return (void*)(i + 1); -} - -static int -_parse(struct plugin *plugin, struct lms_context *ctxt, const struct lms_file_info *finfo, void *match) -{ - struct rm_info info = {{0}, {0}}; - struct lms_audio_info audio_info = {0, {0}, {0}, {0}, {0}, 0, 0, 0}; - struct lms_video_info video_info = {0, {0}, {0}}; - int r, fd, stream_type = STREAM_TYPE_UNKNOWN; - struct rm_file_header file_header; - char type[4]; - uint32_t size; - - fd = open(finfo->path, O_RDONLY); - if (fd < 0) { - perror("open"); - return -1; - } - - if (_parse_file_header(fd, &file_header) != 0) { - r = -2; - goto done; - } - - if (_read_header_type_and_size(fd, type, &size) != 0) { - r = -3; - goto done; - } - while (memcmp(type, "DATA", 4) != 0) { - if (memcmp(type, "CONT", 4) == 0) { - _parse_cont_header(fd, &info); - break; - } - /* TODO check for mimetype - else if (memcmp(type, "MDPR", 4) == 0) { - } - */ - /* ignore other headers */ - else - lseek(fd, size - 8, SEEK_CUR); - - if (_read_header_type_and_size(fd, type, &size) != 0) { - r = -4; - goto done; - } - } - - /* try to define stream type by extension */ - if (stream_type == STREAM_TYPE_UNKNOWN) { - int ext_idx = ((int)match) - 1; - if (strcmp(_exts[ext_idx].str, ".ra") == 0) - stream_type = STREAM_TYPE_AUDIO; - /* consider rv, rm, rmj and rmvb as video */ - else - stream_type = STREAM_TYPE_VIDEO; - } - - lms_string_size_strip_and_free(&info.title); - lms_string_size_strip_and_free(&info.artist); - - if (!info.title.str) { - int ext_idx; - ext_idx = ((int)match) - 1; - info.title.len = finfo->path_len - finfo->base - _exts[ext_idx].len; - info.title.str = malloc((info.title.len + 1) * sizeof(char)); - memcpy(info.title.str, finfo->path + finfo->base, info.title.len); - info.title.str[info.title.len] = '\0'; - } - lms_charset_conv(ctxt->cs_conv, &info.title.str, &info.title.len); - - if (info.artist.str) - lms_charset_conv(ctxt->cs_conv, &info.artist.str, &info.artist.len); - -#if 0 - fprintf(stderr, "file %s info\n", finfo->path); - fprintf(stderr, "\ttitle=%s\n", info.title); - fprintf(stderr, "\tartist=%s\n", info.artist); -#endif - - if (stream_type == STREAM_TYPE_AUDIO) { - audio_info.id = finfo->id; - audio_info.title = info.title; - audio_info.artist = info.artist; - r = lms_db_audio_add(plugin->audio_db, &audio_info); - } - else { - video_info.id = finfo->id; - video_info.title = info.title; - video_info.artist = info.artist; - r = lms_db_video_add(plugin->video_db, &video_info); - } - - done: - if (info.title.str) - free(info.title.str); - if (info.artist.str) - free(info.artist.str); - - posix_fadvise(fd, 0, 0, POSIX_FADV_DONTNEED); - close(fd); - - return r; -} - -static int -_setup(struct plugin *plugin, struct lms_context *ctxt) -{ - plugin->audio_db = lms_db_audio_new(ctxt->db); - if (!plugin->audio_db) - return -1; - plugin->video_db = lms_db_video_new(ctxt->db); - if (!plugin->video_db) - return -1; - - return 0; -} - -static int -_start(struct plugin *plugin, struct lms_context *ctxt) -{ - int r; - r = lms_db_audio_start(plugin->audio_db); - r |= lms_db_video_start(plugin->video_db); - return r; -} - -static int -_finish(struct plugin *plugin, struct lms_context *ctxt) -{ - if (plugin->audio_db) - lms_db_audio_free(plugin->audio_db); - if (plugin->video_db) - lms_db_video_free(plugin->video_db); - - return 0; -} - -static int -_close(struct plugin *plugin) -{ - free(plugin); - return 0; -} - -API struct lms_plugin * -lms_plugin_open(void) -{ - struct plugin *plugin; - - plugin = (struct plugin *)malloc(sizeof(*plugin)); - plugin->plugin.name = _name; - plugin->plugin.match = (lms_plugin_match_fn_t)_match; - plugin->plugin.parse = (lms_plugin_parse_fn_t)_parse; - plugin->plugin.close = (lms_plugin_close_fn_t)_close; - plugin->plugin.setup = (lms_plugin_setup_fn_t)_setup; - plugin->plugin.start = (lms_plugin_start_fn_t)_start; - plugin->plugin.finish = (lms_plugin_finish_fn_t)_finish; - - return (struct lms_plugin *)plugin; -} diff --git a/lightmediascanner/src/plugins/video-dummy/Makefile.am b/lightmediascanner/src/plugins/video-dummy/Makefile.am deleted file mode 100644 index f40813c..0000000 --- a/lightmediascanner/src/plugins/video-dummy/Makefile.am +++ /dev/null @@ -1,10 +0,0 @@ -MAINTAINERCLEANFILES = Makefile.in - -AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_srcdir)/src/plugins/video-dummy - -pkgdir = $(pluginsdir) -pkg_LTLIBRARIES = video-dummy.la -video_dummy_la_SOURCES = video-dummy.c -video_dummy_la_DEPENDENCIES = $(top_builddir)/config.h -video_dummy_la_LIBADD = $(top_builddir)/src/lib/liblightmediascanner.la -video_dummy_la_LDFLAGS = -module -avoid-version diff --git a/lightmediascanner/src/plugins/video-dummy/video-dummy.c b/lightmediascanner/src/plugins/video-dummy/video-dummy.c deleted file mode 100644 index 51173e5..0000000 --- a/lightmediascanner/src/plugins/video-dummy/video-dummy.c +++ /dev/null @@ -1,133 +0,0 @@ -/** - * Copyright (C) 2007 by INdT - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser 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 Lesser General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * @author Gustavo Sverzut Barbieri - */ - -/** - * @brief - * - * Video Dummy plugin, just register matched extensions in videos DB. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#define _XOPEN_SOURCE 600 -#include -#include -#include -#include -#include - -static const char _name[] = "video-dummy"; -static const struct lms_string_size _exts[] = { - LMS_STATIC_STRING_SIZE(".avi"), - LMS_STATIC_STRING_SIZE(".mpg"), - LMS_STATIC_STRING_SIZE(".mpeg"), - LMS_STATIC_STRING_SIZE(".ram"), - LMS_STATIC_STRING_SIZE(".ogm"), -}; - -struct plugin { - struct lms_plugin plugin; - lms_db_video_t *video_db; -}; - -static void * -_match(struct plugin *p, const char *path, int len, int base) -{ - int i; - - i = lms_which_extension(path, len, _exts, LMS_ARRAY_SIZE(_exts)); - if (i < 0) - return NULL; - else - return (void*)(i + 1); -} - -static int -_parse(struct plugin *plugin, struct lms_context *ctxt, const struct lms_file_info *finfo, void *match) -{ - struct lms_video_info info = {0}; - int r, ext_idx; - - ext_idx = ((int)match) - 1; - info.title.len = finfo->path_len - finfo->base - _exts[ext_idx].len; - info.title.str = malloc((info.title.len + 1) * sizeof(char)); - memcpy(info.title.str, finfo->path + finfo->base, info.title.len); - info.title.str[info.title.len] = '\0'; - lms_charset_conv(ctxt->cs_conv, &info.title.str, &info.title.len); - - info.id = finfo->id; - r = lms_db_video_add(plugin->video_db, &info); - - free(info.title.str); - - return r; -} - -static int -_setup(struct plugin *plugin, struct lms_context *ctxt) -{ - plugin->video_db = lms_db_video_new(ctxt->db); - if (!plugin->video_db) - return -1; - - return 0; -} - -static int -_start(struct plugin *plugin, struct lms_context *ctxt) -{ - return lms_db_video_start(plugin->video_db); -} - -static int -_finish(struct plugin *plugin, struct lms_context *ctxt) -{ - if (plugin->video_db) - return lms_db_video_free(plugin->video_db); - - return 0; -} - - -static int -_close(struct plugin *plugin) -{ - free(plugin); - return 0; -} - -API struct lms_plugin * -lms_plugin_open(void) -{ - struct plugin *plugin; - - plugin = malloc(sizeof(*plugin)); - plugin->plugin.name = _name; - plugin->plugin.match = (lms_plugin_match_fn_t)_match; - plugin->plugin.parse = (lms_plugin_parse_fn_t)_parse; - plugin->plugin.close = (lms_plugin_close_fn_t)_close; - plugin->plugin.setup = (lms_plugin_setup_fn_t)_setup; - plugin->plugin.start = (lms_plugin_start_fn_t)_start; - plugin->plugin.finish = (lms_plugin_finish_fn_t)_finish; - - return (struct lms_plugin *)plugin; -} -- 1.7.9.5