pax_global_header00006660000000000000000000000064124712247070014520gustar00rootroot0000000000000052 comment=158f9d750af6552e14c91853c9e2b38be89e947e .gitignore000066400000000000000000000001211247122470700130460ustar00rootroot00000000000000*.mode* *.pbxuser *.xcworkspace xcuserdata .DS_Store build External/MobileVLCKit COPYING000066400000000000000000000636421247122470700121320ustar00rootroot00000000000000 GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [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 Street, 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! External/000077500000000000000000000000001247122470700126465ustar00rootroot00000000000000External/TouchXML/000077500000000000000000000000001247122470700143115ustar00rootroot00000000000000External/TouchXML/Source/000077500000000000000000000000001247122470700155515ustar00rootroot00000000000000External/TouchXML/Source/CXHTMLDocument.h000066400000000000000000000037211247122470700204230ustar00rootroot00000000000000// // CXHTMLDocument.h // TouchCode // // Created by Jonathan Wight on 03/07/08. // Copyright 2011 toxicsoftware.com. All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, are // permitted provided that the following conditions are met: // // 1. Redistributions of source code must retain the above copyright notice, this list of // conditions and the following disclaimer. // // 2. Redistributions in binary form must reproduce the above copyright notice, this list // of conditions and the following disclaimer in the documentation and/or other materials // provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY TOXICSOFTWARE.COM ``AS IS'' AND ANY EXPRESS OR IMPLIED // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL TOXICSOFTWARE.COM OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // The views and conclusions contained in the software and documentation are those of the // authors and should not be interpreted as representing official policies, either expressed // or implied, of toxicsoftware.com. #import "CXMLDocument.h" @interface CXHTMLDocument : CXMLDocument { } - (id)initWithXHTMLData:(NSData *)inData encoding:(NSStringEncoding)encoding options:(NSUInteger)inOptions error:(NSError **)outError; - (id)initWithXHTMLString:(NSString *)inString options:(NSUInteger)inOptions error:(NSError **)outError; @end External/TouchXML/Source/CXHTMLDocument.m000066400000000000000000000135641247122470700204360ustar00rootroot00000000000000// // CXHTMLDocument.m // TouchCode // // Created by Jonathan Wight on 03/07/08. // Copyright 2011 toxicsoftware.com. All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, are // permitted provided that the following conditions are met: // // 1. Redistributions of source code must retain the above copyright notice, this list of // conditions and the following disclaimer. // // 2. Redistributions in binary form must reproduce the above copyright notice, this list // of conditions and the following disclaimer in the documentation and/or other materials // provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY TOXICSOFTWARE.COM ``AS IS'' AND ANY EXPRESS OR IMPLIED // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL TOXICSOFTWARE.COM OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // The views and conclusions contained in the software and documentation are those of the // authors and should not be interpreted as representing official policies, either expressed // or implied, of toxicsoftware.com. // This is an experiment to see if we can utilize the HTMLParser functionality // of libXML to serve as a XHTML parser, I question if this is a good idea or not // need to test some of the following // [-] How are xml namespaces handled // [-] Can we support DTD // [-] #import "CXHTMLDocument.h" #include #include #include #include #import "CXMLNode_PrivateExtensions.h" #import "CXMLElement.h" #if TOUCHXMLUSETIDY #import "CTidy.h" #endif /* TOUCHXMLUSETIDY */ @implementation CXHTMLDocument // Differs from initWithXMLString by using libXML's HTML parser, which automatically decodes XHTML/HTML entities found within the document // which eliminates the need to resanitize strings extracted from the document // libXML treats a htmlDocPtr the same as xmlDocPtr - (id)initWithXHTMLString:(NSString *)inString options:(NSUInteger)inOptions error:(NSError **)outError { #pragma unused (inOptions) if ((self = [super init]) != NULL) { NSError *theError = NULL; htmlDocPtr theDoc = htmlParseDoc(BAD_CAST[inString UTF8String], xmlGetCharEncodingName(XML_CHAR_ENCODING_UTF8)); if (theDoc != NULL) { // TODO: change code to not depend on XPATH, should be a task simple enough to do // alternatively see if we can prevent the HTML parser from adding implied tags xmlXPathContextPtr xpathContext = xmlXPathNewContext (theDoc); xmlXPathObjectPtr xpathObject = NULL; if (xpathContext) xpathObject = xmlXPathEvalExpression (BAD_CAST("/html/body"), xpathContext); xmlNodePtr bodyNode = NULL; if (xpathObject && xpathObject->nodesetval->nodeMax) bodyNode = xpathObject->nodesetval->nodeTab[0]; // TODO: Determine if this is sufficient to handle memory in libXML, is the old root removed / deleted, etc if (bodyNode) xmlDocSetRootElement(theDoc, bodyNode->children); _node = (xmlNodePtr)theDoc; NSAssert(_node->_private == NULL, @"TODO"); _node->_private = (__bridge void *)(self); // Note. NOT retained (TODO think more about _private usage) if (xpathObject) xmlXPathFreeObject (xpathObject); if (xpathContext) xmlXPathFreeContext (xpathContext); } else { xmlErrorPtr theLastErrorPtr = xmlGetLastError(); NSDictionary *theUserInfo = @{NSLocalizedDescriptionKey: theLastErrorPtr ? @(theLastErrorPtr->message) : @"unknown"}; theError = [NSError errorWithDomain:@"CXMLErrorDomain" code:1 userInfo:theUserInfo]; xmlResetLastError(); } if (outError) { *outError = theError; } if (theError != NULL) { self = NULL; } } return(self); } - (id)initWithXHTMLData:(NSData *)inData encoding:(NSStringEncoding)encoding options:(NSUInteger)inOptions error:(NSError **)outError { #pragma unused (inOptions) if ((self = [super init]) != NULL) { NSError *theError = NULL; if (theError == NULL) { xmlDocPtr theDoc = NULL; if (inData && inData.length > 0) { CFStringEncoding cfenc = CFStringConvertNSStringEncodingToEncoding(encoding); CFStringRef cfencstr = CFStringConvertEncodingToIANACharSetName(cfenc); const char *enc = CFStringGetCStringPtr(cfencstr, 0); theDoc = htmlReadMemory([inData bytes], (int)[inData length], NULL, enc, HTML_PARSE_NONET | HTML_PARSE_NOBLANKS | HTML_PARSE_NOWARNING); } if (theDoc != NULL) { _node = (xmlNodePtr)theDoc; _node->_private = (__bridge void *)(self); // Note. NOT retained (TODO think more about _private usage) } else { theError = [NSError errorWithDomain:@"CXMLErrorDomain" code:-1 userInfo:NULL]; } } if (outError) { *outError = theError; } if (theError != NULL) { self = NULL; } } return(self); } @end External/TouchXML/Source/CXMLDocument.h000066400000000000000000000061351247122470700201710ustar00rootroot00000000000000// // CXMLDocument.h // TouchCode // // Created by Jonathan Wight on 03/07/08. // Copyright 2011 toxicsoftware.com. All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, are // permitted provided that the following conditions are met: // // 1. Redistributions of source code must retain the above copyright notice, this list of // conditions and the following disclaimer. // // 2. Redistributions in binary form must reproduce the above copyright notice, this list // of conditions and the following disclaimer in the documentation and/or other materials // provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY TOXICSOFTWARE.COM ``AS IS'' AND ANY EXPRESS OR IMPLIED // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL TOXICSOFTWARE.COM OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // The views and conclusions contained in the software and documentation are those of the // authors and should not be interpreted as representing official policies, either expressed // or implied, of toxicsoftware.com. #import "CXMLNode.h" enum { CXMLDocumentTidyHTML = 1 << 9, // Based on NSXMLDocumentTidyHTML CXMLDocumentTidyXML = 1 << 10, // Based on NSXMLDocumentTidyXML }; @class CXMLElement; @interface CXMLDocument : CXMLNode { NSMutableSet *nodePool; } - (id)initWithData:(NSData *)inData options:(NSUInteger)inOptions error:(NSError **)outError; - (id)initWithData:(NSData *)inData encoding:(NSStringEncoding)encoding options:(NSUInteger)inOptions error:(NSError **)outError; - (id)initWithXMLString:(NSString *)inString options:(NSUInteger)inOptions error:(NSError **)outError; - (id)initWithContentsOfURL:(NSURL *)inURL options:(NSUInteger)inOptions error:(NSError **)outError; - (id)initWithContentsOfURL:(NSURL *)inURL encoding:(NSStringEncoding)encoding options:(NSUInteger)inOptions error:(NSError **)outError; //- (NSString *)characterEncoding; //- (NSString *)version; //- (BOOL)isStandalone; //- (CXMLDocumentContentKind)documentContentKind; //- (NSString *)MIMEType; //- (CXMLDTD *)DTD; - (CXMLElement *)rootElement; - (NSData *)XMLData; - (NSData *)XMLDataWithOptions:(NSUInteger)options; //- (id)objectByApplyingXSLT:(NSData *)xslt arguments:(NSDictionary *)arguments error:(NSError **)error; //- (id)objectByApplyingXSLTString:(NSString *)xslt arguments:(NSDictionary *)arguments error:(NSError **)error; //- (id)objectByApplyingXSLTAtURL:(NSURL *)xsltURL arguments:(NSDictionary *)argument error:(NSError **)error; - (id)XMLStringWithOptions:(NSUInteger)options; @end External/TouchXML/Source/CXMLDocument.m000066400000000000000000000214271247122470700201770ustar00rootroot00000000000000// // CXMLDocument.m // TouchCode // // Created by Jonathan Wight on 03/07/08. // Copyright 2011 toxicsoftware.com. All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, are // permitted provided that the following conditions are met: // // 1. Redistributions of source code must retain the above copyright notice, this list of // conditions and the following disclaimer. // // 2. Redistributions in binary form must reproduce the above copyright notice, this list // of conditions and the following disclaimer in the documentation and/or other materials // provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY TOXICSOFTWARE.COM ``AS IS'' AND ANY EXPRESS OR IMPLIED // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL TOXICSOFTWARE.COM OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // The views and conclusions contained in the software and documentation are those of the // authors and should not be interpreted as representing official policies, either expressed // or implied, of toxicsoftware.com. #import "CXMLDocument.h" #include #import "CXMLNode_PrivateExtensions.h" #import "CXMLElement.h" #if TOUCHXMLUSETIDY #import "CTidy.h" #endif /* TOUCHXMLUSETIDY */ @implementation CXMLDocument - (id)initWithXMLString:(NSString *)inString options:(NSUInteger)inOptions error:(NSError **)outError { #pragma unused (inOptions) if ((self = [super init]) != NULL) { NSError *theError = NULL; #if TOUCHXMLUSETIDY if (inOptions & CXMLDocumentTidyHTML) { inString = [[CTidy tidy] tidyString:inString inputFormat:TidyFormat_HTML outputFormat:TidyFormat_XHTML diagnostics:NULL error:&theError]; } else if (inOptions & CXMLDocumentTidyXML) { inString = [[CTidy tidy] tidyString:inString inputFormat:TidyFormat_XML outputFormat:TidyFormat_XML diagnostics:NULL error:&theError]; } #endif xmlDocPtr theDoc = xmlParseDoc((xmlChar *)[inString UTF8String]); if (theDoc != NULL) { _node = (xmlNodePtr)theDoc; NSAssert(_node->_private == NULL, @"TODO"); _node->_private = (__bridge void *)(self); // Note. NOT retained (TODO think more about _private usage) } else { xmlErrorPtr theLastErrorPtr = xmlGetLastError(); NSString* message = @(theLastErrorPtr ? theLastErrorPtr->message : "Unknown error"); NSDictionary *theUserInfo = @{NSLocalizedDescriptionKey: message}; theError = [NSError errorWithDomain:@"CXMLErrorDomain" code:1 userInfo:theUserInfo]; xmlResetLastError(); } if (outError) *outError = theError; if (theError != NULL) { self = NULL; } } return(self); } - (id)initWithData:(NSData *)inData options:(NSUInteger)inOptions error:(NSError **)outError { return [self initWithData:inData encoding:NSUTF8StringEncoding options:inOptions error:outError]; } - (id)initWithData:(NSData *)inData encoding:(NSStringEncoding)encoding options:(NSUInteger)inOptions error:(NSError **)outError { #pragma unused (inOptions) if ((self = [super init]) != NULL) { NSError *theError = NULL; #if TOUCHXMLUSETIDY if (inOptions & CXMLDocumentTidyHTML) { inData = [[CTidy tidy] tidyData:inData inputFormat:TidyFormat_HTML outputFormat:TidyFormat_XHTML diagnostics:NULL error:&theError]; } else if (inOptions & CXMLDocumentTidyXML) { inData = [[CTidy tidy] tidyData:inData inputFormat:TidyFormat_XML outputFormat:TidyFormat_XML diagnostics:NULL error:&theError]; } #endif if (theError == NULL) { xmlDocPtr theDoc = NULL; if (inData && inData.length > 0) { CFStringEncoding cfenc = CFStringConvertNSStringEncodingToEncoding(encoding); CFStringRef cfencstr = CFStringConvertEncodingToIANACharSetName(cfenc); const char *enc = CFStringGetCStringPtr(cfencstr, 0); theDoc = xmlReadMemory([inData bytes], (int)[inData length], NULL, enc, XML_PARSE_RECOVER | XML_PARSE_NOWARNING); } if (theDoc != NULL && xmlDocGetRootElement(theDoc) != NULL) { _node = (xmlNodePtr)theDoc; _node->_private = (__bridge void *)(self); // Note. NOT retained (TODO think more about _private usage) } else { xmlErrorPtr theLastErrorPtr = xmlGetLastError(); NSString* message = @(theLastErrorPtr ? theLastErrorPtr->message : "Unknown error"); NSDictionary *theUserInfo = @{NSLocalizedDescriptionKey: message}; theError = [NSError errorWithDomain:@"CXMLErrorDomain" code:1 userInfo:theUserInfo]; xmlResetLastError(); } } if (outError) *outError = theError; if (theError != NULL) { self = NULL; } } return(self); } - (id)initWithContentsOfURL:(NSURL *)inURL options:(NSUInteger)inOptions error:(NSError **)outError { return [self initWithContentsOfURL:inURL encoding:NSUTF8StringEncoding options:inOptions error:outError]; } - (id)initWithContentsOfURL:(NSURL *)inURL encoding:(NSStringEncoding)encoding options:(NSUInteger)inOptions error:(NSError **)outError { if (outError) *outError = NULL; NSData *theData = [NSData dataWithContentsOfURL:inURL options:NSUncachedRead error:outError]; if (theData) { self = [self initWithData:theData encoding:encoding options:inOptions error:outError]; } else { self = NULL; } return(self); } - (void)dealloc { // Fix for #35 http://code.google.com/p/touchcode/issues/detail?id=35 -- clear up the node objects first (inside a pool so I _know_ they're cleared) and then freeing the document @autoreleasepool { for (CXMLNode *theNode in nodePool) { [theNode invalidate]; } nodePool = NULL; } // xmlUnlinkNode(_node); xmlFreeDoc((xmlDocPtr)_node); _node = NULL; } //- (NSString *)characterEncoding; //- (NSString *)version; //- (BOOL)isStandalone; //- (CXMLDocumentContentKind)documentContentKind; //- (NSString *)MIMEType; //- (CXMLDTD *)DTD; - (CXMLElement *)rootElement { xmlNodePtr theLibXMLNode = xmlDocGetRootElement((xmlDocPtr)_node); return([CXMLNode nodeWithLibXMLNode:theLibXMLNode freeOnDealloc:NO]); } - (NSData *)XMLData { return([self XMLDataWithOptions:0]); } - (NSData *)XMLDataWithOptions:(NSUInteger)options { #pragma unused (options) xmlChar *theBuffer = NULL; int theBufferSize = 0; xmlDocDumpMemory((xmlDocPtr)self->_node, &theBuffer, &theBufferSize); NSData *theData = [NSData dataWithBytes:theBuffer length:theBufferSize]; xmlFree(theBuffer); return(theData); } //- (id)objectByApplyingXSLT:(NSData *)xslt arguments:(NSDictionary *)arguments error:(NSError **)error; //- (id)objectByApplyingXSLTString:(NSString *)xslt arguments:(NSDictionary *)arguments error:(NSError **)error; //- (id)objectByApplyingXSLTAtURL:(NSURL *)xsltURL arguments:(NSDictionary *)argument error:(NSError **)error; - (id)XMLStringWithOptions:(NSUInteger)options { CXMLElement *theRoot = [self rootElement]; NSMutableString *xmlString = [NSMutableString string]; [xmlString appendString:[theRoot XMLStringWithOptions:options]]; return xmlString; } - (NSString *)description { NSAssert(_node != NULL, @"TODO"); NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p [%p]> ", NSStringFromClass([self class]), self, self->_node]; xmlChar *xmlbuff; int buffersize; xmlDocDumpFormatMemory((xmlDocPtr)(self->_node), &xmlbuff, &buffersize, 1); NSString *dump = [[NSString alloc] initWithBytes:xmlbuff length:buffersize encoding:NSUTF8StringEncoding]; xmlFree(xmlbuff); [result appendString:dump]; return result; } @end External/TouchXML/Source/CXMLDocument_PrivateExtensions.h000066400000000000000000000036561247122470700237500ustar00rootroot00000000000000// // CXMLDocument_PrivateExtensions.h // TouchCode // // Created by Jonathan Wight on 03/07/08. // Copyright 2011 toxicsoftware.com. All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, are // permitted provided that the following conditions are met: // // 1. Redistributions of source code must retain the above copyright notice, this list of // conditions and the following disclaimer. // // 2. Redistributions in binary form must reproduce the above copyright notice, this list // of conditions and the following disclaimer in the documentation and/or other materials // provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY TOXICSOFTWARE.COM ``AS IS'' AND ANY EXPRESS OR IMPLIED // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL TOXICSOFTWARE.COM OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // The views and conclusions contained in the software and documentation are those of the // authors and should not be interpreted as representing official policies, either expressed // or implied, of toxicsoftware.com. #import "CXMLDocument.h" #include @interface CXMLDocument (CXMLDocument_PrivateExtensions) //- (id)initWithLibXmlParserContext:(xmlParserCtxtPtr)inContext options:(NSUInteger)inOptions error:(NSError **)outError; - (NSMutableSet *)nodePool; @end External/TouchXML/Source/CXMLDocument_PrivateExtensions.m000066400000000000000000000041161247122470700237450ustar00rootroot00000000000000// // CXMLDocument_PrivateExtensions.m // TouchCode // // Created by Jonathan Wight on 03/07/08. // Copyright 2011 toxicsoftware.com. All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, are // permitted provided that the following conditions are met: // // 1. Redistributions of source code must retain the above copyright notice, this list of // conditions and the following disclaimer. // // 2. Redistributions in binary form must reproduce the above copyright notice, this list // of conditions and the following disclaimer in the documentation and/or other materials // provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY TOXICSOFTWARE.COM ``AS IS'' AND ANY EXPRESS OR IMPLIED // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL TOXICSOFTWARE.COM OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // The views and conclusions contained in the software and documentation are those of the // authors and should not be interpreted as representing official policies, either expressed // or implied, of toxicsoftware.com. #import "CXMLDocument_PrivateExtensions.h" @implementation CXMLDocument (CXMLDocument_PrivateExtensions) /* - (id)initWithLibXmlParserContext:(xmlParserCtxtPtr)inContext options:(NSUInteger)inOptions error:(NSError **)outError { xmlParseDocument(inContext); } */ - (NSMutableSet *)nodePool { if (nodePool == NULL) { nodePool = [[NSMutableSet alloc] init]; } return(nodePool); } @end External/TouchXML/Source/CXMLElement.h000066400000000000000000000044441247122470700200050ustar00rootroot00000000000000// // CXMLElement.h // TouchCode // // Created by Jonathan Wight on 03/07/08. // Copyright 2011 toxicsoftware.com. All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, are // permitted provided that the following conditions are met: // // 1. Redistributions of source code must retain the above copyright notice, this list of // conditions and the following disclaimer. // // 2. Redistributions in binary form must reproduce the above copyright notice, this list // of conditions and the following disclaimer in the documentation and/or other materials // provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY TOXICSOFTWARE.COM ``AS IS'' AND ANY EXPRESS OR IMPLIED // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL TOXICSOFTWARE.COM OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // The views and conclusions contained in the software and documentation are those of the // authors and should not be interpreted as representing official policies, either expressed // or implied, of toxicsoftware.com. #import "CXMLNode.h" // NSXMLElement @interface CXMLElement : CXMLNode { } - (NSArray *)elementsForName:(NSString *)name; - (NSArray *)elementsForLocalName:(NSString *)localName URI:(NSString *)URI; - (NSArray *)attributes; - (CXMLNode *)attributeForName:(NSString *)name; - (CXMLNode *)attributeForLocalName:(NSString *)localName URI:(NSString *)URI; - (NSArray *)namespaces; - (CXMLNode *)namespaceForPrefix:(NSString *)name; - (CXMLNode *)resolveNamespaceForName:(NSString *)name; - (NSString *)resolvePrefixForNamespaceURI:(NSString *)namespaceURI; //- (NSString*)_XMLStringWithOptions:(NSUInteger)options appendingToString:(NSMutableString*)str; @end External/TouchXML/Source/CXMLElement.m000066400000000000000000000225061247122470700200110ustar00rootroot00000000000000// // CXMLElement.m // TouchCode // // Created by Jonathan Wight on 03/07/08. // Copyright 2011 toxicsoftware.com. All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, are // permitted provided that the following conditions are met: // // 1. Redistributions of source code must retain the above copyright notice, this list of // conditions and the following disclaimer. // // 2. Redistributions in binary form must reproduce the above copyright notice, this list // of conditions and the following disclaimer in the documentation and/or other materials // provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY TOXICSOFTWARE.COM ``AS IS'' AND ANY EXPRESS OR IMPLIED // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL TOXICSOFTWARE.COM OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // The views and conclusions contained in the software and documentation are those of the // authors and should not be interpreted as representing official policies, either expressed // or implied, of toxicsoftware.com. #import "CXMLElement.h" #import "CXMLNode_PrivateExtensions.h" #import "CXMLNode_CreationExtensions.h" #import "CXMLNamespaceNode.h" @implementation CXMLElement - (NSArray *)elementsForName:(NSString *)name { NSMutableArray *theElements = [NSMutableArray array]; // TODO -- native xml api? const xmlChar *theName = (const xmlChar *)[name UTF8String]; xmlNodePtr theCurrentNode = _node->children; while (theCurrentNode != NULL) { if (theCurrentNode->type == XML_ELEMENT_NODE && xmlStrcmp(theName, theCurrentNode->name) == 0) { CXMLNode *theNode = [CXMLNode nodeWithLibXMLNode:(xmlNodePtr)theCurrentNode freeOnDealloc:NO]; [theElements addObject:theNode]; } theCurrentNode = theCurrentNode->next; } return(theElements); } - (NSArray *)elementsForLocalName:(NSString *)localName URI:(NSString *)URI { if (URI == nil || [URI length] == 0) { return [self elementsForName:localName]; } NSMutableArray *theElements = [NSMutableArray array]; const xmlChar *theLocalName = (const xmlChar *)[localName UTF8String]; const xmlChar *theNamespaceName = (const xmlChar *)[URI UTF8String]; xmlNodePtr theCurrentNode = _node->children; while (theCurrentNode != NULL) { if (theCurrentNode->type == XML_ELEMENT_NODE && xmlStrcmp(theLocalName, theCurrentNode->name) == 0 && theCurrentNode->ns && xmlStrcmp(theNamespaceName, theCurrentNode->ns->href) == 0) { CXMLNode *theNode = [CXMLNode nodeWithLibXMLNode:(xmlNodePtr)theCurrentNode freeOnDealloc:NO]; [theElements addObject:theNode]; } theCurrentNode = theCurrentNode->next; } return theElements; } - (NSArray *)attributes { NSMutableArray *theAttributes = [NSMutableArray array]; xmlAttrPtr theCurrentNode = _node->properties; while (theCurrentNode != NULL) { CXMLNode *theAttribute = [CXMLNode nodeWithLibXMLNode:(xmlNodePtr)theCurrentNode freeOnDealloc:NO]; [theAttributes addObject:theAttribute]; theCurrentNode = theCurrentNode->next; } return(theAttributes); } - (CXMLNode *)attributeForName:(NSString *)name { // TODO -- look for native libxml2 function for finding a named attribute (like xmlGetProp) NSRange split = [name rangeOfString:@":"]; xmlChar *theLocalName = NULL; xmlChar *thePrefix = NULL; if (split.length > 0) { theLocalName = (xmlChar *)[[name substringFromIndex:split.location + 1] UTF8String]; thePrefix = (xmlChar *)[[name substringToIndex:split.location] UTF8String]; } else { theLocalName = (xmlChar *)[name UTF8String]; } xmlAttrPtr theCurrentNode = _node->properties; while (theCurrentNode != NULL) { if (xmlStrcmp(theLocalName, theCurrentNode->name) == 0) { if (thePrefix == NULL || (theCurrentNode->ns && theCurrentNode->ns->prefix && xmlStrcmp(thePrefix, theCurrentNode->ns->prefix) == 0)) { CXMLNode *theAttribute = [CXMLNode nodeWithLibXMLNode:(xmlNodePtr)theCurrentNode freeOnDealloc:NO]; return(theAttribute); } } theCurrentNode = theCurrentNode->next; } return(NULL); } - (CXMLNode *)attributeForLocalName:(NSString *)localName URI:(NSString *)URI { if (URI == nil) { return [self attributeForName:localName]; } // TODO -- look for native libxml2 function for finding a named attribute (like xmlGetProp) const xmlChar *theLocalName = (const xmlChar *)[localName UTF8String]; const xmlChar *theNamespaceName = (const xmlChar *)[URI UTF8String]; xmlAttrPtr theCurrentNode = _node->properties; while (theCurrentNode != NULL) { if (theCurrentNode->ns && theCurrentNode->ns->href && xmlStrcmp(theLocalName, theCurrentNode->name) == 0 && xmlStrcmp(theNamespaceName, theCurrentNode->ns->href) == 0) { CXMLNode *theAttribute = [CXMLNode nodeWithLibXMLNode:(xmlNodePtr)theCurrentNode freeOnDealloc:NO]; return(theAttribute); } theCurrentNode = theCurrentNode->next; } return(NULL); } - (NSArray *)namespaces { NSMutableArray *theNamespaces = [[NSMutableArray alloc] init]; xmlNsPtr theCurrentNamespace = _node->nsDef; while (theCurrentNamespace != NULL) { NSString *thePrefix = theCurrentNamespace->prefix ? @((const char *)theCurrentNamespace->prefix) : @""; NSString *theURI = @((const char *)theCurrentNamespace->href); CXMLNamespaceNode *theNode = [[CXMLNamespaceNode alloc] initWithPrefix:thePrefix URI:theURI parentElement:self]; [theNamespaces addObject:theNode]; theCurrentNamespace = theCurrentNamespace->next; } return theNamespaces; } - (CXMLNode *)namespaceForPrefix:(NSString *)name { const xmlChar *thePrefix = (const xmlChar *)[name UTF8String]; xmlNsPtr theCurrentNamespace = _node->nsDef; while (theCurrentNamespace != NULL) { if (xmlStrcmp(theCurrentNamespace->prefix, thePrefix) == 0) { NSString *thePrefixString = theCurrentNamespace->prefix ? @((const char *)theCurrentNamespace->prefix) : @""; NSString *theURI = @((const char *)theCurrentNamespace->href); return [[CXMLNamespaceNode alloc] initWithPrefix:thePrefixString URI:theURI parentElement:self]; } theCurrentNamespace = theCurrentNamespace->next; } return nil; } - (CXMLNode *)resolveNamespaceForName:(NSString *)name { NSRange split = [name rangeOfString:@":"]; if (split.length > 0) return [self namespaceForPrefix:[name substringToIndex:split.location]]; xmlNsPtr theCurrentNamespace = _node->nsDef; while (theCurrentNamespace != NULL) { if (theCurrentNamespace->prefix == 0 || (theCurrentNamespace->prefix)[0] == 0) { NSString *thePrefix = theCurrentNamespace->prefix ? @((const char *)theCurrentNamespace->prefix) : @""; NSString *theURI = @((const char *)theCurrentNamespace->href); return [[CXMLNamespaceNode alloc] initWithPrefix:thePrefix URI:theURI parentElement:self]; } theCurrentNamespace = theCurrentNamespace->next; } return nil; } - (NSString *)resolvePrefixForNamespaceURI:(NSString *)namespaceURI { const xmlChar *theXMLURI = (const xmlChar *)[namespaceURI UTF8String]; xmlNsPtr theCurrentNamespace = _node->nsDef; while (theCurrentNamespace != NULL) { if (xmlStrcmp(theCurrentNamespace->href, theXMLURI) == 0) { if(theCurrentNamespace->prefix) return @((const char *)theCurrentNamespace->prefix); return @""; } theCurrentNamespace = theCurrentNamespace->next; } return nil; } //- (NSString*)_XMLStringWithOptions:(NSUInteger)options appendingToString:(NSMutableString*)str //{ //NSString* name = [self name]; //[str appendString:[NSString stringWithFormat:@"<%@", name]]; // //for (id attribute in [self attributes] ) // { // [attribute _XMLStringWithOptions:options appendingToString:str]; // } // //if ( ! _node->children ) // { // bool isEmpty = NO; // NSArray *emptyTags = [NSArray arrayWithObjects: @"br", @"area", @"link", @"img", @"param", @"hr", @"input", @"col", @"base", @"meta", nil ]; // for (id s in emptyTags) // { // if ( [s isEqualToString:@"base"] ) // { // isEmpty = YES; // break; // } // } // if ( isEmpty ) // { // [str appendString:@"/>"]; // return str; // } // } // //[str appendString:@">"]; // //if ( _node->children ) // { // for (id child in [self children]) // [child _XMLStringWithOptions:options appendingToString:str]; // } //[str appendString:[NSString stringWithFormat:@"", name]]; //return str; //} - (NSString *)description { NSAssert(_node != NULL, @"TODO"); return([NSString stringWithFormat:@"<%@ %p [%p] %@ %@>", NSStringFromClass([self class]), self, self->_node, [self name], [self XMLStringWithOptions:0]]); } @end External/TouchXML/Source/CXMLElement_CreationExtensions.h000066400000000000000000000035151247122470700237070ustar00rootroot00000000000000// // CXMLElement_CreationExtensions.h // TouchCode // // Created by Jonathan Wight on 04/01/08. // Copyright 2011 toxicsoftware.com. All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, are // permitted provided that the following conditions are met: // // 1. Redistributions of source code must retain the above copyright notice, this list of // conditions and the following disclaimer. // // 2. Redistributions in binary form must reproduce the above copyright notice, this list // of conditions and the following disclaimer in the documentation and/or other materials // provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY TOXICSOFTWARE.COM ``AS IS'' AND ANY EXPRESS OR IMPLIED // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL TOXICSOFTWARE.COM OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // The views and conclusions contained in the software and documentation are those of the // authors and should not be interpreted as representing official policies, either expressed // or implied, of toxicsoftware.com. #import "CXMLElement.h" @interface CXMLElement (CXMLElement_CreationExtensions) - (void)addChild:(CXMLNode *)inNode; - (void)addNamespace:(CXMLNode *)inNamespace; @end External/TouchXML/Source/CXMLElement_CreationExtensions.m000066400000000000000000000051461247122470700237160ustar00rootroot00000000000000// // CXMLElement_CreationExtensions.m // TouchCode // // Created by Jonathan Wight on 04/01/08. // Copyright 2011 toxicsoftware.com. All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, are // permitted provided that the following conditions are met: // // 1. Redistributions of source code must retain the above copyright notice, this list of // conditions and the following disclaimer. // // 2. Redistributions in binary form must reproduce the above copyright notice, this list // of conditions and the following disclaimer in the documentation and/or other materials // provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY TOXICSOFTWARE.COM ``AS IS'' AND ANY EXPRESS OR IMPLIED // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL TOXICSOFTWARE.COM OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // The views and conclusions contained in the software and documentation are those of the // authors and should not be interpreted as representing official policies, either expressed // or implied, of toxicsoftware.com. #import "CXMLElement_CreationExtensions.h" @implementation CXMLElement (CXMLElement_CreationExtensions) - (void)addChild:(CXMLNode *)inNode { NSAssert(inNode->_node->doc == NULL, @"Cannot addChild with a node that already is part of a document. Copy it first!"); NSAssert(self->_node != NULL, @"_node should not be null"); NSAssert(inNode->_node != NULL, @"_node should not be null"); xmlAddChild(self->_node, inNode->_node); // now XML element is tracked by document, do not release on dealloc inNode->_freeNodeOnRelease = NO; } - (void)addNamespace:(CXMLNode *)inNamespace { xmlSetNs(self->_node, (xmlNsPtr)inNamespace->_node); } - (void)setStringValue:(NSString *)inStringValue { NSAssert(inStringValue != NULL, @"CXMLElement setStringValue should not be null"); xmlNodePtr theContentNode = xmlNewText((const xmlChar *)[inStringValue UTF8String]); NSAssert(self->_node != NULL, @"_node should not be null"); xmlAddChild(self->_node, theContentNode); } @end External/TouchXML/Source/CXMLElement_ElementTreeExtensions.h000066400000000000000000000034601247122470700243530ustar00rootroot00000000000000// // CXMLElement_ElementTreeExtensions.h // TouchCode // // Created by Jonathan Wight on 11/14/08. // Copyright 2011 toxicsoftware.com. All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, are // permitted provided that the following conditions are met: // // 1. Redistributions of source code must retain the above copyright notice, this list of // conditions and the following disclaimer. // // 2. Redistributions in binary form must reproduce the above copyright notice, this list // of conditions and the following disclaimer in the documentation and/or other materials // provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY TOXICSOFTWARE.COM ``AS IS'' AND ANY EXPRESS OR IMPLIED // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL TOXICSOFTWARE.COM OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // The views and conclusions contained in the software and documentation are those of the // authors and should not be interpreted as representing official policies, either expressed // or implied, of toxicsoftware.com. #import "CXMLElement.h" @interface CXMLElement (CXMLElement_ElementTreeExtensions) - (CXMLElement *)subelement:(NSString *)inName; @end External/TouchXML/Source/CXMLElement_ElementTreeExtensions.m000066400000000000000000000040301247122470700243520ustar00rootroot00000000000000// // CXMLElement_ElementTreeExtensions.m // TouchCode // // Created by Jonathan Wight on 11/14/08. // Copyright 2011 toxicsoftware.com. All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, are // permitted provided that the following conditions are met: // // 1. Redistributions of source code must retain the above copyright notice, this list of // conditions and the following disclaimer. // // 2. Redistributions in binary form must reproduce the above copyright notice, this list // of conditions and the following disclaimer in the documentation and/or other materials // provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY TOXICSOFTWARE.COM ``AS IS'' AND ANY EXPRESS OR IMPLIED // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL TOXICSOFTWARE.COM OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // The views and conclusions contained in the software and documentation are those of the // authors and should not be interpreted as representing official policies, either expressed // or implied, of toxicsoftware.com. #import "CXMLElement_ElementTreeExtensions.h" #import "CXMLElement_CreationExtensions.h" #import "CXMLNode_CreationExtensions.h" @implementation CXMLElement (CXMLElement_ElementTreeExtensions) - (CXMLElement *)subelement:(NSString *)inName; { CXMLElement *theSubelement = [CXMLNode elementWithName:inName]; [self addChild:theSubelement]; return(theSubelement); } @end External/TouchXML/Source/CXMLNamespaceNode.h000066400000000000000000000036651247122470700211220ustar00rootroot00000000000000// // CXMLNamespaceNode.h // TouchXML // // Created by Jonathan Wight on 1/1/2000. // Copyright 2011 toxicsoftware.com. All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, are // permitted provided that the following conditions are met: // // 1. Redistributions of source code must retain the above copyright notice, this list of // conditions and the following disclaimer. // // 2. Redistributions in binary form must reproduce the above copyright notice, this list // of conditions and the following disclaimer in the documentation and/or other materials // provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY TOXICSOFTWARE.COM ``AS IS'' AND ANY EXPRESS OR IMPLIED // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL TOXICSOFTWARE.COM OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // The views and conclusions contained in the software and documentation are those of the // authors and should not be interpreted as representing official policies, either expressed // or implied, of toxicsoftware.com. #import #import "CXMLNode.h" #import "CXMLElement.h" @interface CXMLNamespaceNode : CXMLNode { NSString *_prefix; NSString *_uri; CXMLElement *_parent; } - (id) initWithPrefix:(NSString *)prefix URI:(NSString *)uri parentElement:(CXMLElement *)parent; @end External/TouchXML/Source/CXMLNamespaceNode.m000066400000000000000000000074421247122470700211240ustar00rootroot00000000000000// // CXMLNamespaceNode.m // TouchXML // // Created by Jonathan Wight on 1/1/2000. // Copyright 2011 toxicsoftware.com. All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, are // permitted provided that the following conditions are met: // // 1. Redistributions of source code must retain the above copyright notice, this list of // conditions and the following disclaimer. // // 2. Redistributions in binary form must reproduce the above copyright notice, this list // of conditions and the following disclaimer in the documentation and/or other materials // provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY TOXICSOFTWARE.COM ``AS IS'' AND ANY EXPRESS OR IMPLIED // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL TOXICSOFTWARE.COM OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // The views and conclusions contained in the software and documentation are those of the // authors and should not be interpreted as representing official policies, either expressed // or implied, of toxicsoftware.com. #import "CXMLNamespaceNode.h" @implementation CXMLNamespaceNode #pragma mark - #pragma mark Init and dealloc - (id) initWithPrefix:(NSString *)prefix URI:(NSString *)uri parentElement:(CXMLElement *)parent { if ((self = [super init]) != NULL) { _prefix = [prefix copy]; _uri = [uri copy]; _parent = parent; // Don't retain parent } return self; } - (void) dealloc { _prefix = nil; _uri = nil; _parent = nil; // Parent not retained } #pragma mark - #pragma mark Overidden methods // NB: We need to override every method that relies on _node as namespaces in libXML don't have a xmlNode - (CXMLNodeKind)kind { return CXMLNamespaceKind; } - (NSString *)name { return _prefix ? [_prefix copy] : @""; } - (NSString *)stringValue { return _uri ? [_uri copy] : @""; } - (NSUInteger)index { return 0; // TODO: Write tets, Fix } - (NSUInteger)level { return _parent ? [_parent level] + 1 : 2; } - (CXMLDocument *)rootDocument { return [_parent rootDocument]; } - (CXMLNode *)parent { return _parent; } - (NSUInteger)childCount { return 0; } - (NSArray *)children { return nil; } - (CXMLNode *)childAtIndex:(NSUInteger)index { return nil; } - (CXMLNode *)previousSibling { return nil; // TODO: Write tets, Fix } - (CXMLNode *)nextSibling { return nil; // TODO: Write tets, Fix } //- (CXMLNode *)previousNode; //- (CXMLNode *)nextNode; //- (NSString *)XPath; - (NSString *)localName { return [self name]; } - (NSString *)prefix { return @""; } - (NSString *)URI { return nil; } //+ (NSString *)localNameForName:(NSString *)name; //+ (NSString *)prefixForName:(NSString *)name; //+ (CXMLNode *)predefinedNamespaceForPrefix:(NSString *)name; - (NSString *)description { if (_prefix && [_prefix length] > 0) return [NSString stringWithFormat:@"xmlns:%@=\"%@\"", _prefix, _uri]; return [NSString stringWithFormat:@"xmlns=\"%@\"", _uri]; } - (NSString *)XMLString { return [self description]; } - (NSString *)XMLStringWithOptions:(NSUInteger)options { return [self description]; } //- (NSString *)canonicalXMLStringPreservingComments:(BOOL)comments; - (NSArray *)nodesForXPath:(NSString *)xpath error:(NSError **)error { return nil; } @end External/TouchXML/Source/CXMLNode.h000066400000000000000000000062611247122470700173000ustar00rootroot00000000000000// // CXMLNode.h // TouchCode // // Created by Jonathan Wight on 03/07/08. // Copyright 2011 toxicsoftware.com. All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, are // permitted provided that the following conditions are met: // // 1. Redistributions of source code must retain the above copyright notice, this list of // conditions and the following disclaimer. // // 2. Redistributions in binary form must reproduce the above copyright notice, this list // of conditions and the following disclaimer in the documentation and/or other materials // provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY TOXICSOFTWARE.COM ``AS IS'' AND ANY EXPRESS OR IMPLIED // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL TOXICSOFTWARE.COM OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // The views and conclusions contained in the software and documentation are those of the // authors and should not be interpreted as representing official policies, either expressed // or implied, of toxicsoftware.com. #import #include typedef enum { CXMLInvalidKind = 0, CXMLElementKind = XML_ELEMENT_NODE, CXMLAttributeKind = XML_ATTRIBUTE_NODE, CXMLTextKind = XML_TEXT_NODE, CXMLProcessingInstructionKind = XML_PI_NODE, CXMLCommentKind = XML_COMMENT_NODE, CXMLNotationDeclarationKind = XML_NOTATION_NODE, CXMLDTDKind = XML_DTD_NODE, CXMLElementDeclarationKind = XML_ELEMENT_DECL, CXMLAttributeDeclarationKind = XML_ATTRIBUTE_DECL, CXMLEntityDeclarationKind = XML_ENTITY_DECL, CXMLNamespaceKind = XML_NAMESPACE_DECL, } CXMLNodeKind; @class CXMLDocument; // NSXMLNode @interface CXMLNode : NSObject { xmlNodePtr _node; BOOL _freeNodeOnRelease; } - (CXMLNodeKind)kind; - (NSString *)name; - (NSString *)stringValue; - (NSUInteger)index; - (NSUInteger)level; - (CXMLDocument *)rootDocument; - (CXMLNode *)parent; - (NSUInteger)childCount; - (NSArray *)children; - (CXMLNode *)childAtIndex:(NSUInteger)index; - (CXMLNode *)previousSibling; - (CXMLNode *)nextSibling; //- (CXMLNode *)previousNode; //- (CXMLNode *)nextNode; //- (NSString *)XPath; - (NSString *)localName; - (NSString *)prefix; - (NSString *)URI; + (NSString *)localNameForName:(NSString *)name; + (NSString *)prefixForName:(NSString *)name; + (CXMLNode *)predefinedNamespaceForPrefix:(NSString *)name; - (NSString *)description; - (NSString *)XMLString; - (NSString *)XMLStringWithOptions:(NSUInteger)options; //- (NSString *)canonicalXMLStringPreservingComments:(BOOL)comments; - (NSArray *)nodesForXPath:(NSString *)xpath error:(NSError **)error; @end External/TouchXML/Source/CXMLNode.m000066400000000000000000000237751247122470700173160ustar00rootroot00000000000000// // CXMLNode.m // TouchCode // // Created by Jonathan Wight on 03/07/08. // Copyright 2011 toxicsoftware.com. All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, are // permitted provided that the following conditions are met: // // 1. Redistributions of source code must retain the above copyright notice, this list of // conditions and the following disclaimer. // // 2. Redistributions in binary form must reproduce the above copyright notice, this list // of conditions and the following disclaimer in the documentation and/or other materials // provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY TOXICSOFTWARE.COM ``AS IS'' AND ANY EXPRESS OR IMPLIED // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL TOXICSOFTWARE.COM OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // The views and conclusions contained in the software and documentation are those of the // authors and should not be interpreted as representing official policies, either expressed // or implied, of toxicsoftware.com. #import "CXMLNode.h" #import "CXMLNode_PrivateExtensions.h" #import "CXMLDocument.h" #import "CXMLElement.h" #import "CXMLNode_CreationExtensions.h" #include #include #include static int MyXmlOutputWriteCallback(void * context, const char * buffer, int len); static int MyXmlOutputCloseCallback(void * context); @implementation CXMLNode - (void)dealloc { [self invalidate]; // } - (id)copyWithZone:(NSZone *)zone; { #pragma unused (zone) xmlNodePtr theNewNode = xmlCopyNode(_node, 1); CXMLNode *theNode = [[[self class] alloc] initWithLibXMLNode:theNewNode freeOnDealloc:YES]; theNewNode->_private = (__bridge void *)(theNode); return(theNode); } #pragma mark - - (CXMLNodeKind)kind { NSAssert(_node != NULL, @"CXMLNode does not have attached libxml2 _node."); return((CXMLNodeKind)_node->type); // TODO this isn't 100% accurate! } - (NSString *)name { NSAssert(_node != NULL, @"CXMLNode does not have attached libxml2 _node."); // TODO use xmlCheckUTF8 to check name if (_node->name == NULL) return(NULL); NSString *localName = @((const char *)_node->name); if (_node->ns == NULL || _node->ns->prefix == NULL) return localName; return [NSString stringWithFormat:@"%@:%@", @((const char *)_node->ns->prefix), localName]; } - (NSString *)stringValue { NSAssert(_node != NULL, @"CXMLNode does not have attached libxml2 _node."); if (_node->type == XML_TEXT_NODE || _node->type == XML_CDATA_SECTION_NODE) return @((const char *)_node->content); if (_node->type == XML_ATTRIBUTE_NODE) return @((const char *)_node->children->content); NSMutableString *theStringValue = [[NSMutableString alloc] init]; for (CXMLNode *child in [self children]) { [theStringValue appendString:[child stringValue]]; } return theStringValue; } - (NSUInteger)index { NSAssert(_node != NULL, @"CXMLNode does not have attached libxml2 _node."); xmlNodePtr theCurrentNode = _node->prev; NSUInteger N; for (N = 0; theCurrentNode != NULL; ++N, theCurrentNode = theCurrentNode->prev) ; return(N); } - (NSUInteger)level { NSAssert(_node != NULL, @"CXMLNode does not have attached libxml2 _node."); xmlNodePtr theCurrentNode = _node->parent; NSUInteger N; for (N = 0; theCurrentNode != NULL; ++N, theCurrentNode = theCurrentNode->parent) ; return(N); } - (CXMLDocument *)rootDocument { NSAssert(_node != NULL, @"CXMLNode does not have attached libxml2 _node."); return(__bridge CXMLDocument *)((_node->doc->_private)); } - (CXMLNode *)parent { NSAssert(_node != NULL, @"CXMLNode does not have attached libxml2 _node."); if (_node->parent == NULL) return(NULL); else return (__bridge CXMLNode *)((_node->parent->_private)); } - (NSUInteger)childCount { NSAssert(_node != NULL, @"CXMLNode does not have attached libxml2 _node."); if (_node->type == CXMLAttributeKind) return 0; // NSXMLNodes of type NSXMLAttributeKind can't have children xmlNodePtr theCurrentNode = _node->children; NSUInteger N; for (N = 0; theCurrentNode != NULL; ++N, theCurrentNode = theCurrentNode->next) ; return(N); } - (NSArray *)children { NSAssert(_node != NULL, @"CXMLNode does not have attached libxml2 _node."); NSMutableArray *theChildren = [NSMutableArray array]; if (_node->type != CXMLAttributeKind) // NSXML Attribs don't have children. { xmlNodePtr theCurrentNode = _node->children; while (theCurrentNode != NULL) { CXMLNode *theNode = [CXMLNode nodeWithLibXMLNode:theCurrentNode freeOnDealloc:NO]; [theChildren addObject:theNode]; theCurrentNode = theCurrentNode->next; } } return(theChildren); } - (CXMLNode *)childAtIndex:(NSUInteger)index { NSAssert(_node != NULL, @"CXMLNode does not have attached libxml2 _node."); xmlNodePtr theCurrentNode = _node->children; NSUInteger N; for (N = 0; theCurrentNode != NULL && N != index; ++N, theCurrentNode = theCurrentNode->next) ; if (theCurrentNode) return([CXMLNode nodeWithLibXMLNode:theCurrentNode freeOnDealloc:NO]); return(NULL); } - (CXMLNode *)previousSibling { NSAssert(_node != NULL, @"CXMLNode does not have attached libxml2 _node."); if (_node->prev == NULL) return(NULL); else return([CXMLNode nodeWithLibXMLNode:_node->prev freeOnDealloc:NO]); } - (CXMLNode *)nextSibling { NSAssert(_node != NULL, @"CXMLNode does not have attached libxml2 _node."); if (_node->next == NULL) return(NULL); else return([CXMLNode nodeWithLibXMLNode:_node->next freeOnDealloc:NO]); } //- (CXMLNode *)previousNode; //- (CXMLNode *)nextNode; //- (NSString *)XPath; - (NSString *)localName { NSAssert(_node != NULL, @"CXMLNode does not have attached libxml2 _node."); // TODO use xmlCheckUTF8 to check name if (_node->name == NULL) return(NULL); else return(@((const char *)_node->name)); } - (NSString *)prefix { if (_node->ns && _node->ns->prefix) return(@((const char *)_node->ns->prefix)); else return(@""); } - (NSString *)URI { if (_node->ns) return(@((const char *)_node->ns->href)); else return(NULL); } + (NSString *)localNameForName:(NSString *)name { NSRange split = [name rangeOfString:@":"]; if (split.length > 0) return [name substringFromIndex:split.location + 1]; return name; } + (NSString *)prefixForName:(NSString *)name { NSRange split = [name rangeOfString:@":"]; if (split.length > 0) return [name substringToIndex:split.location]; return @""; } + (CXMLNode *)predefinedNamespaceForPrefix:(NSString *)name { if ([name isEqualToString:@"xml"]) return [CXMLNode namespaceWithName:@"xml" stringValue:@"http://www.w3.org/XML/1998/namespace"]; if ([name isEqualToString:@"xs"]) return [CXMLNode namespaceWithName:@"xs" stringValue:@"http://www.w3.org/2001/XMLSchema"]; if ([name isEqualToString:@"xsi"]) return [CXMLNode namespaceWithName:@"xsi" stringValue:@"http://www.w3.org/2001/XMLSchema-instance"]; if ([name isEqualToString:@"xmlns"]) // Not in Cocoa, but should be as it's reserved by W3C return [CXMLNode namespaceWithName:@"xmlns" stringValue:@"http://www.w3.org/2000/xmlns/"]; return nil; } - (NSString *)description { NSAssert(_node != NULL, @"CXMLNode does not have attached libxml2 _node."); return([NSString stringWithFormat:@"<%@ %p [%p] %@ %@>", NSStringFromClass([self class]), self, self->_node, [self name], [self XMLStringWithOptions:0]]); } - (NSString *)XMLString { return([self XMLStringWithOptions:0]); } - (NSString *)XMLStringWithOptions:(NSUInteger)options { #pragma unused (options) NSMutableData *theData = [[NSMutableData alloc] init]; xmlOutputBufferPtr theOutputBuffer = xmlOutputBufferCreateIO(MyXmlOutputWriteCallback, MyXmlOutputCloseCallback, (__bridge void *)(theData), NULL); xmlNodeDumpOutput(theOutputBuffer, _node->doc, _node, 0, 0, "utf-8"); xmlOutputBufferFlush(theOutputBuffer); NSString *theString = [[NSString alloc] initWithData:theData encoding:NSUTF8StringEncoding]; xmlOutputBufferClose(theOutputBuffer); return(theString); } //- (NSString *)canonicalXMLStringPreservingComments:(BOOL)comments; - (NSArray *)nodesForXPath:(NSString *)xpath error:(NSError **)error { #pragma unused (error) NSAssert(_node != NULL, @"CXMLNode does not have attached libxml2 _node."); NSArray *theResult = NULL; xmlXPathContextPtr theXPathContext = xmlXPathNewContext(_node->doc); theXPathContext->node = _node; // TODO considering putting xmlChar <-> UTF8 into a NSString category xmlXPathObjectPtr theXPathObject = xmlXPathEvalExpression((const xmlChar *)[xpath UTF8String], theXPathContext); if (theXPathObject == NULL) { if (error) *error = [NSError errorWithDomain:@"TODO_DOMAIN" code:-1 userInfo:NULL]; return(NULL); } if (xmlXPathNodeSetIsEmpty(theXPathObject->nodesetval)) theResult = @[]; // TODO better to return NULL? else { NSMutableArray *theArray = [NSMutableArray array]; int N; for (N = 0; N < theXPathObject->nodesetval->nodeNr; N++) { xmlNodePtr theNode = theXPathObject->nodesetval->nodeTab[N]; [theArray addObject:[CXMLNode nodeWithLibXMLNode:theNode freeOnDealloc:NO]]; } theResult = theArray; } xmlXPathFreeObject(theXPathObject); xmlXPathFreeContext(theXPathContext); return(theResult); } //- (NSArray *)objectsForXQuery:(NSString *)xquery constants:(NSDictionary *)constants error:(NSError **)error; //- (NSArray *)objectsForXQuery:(NSString *)xquery error:(NSError **)error; @end static int MyXmlOutputWriteCallback(void * context, const char * buffer, int len) { NSMutableData *theData = (__bridge NSMutableData *)(context); [theData appendBytes:buffer length:len]; return(len); } static int MyXmlOutputCloseCallback(void * context) { return(0); } External/TouchXML/Source/CXMLNode_PrivateExtensions.h000066400000000000000000000037511247122470700230530ustar00rootroot00000000000000// // CXMLNode_PrivateExtensions.h // TouchCode // // Created by Jonathan Wight on 03/07/08. // Copyright 2011 toxicsoftware.com. All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, are // permitted provided that the following conditions are met: // // 1. Redistributions of source code must retain the above copyright notice, this list of // conditions and the following disclaimer. // // 2. Redistributions in binary form must reproduce the above copyright notice, this list // of conditions and the following disclaimer in the documentation and/or other materials // provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY TOXICSOFTWARE.COM ``AS IS'' AND ANY EXPRESS OR IMPLIED // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL TOXICSOFTWARE.COM OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // The views and conclusions contained in the software and documentation are those of the // authors and should not be interpreted as representing official policies, either expressed // or implied, of toxicsoftware.com. #import "CXMLNode.h" @interface CXMLNode (CXMLNode_PrivateExtensions) @property (readonly, nonatomic, assign) xmlNodePtr node; - (id)initWithLibXMLNode:(xmlNodePtr)inLibXMLNode freeOnDealloc:(BOOL)infreeOnDealloc; + (id)nodeWithLibXMLNode:(xmlNodePtr)inLibXMLNode freeOnDealloc:(BOOL)infreeOnDealloc; - (void)invalidate; @end External/TouchXML/Source/CXMLNode_PrivateExtensions.m000066400000000000000000000067601247122470700230630ustar00rootroot00000000000000// // CXMLNode_PrivateExtensions.m // TouchCode // // Created by Jonathan Wight on 03/07/08. // Copyright 2011 toxicsoftware.com. All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, are // permitted provided that the following conditions are met: // // 1. Redistributions of source code must retain the above copyright notice, this list of // conditions and the following disclaimer. // // 2. Redistributions in binary form must reproduce the above copyright notice, this list // of conditions and the following disclaimer in the documentation and/or other materials // provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY TOXICSOFTWARE.COM ``AS IS'' AND ANY EXPRESS OR IMPLIED // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL TOXICSOFTWARE.COM OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // The views and conclusions contained in the software and documentation are those of the // authors and should not be interpreted as representing official policies, either expressed // or implied, of toxicsoftware.com. #import "CXMLNode_PrivateExtensions.h" #import "CXMLElement.h" #import "CXMLDocument_PrivateExtensions.h" @implementation CXMLNode (CXMLNode_PrivateExtensions) - (id)initWithLibXMLNode:(xmlNodePtr)inLibXMLNode freeOnDealloc:(BOOL)infreeOnDealloc { if (inLibXMLNode == NULL) return nil; if ((self = [super init]) != NULL) { _node = inLibXMLNode; _freeNodeOnRelease = infreeOnDealloc; } return(self); } + (id)nodeWithLibXMLNode:(xmlNodePtr)inLibXMLNode freeOnDealloc:(BOOL)infreeOnDealloc { // TODO more checking. if (inLibXMLNode == NULL) return nil; if (inLibXMLNode->_private) return(__bridge id)(inLibXMLNode->_private); Class theClass = [CXMLNode class]; switch (inLibXMLNode->type) { case XML_ELEMENT_NODE: theClass = [CXMLElement class]; break; case XML_DOCUMENT_NODE: theClass = [CXMLDocument class]; break; case XML_ATTRIBUTE_NODE: case XML_TEXT_NODE: case XML_CDATA_SECTION_NODE: case XML_COMMENT_NODE: break; default: NSAssert1(NO, @"TODO Unhandled type (%d).", inLibXMLNode->type); return(NULL); } CXMLNode *theNode = [[theClass alloc] initWithLibXMLNode:inLibXMLNode freeOnDealloc:infreeOnDealloc]; if (inLibXMLNode->doc != NULL) { CXMLDocument *theXMLDocument = (__bridge CXMLDocument *)(inLibXMLNode->doc->_private); if (theXMLDocument != NULL) { NSAssert([theXMLDocument isKindOfClass:[CXMLDocument class]] == YES, @"TODO"); [[theXMLDocument nodePool] addObject:theNode]; theNode->_node->_private = (__bridge void *)(theNode); } } return(theNode); } - (xmlNodePtr)node { return(_node); } - (void)invalidate; { if (_node) { if (_node->_private == (__bridge void *)(self)) _node->_private = NULL; if (_freeNodeOnRelease) { xmlUnlinkNode(_node); xmlFreeNode(_node); } _node = NULL; } } @end External/TouchXML/Source/CXMLNode_XPathExtensions.h000066400000000000000000000036541247122470700224670ustar00rootroot00000000000000// // CXMLNode_XPathExtensions.h // TouchCode // // Created by Jonathan Wight on 04/01/08. // Copyright 2011 toxicsoftware.com. All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, are // permitted provided that the following conditions are met: // // 1. Redistributions of source code must retain the above copyright notice, this list of // conditions and the following disclaimer. // // 2. Redistributions in binary form must reproduce the above copyright notice, this list // of conditions and the following disclaimer in the documentation and/or other materials // provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY TOXICSOFTWARE.COM ``AS IS'' AND ANY EXPRESS OR IMPLIED // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL TOXICSOFTWARE.COM OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // The views and conclusions contained in the software and documentation are those of the // authors and should not be interpreted as representing official policies, either expressed // or implied, of toxicsoftware.com. #import "CXMLNode.h" @interface CXMLNode (CXMLNode_XPathExtensions) - (NSArray *)nodesForXPath:(NSString *)xpath namespaceMappings:(NSDictionary *)inNamespaceMappings error:(NSError **)error; - (CXMLNode *)nodeForXPath:(NSString *)xpath error:(NSError **)outError; @end External/TouchXML/Source/CXMLNode_XPathExtensions.m000066400000000000000000000065061247122470700224730ustar00rootroot00000000000000// // CXMLNode_XPathExtensions.m // TouchCode // // Created by Jonathan Wight on 04/01/08. // Copyright 2011 toxicsoftware.com. All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, are // permitted provided that the following conditions are met: // // 1. Redistributions of source code must retain the above copyright notice, this list of // conditions and the following disclaimer. // // 2. Redistributions in binary form must reproduce the above copyright notice, this list // of conditions and the following disclaimer in the documentation and/or other materials // provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY TOXICSOFTWARE.COM ``AS IS'' AND ANY EXPRESS OR IMPLIED // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL TOXICSOFTWARE.COM OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // The views and conclusions contained in the software and documentation are those of the // authors and should not be interpreted as representing official policies, either expressed // or implied, of toxicsoftware.com. #import "CXMLNode_XPathExtensions.h" #import "CXMLDocument.h" #import "CXMLDocument_PrivateExtensions.h" #import "CXMLNode_PrivateExtensions.h" #include #include @implementation CXMLNode (CXMLNode_NamespaceExtensions) - (NSArray *)nodesForXPath:(NSString *)xpath namespaceMappings:(NSDictionary *)inNamespaceMappings error:(NSError **)error; { #pragma unused (error) NSAssert(_node != NULL, @"TODO"); NSArray *theResult = NULL; xmlXPathContextPtr theXPathContext = xmlXPathNewContext(_node->doc); theXPathContext->node = _node; for (NSString *thePrefix in inNamespaceMappings) { xmlXPathRegisterNs(theXPathContext, (xmlChar *)[thePrefix UTF8String], (xmlChar *)[inNamespaceMappings[thePrefix] UTF8String]); } // TODO considering putting xmlChar <-> UTF8 into a NSString category xmlXPathObjectPtr theXPathObject = xmlXPathEvalExpression((const xmlChar *)[xpath UTF8String], theXPathContext); if (xmlXPathNodeSetIsEmpty(theXPathObject->nodesetval)) theResult = @[]; // TODO better to return NULL? else { NSMutableArray *theArray = [NSMutableArray array]; int N; for (N = 0; N < theXPathObject->nodesetval->nodeNr; N++) { xmlNodePtr theLibXMLNode = theXPathObject->nodesetval->nodeTab[N]; CXMLNode *theNode = [CXMLNode nodeWithLibXMLNode:theLibXMLNode freeOnDealloc:YES]; [self.rootDocument.nodePool addObject:theNode]; [theArray addObject:theNode]; } theResult = theArray; } xmlXPathFreeObject(theXPathObject); xmlXPathFreeContext(theXPathContext); return(theResult); } - (CXMLNode *)nodeForXPath:(NSString *)xpath error:(NSError **)outError { return([[self nodesForXPath:xpath error:outError] lastObject]); } @end External/TouchXML/Source/Creation/000077500000000000000000000000001247122470700173155ustar00rootroot00000000000000External/TouchXML/Source/Creation/CXMLDocument_CreationExtensions.h000066400000000000000000000047041247122470700256410ustar00rootroot00000000000000// // CXMLDocument_CreationExtensions.h // TouchCode // // Created by Jonathan Wight on 11/11/08. // Copyright 2011 toxicsoftware.com. All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, are // permitted provided that the following conditions are met: // // 1. Redistributions of source code must retain the above copyright notice, this list of // conditions and the following disclaimer. // // 2. Redistributions in binary form must reproduce the above copyright notice, this list // of conditions and the following disclaimer in the documentation and/or other materials // provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY TOXICSOFTWARE.COM ``AS IS'' AND ANY EXPRESS OR IMPLIED // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL TOXICSOFTWARE.COM OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // The views and conclusions contained in the software and documentation are those of the // authors and should not be interpreted as representing official policies, either expressed // or implied, of toxicsoftware.com. #import "CXMLDocument.h" @interface CXMLDocument (CXMLDocument_CreationExtensions) //- (void)setVersion:(NSString *)version; //primitive //- (void)setStandalone:(BOOL)standalone; //primitive //- (void)setDocumentContentKind:(CXMLDocumentContentKind)kind; //primitive //- (void)setMIMEType:(NSString *)MIMEType; //primitive //- (void)setDTD:(CXMLDTD *)documentTypeDeclaration; //primitive //- (void)setRootElement:(CXMLNode *)root; - (void)insertChild:(CXMLNode *)child atIndex:(NSUInteger)index; //- (void)insertChildren:(NSArray *)children atIndex:(NSUInteger)index; //- (void)removeChildAtIndex:(NSUInteger)index; //primitive //- (void)setChildren:(NSArray *)children; //primitive - (void)addChild:(CXMLNode *)child; //- (void)replaceChildAtIndex:(NSUInteger)index withNode:(CXMLNode *)node; @end External/TouchXML/Source/Creation/CXMLDocument_CreationExtensions.m000066400000000000000000000043031247122470700256410ustar00rootroot00000000000000// // CXMLDocument_CreationExtensions.m // TouchCode // // Created by Jonathan Wight on 11/11/08. // Copyright 2011 toxicsoftware.com. All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, are // permitted provided that the following conditions are met: // // 1. Redistributions of source code must retain the above copyright notice, this list of // conditions and the following disclaimer. // // 2. Redistributions in binary form must reproduce the above copyright notice, this list // of conditions and the following disclaimer in the documentation and/or other materials // provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY TOXICSOFTWARE.COM ``AS IS'' AND ANY EXPRESS OR IMPLIED // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL TOXICSOFTWARE.COM OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // The views and conclusions contained in the software and documentation are those of the // authors and should not be interpreted as representing official policies, either expressed // or implied, of toxicsoftware.com. #import "CXMLDocument_CreationExtensions.h" #import "CXMLElement.h" #import "CXMLNode_PrivateExtensions.h" #import "CXMLDocument_PrivateExtensions.h" @implementation CXMLDocument (CXMLDocument_CreationExtensions) - (void)insertChild:(CXMLNode *)child atIndex:(NSUInteger)index { [self.nodePool addObject:child]; CXMLNode *theCurrentNode = (self.children)[index]; xmlAddPrevSibling(theCurrentNode->_node, child->_node); } - (void)addChild:(CXMLNode *)child { [self.nodePool addObject:child]; xmlAddChild(self->_node, child->_node); } @end External/TouchXML/Source/Creation/CXMLNode_CreationExtensions.h000066400000000000000000000054041247122470700247460ustar00rootroot00000000000000// // CXMLNode_CreationExtensions.h // TouchCode // // Created by Jonathan Wight on 04/01/08. // Copyright 2011 toxicsoftware.com. All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, are // permitted provided that the following conditions are met: // // 1. Redistributions of source code must retain the above copyright notice, this list of // conditions and the following disclaimer. // // 2. Redistributions in binary form must reproduce the above copyright notice, this list // of conditions and the following disclaimer in the documentation and/or other materials // provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY TOXICSOFTWARE.COM ``AS IS'' AND ANY EXPRESS OR IMPLIED // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL TOXICSOFTWARE.COM OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // The views and conclusions contained in the software and documentation are those of the // authors and should not be interpreted as representing official policies, either expressed // or implied, of toxicsoftware.com. #import "CXMLNode.h" @class CXMLElement; @interface CXMLNode (CXMLNode_CreationExtensions) //- (id)initWithKind:(NSXMLNodeKind)kind; //- (id)initWithKind:(NSXMLNodeKind)kind options:(NSUInteger)options; //primitive + (id)document; + (id)documentWithRootElement:(CXMLElement *)element; + (id)elementWithName:(NSString *)name; + (id)elementWithName:(NSString *)name URI:(NSString *)URI; + (id)elementWithName:(NSString *)name stringValue:(NSString *)string; //+ (id)elementWithName:(NSString *)name children:(NSArray *)children attributes:(NSArray *)attributes; //+ (id)attributeWithName:(NSString *)name stringValue:(NSString *)stringValue; //+ (id)attributeWithName:(NSString *)name URI:(NSString *)URI stringValue:(NSString *)stringValue; + (id)namespaceWithName:(NSString *)name stringValue:(NSString *)stringValue; + (id)processingInstructionWithName:(NSString *)name stringValue:(NSString *)stringValue; //+ (id)commentWithStringValue:(NSString *)stringValue; //+ (id)textWithStringValue:(NSString *)stringValue; //+ (id)DTDNodeWithXMLString:(NSString *)string; - (void)setStringValue:(NSString *)inStringValue; @end External/TouchXML/Source/Creation/CXMLNode_CreationExtensions.m000066400000000000000000000104411247122470700247500ustar00rootroot00000000000000// // CXMLNode_CreationExtensions.m // TouchCode // // Created by Jonathan Wight on 04/01/08. // Copyright 2011 toxicsoftware.com. All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, are // permitted provided that the following conditions are met: // // 1. Redistributions of source code must retain the above copyright notice, this list of // conditions and the following disclaimer. // // 2. Redistributions in binary form must reproduce the above copyright notice, this list // of conditions and the following disclaimer in the documentation and/or other materials // provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY TOXICSOFTWARE.COM ``AS IS'' AND ANY EXPRESS OR IMPLIED // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL TOXICSOFTWARE.COM OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // The views and conclusions contained in the software and documentation are those of the // authors and should not be interpreted as representing official policies, either expressed // or implied, of toxicsoftware.com. #import "CXMLNode_CreationExtensions.h" #import "CXMLDocument.h" #import "CXMLElement.h" #import "CXMLNode_PrivateExtensions.h" #import "CXMLDocument_PrivateExtensions.h" #import "CXMLNamespaceNode.h" @implementation CXMLNode (CXMLNode_CreationExtensions) + (id)document; { xmlDocPtr theDocumentNode = xmlNewDoc((const xmlChar *)"1.0"); NSAssert(theDocumentNode != NULL, @"xmlNewDoc failed"); CXMLDocument *theDocument = [[CXMLDocument alloc] initWithLibXMLNode:(xmlNodePtr)theDocumentNode freeOnDealloc:NO]; return(theDocument); } + (id)documentWithRootElement:(CXMLElement *)element; { xmlDocPtr theDocumentNode = xmlNewDoc((const xmlChar *)"1.0"); NSAssert(theDocumentNode != NULL, @"xmlNewDoc failed"); xmlDocSetRootElement(theDocumentNode, element.node); CXMLDocument *theDocument = [[CXMLDocument alloc] initWithLibXMLNode:(xmlNodePtr)theDocumentNode freeOnDealloc:NO]; [theDocument.nodePool addObject:element]; return(theDocument); } + (id)elementWithName:(NSString *)name { xmlNodePtr theElementNode = xmlNewNode(NULL, (const xmlChar *)[name UTF8String]); CXMLElement *theElement = [[CXMLElement alloc] initWithLibXMLNode:(xmlNodePtr)theElementNode freeOnDealloc:NO]; return(theElement); } + (id)elementWithName:(NSString *)name URI:(NSString *)URI { xmlNodePtr theElementNode = xmlNewNode(NULL, (const xmlChar *)[name UTF8String]); xmlNsPtr theNSNode = xmlNewNs(theElementNode, (const xmlChar *)[URI UTF8String], NULL); theElementNode->ns = theNSNode; CXMLElement *theElement = [[CXMLElement alloc] initWithLibXMLNode:(xmlNodePtr)theElementNode freeOnDealloc:NO]; return(theElement); } + (id)elementWithName:(NSString *)name stringValue:(NSString *)string { xmlNodePtr theElementNode = xmlNewNode(NULL, (const xmlChar *)[name UTF8String]); CXMLElement *theElement = [[CXMLElement alloc] initWithLibXMLNode:(xmlNodePtr)theElementNode freeOnDealloc:NO]; theElement.stringValue = string; return(theElement); } + (id)namespaceWithName:(NSString *)name stringValue:(NSString *)stringValue { return [[CXMLNamespaceNode alloc] initWithPrefix:name URI:stringValue parentElement:nil]; } + (id)processingInstructionWithName:(NSString *)name stringValue:(NSString *)stringValue; { xmlNodePtr theNode = xmlNewPI((const xmlChar *)[name UTF8String], (const xmlChar *)[stringValue UTF8String]); NSAssert(theNode != NULL, @"xmlNewPI failed"); CXMLNode *theNodeObject = [[CXMLNode alloc] initWithLibXMLNode:theNode freeOnDealloc:NO]; return(theNodeObject); } - (void)setStringValue:(NSString *)inStringValue { NSAssert(_node->type == XML_TEXT_NODE, @"CNode setStringValue only implemented for text nodes"); xmlNodeSetContent(_node, (const xmlChar *)[inStringValue UTF8String]); } @end External/TouchXML/Source/Tidy/000077500000000000000000000000001247122470700164625ustar00rootroot00000000000000External/TouchXML/Source/Tidy/CTidy.h000066400000000000000000000045221247122470700176520ustar00rootroot00000000000000// // CTidy.h // TouchCode // // Created by Jonathan Wight on 03/07/08. // Copyright 2011 toxicsoftware.com. All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, are // permitted provided that the following conditions are met: // // 1. Redistributions of source code must retain the above copyright notice, this list of // conditions and the following disclaimer. // // 2. Redistributions in binary form must reproduce the above copyright notice, this list // of conditions and the following disclaimer in the documentation and/or other materials // provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY TOXICSOFTWARE.COM ``AS IS'' AND ANY EXPRESS OR IMPLIED // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL TOXICSOFTWARE.COM OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // The views and conclusions contained in the software and documentation are those of the // authors and should not be interpreted as representing official policies, either expressed // or implied, of toxicsoftware.com. #ifdef TOUCHXMLUSETIDY #import #include "tidy.h" #include "buffio.h" typedef enum { TidyFormat_HTML, TidyFormat_XML, TidyFormat_XHTML, } CTidyFormat; @interface CTidy : NSObject { } + (CTidy *)tidy; - (NSData *)tidyData:(NSData *)inData inputFormat:(CTidyFormat)inInputFormat outputFormat:(CTidyFormat)inOutputFormat encoding:(const char *)encoding diagnostics:(NSString **)outDiagnostics error:(NSError **)outError; - (NSString *)tidyString:(NSString *)inString inputFormat:(CTidyFormat)inInputFormat outputFormat:(CTidyFormat)inOutputFormat encoding:(const char *)encoding diagnostics:(NSString **)outDiagnostics error:(NSError **)outError; @end #endif /* TOUCHXMLUSETIDY */ External/TouchXML/Source/Tidy/CTidy.m000066400000000000000000000203131247122470700176530ustar00rootroot00000000000000// // CTidy.m // TouchCode // // Created by Jonathan Wight on 03/07/08. // Copyright 2011 toxicsoftware.com. All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, are // permitted provided that the following conditions are met: // // 1. Redistributions of source code must retain the above copyright notice, this list of // conditions and the following disclaimer. // // 2. Redistributions in binary form must reproduce the above copyright notice, this list // of conditions and the following disclaimer in the documentation and/or other materials // provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY TOXICSOFTWARE.COM ``AS IS'' AND ANY EXPRESS OR IMPLIED // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL TOXICSOFTWARE.COM OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // The views and conclusions contained in the software and documentation are those of the // authors and should not be interpreted as representing official policies, either expressed // or implied, of toxicsoftware.com. #ifdef TOUCHXMLUSETIDY #import "CTidy.h" @interface CTidy () @end #pragma mark - @implementation CTidy + (CTidy *)tidy { return([[[self alloc] init] autorelease]); } - (NSData *)tidyData:(NSData *)inData inputFormat:(CTidyFormat)inInputFormat outputFormat:(CTidyFormat)inOutputFormat encoding:(const char*)encoding diagnostics:(NSString **)outDiagnostics error:(NSError **)outError { TidyDoc theTidyDocument = tidyCreate(); int theResultCode = 0; // Set input format if input is XML (xhtml & html are the tidy 'default') if (inInputFormat == TidyFormat_XML) { theResultCode = tidyOptSetBool(theTidyDocument, TidyXmlTags, YES); NSAssert(theResultCode >= 0, @"tidyOptSetBool() should return 0"); } // Set output format TidyOptionId theOutputValue = TidyXmlOut; if (inOutputFormat == TidyFormat_HTML) theOutputValue = TidyHtmlOut; else if (inOutputFormat == TidyFormat_XHTML) theOutputValue = TidyXhtmlOut; theResultCode = tidyOptSetBool(theTidyDocument, theOutputValue, YES); NSAssert(theResultCode >= 0, @"tidyOptSetBool() should return 0"); // Force output even if errors found theResultCode = tidyOptSetBool(theTidyDocument, TidyForceOutput, YES); NSAssert(theResultCode >= 0, @"tidyOptSetBool() should return 0"); // Set encoding - same for input and output theResultCode = tidySetInCharEncoding(theTidyDocument, encoding) NSAssert(theResultCode >= 0, @"tidySetInCharEncoding() should return 0"); theResultCode = tidySetOutCharEncoding(theTidyDocument, encoding); NSAssert(theResultCode >= 0, @"tidySetOutCharEncoding() should return 0"); // Create an error buffer TidyBuffer theErrorBuffer; tidyBufInit(&theErrorBuffer); theResultCode = tidySetErrorBuffer(theTidyDocument, &theErrorBuffer); NSAssert(theResultCode >= 0, @"tidySetErrorBuffer() should return 0"); // ############################################################################# // Create an input buffer and copy input to it (TODO uses 2X memory == bad!) TidyBuffer theInputBuffer; tidyBufAlloc(&theInputBuffer, [inData length]); memcpy(theInputBuffer.bp, [inData bytes], [inData length]); theInputBuffer.size = [inData length]; // Parse the data. theResultCode = tidyParseBuffer(theTidyDocument, &theInputBuffer); if (theResultCode < 0) { if (outError) { NSDictionary *theUserInfo = [NSDictionary dictionaryWithObjectsAndKeys: [NSString stringWithUTF8String:(char *)theErrorBuffer.bp], NSLocalizedDescriptionKey, NULL]; *outError = [NSError errorWithDomain:@"TODO_DOMAIN" code:theResultCode userInfo:theUserInfo]; } return(NO); } // Clean up input buffer. tidyBufFree(&theInputBuffer); // Repair the data theResultCode = tidyCleanAndRepair(theTidyDocument); if (theResultCode < 0) { return(NULL); } //theResultCode = tidyRunDiagnostics(theTidyDocument); // TidyBuffer theOutputBuffer; tidyBufInit(&theOutputBuffer); theResultCode = tidySaveBuffer(theTidyDocument, &theOutputBuffer); if (theResultCode < 0) return(NULL); NSAssert(theOutputBuffer.bp != NULL, @"The buffer should not be null."); NSData *theOutput = [NSData dataWithBytes:theOutputBuffer.bp length:theOutputBuffer.size]; tidyBufFree(&theOutputBuffer); // if (outDiagnostics && theErrorBuffer.bp != NULL) { NSData *theErrorData = [NSData dataWithBytes:theErrorBuffer.bp length:theErrorBuffer.size]; *outDiagnostics = [[[NSString alloc] initWithData:theErrorData encoding:NSUTF8StringEncoding] autorelease]; } tidyBufFree(&theErrorBuffer); // ############################################################################# tidyRelease(theTidyDocument); return(theOutput); } - (NSString *)tidyString:(NSString *)inString inputFormat:(CTidyFormat)inInputFormat outputFormat:(CTidyFormat)inOutputFormat encoding:(const char*)encoding diagnostics:(NSString **)outDiagnostics error:(NSError **)outError { TidyDoc theTidyDocument = tidyCreate(); int theResultCode = 0; // Set input format if input is XML (xhtml & html are the tidy 'default') if (inInputFormat == TidyFormat_XML) { theResultCode = tidyOptSetBool(theTidyDocument, TidyXmlTags, YES); NSAssert(theResultCode >= 0, @"tidyOptSetBool() should return 0"); } // Set output format TidyOptionId theOutputValue = TidyXmlOut; if (inOutputFormat == TidyFormat_HTML) theOutputValue = TidyHtmlOut; else if (inOutputFormat == TidyFormat_XHTML) theOutputValue = TidyXhtmlOut; theResultCode = tidyOptSetBool(theTidyDocument, theOutputValue, YES); NSAssert(theResultCode >= 0, @"tidyOptSetBool() should return 0"); // Force output even if errors found theResultCode = tidyOptSetBool(theTidyDocument, TidyForceOutput, YES); NSAssert(theResultCode >= 0, @"tidyOptSetBool() should return 0"); // Set encoding - same for input and output theResultCode = tidySetInCharEncoding(theTidyDocument, encoding) NSAssert(theResultCode >= 0, @"tidySetInCharEncoding() should return 0"); theResultCode = tidySetOutCharEncoding(theTidyDocument, encoding); NSAssert(theResultCode >= 0, @"tidySetOutCharEncoding() should return 0"); // Create an error buffer TidyBuffer theErrorBuffer; tidyBufInit(&theErrorBuffer); theResultCode = tidySetErrorBuffer(theTidyDocument, &theErrorBuffer); NSAssert(theResultCode >= 0, @"tidySetErrorBuffer() should return 0"); // ############################################################################# // Parse the data. theResultCode = tidyParseString(theTidyDocument, [inString UTF8String]); if (theResultCode < 0) { if (outError) { NSDictionary *theUserInfo = [NSDictionary dictionaryWithObjectsAndKeys: [NSString stringWithUTF8String:(char *)theErrorBuffer.bp], NSLocalizedDescriptionKey, NULL]; *outError = [NSError errorWithDomain:@"TODO_DOMAIN" code:theResultCode userInfo:theUserInfo]; } return(NO); } // Repair the data theResultCode = tidyCleanAndRepair(theTidyDocument); if (theResultCode < 0) { return(NULL); } //theResultCode = tidyRunDiagnostics(theTidyDocument); // uint theBufferLength = 0; theResultCode = tidySaveString(theTidyDocument, NULL, &theBufferLength); NSMutableData *theOutputBuffer = [NSMutableData dataWithLength:theBufferLength]; theResultCode = tidySaveString(theTidyDocument, [theOutputBuffer mutableBytes], &theBufferLength); NSString *theString = [[[NSString alloc] initWithData:theOutputBuffer encoding:NSUTF8StringEncoding] autorelease]; // if (outDiagnostics && theErrorBuffer.bp != NULL) { NSData *theErrorData = [NSData dataWithBytes:theErrorBuffer.bp length:theErrorBuffer.size]; *outDiagnostics = [[[NSString alloc] initWithData:theErrorData encoding:NSUTF8StringEncoding] autorelease]; } tidyBufFree(&theErrorBuffer); // ############################################################################# tidyRelease(theTidyDocument); return(theString); } @end #endif /* TOUCHXMLUSETIDY */ External/TouchXML/Source/TouchXML.h000066400000000000000000000036431247122470700173730ustar00rootroot00000000000000// // TouchXML.h // TouchCode // // Created by Jonathan Wight on 07/11/08. // Copyright 2011 toxicsoftware.com. All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, are // permitted provided that the following conditions are met: // // 1. Redistributions of source code must retain the above copyright notice, this list of // conditions and the following disclaimer. // // 2. Redistributions in binary form must reproduce the above copyright notice, this list // of conditions and the following disclaimer in the documentation and/or other materials // provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY TOXICSOFTWARE.COM ``AS IS'' AND ANY EXPRESS OR IMPLIED // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL TOXICSOFTWARE.COM OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // The views and conclusions contained in the software and documentation are those of the // authors and should not be interpreted as representing official policies, either expressed // or implied, of toxicsoftware.com. #import "CXMLDocument.h" #import "CXMLDocument_CreationExtensions.h" #import "CXMLElement.h" #import "CXMLElement_CreationExtensions.h" #import "CXMLElement_ElementTreeExtensions.h" #import "CXMLNode.h" #import "CXMLNode_CreationExtensions.h" #import "CXMLNode_XPathExtensions.h" Headers/000077500000000000000000000000001247122470700124375ustar00rootroot00000000000000Headers/Internal/000077500000000000000000000000001247122470700142135ustar00rootroot00000000000000Headers/Internal/MLMovieInfoGrabber.h000066400000000000000000000037751247122470700200110ustar00rootroot00000000000000/***************************************************************************** * MLMovieInfoGrabber.h * Lunettes ***************************************************************************** * Copyright (C) 2010 Pierre d'Herbemont * Copyright (C) 2010-2013 VLC authors and VideoLAN * $Id$ * * Authors: Pierre d'Herbemont * * 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.1 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 Lesser 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ @protocol MLMovieInfoGrabberDelegate; @interface MLMovieInfoGrabber : NSObject { NSURLConnection *_connection; NSMutableData *_data; NSArray *_results; id __weak _delegate; #if HAVE_BLOCK void (^_block)(NSError *); #else id _userData; #endif } @property (readwrite, weak) id delegate; #if !HAVE_BLOCK @property (readwrite, strong) id userData; #endif @property (readonly, strong) NSArray *results; - (void)lookUpForTitle:(NSString *)title; #if HAVE_BLOCK - (void)lookUpForTitle:(NSString *)title andExecuteBlock:(void (^)(NSError *))block; #endif @end @protocol MLMovieInfoGrabberDelegate @optional - (void)movieInfoGrabber:(MLMovieInfoGrabber *)grabber didFailWithError:(NSError *)error; - (void)movieInfoGrabberDidFinishGrabbing:(MLMovieInfoGrabber *)grabber; @end Headers/Internal/MLTVShowEpisodesInfoGrabber.h000066400000000000000000000042331247122470700216060ustar00rootroot00000000000000/***************************************************************************** * MLTVShowEpisodesInfoGrabber.h * Lunettes ***************************************************************************** * Copyright (C) 2010 Pierre d'Herbemont * Copyright (C) 2010-2013 VLC authors and VideoLAN * $Id$ * * Authors: Pierre d'Herbemont * * 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.1 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 Lesser 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ @class MLURLConnection; @protocol MLTVShowEpisodesInfoGrabberDelegate; @interface MLTVShowEpisodesInfoGrabber : NSObject { MLURLConnection *_connection; NSDictionary *_results; NSArray *_episodesResults; id __weak _delegate; void (^_block)(); #if !HAVE_BLOCK id _userData; #endif } @property (readwrite, weak) id delegate; @property (readonly, strong) NSArray *episodesResults; @property (readonly, strong) NSDictionary *results; #if !HAVE_BLOCK @property (readwrite, strong) id userData; #endif - (void)lookUpForShowID:(NSString *)id; #if HAVE_BLOCK - (void)lookUpForShowID:(NSString *)id andExecuteBlock:(void (^)())block; #endif @end @protocol MLTVShowEpisodesInfoGrabberDelegate @optional - (void)tvShowEpisodesInfoGrabber:(MLTVShowEpisodesInfoGrabber *)grabber didFailWithError:(NSError *)error; - (void)tvShowEpisodesInfoGrabberDidFinishGrabbing:(MLTVShowEpisodesInfoGrabber *)grabber; @end Headers/Internal/MLTVShowInfoGrabber.h000066400000000000000000000047211247122470700201140ustar00rootroot00000000000000/***************************************************************************** * MLTVShowInfoGrabber.h * Lunettes ***************************************************************************** * Copyright (C) 2010 Pierre d'Herbemont * Copyright (C) 2010-2013 VLC authors and VideoLAN * $Id$ * * Authors: Pierre d'Herbemont * * 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.1 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 Lesser 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ @protocol MLTVShowInfoGrabberDelegate; @interface MLTVShowInfoGrabber : NSObject { NSURLConnection *_connection; NSMutableData *_data; NSArray *_results; void (^_block)(); id __weak _delegate; #if !HAVE_BLOCK id _userData; #endif } @property (readwrite, weak) id delegate; @property (readonly, strong) NSArray *results; #if !HAVE_BLOCK @property (readwrite, strong) id userData; #endif - (void)lookUpForTitle:(NSString *)title; #if HAVE_BLOCK - (void)lookUpForTitle:(NSString *)title andExecuteBlock:(void (^)())block; #endif #if HAVE_BLOCK + (void)fetchServerTimeAndExecuteBlock:(void (^)(NSNumber *))block; + (void)fetchUpdatesSinceServerTime:(NSNumber *)serverTime andExecuteBlock:(void (^)(NSArray *))block; #else - (void)fetchUpdatesSinceServerTime:(NSNumber *)serverTime; - (void)fetchServerTime; + (NSNumber *)serverTime; #endif @end @protocol MLTVShowInfoGrabberDelegate @required - (void)tvShowInfoGrabber:(MLTVShowInfoGrabber *)grabber didFailWithError:(NSError *)error; - (void)tvShowInfoGrabberDidFinishGrabbing:(MLTVShowInfoGrabber *)grabber; - (void)tvShowInfoGrabberDidFetchServerTime:(MLTVShowInfoGrabber *)grabber; - (void)tvShowInfoGrabber:(MLTVShowInfoGrabber *)grabber didFetchUpdates:(NSArray *)updates; @end Headers/Internal/MLTitleDecrapifier.h000066400000000000000000000026741247122470700200450ustar00rootroot00000000000000/***************************************************************************** * MLTitleDecrapifier.h * Lunettes ***************************************************************************** * Copyright (C) 2010 Pierre d'Herbemont * Copyright (C) 2010-2013 VLC authors and VideoLAN * $Id$ * * Authors: Pierre d'Herbemont * * 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.1 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 Lesser 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ #import "MLFile.h" @interface MLTitleDecrapifier : NSObject + (NSString *)decrapify:(NSString *)string; + (BOOL)isTVShowEpisodeTitle:(NSString *)string; + (NSDictionary *)tvShowEpisodeInfoFromString:(NSString *)string; + (NSDictionary *)audioContentInfoFromFile:(MLFile *)file; @end Headers/Internal/MLURLConnection.h000066400000000000000000000042451247122470700173040ustar00rootroot00000000000000/***************************************************************************** * MLURLConnection.h * MobileMediaLibraryKit ***************************************************************************** * Copyright (C) 2010 Pierre d'Herbemont * Copyright (C) 2010-2013 VLC authors and VideoLAN * $Id$ * * Authors: Pierre d'Herbemont * * 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.1 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 Lesser 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ @protocol MLURLConnectionDelegate; @class MLURLConnection; @interface MLURLConnection : NSObject { NSMutableData *_data; NSURLConnection *_connection; id _delegate; id _userObject; #if HAVE_BLOCK void (^_block)(MLURLConnection *connection, NSError *error); #endif } @property (readonly, strong) NSData *data; @property (readwrite, strong) id userObject; @property (readwrite, strong) id delegate; #if HAVE_BLOCK + (id)runConnectionWithURL:(NSURL *)url andBlock:(void (^)(MLURLConnection *connection, NSError *error))block; - (void)loadURL:(NSURL *)url andPerformBlock:(void (^)(MLURLConnection *connection, NSError *error))block; #else + (id)runConnectionWithURL:(NSURL *)url delegate:(id)delegate userObject:(id)userObject; - (void)loadURL:(NSURL *)url; #endif - (void)cancel; @end @protocol MLURLConnectionDelegate - (void)urlConnection:(MLURLConnection *)connection didFinishWithError:(NSError *)error; @end Headers/Internal/NSXMLNode_Additions.h000066400000000000000000000024761247122470700201020ustar00rootroot00000000000000/***************************************************************************** * CXMLNode_Additions.h * MobileMediaLibraryKit ***************************************************************************** * Copyright (C) 2010 Pierre d'Herbemont * Copyright (C) 2010-2013 VLC authors and VideoLAN * $Id$ * * Authors: Pierre d'Herbemont * * 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.1 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 Lesser 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ @interface NSXMLNode (MLAdditions) - (NSString *)stringValueForXPath:(NSString *)string; - (NSNumber *)numberValueForXPath:(NSString *)string; @end Headers/Internal/TheTVDBGrabber.h000066400000000000000000000036121247122470700170530ustar00rootroot00000000000000/***************************************************************************** * TheTVDBGrabber.h * Lunettes ***************************************************************************** * Copyright (C) 2010 Pierre d'Herbemont * Copyright (C) 2010-2013 VLC authors and VideoLAN * $Id$ * * Authors: Pierre d'Herbemont * * 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.1 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 Lesser 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ #define TVDB_DEFAULT_LANGUAGE "en" #define TVDB_HOSTNAME "thetvdb.com" #define TVDB_IMAGES_HOSTNAME "thetvdb.com" #define TVDB_API_KEY "EACB874D8C2A90E2" /* See http://thetvdb.com/wiki/index.php?title=Programmers_API */ #define TVDB_QUERY_SEARCH @"http://%s/api/GetSeries.php?seriesname=%@" #define TVDB_QUERY_SEARCH_NEW @"http://%s/api/GetSeriesNew.php?seriesname=%@" #define TVDB_QUERY_SERVER_TIME @"http://%s/api/Updates.php?type=none" #define TVDB_QUERY_UPDATES @"http://%s/api/Updates.php?type=all&time=%@" #define TVDB_QUERY_INFO @"http://%s/api/%s/series/%@/%s.xml" #define TVDB_QUERY_EPISODE_INFO @"http://%s/api/%s/series/%@/all/%s.xml" #define TVDB_COVERS_URL @"http://%s/banners/%@" Headers/Public/000077500000000000000000000000001247122470700136555ustar00rootroot00000000000000Headers/Public/MLAlbum.h000066400000000000000000000036131247122470700153220ustar00rootroot00000000000000/***************************************************************************** * MLAlbum.h ***************************************************************************** * Copyright (C) 2010 Pierre d'Herbemont * Copyright (C) 2013 Felix Paul Kühne * $Id$ * * Authors: Pierre d'Herbemont * Felix Paul Kühne * * 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.1 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 Lesser 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ @class MLAlbumTrack; @interface MLAlbum : NSManagedObject + (NSArray *)allAlbums; + (MLAlbum *)albumWithName:(NSString *)name; @property (nonatomic, strong) NSString *name; @property (nonatomic, strong) NSString *releaseYear; @property (nonatomic, strong) NSSet *tracks; @property (nonatomic, strong, readonly) NSSet *unreadTracks; @property (weak, nonatomic, readonly) NSArray *sortedTracks; - (void)removeTrack:(MLAlbumTrack *)track; - (void)removeTrackWithNumber:(NSNumber *)trackNumber; @end @interface MLAlbum (CoreDataGeneratedAccessors) - (void)addTracksObject:(NSManagedObject *)value; - (void)removeTracksObject:(NSManagedObject *)value; - (void)addTracks:(NSSet *)value; - (void)removeTracks:(NSSet *)value; @end Headers/Public/MLAlbumTrack.h000066400000000000000000000041371247122470700163110ustar00rootroot00000000000000/***************************************************************************** * MLAlbumTrack.h ***************************************************************************** * Copyright (C) 2010 Pierre d'Herbemont * Copyright (C) 2013 Felix Paul Kühne * $Id$ * * Authors: Pierre d'Herbemont * Felix Paul Kühne * * 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.1 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 Lesser 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ #import "MLAlbum.h" @interface MLAlbumTrack : NSManagedObject + (NSArray *)allTracks; + (MLAlbumTrack *)trackWithAlbum:(id)album trackNumber:(NSNumber *)trackNumber createIfNeeded:(BOOL)createIfNeeded; + (MLAlbumTrack *)trackWithAlbumName:(NSString *)albumName trackNumber:(NSNumber *)trackNumber createIfNeeded:(BOOL)createIfNeeded wasCreated:(BOOL *)wasCreated; @property (nonatomic, strong) NSNumber *unread; @property (nonatomic, strong) NSString *artist; @property (nonatomic, strong) NSString *genre; @property (nonatomic, strong) NSString *title; @property (nonatomic, strong) NSNumber *trackNumber; @property (nonatomic, strong) MLAlbum *album; @property (nonatomic, strong) NSSet *files; @end @interface MLAlbumTrack (CoreDataGeneratedAccessors) - (void)addFilesObject:(NSManagedObject *)value; - (void)removeFilesObject:(NSManagedObject *)value; - (void)addFiles:(NSSet *)value; - (void)removeFiles:(NSSet *)value; @end Headers/Public/MLFile.h000066400000000000000000000104221247122470700151350ustar00rootroot00000000000000/***************************************************************************** * MLFile.h * Lunettes ***************************************************************************** * Copyright (C) 2010 Pierre d'Herbemont * Copyright (C) 2010-2013 VLC authors and VideoLAN * $Id$ * * Authors: Pierre d'Herbemont * Felix Paul Kühne * * 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.1 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 Lesser 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ #import @class MLShowEpisode; @class MLAlbumTrack; extern NSString *kMLFileTypeMovie; extern NSString *kMLFileTypeClip; extern NSString *kMLFileTypeTVShowEpisode; extern NSString *kMLFileTypeAudio; @interface MLFile : NSManagedObject + (NSArray *)allFiles; + (NSArray *)fileForURL:(NSString *)url; - (BOOL)isKindOfType:(NSString *)type; - (BOOL)isMovie; - (BOOL)isClip; - (BOOL)isShowEpisode; - (BOOL)isAlbumTrack; - (BOOL)isSupportedAudioFile; @property (nonatomic, strong) NSNumber *seasonNumber; @property (nonatomic, strong) NSNumber *remainingTime; @property (nonatomic, strong) NSString *releaseYear; @property (nonatomic, strong) NSNumber *lastPosition; @property (nonatomic, strong) NSNumber *lastSubtitleTrack; @property (nonatomic, strong) NSNumber *lastAudioTrack; @property (nonatomic, strong) NSNumber *playCount; @property (nonatomic, strong) NSString *artworkURL; @property (nonatomic, strong) NSString *url; @property (nonatomic, strong) NSString *type; @property (nonatomic, strong) NSString *title; @property (nonatomic, strong) NSString *shortSummary; @property (nonatomic, strong) NSNumber *currentlyWatching; @property (nonatomic, strong) NSNumber *episodeNumber; @property (nonatomic, strong) NSNumber *unread; @property (nonatomic, strong) NSNumber *hasFetchedInfo; @property (nonatomic, strong) NSNumber *noOnlineMetaData; @property (nonatomic, strong) MLShowEpisode *showEpisode; @property (nonatomic, strong) NSSet *labels; @property (nonatomic, strong) NSSet *tracks; @property (nonatomic, strong) NSNumber *isOnDisk; @property (nonatomic, strong) NSNumber *duration; @property (nonatomic, strong) NSString *artist; @property (nonatomic, strong) NSString *album; @property (nonatomic, strong) NSNumber *albumTrackNumber; @property (nonatomic, strong) NSNumber *folderTrackNumber; @property (nonatomic, strong) NSString *genre; @property (nonatomic, strong) MLAlbumTrack *albumTrack; @property (nonatomic, strong) UIImage *computedThumbnail; @property (nonatomic, assign) BOOL isSafe; @property (nonatomic, assign) BOOL isBeingParsed; @property (nonatomic, assign) BOOL thumbnailTimeouted; /** * the data in this object are about to be put on screen * * If multiple MLFile object are processed, this * increase the priority of the processing for this MLFile. */ - (void)willDisplay; /** * We don't display the data of this object on screen. * * This put back the eventually increased priority for this MLFile, * to a default one. * \see willDisplay */ - (void)didHide; /** * do not rely on this path unless you are a MLKit object */ - (NSString *)thumbnailPath; /** * Shortcuts to the videoTracks. */ - (NSManagedObject *)videoTrack; - (size_t)fileSizeInBytes; @end @interface MLFile (CoreDataGeneratedAccessors) - (void)addLabelsObject:(NSManagedObject *)value; - (void)removeLabelsObject:(NSManagedObject *)value; - (void)addLabels:(NSSet *)value; - (void)removeLabels:(NSSet *)value; - (void)addTracksObject:(NSManagedObject *)value; - (void)removeTracksObject:(NSManagedObject *)value; - (void)addTracks:(NSSet *)value; - (void)removeTracks:(NSSet *)value; @end Headers/Public/MLLabel.h000066400000000000000000000032131247122470700152750ustar00rootroot00000000000000/***************************************************************************** * MLLabel.h * Lunettes ***************************************************************************** * Copyright (C) 2010 Pierre d'Herbemont * Copyright (C) 2010-2013 VLC authors and VideoLAN * $Id$ * * Authors: Pierre d'Herbemont * Felix Paul Kühne * * 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.1 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 Lesser 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ #import @class MLFile; @interface MLLabel : NSManagedObject + (NSArray *)allLabels; - (NSArray *)sortedFolderItems; @property (nonatomic, strong) NSString * name; @property (nonatomic, strong) NSSet* files; @end @interface MLLabel (CoreDataGeneratedAccessors) - (void)addFilesObject:(MLFile *)value; - (void)removeFilesObject:(MLFile *)value; - (void)addFiles:(NSSet *)value; - (void)removeFiles:(NSSet *)value; @end Headers/Public/MLMediaLibrary.h000066400000000000000000000040451247122470700166260ustar00rootroot00000000000000/***************************************************************************** * MLMediaLibrary.h * MobileMediaLibraryKit ***************************************************************************** * Copyright (C) 2010 Pierre d'Herbemont * Copyright (C) 2010-2014 VLC authors and VideoLAN * $Id$ * * Authors: Pierre d'Herbemont * * 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.1 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 Lesser 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ #import @interface MLMediaLibrary : NSObject @property (readonly) BOOL libraryNeedsUpgrade; @property (nonatomic, strong) id delegate; @property (nonatomic, strong) NSURL *persistentStoreURL; @property (nonatomic, strong) NSPersistentStoreCoordinator *persistentStoreCoordinator; + (id)sharedMediaLibrary; - (void)addFilePaths:(NSArray *)filepaths; - (void)upgradeLibrary; - (void)updateMediaDatabase; // May be internal - (NSFetchRequest *)fetchRequestForEntity:(NSString *)entity; - (id)createObjectForEntity:(NSString *)entity; - (void)removeObject:(NSManagedObject *)object; - (NSString *)thumbnailFolderPath; - (NSString *)documentFolderPath; - (void)applicationWillStart; - (void)applicationWillExit; - (void)save; - (void)libraryDidDisappear; - (void)libraryDidAppear; @end @protocol MLMediaLibrary @optional - (void)libraryUpgradeComplete; @endHeaders/Public/MLShow.h000066400000000000000000000043201247122470700151760ustar00rootroot00000000000000/***************************************************************************** * MLShow.h * Lunettes ***************************************************************************** * Copyright (C) 2010 Pierre d'Herbemont * Copyright (C) 2010-2013 VLC authors and VideoLAN * $Id$ * * Authors: Pierre d'Herbemont * * 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.1 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 Lesser 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ #import @class MLShowEpisode; @interface MLShow : NSManagedObject + (NSArray *)allShows; + (MLShow *)showWithName:(NSString *)name; @property (nonatomic, strong) NSString *theTVDBID; @property (nonatomic, strong) NSString *shortSummary; @property (nonatomic, strong) NSString *artworkURL; @property (nonatomic, strong) NSString *name; @property (nonatomic, strong) NSString *releaseYear; @property (nonatomic, strong) NSNumber *lastSyncDate; @property (nonatomic, strong) NSSet *episodes; @property (weak, nonatomic, readonly) NSArray *sortedEpisodes; @property (nonatomic, strong, readonly) NSSet *unreadEpisodes; - (void)addEpisode:(MLShowEpisode*)episode; - (void)removeEpisode:(MLShowEpisode*)episode; - (void)removeEpisodeWithSeasonNumber:(NSNumber *)seasonNumber andEpisodeNumber:(NSNumber *)episodeNumber; @end @interface MLShow (CoreDataGeneratedAccessors) - (void)addEpisodesObject:(NSManagedObject *)value; - (void)removeEpisodesObject:(NSManagedObject *)value; - (void)addEpisodes:(NSSet *)value; - (void)removeEpisodes:(NSSet *)value; @end Headers/Public/MLShowEpisode.h000066400000000000000000000047421247122470700165170ustar00rootroot00000000000000/***************************************************************************** * MLShowEpisode.h * Lunettes ***************************************************************************** * Copyright (C) 2010 Pierre d'Herbemont * Copyright (C) 2010-2013 VLC authors and VideoLAN * $Id$ * * Authors: Pierre d'Herbemont * * 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.1 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 Lesser 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ #import @class MLShow; @interface MLShowEpisode : NSManagedObject + (NSArray *)allEpisodes; // This will eventually create the show + (MLShowEpisode *)episodeWithShow:(MLShow *)show episodeNumber:(NSNumber *)episodeNumber seasonNumber:(NSNumber *)seasonNumber createIfNeeded:(BOOL)createIfNeeded; + (MLShowEpisode *)episodeWithShowName:(NSString *)showName episodeNumber:(NSNumber *)episodeNumber seasonNumber:(NSNumber *)seasonNumber createIfNeeded:(BOOL)createIfNeeded wasCreated:(BOOL *)wasCreated; @property (nonatomic, strong) NSNumber *unread; @property (nonatomic, strong) NSString *theTVDBID; @property (nonatomic, strong) NSString *shortSummary; @property (nonatomic, strong) NSNumber *shouldBeDisplayed; @property (nonatomic, strong) NSNumber *episodeNumber; @property (nonatomic, strong) NSNumber *seasonNumber; @property (nonatomic, strong) NSNumber *lastSyncDate; @property (nonatomic, strong) NSString *artworkURL; @property (nonatomic, strong) NSString *name; @property (nonatomic, strong) MLShow *show; @property (nonatomic, strong) NSSet *files; @end @interface MLShowEpisode (CoreDataGeneratedAccessors) - (void)addFilesObject:(NSManagedObject *)value; - (void)removeFilesObject:(NSManagedObject *)value; - (void)addFiles:(NSSet *)value; - (void)removeFiles:(NSSet *)value; @end Headers/Public/MediaLibraryKit.h000066400000000000000000000027271247122470700170520ustar00rootroot00000000000000/***************************************************************************** * MediaLibraryKit ***************************************************************************** * Copyright (C) 2013 Felix Paul Kühne * * Authors: Felix Paul Kühne * * 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.1 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 Lesser 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ #import #import #import #import #import #import #import @class MLFile; @class MLLabel; @class MLMediaLibrary; @class MLShow; @class MLShowEpisode; @class MLAlbum; @class MLAlbumTrack; MediaLibrary.xcdatamodel/000077500000000000000000000000001247122470700157145ustar00rootroot00000000000000MediaLibrary.xcdatamodel/elements000066400000000000000000007661561247122470700175000ustar00rootroot00000000000000bplist00^^X$versionX$objectsY$archiverT$topn456NOPQRSTUVWrstz{q  $39:BQR[uvwxyz{|}~'6EQcdefghijyz+:IM\kz.';JYhwz      !"#$%&;<DPds +:TU[g{%1ETcrv ,;J_`ht   " 1 @ O ^ m |  ) 8 < K Z i x   % & . : N ] l {    $ 3 B Q f g o {  ) 8 G V e t u  />MYkz"1@DSbq,-5AUds +:IXmnv0?N]lm| '6ET`r(7FJYhw 12:FZix!0?N]rs{#5DSbq  +:IXdv ,;JN]l{!67?K_n}&5DSbwx (:IJYhw"1@O^j|#2APTcr '<=EQet   , ; J Y h } ~ !!!"!.!@!O!P!_!n!}!!!!!!!!!""""("7"F"U"d"p""""""""### ##)#8#G#V#Z#i#x#########$$$ $,$@$O$R$a$p$$$$$$$$$$$$$$$$$$$%%%)%8%G%K%Z%i%x%%%%%%%%%&&&2&3&;&G&[&j&y&&&&&&&&&'''"'1'@'O'^'s't'|'''''''''( (($(6(E(T(c(r(((((((((() ))),);)J)Y)e)w))))))))))* **-*<*K*O*^*m*|********++++!+5+D+G+V+e+t+w+++++++++++++++++, ,,*,9,=,L,[,j,y,,,,,,,,---$-%---9-M-\-k-z-~--------...#.2.A.P.e.f.n.z........./ //(/7/F/U/d/s////////////000,0;0G0M0N0]0f0g0h0l0t0w0000000001111"111@1O1^1j1|111111111222*2+232?2S2b2q22222222223 33)383G3V3k3l3t3333333334444.4=4L4[4j4y4444444445555$535B5Q5]5o5~555555555666%646C6G6V6e6t6666666667 77.7/777C7W7f7u7777777778888-8<8K8Z8o8p8x888888888999 929A9P9_9n9999999999:::::*:9:::B:C:D:Y:Z:b:n::::::::::; ;;+;:;I;X;g;v;;;;;;;;;;<<>>>$>3>B>Q>`>l>~>>>>>>>>>???%?4?C?R?V?e?t?????????@ @@(@,@-@3@:@T@U@[@g@{@@@@@@@@@@@@@AAA AAA'A3AGAVAeAtAxAAAAAAAAABBB,B;BJB_B`BhBtBBBBBBBBBCCC"C1C@COC^CmC|CCCCCCCCCCCD DD(D,D;DJDYDhDwDDDDDDDDDEEEE(EIMI\I`IoI~IIIIIIIIJJJ#J2JGJHJPJ\JpJJJJJJJJJJK KK(K7KFKUKdKsKKKKKKKKKKLLLL-L9LKLZLiLxLLLLLLLLLMMMM#M2MAMPM_MnMzMMMMMMMMN N NNN3NBNQN`NdNsNNNNNNNNNO O#O$O*O6OJOYOhOwOOOOOOOOOOOOOOOOOPPP$P3PBPQPUPdPsPPPPPPPPPQ QQ'Q?@AB DEFGHIJKLM5Ҁ,[ShowEpisodeUAlbumTShowTFile_TrackInformation_AudioTrackInformationZAlbumTrack_VideoTrackInformationULabelXYZ[\] ^_ "`a%bcd&&hi.&cl:copq_!XDBucketForOwnedAttributesordered_!XDBucketForOwnedAttributesstorage_ XDBucketForStereotypeswasEncoded_$XDBucketForOwnedAttributeswasEncoded_XDBucketForStereotypesstorage_$XDBucketForGeneralizationsduplicates_$XDBucketForGeneralizationswasEncoded_XDBucketForStereotypesordered_!XDBucketForGeneralizationsordered_!XDBucketForGeneralizationsstorage[_isAbstract4eBoWordered78 uwMvx,^XD_PStereotype"| %} b~Dvc&.q_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorage378 M!"#&(-1,_XDPMCompoundIndexes_XD_PSK_elementID_XD_PSK_versionHashModifier_XD_PSK_fetchRequestsArray_XD_PSK_isAbstract_XD_PSK_userInfo_XD_PSK_classMapping_XD_PSK_entityClassName "%xqqq.qqqqU_typeX_default\_association[_isReadOnlyY_isStaticY_isUniqueZ_isDerivedZ_isOrdered\_isCompositeW_isLeaf Z$classnameX$classes_XDUMLPropertyImp_XDUMLPropertyImp_XDUMLNamedElementImp_XDUMLElementImpXNSObject "%xqqq.qqqq  "%xqqq.qqqq  "%xqqq.qqqq$ 8 %^NSMutableArrayWNSArray "%xqqq.qqqq'  "% xqqq.qqqq) 78 M*+,_ com.apple.syncservices.DataClass_MediaLibraryFile!"_NSMutableDictionary!#\NSDictionary "%&xqqq.qqqq. " %b 45q./0_XDGenericRecordClass;<]XDUMLClassImp=>?@A]XDUMLClassImp_XDUMLClassifierImp_XDUMLNamespaceImp_XDUMLNamedElementImp_XDUMLElementImp "%Dxqqq.qqqq2 ]MLShowEpisodeST_XDUMLStereotypeImpUVWXYZ_XDUMLStereotypeImp]XDUMLClassImp_XDUMLClassifierImp_XDUMLNamespaceImp_XDUMLNamedElementImp_XDUMLElementImp78 \hM]^_`abcdefg56789:;<=>?ijklmnopqrs@l݁ "9  7N,VunreadUfiles\shortSummary_shouldBeDisplayed]episodeNumber\seasonNumberTshowZartworkURL\lastSyncDateTnameYtheTVDBID  "%&Dqq.qcq]qqq_ XDBucketForStereotypeswasEncoded_XDBucketForStereotypesstorage_XDBucketForStereotypesorderedBk5AI78 MCDEY,_XD_PPropStereotype_XD_PAtt_Stereotype" % bic&.q_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorage@C3F78 MGHIJKLMNOPQSTVWX,_XD_PPSK_isStoredInTruthFile_XD_PPSK_versionHashModifier_XD_PPSK_userInfo_XD_PPSK_isIndexed_XD_PPSK_isOptional_XD_PPSK_isSpotlightIndexed_XD_PPSK_elementID_XD_PPSK_isTransient "%qqq.qqqq'E G "%qqq.qqqqE H "%qqq.qqqqRE I78 M, "%qqq.qqqq'E J "% qqq.qqqqUE K  "%qqq.qqqq'E L "%qqq.qqqqE M "%qqq.qqqq'E N"F %G bHic&.qP_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorage@D3Z78 RZMSTUVWXY[\]^_`a[\]^_`abdefhij,_XD_PAttK_defaultValueAsString_(XD_PAttK_allowsExternalBinaryDataStorage_XD_PAttK_minValueString_XD_PAttK_attributeType_XD_PAttK_maxValueString_XD_PAttK_valueTransformerName_ XD_PAttK_regularExpressionString "%lqqq.qSqqqcY [RNO "%qqq.qTqqq'Y \ "%qqq.qUqqqY ] "%qqq.qVqqqgY ^  "%qqq.qWqqqY _ "%qqq.qXqqqY ` "%qqq.qYqqqY a]XDPMAttribute]XDPMAttribute\XDPMProperty_XDUMLPropertyImp_XDUMLNamedElementImp_XDUMLElementImp  "%&Dqq.qcq^qqq_ XDBucketForStereotypeswasEncoded_XDBucketForStereotypesstorage_XDBucketForStereotypesorderedn6mB"78 MCop{,_XD_PR_Stereotype" % bjc&.q_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstoragelC3q78  MGHIJKLMNrstvwxyz, "%qqq.qqqq'p G "%qqq.qqqqp H "%<qqq.qqqqup I78 JKM, "% qqq.qqqqUp J "% qqq.qqqqUp K "%qqq.qqqq'p L "%qqq.qqqqp M "%qqq.qqqq'p N" % bjc&.q_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstoragelo3|78 M}~ځہ܀,_XD_PRK_minCount_XD_PRK_deleteRule_XD_PRK_maxCount_XD_PRK_destination_XD_PRK_isToMany^XD_PRK_ordered_XD_PRK_inverseRelationship "%qqq.qqqq{ } "%qqq.qqqq{ ~ "%qqq.qqqq{  "%Gqqq.qqqq{   "%bc&& i.&cl=cq_!XDBucketForOwnedAttributesordered_!XDBucketForOwnedAttributesstorage_ XDBucketForStereotypeswasEncoded_$XDBucketForOwnedAttributeswasEncoded_XDBucketForStereotypesstorage_$XDBucketForGeneralizationsduplicates_$XDBucketForGeneralizationswasEncoded_XDBucketForStereotypesordered_!XDBucketForGeneralizationsordered_!XDBucketForGeneralizationsstorage ـ 78 Mv," % bGvc&.q&_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorage378 (1M23456789, "%qqq.qqqq  "%qqq.qqqq  "%qqq.qqqq  "%jqqq.qqqq 8 x% "%qqq.qqqq'  "%qqq.qqqq 78 M+,_com.apple.syncservices.Syncable_ com.apple.syncservices.DataClassRNO "%&qqq.qqqq.  "%qqq.qqqq VMLFile78 M 〞 5Ld|Áځ6Ne}Áہ"9Pg~}€,Vlabels\lastPositionUtitleSurl]episodeNumberXduration_noOnlineMetaData_lastParsingDate^hasFetchedInfo^lastAudioTrack\shortSummary\seasonNumber_lastSubtitleTrack[releaseYearZartworkURLTtype_thumbnailTimeoutedYplayCount_currentlyWatchingXisOnDiskVunreadZalbumTrack]remainingTime_albumTrackNumberVartist_folderTrackNumber[showEpisodeVtracksUgenreUalbum]isBeingParsedVisSafe'( ) "%&Gqq1.qcqqq9q_ XDBucketForStereotypeswasEncoded_XDBucketForStereotypesstorage_XDBucketForStereotypesorderedu78 =@MCoAB̀,"E %F bGc&.qO_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageC378 QZMGHIJKLMN[\]^_`abÀĀŀǀȀɀʀˀ, "%Aqqq.qqqq' G "%Aqqq.qqqq H "%Aqqq.qqqqƀ I78 M, "% Aqqq.qqqqU J "% Aqqq.qqqqU K "%Aqqq.qqqq' L "%Aqqq.qqqq M "%Aqqq.qqqq' N" % bc&.q_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageo378 M}~΀πЀс, "%Bqqq.qqqq } "%Bqqq.qqqq ~ "%Bqqq.qqqq  "%LBqqq.qqqqҀ ;<=>?@ AB "CD%bcF&&Ji.&clBcQRq_!XDBucketForOwnedAttributesordered_!XDBucketForOwnedAttributesstorage_ XDBucketForStereotypeswasEncoded_$XDBucketForOwnedAttributeswasEncoded_XDBucketForStereotypesstorage_$XDBucketForGeneralizationsduplicates_$XDBucketForGeneralizationswasEncoded_XDBucketForStereotypesordered_!XDBucketForGeneralizationsordered_!XDBucketForGeneralizationsstorageԁiJ78 VXMvYՀ,"\ %] b^Lvc&.qf_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageҀ378 hqMrstuvwxy׀؀ـڀ܀݀, "%Yqqq.qqqq  "%Yqqq.qqqq  "%Yqqq.qqqq  "%Yqqq.qqqqۀ 8 % "%Yqqq.qqqq'  "%Yqqq.qqqqހ 78 Mڀߡ+,_ com.apple.syncservices.DataClass "%&Yqqq.qqqq.  "%Yqqq.qqqq WMLLabel78 Mf>,Ufiles  "%&Lqq.qcqfqqq_ XDBucketForStereotypeswasEncoded_XDBucketForStereotypesstorage_XDBucketForStereotypesorderedk>ḁ78 !MCD"#,"& %' b(c&.q0_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageC378 2;MGHIJKLMN<=>?@ABC, "%"qqq.qqqq' G "%"qqq.qqqq H "%e"qqq.qqqq I78 stM, "%"qqq.qqqq' J "%"qqq.qqqq' K "%"qqq.qqqq' L "%"qqq.qqqq M "%"qqq.qqqq' N" % bc&.q_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageD378 MSTUVWXY[\]^_`a݀, "%#qqq.qSqqq [XUntitled "%#qqq.qTqqq' \ "%#qqq.qUqqq ] "%#qqq.qVqqq ^ "%#qqq.qWqqq _ "%#qqq.qXqqq ` "%#qqq.qYqqq aKL M "%&LqqU.qcqqq]q_ XDBucketForStereotypeswasEncoded_XDBucketForStereotypesstorage_XDBucketForStereotypesorderediJQ78 adMCoef ,"i %j bkc&.qs_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageC378 u~MGHIJKLMN   , "%eqqq.qqqq' G "%eqqq.qqqq H "%eqqq.qqqq I78 M, "% eqqq.qqqqU J "%eqqq.qqqq' K "%eqqq.qqqq' L "%eqqq.qqqq M "%eqqq.qqqq' N"  %  b c&.q _!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageo3 78  M}~       , "%fqqq.qqqq  } "%fqqq.qqqq  ~ "%fqqq.qqqq   "%Gfqqq.qqqq   "% fqqq.qqqqU   "%fqqq.qqqq'   "%fqqq.qqqq   _XDPMRelationship _XDPMRelationship\XDPMProperty_XDUMLPropertyImp_XDUMLNamedElementImp_XDUMLElementImpZduplicates8 % ZXDPMEntity ZXDPMEntity]XDUMLClassImp_XDUMLClassifierImp_XDUMLNamespaceImp_XDUMLNamedElementImp_XDUMLElementImp "% Bqqq.qqqqU  "%Bqqq.qqqq'  "%Bqqq.qqqq   "%&Gqq .qcqqq q_ XDBucketForStereotypeswasEncoded_XDBucketForStereotypesstorage_XDBucketForStereotypesorderedk78 MCD *," % b c&.q _!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageC3 78 MGHIJKLMN        !"#%&'(), "% qqq.qqqq' G "% qqq.qqqq H "% + qqq.qqqq$ I78 9 :M, "% qqq.qqqq' J "%  qqq.qqqqU K "% qqq.qqqq' L "% qqq.qqqq M "% qqq.qqqq' N" % b c&.q _!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageD3+78 MSTUVWXY[\]^_`a ,./0234, "%  qqq.qSqqq-* [Q0 "% qqq.qTqqq'* \ "% qqq.qUqqq* ] "%  qqq.qVqqq1* ^ "% qqq.qWqqq* _ "% qqq.qXqqq* ` "% qqq.qYqqq* a    "%&Gqq .qcqqq #q_ XDBucketForStereotypeswasEncoded_XDBucketForStereotypesstorage_XDBucketForStereotypesordered7k61,78 ' *MCD + ,8C," / % 0 b 1c&.q 9_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorage5C3978 ; DMGHIJKLMN E F G H I J K L:;<>?@AB, "% +qqq.qqqq'8 G "% +qqq.qqqq8 H "% n +qqq.qqqq=8 I78 | }M, "% +qqq.qqqq'8 J "%  +qqq.qqqqU8 K "% +qqq.qqqq'8 L "% +qqq.qqqq8 M "% +qqq.qqqq'8 N" % b c&.q _!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorage5D3D78 MSTUVWXY[\]^_`a EFGHIJK, "% ,qqq.qSqqqC [ "% ,qqq.qTqqq'C \ "% ,qqq.qUqqqC ] "% ,qqq.qVqqqC ^ "% ,qqq.qWqqqC _ "% ,qqq.qXqqqC ` "% ,qqq.qYqqqC a R S T "%&Gqq \.qcqqq dq_ XDBucketForStereotypeswasEncoded_XDBucketForStereotypesstorage_XDBucketForStereotypesorderedNkM{fK78 h kMCD l mOZ," p % q b rc&.q z_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageLC3P78 | MGHIJKLMN QRSUVWXY, "% lqqq.qqqq'O G "% lqqq.qqqqO H "%  lqqq.qqqqTO I78 M, "% lqqq.qqqq'O J "% lqqq.qqqq'O K "% lqqq.qqqq'O L "% lqqq.qqqqO M "% lqqq.qqqq'O N" % b c&.q _!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageLD3[78  MSTUVWXY[\]^_`a ! " # $ % & '\]^_`bc, "% mqqq.qSqqqZ [ "% mqqq.qTqqq'Z \ "% mqqq.qUqqqZ ] "% mqqq.qVqqqZ ^ "% g mqqq.qWqqqaZ _T1024 "% mqqq.qXqqqZ ` "% mqqq.qYqqqZ a  "%&Gqq .qcqqq q_ XDBucketForStereotypeswasEncoded_XDBucketForStereotypesstorage_XDBucketForStereotypesorderedfkeA$78 MCD gr," % b c&.q _!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstoragedC3h78 MGHIJKLMN ρijkmnopq, "% qqq.qqqq'g G "% qqq.qqqqg H "%  qqq.qqqqlg I78 M, "% qqq.qqqq'g J "%  qqq.qqqqUg K "% qqq.qqqq'g L "% qqq.qqqqg M "% qqq.qqqq'g N"N %O bPc&.qX_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstoragedD3s78 ZbMSTUVWXY[\]^_`acdefghituvwyz{, "%  qqq.qSqqq-r [ "% qqq.qTqqq'r \ "% qqq.qUqqqr ] "% qqq.qVqqqxr ^d "% qqq.qWqqqr _ "% qqq.qXqqqr ` "% qqq.qYqqqr a  "%&Gqq.qcqqqq_ XDBucketForStereotypeswasEncoded_XDBucketForStereotypesstorage_XDBucketForStereotypesordered~k}#78 MCD," % bc&.q_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorage|C378  MGHIJKLMN    , "%qqq.qqqq' G "%qqq.qqqq H "%3qqq.qqqq I78 ABM, "%qqq.qqqq' J "% qqq.qqqqU K "%qqq.qqqq' L "%qqq.qqqq M "%qqq.qqqq' N" % bc&.q_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorage|D378 MSTUVWXY[\]^_`a, "%qqq.qSqqq [ "%qqq.qTqqq' \ "%qqq.qUqqq ] "%qqq.qVqqq ^, "%qqq.qWqqq _ "%qqq.qXqqq ` "%qqq.qYqqq a  "%&Gqq".qcqqq*q_ XDBucketForStereotypeswasEncoded_XDBucketForStereotypesstorage_XDBucketForStereotypesorderedksW78 .1MCD23,"6 %7 b8c&.q@_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageC378 BKMGHIJKLMNLMNOPQRS, "%2qqq.qqqq' G "%2qqq.qqqq H "%u2qqq.qqqq I78 M, "%2qqq.qqqq' J "% 2qqq.qqqqU K "%2qqq.qqqq' L "%2qqq.qqqq M "%2qqq.qqqq' N" % bc&.q_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageD378 MSTUVWXY[\]^_`a, "%l3qqq.qSqqqc [ "%3qqq.qTqqq' \ "%3qqq.qUqqq ] "%3qqq.qVqqqg ^ "%3qqq.qWqqq _ "%3qqq.qXqqq ` "%3qqq.qYqqq aYZ [ "%&Gqqc.qcqqqkq_ XDBucketForStereotypeswasEncoded_XDBucketForStereotypesstorage_XDBucketForStereotypesorderedk H78 orMCDst,"w %x byc&.q_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageC378 MGHIJKLMN, "%sqqq.qqqq' G "%sqqq.qqqq H "%sqqq.qqqq I78 M, "%sqqq.qqqq' J "% sqqq.qqqqU K "%sqqq.qqqq' L "%sqqq.qqqq M "%sqqq.qqqq' N" % bc&.q_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageD378 'MSTUVWXY[\]^_`a()*+,-.€, "%tqqq.qSqqq [ "%tqqq.qTqqq' \ "%tqqq.qUqqq ] "%_tqqq.qVqqq ^ "%tqqq.qWqqq _ "%tqqq.qXqqq ` "%tqqq.qYqqq a  "%&Gqq.qcqqqq_ XDBucketForStereotypeswasEncoded_XDBucketForStereotypesstorage_XDBucketForStereotypesorderedkm#78 MCDƁр," % bc&.q_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageÀC378 MGHIJKLMNցȁɁʁ́́΁ρЀ, "%qqq.qqqq' G "%qqq.qqqq H "%qqq.qqqqˀ I78 M, "% qqq.qqqqU J "% qqq.qqqqU K "%qqq.qqqq' L "%qqq.qqqq M "%qqq.qqqq' N"U %V bWc&.q__!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageÀD378 aiMSTUVWXY[\]^_`ajklmnopӁԁՁցׁ؁ـ, "%lqqq.qSqqqc [ "%qqq.qTqqq' \ "%qqq.qUqqq ] "%qqq.qVqqqg ^ "%qqq.qWqqq _ "%qqq.qXqqq ` "%qqq.qYqqq a  "%&Gqq.qcqqqq_ XDBucketForStereotypeswasEncoded_XDBucketForStereotypesstorage_XDBucketForStereotypesorderedkq78 MCD݁," % bc&.q_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageڀC378 MGHIJKLMN߁, "%qqq.qqqq' G "%qqq.qqqq H "%9qqq.qqqq I78 GHM, "%qqq.qqqq' J "% qqq.qqqqU K "%qqq.qqqq' L "%qqq.qqqq M "%qqq.qqqq' N" % bc&.q_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageڀD378 MSTUVWXY[\]^_`a, "% qqq.qSqqq- [ "%qqq.qTqqq' \ "%qqq.qUqqq ] "%qqq.qVqqqx ^ "%qqq.qWqqq _ "%qqq.qXqqq ` "%qqq.qYqqq a  "%&Gqq'.qcqqq/q_ XDBucketForStereotypeswasEncoded_XDBucketForStereotypesstorage_XDBucketForStereotypesorderedk ޘ78 36MCD78,"; %< b=c&.qE_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageC378 GPMGHIJKLMNQRSTUVWX, "%7qqq.qqqq' G "%7qqq.qqqq H "%z7qqq.qqqq I78 M, "%7qqq.qqqq' J "% 7qqq.qqqqU K "%7qqq.qqqq' L "%7qqq.qqqq M "%7qqq.qqqq' N" % bc&.q_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageD378 MSTUVWXY[\]^_`a, "%8qqq.qSqqq [ "%8qqq.qTqqq' \ "%8qqq.qUqqq ] "%8qqq.qVqqq ^ "%8qqq.qWqqq _ "%8qqq.qXqqq ` "%8qqq.qYqqq a^_ ` "%&Gqqh.qcqqqpq_ XDBucketForStereotypeswasEncoded_XDBucketForStereotypesstorage_XDBucketForStereotypesordered k eY78 twMCDxy ,"| %} b~c&.q_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageC3 78 MGHIJKLMN , "%xqqq.qqqq'  G "%xqqq.qqqq  H "%xqqq.qqqq  I78 M, "%xqqq.qqqq'  J "% xqqq.qqqqU  K "%xqqq.qqqq'  L "%xqqq.qqqq  M "%xqqq.qqqq'  N" % bc&.q"_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageD378 $,MSTUVWXY[\]^_`a-./0123, "% yqqq.qSqqq- [ "%yqqq.qTqqq' \ "%yqqq.qUqqq ] "%yqqq.qVqqqx ^ "%yqqq.qWqqq _ "%yqqq.qXqqq ` "%yqqq.qYqqq a  "%&Gqq.qcqqqq_ XDBucketForStereotypeswasEncoded_XDBucketForStereotypesstorage_XDBucketForStereotypesordered!k Y78 MCD"-," % bc&.q_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageC3#78 MGHIJKLMNځ$%&()*+,, "%qqq.qqqq'" G "%qqq.qqqq" H "%qqq.qqqq'" I78   M, "%qqq.qqqq'" J "% qqq.qqqqU" K "%qqq.qqqq'" L "%qqq.qqqq" M "%qqq.qqqq'" N"Y %Z b[c&.qc_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageD3.78 emMSTUVWXY[\]^_`anopqrst/012345, "% qqq.qSqqq-- [ "%qqq.qTqqq'- \ "%qqq.qUqqq- ] "%qqq.qVqqqx- ^ "%qqq.qWqqq- _ "%qqq.qXqqq- ` "%qqq.qYqqq- a  "%&Gqq.qcqqqq_ XDBucketForStereotypeswasEncoded_XDBucketForStereotypesstorage_XDBucketForStereotypesordered8k77V<78 MCD9D," % bc&.q_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorage6C3:78  MGHIJKLMN;<=?@ABC, "%qqq.qqqq'9 G "%qqq.qqqq9 H "%=qqq.qqqq>9 I78 KLM, "%qqq.qqqq'9 J "% qqq.qqqqU9 K "%qqq.qqqq'9 L "%qqq.qqqq9 M "%qqq.qqqq'9 N" % bc&.q_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorage6D3E78 MSTUVWXY[\]^_`aFGHIJLM, "%qqq.qSqqqD [ "%qqq.qTqqq'D \ "%qqq.qUqqqD ] "%qqq.qVqqqD ^ "%qqq.qWqqqKD _Q4 "%qqq.qXqqqD ` "%qqq.qYqqqD a"# $ "%&Gqq,.qcqqq4q_ XDBucketForStereotypeswasEncoded_XDBucketForStereotypesstorage_XDBucketForStereotypesorderedPkOQ)78 8;MCD<=Q\,"@ %A bBc&.qJ_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageNC3R78 LUMGHIJKLMNVWXYZ[\]STUWXYZ[, "%<qqq.qqqq'Q G "%<qqq.qqqqQ H "%<qqq.qqqqVQ I78 M, "%<qqq.qqqq'Q J "% <qqq.qqqqUQ K "%<qqq.qqqq'Q L "%<qqq.qqqqQ M "%<qqq.qqqq'Q N" % bc&.q_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageND3]78 MSTUVWXY[\]^_`a^_`abcd, "% =qqq.qSqqq-\ [ "%=qqq.qTqqq'\ \ "%=qqq.qUqqq\ ] "%=qqq.qVqqqx\ ^ "%=qqq.qWqqq\ _ "%=qqq.qXqqq\ ` "%=qqq.qYqqq\ acd e "%&Gqqm.qcqqquq_ XDBucketForStereotypeswasEncoded_XDBucketForStereotypesstorage_XDBucketForStereotypesorderedgkf ]}78 y|MCD}~hs," % bc&.q_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageeC3i78 MGHIJKLMNjklnopqr, "%}qqq.qqqq'h G "%}qqq.qqqqh H "%}qqq.qqqqmh I78 M, "%}qqq.qqqq'h J "% }qqq.qqqqUh K "%}qqq.qqqq'h L "%}qqq.qqqqh M "%}qqq.qqqq'h N" % bc&.q'_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageeD3t78 )1MSTUVWXY[\]^_`a2345678uwxyz{|, "%<~qqq.qSqqqvs [Umovie "%~qqq.qTqqq's \ "%~qqq.qUqqqs ] "%~qqq.qVqqqs ^ "%~qqq.qWqqqs _ "%~qqq.qXqqqs ` "%~qqq.qYqqqs a  "%&Gqq.qcqqqq_ XDBucketForStereotypeswasEncoded_XDBucketForStereotypesstorage_XDBucketForStereotypesorderedk~'78 MCD," % bc&.q_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorage}C378 MGHIJKLMN, "%qqq.qqqq' G "%qqq.qqqq H "%qqq.qqqq I78 M, "%qqq.qqqq' J "% qqq.qqqqU K "%qqq.qqqq' L "%qqq.qqqq M "%qqq.qqqq' N"_ %` bac&.qi_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorage}D378 ksMSTUVWXY[\]^_`atuvwxyz, "%lqqq.qSqqqc [ "%qqq.qTqqq' \ "%qqq.qUqqq ] "%qqq.qVqqqg ^ "%qqq.qWqqq _ "%qqq.qXqqq ` "%qqq.qYqqq a  "%&Gqq.qcqqqq_ XDBucketForStereotypeswasEncoded_XDBucketForStereotypesstorage_XDBucketForStereotypesorderedkV|M78 MCD," % bc&.q_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageC378 MGHIJKLMN !, "%qqq.qqqq' G "%qqq.qqqq H "%Cqqq.qqqq I78 QRM, "%qqq.qqqq' J "% qqq.qqqqU K "%qqq.qqqq' L "%qqq.qqqq M "%qqq.qqqq' N" % bc&.q_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageD378 MSTUVWXY[\]^_`a, "% qqq.qSqqq- [ "%qqq.qTqqq' \ "%qqq.qUqqq ] "%qqq.qVqqq ^ "%qqq.qWqqq _ "%qqq.qXqqq ` "%qqq.qYqqq a() * "%&Gqq2.qcqqq:q_ XDBucketForStereotypeswasEncoded_XDBucketForStereotypesstorage_XDBucketForStereotypesorderedk78 >AMCDBC,"F %G bHc&.qP_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageC378 R[MGHIJKLMN\]^_`abc, "%Bqqq.qqqq' G "%Bqqq.qqqq H "%Bqqq.qqqq I78 M, "%Bqqq.qqqq' J "% Bqqq.qqqqU K "%Bqqq.qqqq' L "%Bqqq.qqqq M "%Bqqq.qqqq' N" % bc&.q_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageD378 MSTUVWXY[\]^_`a€, "%lCqqq.qSqqqc [ "%Cqqq.qTqqq' \ "%Cqqq.qUqqq ] "%Cqqq.qVqqqg ^ "%Cqqq.qWqqq _ "%Cqqq.qXqqq ` "%Cqqq.qYqqq a i j k "%&Gqq s.qcqqq {q_ XDBucketForStereotypeswasEncoded_XDBucketForStereotypesstorage_XDBucketForStereotypesorderedku78  MCD Ɓр," % b c&.q _!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageÀC378 MGHIJKLMN ȁɁʁ́́΁ρЀ, "% qqq.qqqq' G "% qqq.qqqq H "%  qqq.qqqqˀ I78 M, "% qqq.qqqq' J "%  qqq.qqqqU K "% qqq.qqqq' L "% qqq.qqqq M "% qqq.qqqq' N"!# %!$ b!%c&.q!-_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageÀD378 !/!7MSTUVWXY[\]^_`a!8!9!:!;!ӁՁցׁ؁فڀ, "%!B qqq.qSqqqԀ [SYES "% qqq.qTqqq' \ "% qqq.qUqqq ] "% qqq.qVqqqg ^ "% qqq.qWqqq _ "% qqq.qXqqq ` "% qqq.qYqqq a!! ! "%&Gqq!.qcqqq!q_ XDBucketForStereotypeswasEncoded_XDBucketForStereotypesstorage_XDBucketForStereotypesorderedkq78 !!MCD!!Ɓށ,"! %! b!c&.q!_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageۀC378 !!MGHIJKLMN!!!!!!!!, "%!qqq.qqqq' G "%!qqq.qqqq H "%"!qqq.qqqq I78 ""M, "% !qqq.qqqqU J "% !qqq.qqqqU K "%!qqq.qqqq' L "%!qqq.qqqq M "%!qqq.qqqq' N""e %"f b"gc&.q"o_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageۀD378 "q"yMSTUVWXY[\]^_`a"z"{"|"}"~"", "%!B!qqq.qSqqqԀ [ "%!qqq.qTqqq' \ "%!qqq.qUqqq ] "%!qqq.qVqqqg ^ "%!qqq.qWqqq _ "%!qqq.qXqqq ` "%!qqq.qYqqq a"" " "%&Gqq".qcqqq"q_ XDBucketForStereotypeswasEncoded_XDBucketForStereotypesstorage_XDBucketForStereotypesordered?78 ##MCo##,"# %# b# c&.q#_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageC378 ##MGHIJKLMN# #!#"###$#%#&#', "%#qqq.qqqq' G "%#qqq.qqqq H "%#I#qqq.qqqq I78 #W#XM, "% #qqq.qqqqU J "% #qqq.qqqqU K "%#qqq.qqqq' L "%#qqq.qqqq M "%#qqq.qqqq' N"# %# b#c&.q#_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageo378 ##M}~####### !, "%#qqq.qqqq } "%#qqq.qqqq ~ "%#qqq.qqqq  "%J#qqq.qqqq $$$$$$ $$ "$$ %bc$ &&$i.&cl@c$$q_!XDBucketForOwnedAttributesordered_!XDBucketForOwnedAttributesstorage_ XDBucketForStereotypeswasEncoded_$XDBucketForOwnedAttributeswasEncoded_XDBucketForStereotypesstorage_$XDBucketForGeneralizationsduplicates_$XDBucketForGeneralizationswasEncoded_XDBucketForStereotypesordered_!XDBucketForGeneralizationsordered_!XDBucketForGeneralizationsstorage M78 $$Mv$ ,"$! %$" b$#Jvc&.q$+_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorage3 78 $-$6M$7$8$9$:$;$<$=$>  , "%$B$qqq.qqqq   8 $P% "%$qqq.qqqq   "%$qqq.qqqq   "%$r$qqq.qqqq  8 $% "%$qqq.qqqq'   "%$$qqq.qqqq  78 $$M$$,_ com.apple.syncservices.DataClass_MediaLibraryFile "%&$qqq.qqqq.   "%$$qqq.qqqq  \MLAlbumTrack78 $$M$$$$$΁$$$$$$Ձ6Md{,Vartist[trackNumberUfilesUalbumUgenre$$ $ "%&Jqq$.qcq$qq$q_ XDBucketForStereotypeswasEncoded_XDBucketForStereotypesstorage_XDBucketForStereotypesordered!k 578 $$MCD$$"-,"$ %$ b$$c&.q%_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageC3#78 %%MGHIJKLMN%%%%%%%%$%&()*+,, "%$qqq.qqqq'" G "%$qqq.qqqq" H "%%:$qqq.qqqq'" I78 %H%IM, "%$qqq.qqqq'" J "% $qqq.qqqqU" K "%$qqq.qqqq'" L "%$qqq.qqqq" M "%$qqq.qqqq'" N"% %% b%$c&.q%_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageD3.78 %%MSTUVWXY[\]^_`a%%%%%%%/012345, "%$qqq.qSqqq- [ "%$qqq.qTqqq'- \ "%$qqq.qUqqq- ] "%$qqq.qVqqq- ^ "%$qqq.qWqqq- _ "%$qqq.qXqqq- ` "%$qqq.qYqqq- a&& & "%&Jqq&(.qcq$qq&0q_ XDBucketForStereotypeswasEncoded_XDBucketForStereotypesstorage_XDBucketForStereotypesordered8k7{9|78 &4&7MCD&8&99D,"&< %&= b&>$c&.q&F_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorage6C3:78 &H&QMGHIJKLMN&R&S&T&U&V&W&X&Y;<=?@ABC, "%&8qqq.qqqq'9 G "%&8qqq.qqqq9 H "%&{&8qqq.qqqq>9 I78 &&M, "%&8qqq.qqqq'9 J "% &8qqq.qqqqU9 K "%&8qqq.qqqq'9 L "%&8qqq.qqqq9 M "%&8qqq.qqqq'9 N"& %& b&$c&.q&_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorage6D3E78 &&MSTUVWXY[\]^_`a&&&&&&&FGHIJKL, "% &9qqq.qSqqq-D [ "%&9qqq.qTqqq'D \ "%&9qqq.qUqqqD ] "%&9qqq.qVqqqxD ^ "%&9qqq.qWqqqD _ "%&9qqq.qXqqqD ` "%&9qqq.qYqqqD a'_'` 'a "%&Jqq'i.qcqqq'qq_ XDBucketForStereotypeswasEncoded_XDBucketForStereotypesstorage_XDBucketForStereotypesorderedOkNr~78 'u'xMCD'y'zP[,"'} %'~ b'$c&.q'_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageMC3Q78 ''MGHIJKLMN''''''''RSTVWXYZ, "%'yqqq.qqqq'P G "%'yqqq.qqqqP H "%''yqqq.qqqqUP I78 ''M, "%'yqqq.qqqq'P J "% 'yqqq.qqqqUP K "%'yqqq.qqqq'P L "%'yqqq.qqqqP M "%'yqqq.qqqq'P N"( %( b($c&.q(#_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageMD3\78 (%(-MSTUVWXY[\]^_`a(.(/(0(1(2(3(4]^_`abc, "%'zqqq.qSqqq[ [ "%'zqqq.qTqqq'[ \ "%'zqqq.qUqqq[ ] "%'zqqq.qVqqq[ ^ "%'zqqq.qWqqq[ _ "%'zqqq.qXqqq[ ` "%'zqqq.qYqqq[ a(( ( "%&Jqq(.qcq$qq(q_ XDBucketForStereotypeswasEncoded_XDBucketForStereotypesstorage_XDBucketForStereotypesorderedfe_78 ((MCo((gr,"( %( b($c&.q(_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstoragedC3h78 ((MGHIJKLMN((((((((ہijkmnopq, "%(qqq.qqqq'g G "%(qqq.qqqqg H "%((qqq.qqqqlg I78 ) ) M, "% (qqq.qqqqUg J "% (qqq.qqqqUg K "%(qqq.qqqq'g L "%(qqq.qqqqg M "%(qqq.qqqq'g N")Z %)[ b)\$c&.q)d_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstoragedo3s78 )f)nM}~)o)p)q)r)s)t)utuvwxyz, "%(qqq.qqqqr } "%(qqq.qqqqr ~ "%(qqq.qqqqr  "%G(qqq.qqqqr  "% (qqq.qqqqUr  "%(qqq.qqqq'r  "%(qqq.qqqqr )) ) "%&Jqq).qcq$qq)q_ XDBucketForStereotypeswasEncoded_XDBucketForStereotypesstorage_XDBucketForStereotypesordered}|78 ))MCo))~,") %* b*$c&.q* _!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorage{C378 * *MGHIJKLMN********, "%)qqq.qqqq'~ G "%)qqq.qqqq~ H "%*>)qqq.qqqq~ I78 *L*MM, "% )qqq.qqqqU~ J "% )qqq.qqqqU~ K "%)qqq.qqqq'~ L "%)qqq.qqqq~ M "%)qqq.qqqq'~ N"* %* b*$c&.q*_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorage{o378 **M}~*******, "%)qqq.qqqq } "%)qqq.qqqq ~ "%)qqq.qqqq  "%E)qqq.qqqq ****** ** "**%bc+&&+i.&cl;c+ + q_!XDBucketForOwnedAttributesordered_!XDBucketForOwnedAttributesstorage_ XDBucketForStereotypeswasEncoded_$XDBucketForOwnedAttributeswasEncoded_XDBucketForStereotypesstorage_$XDBucketForGeneralizationsduplicates_$XDBucketForGeneralizationswasEncoded_XDBucketForStereotypesordered_!XDBucketForGeneralizationsordered_!XDBucketForGeneralizationsstorages78 ++Mv+,"+ %+ b+Evc&.q+ _!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorage378 +"++M+,+-+.+/+0+1+2+3, "%+7+qqq.qqqq 8 +E% "%+qqq.qqqq  "%+qqq.qqqq  "%+g+qqq.qqqq 8 +u% "%+qqq.qqqq'  "%++qqq.qqqq 78 ++M+++,_com.apple.syncservices.Syncable_ com.apple.syncservices.DataClass_MediaLibraryFile "%&+qqq.qqqq.  "%++qqq.qqqq WMLAlbum78 ++M++f+ā>++++ɁՁ,Vtracks[releaseYear\unreadTracks++ + "%&Eqq+.qcq+qq+q_ XDBucketForStereotypeswasEncoded_XDBucketForStereotypesstorage_XDBucketForStereotypesordered*f78 ++MCo++,"+ %+ b++c&.q+_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageC378 +,MGHIJKLMN,,,,,,, , , "%+qqq.qqqq' G "%+qqq.qqqq H "%,,+qqq.qqqq I78 ,:,;M, "% +qqq.qqqqU J "% +qqq.qqqqU K "%+qqq.qqqq' L "%+qqq.qqqq M "%+qqq.qqqq' N", %, b,+c&.q,_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageo378 ,,M}~,,,,,,,, "%+qqq.qqqq } "%+qqq.qqqq ~ "%+qqq.qqqq  "%J+qqq.qqqq  "% +qqq.qqqqU  "%+qqq.qqqq'  "%$+qqq.qqqq{ -- - "%&Eqq-.qcq+qq-"q_ XDBucketForStereotypeswasEncoded_XDBucketForStereotypesstorage_XDBucketForStereotypesorderedk<78 -&-)MCD-*-+̀,"-. %-/ b-0+c&.q-8_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageC378 -:-CMGHIJKLMN-D-E-F-G-H-I-J-KÁāŁǁȁɁʁˀ, "%-*qqq.qqqq' G "%-*qqq.qqqq H "%-m-*qqq.qqqqƀ I78 -{-|M, "%-*qqq.qqqq' J "% -*qqq.qqqqU K "%-*qqq.qqqq' L "%-*qqq.qqqq M "%-*qqq.qqqq' N"- %- b-+c&.q-_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageD378 --MSTUVWXY[\]^_`a-------΁ρЁсҁӁԀ, "%-+qqq.qSqqq [ "%-+qqq.qTqqq' \ "%-+qqq.qUqqq ] "%-+qqq.qVqqq ^ "%-+qqq.qWqqq _ "%-+qqq.qXqqq ` "%-+qqq.qYqqq a.Q.R .S "%&Eqq.[.qcqfqq.cq_ XDBucketForStereotypeswasEncoded_XDBucketForStereotypesstorage_XDBucketForStereotypesorderedk>O"N78 .g.jMCD.k.l؁,".o %.p b.q+c&.q.y_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageՀC378 .{.MGHIJKLMN........ځہ܁ށ߁, "%.kqqq.qqqq' G "%.kqqq.qqqq H "%..kqqq.qqqq݀ I78 ..M, "% .kqqq.qqqqU J "%.kqqq.qqqq' K "%.kqqq.qqqq' L "%.kqqq.qqqq M "%.kqqq.qqqq' N"/ %/ b/ +c&.q/_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageՀD378 //MSTUVWXY[\]^_`a/ /!/"/#/$/%/&, "%.lqqq.qSqqq [ "%.lqqq.qTqqq' \ "%.lqqq.qUqqq ] "%.lqqq.qVqqq ^ "%.lqqq.qWqqq _ "%.lqqq.qXqqq ` "%.lqqq.qYqqq a// / "%&Eqq/.qcq/+qq/q_ XDBucketForStereotypeswasEncoded_XDBucketForStereotypesstorage_XDBucketForStereotypesorderedk78 //M/C//,_XD_PFP_Stereotype"/ %/ b/+c&.q/_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageC378 //MGHIJLMN///////́, "%/qqq.qqqq' G "%/qqq.qqqq H "%//qqq.qqqq I78 //M, "%/qqq.qqqq' J "%/qqq.qqqq' L "%/qqq.qqqq M "% /qqq.qqqqU N"0< %0= b0>+/c&.q0F_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorage378 0H0JM0I0K,_XD_PFP_fetchRequestKey "%0P/qqq.q0Iqqq "0^0_0` 0a+0cE0e__fetchedProperty__predicateStringW_entity_fetchedPropertyFetchRequest_&album == $FETCH_SOURCE AND unread == 10i0j_XDPMFetchRequest0k_XDPMFetchRequest0m0n_XDPMFetchedProperty0o0p0q0r0s_XDPMFetchedProperty\XDPMProperty_XDUMLPropertyImp_XDUMLNamedElementImp_XDUMLElementImp8 0u% "%)qqq.qqqq'  "%)qqq.qqqq'  "%+)qqq.qqqq 00 0 "%&Jqq0.qcq$qq0q_ XDBucketForStereotypeswasEncoded_XDBucketForStereotypesstorage_XDBucketForStereotypesordered k>R78 00MCD00 ,"0 %0 b0$c&.q0_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageC3 78 00MGHIJKLMN00000000  , "%0qqq.qqqq'  G "%0qqq.qqqq  H "%10qqq.qqqq  I78 11M, "%0qqq.qqqq'  J "% 0qqq.qqqqU  K "%0qqq.qqqq'  L "%0qqq.qqqq  M "%0qqq.qqqq'  N"1_ %1` b1a$c&.q1i_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageD378 1k1sMSTUVWXY[\]^_`a1t1u1v1w1x1y1z, "%0qqq.qSqqq [ "%0qqq.qTqqq' \ "%0qqq.qUqqq ] "%0qqq.qVqqq ^ "%0qqq.qWqqq _ "%0qqq.qXqqq ` "%0qqq.qYqqq a8 1% "%#qqq.qqqq'  "%#qqq.qqqq'  "%$#qqq.qqqqd 22 2 "%&Gqq2 .qcqqq2(q_ XDBucketForStereotypeswasEncoded_XDBucketForStereotypesstorage_XDBucketForStereotypesordered$k#)l78 2,2/MCD2021%0,"24 %25 b26c&.q2>_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorage"C3&78 2@2IMGHIJKLMN2J2K2L2M2N2O2P2Q'()+,-./, "%20qqq.qqqq'% G "%20qqq.qqqq% H "%2s20qqq.qqqq*% I78 22M, "%20qqq.qqqq'% J "% 20qqq.qqqqU% K "%20qqq.qqqq'% L "%20qqq.qqqq% M "%20qqq.qqqq'% N"2 %2 b2c&.q2_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorage"D3178 22MSTUVWXY[\]^_`a22222222345678, "% 21qqq.qSqqq-0 [ "%21qqq.qTqqq'0 \ "%21qqq.qUqqq0 ] "%21qqq.qVqqq0 ^ "%21qqq.qWqqq0 _ "%21qqq.qXqqq0 ` "%21qqq.qYqqq0 a3W3X 3Y "%&Gqq3a.qcqqq3iq_ XDBucketForStereotypeswasEncoded_XDBucketForStereotypesstorage_XDBucketForStereotypesordered;k:>78 3m3pMCD3q3r<G,"3u %3v b3wc&.q3_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorage9C3=78 33MGHIJKLMN33333333>?@BCDEF, "%3qqqq.qqqq'< G "%3qqqq.qqqq< H "%33qqqq.qqqqA< I78 33M, "%3qqqq.qqqq'< J "% 3qqqq.qqqqU< K "%3qqqq.qqqq'< L "%3qqqq.qqqq< M "%3qqqq.qqqq'< N"4 %4 b4c&.q4_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorage9D3H78 44%MSTUVWXY[\]^_`a4&4'4(4)4*4+4,IJKLMNO, "% 3rqqq.qSqqq-G [ "%3rqqq.qTqqq'G \ "%3rqqq.qUqqqG ] "%3rqqq.qVqqqxG ^ "%3rqqq.qWqqqG _ "%3rqqq.qXqqqG ` "%3rqqq.qYqqqG a44 4 "%&Gqq4.qcqqq4q_ XDBucketForStereotypeswasEncoded_XDBucketForStereotypesstorage_XDBucketForStereotypesorderedRkQUN\A78 44MCD44S^,"4 %4 b4c&.q4_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstoragePC3T78 44MGHIJKLMN44444444ӁUVWYZ[\], "%4qqq.qqqq'S G "%4qqq.qqqqS H "%44qqq.qqqqXS I78 55M, "%4qqq.qqqq'S J "% 4qqq.qqqqUS K "%4qqq.qqqq'S L "%4qqq.qqqqS M "%4qqq.qqqq'S N"5R %5S b5Tc&.q5\_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstoragePD3_78 5^5fMSTUVWXY[\]^_`a5g5h5i5j5k5l5m`abcdef, "%4qqq.qSqqq^ [ "%4qqq.qTqqq'^ \ "%4qqq.qUqqq^ ] "%4qqq.qVqqq^ ^ "%4qqq.qWqqq^ _ "%4qqq.qXqqq^ ` "%4qqq.qYqqq^ a55 5 "%&Gqq5.qcqqq5q_ XDBucketForStereotypeswasEncoded_XDBucketForStereotypesstorage_XDBucketForStereotypesorderedikhI~\ 78 55MCD55ju,"5 %5 b5c&.q6_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstoragegC3k78 66 MGHIJKLMN6 6666666lmnpqrst, "%5qqq.qqqq'j G "%5qqq.qqqqj H "%665qqq.qqqqoj I78 6D6EM, "%5qqq.qqqq'j J "% 5qqq.qqqqUj K "%5qqq.qqqq'j L "%5qqq.qqqqj M "%5qqq.qqqq'j N"6 %6 b6c&.q6_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstoragegD3v78 66MSTUVWXY[\]^_`a6666666wxyz{|}, "% 5qqq.qSqqq-u [ "%5qqq.qTqqq'u \ "%5qqq.qUqqqu ] "%5qqq.qVqqqxu ^ "%5qqq.qWqqqu _ "%5qqq.qXqqqu ` "%5qqq.qYqqqu a77 7 "%&Gqq7$.qcqqq7,q_ XDBucketForStereotypeswasEncoded_XDBucketForStereotypesstorage_XDBucketForStereotypesorderedA78 7073MCo7475,"78 %79 b7:c&.q7B_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorage~C378 7D7MMGHIJKLMN7N7O7P7Q7R7S7T7U, "%74qqq.qqqq' G "%74qqq.qqqq H "%7w74qqq.qqqq I78 77M, "% 74qqq.qqqqU J "% 74qqq.qqqqU K "%74qqq.qqqq' L "%74qqq.qqqq M "%74qqq.qqqq' N"7 %7 b7c&.q7_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorage~o378 77M}~7777777, "%75qqq.qqqq } "%75qqq.qqqq ~ "%75qqq.qqqq  "%D75qqq.qqqq  "%75qqq.qqqq'  "%75qqq.qqqq'  "%j75qqq.qqqql 8[8\ 8] "%&Gqq8e.qcqqq8mq_ XDBucketForStereotypeswasEncoded_XDBucketForStereotypesstorage_XDBucketForStereotypesordered78 8q8tMCo8u8v,"8y %8z b8{c&.q8_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageC378 88MGHIJKLMN88888888, "%8uqqq.qqqq' G "%8uqqq.qqqq H "%88uqqq.qqqq I78 88M, "% 8uqqq.qqqqU J "% 8uqqq.qqqqU K "%8uqqq.qqqq' L "%8uqqq.qqqq M "%8uqqq.qqqq' N"9 %9 b9c&.q9_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageo378 9!9)M}~9*9+9,9-9.9/90z{|, "%8vqqq.qqqq } "%8vqqq.qqqq ~ "%8vqqq.qqqq  "%H8vqqq.qqqq b9o9p9q9r9s9t 9u"9v%9w9x9y9z9{9| cc9&icl&>99&&c99i._!XDBucketForOwnedAttributesordered_!XDBucketForSpecializationsordered_XDBucketForStereotypesstorage_$XDBucketForOwnedAttributeswasEncoded_$XDBucketForGeneralizationsduplicates_XDBucketForStereotypesordered_$XDBucketForGeneralizationswasEncoded_!XDBucketForGeneralizationsstorage_ XDBucketForStereotypeswasEncoded_$XDBucketForSpecializationswasEncoded_!XDBucketForGeneralizationsordered_!XDBucketForOwnedAttributesstorage_!XDBucketForSpecializationsstorage_$XDBucketForSpecializationsduplicates  78 99Mv9,"9 %9 b9Hvc&.q9_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorage378 99M99999999, "%9qqq.qqqq  "%9qqq.qqqq  "%9qqq.qqqq  "%99qqq.qqqq 8 9% "% 9qqq.qqqqU  "%:9qqq.qqqq 78 ::M:+,_ com.apple.syncservices.DataClass "%&9qqq.qqqq.  "%:,9qqq.qqqq _NSManagedObject78 :;:>M:<:=:?:@Ԁ,UcodecTfile:E:F :G "%&Hqq:O.qcq:<qq:Wq_ XDBucketForStereotypeswasEncoded_XDBucketForStereotypesstorage_XDBucketForStereotypesorderedkV78 :[:^MCD:_:`ˀ,":c %:d b:e:?c&.q:m_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageC378 :o:xMGHIJKLMN:y:z:{:|:}:~::ÁāƁǁȁɁʀ, "%:_qqq.qqqq' G "%:_qqq.qqqq H "%::_qqq.qqqqŀ I78 ::M, "%:_qqq.qqqq' J "% :_qqq.qqqqU K "%:_qqq.qqqq' L "%:_qqq.qqqq M "%:_qqq.qqqq' N": %; b;:?c&.q; _!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageD378 ; ;MSTUVWXY[\]^_`a;;;;;;;́΁ρЁсҁӀ, "%:`qqq.qSqqq [ "%:`qqq.qTqqq' \ "%:`qqq.qUqqq ] "%:`qqq.qVqqq ^ "%:`qqq.qWqqq _ "%:`qqq.qXqqq ` "%:`qqq.qYqqq a;; ; "%&Hqq;.qcq:=qq;q_ XDBucketForStereotypeswasEncoded_XDBucketForStereotypesstorage_XDBucketForStereotypesorderedR 78 ;;MCo;;ׁ,"; %; b;:@c&.q;_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageԀC378 ;;MGHIJKLMN;;;;;;;;فځہ݁ށ߁, "%;qqq.qqqq' G "%;qqq.qqqq H "%;;qqq.qqqq܀ I78 ;;M, "% ;qqq.qqqqU J "% ;qqq.qqqqU K "%;qqq.qqqq' L "%;qqq.qqqq M "%;qqq.qqqq' N"<@ %=qqq.qqqq  I78 >>M, "%=qqq.qqqq' J "% =qqq.qqqqU K "%=qqq.qqqq' L "%=qqq.qqqq M "%=qqq.qqqq' N">a %>b b>c=c&.q>k_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageD378 >m>uMSTUVWXY[\]^_`a>v>w>x>y>z>{>|, "% =qqq.qSqqq- [ "%=qqq.qTqqq' \ "%=qqq.qUqqq ] "%=qqq.qVqqq ^ "%=qqq.qWqqq _ "%=qqq.qXqqq ` "%=qqq.qYqqq a>> > "%&Iqq>.qcq=qq>q_ XDBucketForStereotypeswasEncoded_XDBucketForStereotypesstorage_XDBucketForStereotypesorderedk|78 >?MCD??(,"? %? b?=c&.q?_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageC378 ??MGHIJKLMN????? ?!?"?# !#$%&', "%?qqq.qqqq' G "%?qqq.qqqq H "%?E?qqq.qqqq" I78 ?S?TM, "%?qqq.qqqq' J "% ?qqq.qqqqU K "%?qqq.qqqq' L "%?qqq.qqqq M "%?qqq.qqqq' N"? %? b?=c&.q?_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageD3)78 ??MSTUVWXY[\]^_`a???????*+,-./0, "% ?qqq.qSqqq-( [ "%?qqq.qTqqq'( \ "%?qqq.qUqqq( ] "%?qqq.qVqqq( ^ "%?qqq.qWqqq( _ "%?qqq.qXqqq( ` "%?qqq.qYqqq( a8 @)<ˁ%h@.@/_XDUMLGeneralizationImp@0@1@2_XDUMLGeneralizationImp_XDUMLNamedElementImp_XDUMLElementImp "<%< <KK@8H.355y@;@<@=@>@?@@ @A@B "@C@D%bc@F&&@Ji.&clAc@Q@Rq_!XDBucketForOwnedAttributesordered_!XDBucketForOwnedAttributesstorage_ XDBucketForStereotypeswasEncoded_$XDBucketForOwnedAttributeswasEncoded_XDBucketForStereotypesstorage_$XDBucketForGeneralizationsduplicates_$XDBucketForGeneralizationswasEncoded_XDBucketForStereotypesordered_!XDBucketForGeneralizationsordered_!XDBucketForGeneralizationsstorageG7x678 @V@XMv@Y8,"@\ %@] b@^Kvc&.q@f_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorage53978 @h@qM@r@s@t@u@v@w@x@y:;<=?@DE, "%@Yqqq.qqqq8  "%@Yqqq.qqqq8  "%@Yqqq.qqqq8  "%@@Yqqq.qqqq>8 8 @% "%@Yqqq.qqqq'8  "%@@Yqqq.qqqqA8 78 @@M@ځB@܁C,_ com.apple.syncservices.DataClass_MediaLibraryFile "%&@Yqqq.qqqq.8  "%@@Yqqq.qqqqF8 _NSManagedObject78 AAMAAHIAAJa,UwidthVheightA A A "%&KqqA.qcqAqqAq_ XDBucketForStereotypeswasEncoded_XDBucketForStereotypesstorage_XDBucketForStereotypesordered5LkHKҝ78 A A#MCDA$A%MX,"A( %A) bA*Ac&.qA2_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageJC3N78 A4A=MGHIJKLMNA>A?A@AAABACADAEOPQSTUVW, "%A$qqq.qqqq'M G "%A$qqq.qqqqM H "%AgA$qqq.qqqqRM I78 AuAvM, "%A$qqq.qqqq'M J "% A$qqq.qqqqUM K "%A$qqq.qqqq'M L "%A$qqq.qqqqM M "%A$qqq.qqqq'M N"A %A bAAc&.qA_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageJD3Y78 AAMSTUVWXY[\]^_`aAAAAAAA߁Z[\]^_`, "% A%qqq.qSqqq-X [ "%A%qqq.qTqqq'X \ "%A%qqq.qUqqqX ] "%A%qqq.qVqqqX ^ "%A%qqq.qWqqqX _ "%A%qqq.qXqqqX ` "%A%qqq.qYqqqX aBKBL BM "%&KqqBU.qcqAqqB]q_ XDBucketForStereotypeswasEncoded_XDBucketForStereotypesstorage_XDBucketForStereotypesordered5ckIb;878 BaBdMCDBeBfdo,"Bi %Bj bBkAc&.qBs_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageaC3e78 BuB~MGHIJKLMNBBBBBBBBfghjklmn, "%Beqqq.qqqq'd G "%Beqqq.qqqqd H "%BBeqqq.qqqqid I78 BBM, "%Beqqq.qqqq'd J "% Beqqq.qqqqUd K "%Beqqq.qqqq'd L "%Beqqq.qqqqd M "%Beqqq.qqqq'd N"C %C bCAc&.qC_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageaD3p78 CCMSTUVWXY[\]^_`aCCCCCCC qrstuvw, "% Bfqqq.qSqqq-o [ "%Bfqqq.qTqqq'o \ "%Bfqqq.qUqqqo ] "%Bfqqq.qVqqqo ^ "%Bfqqq.qWqqqo _ "%Bfqqq.qXqqqo ` "%Bfqqq.qYqqqo a8 C<́4%\ "% 8vqqq.qqqqU  "%8vqqq.qqqq'  "%:@8vqqq.qqqqԀ CC C "%&GqqC.qcqqqCq_ XDBucketForStereotypeswasEncoded_XDBucketForStereotypesstorage_XDBucketForStereotypesorderedk~jt78 CCMCDCCف,"C %C bCc&.qC_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorage}C378 CCMGHIJKLMNCCCCCCCC, "%Cqqq.qqqq' G "%Cqqq.qqqq H "%DCqqq.qqqq I78 D)D*M, "%Cqqq.qqqq' J "% Cqqq.qqqqU K "%Cqqq.qqqq' L "%Cqqq.qqqq M "%Cqqq.qqqq' N"Dx %Dy bDzc&.qD_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorage}D378 DDMSTUVWXY[\]^_`aDDDDDDD, "%Cqqq.qSqqq [ "%Cqqq.qTqqq' \ "%Cqqq.qUqqq ] "%Cqqq.qVqqq ^ "%Cqqq.qWqqq _ "%Cqqq.qXqqq ` "%Cqqq.qYqqq aDE E "%&GqqE .qcqqqEq_ XDBucketForStereotypeswasEncoded_XDBucketForStereotypesstorage_XDBucketForStereotypesorderedkZ}r78 EEMCDEE,"E %E bEc&.qE'_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageC378 E)E2MGHIJKLMNE3E4E5E6E7E8E9E:, "%Eqqq.qqqq' G "%Eqqq.qqqq H "%E\Eqqq.qqqq I78 EjEkM, "%Eqqq.qqqq' J "% Eqqq.qqqqU K "%Eqqq.qqqq' L "%Eqqq.qqqq M "%Eqqq.qqqq' N"E %E bEc&.qE_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageD378 EEMSTUVWXY[\]^_`aEEEEEEEԁ, "%Eqqq.qSqqq [ "%Eqqq.qTqqq' \ "%Eqqq.qUqqq ] "%Eqqq.qVqqq ^ "%Eqqq.qWqqq _ "%Eqqq.qXqqq ` "%Eqqq.qYqqq aF@FA FB "%&GqqFJ.qcqqqFRq_ XDBucketForStereotypeswasEncoded_XDBucketForStereotypesstorage_XDBucketForStereotypesorderedk{(ݐ78 FVFYMCDFZF[,"F^ %F_ bF`c&.qFh_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageC378 FjFsMGHIJKLMNFtFuFvFwFxFyFzF{, "%FZqqq.qqqq' G "%FZqqq.qqqq H "%FFZqqq.qqqq I78 FFM, "%FZqqq.qqqq' J "% FZqqq.qqqqU K "%FZqqq.qqqq' L "%FZqqq.qqqq M "%FZqqq.qqqq' N"F %F bFc&.qG_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageD378 GGMSTUVWXY[\]^_`aGGGGGGG, "%lF[qqq.qSqqqc [ "%F[qqq.qTqqq' \ "%F[qqq.qUqqq ] "%F[qqq.qVqqqg ^ "%F[qqq.qWqqq _ "%F[qqq.qXqqq ` "%F[qqq.qYqqq aGG G "%&GqqG.qcqqqGq_ XDBucketForStereotypeswasEncoded_XDBucketForStereotypesstorage_XDBucketForStereotypesorderedknj78 GGMCDGGŁЀ,"G %G bGc&.qG_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorage€C378 GGMGHIJKLMNGGGGGGGGǁȁɁˁ́́΁π, "%Gqqq.qqqq' G "%Gqqq.qqqq H "%GGqqq.qqqqʀ I78 GGM, "%Gqqq.qqqq' J "% Gqqq.qqqqU K "%Gqqq.qqqq' L "%Gqqq.qqqq M "%Gqqq.qqqq' N"H; %H< bH=c&.qHE_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorage€D378 HGHOMSTUVWXY[\]^_`aHPHQHRHSHTHUHVҁӁԁՁցׁ؀, "%!BGqqq.qSqqqԀ [ "%Gqqq.qTqqq' \ "%Gqqq.qUqqq ] "%Gqqq.qVqqqg ^ "%Gqqq.qWqqq _ "%Gqqq.qXqqq ` "%Gqqq.qYqqq a8 H% "% qqq.qqqqU{  "%qqq.qqqq'{  "%qqq.qqqq~{ HH H "%&DqqH.qcq_qqIq_ XDBucketForStereotypeswasEncoded_XDBucketForStereotypesstorage_XDBucketForStereotypesorderedk7R=-78 II MCDI I ,"I %I bIkc&.qI_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorage݀C378 II%MGHIJKLMNI&I'I(I)I*I+I,I-, "%I qqq.qqqq' G "%I qqq.qqqq H "%IOI qqq.qqqq I78 I]I^M, "%I qqq.qqqq' J "% I qqq.qqqqU K "%I qqq.qqqq' L "%I qqq.qqqq M "%I qqq.qqqq' N"I %I bIkc&.qI_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorage݀D378 IIMSTUVWXY[\]^_`aIIIIIIIǁ, "%I qqq.qSqqq [ "%I qqq.qTqqq' \ "%I qqq.qUqqq ] "%I qqq.qVqqq ^ "%I qqq.qWqqq _ "%I qqq.qXqqq ` "%I qqq.qYqqq aJ3J4 J5 "%&DqqJ=.qcq`qqJEq_ XDBucketForStereotypeswasEncoded_XDBucketForStereotypesstorage_XDBucketForStereotypesorderedk8͑78 JIJLMCDJMJN,"JQ %JR bJSlc&.qJ[_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageC378 J]JfMGHIJKLMNJgJhJiJjJkJlJmJn, "%JMqqq.qqqq' G "%JMqqq.qqqq H "%JJMqqq.qqqq I78 JJM, "%JMqqq.qqqq' J "% JMqqq.qqqqU K "%JMqqq.qqqq' L "%JMqqq.qqqq M "%JMqqq.qqqq' N"J %J bJlc&.qJ_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageD378 JKMSTUVWXY[\]^_`aKKKKKKK  , "%lJNqqq.qSqqqc [ "%JNqqq.qTqqq' \ "%JNqqq.qUqqq ] "%JNqqq.qVqqqg ^ "%JNqqq.qWqqq _ "%JNqqq.qXqqq ` "%JNqqq.qYqqq aKtKu Kv "%&DqqK~.qcqaqqKq_ XDBucketForStereotypeswasEncoded_XDBucketForStereotypesstorage_XDBucketForStereotypesordered k9 R78 KKMCDKK,"K %K bKmc&.qK_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorage C378 KKMGHIJKLMNKKKKKKKK, "%Kqqq.qqqq' G "%Kqqq.qqqq H "%KKqqq.qqqq I78 KKM, "%Kqqq.qqqq' J "% Kqqq.qqqqU K "%Kqqq.qqqq' L "%Kqqq.qqqq M "%Kqqq.qqqq' N"L. %L/ bL0mc&.qL8_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorage D378 L:LBMSTUVWXY[\]^_`aLCLDLELFLGLHLI !, "% Kqqq.qSqqq- [ "%Kqqq.qTqqq' \ "%Kqqq.qUqqq ] "%Kqqq.qVqqqx ^ "%Kqqq.qWqqq _ "%Kqqq.qXqqq ` "%Kqqq.qYqqq aLL L "%&DqqL.qcqbqqLq_ XDBucketForStereotypeswasEncoded_XDBucketForStereotypesstorage_XDBucketForStereotypesordered$k:# >78 LLMCDLLЁ%0,"L %L bLnc&.qL_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorage"C3&78 LLMGHIJKLMNLLLLLLLL'()+,-./, "%Lqqq.qqqq'% G "%Lqqq.qqqq% H "%MLqqq.qqqq*% I78 M M!M, "%Lqqq.qqqq'% J "% Lqqq.qqqqU% K "%Lqqq.qqqq'% L "%Lqqq.qqqq% M "%Lqqq.qqqq'% N"Mo %Mp bMqnc&.qMy_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorage"D3178 M{MMSTUVWXY[\]^_`aMMMMMMM2345678, "% Lqqq.qSqqq-0 [ "%Lqqq.qTqqq'0 \ "%Lqqq.qUqqq0 ] "%Lqqq.qVqqqx0 ^ "%Lqqq.qWqqq0 _ "%Lqqq.qXqqq0 ` "%Lqqq.qYqqq0 aMM M "%&DqqN.qcqcqqNq_ XDBucketForStereotypeswasEncoded_XDBucketForStereotypesstorage_XDBucketForStereotypesordered;;:Y78 N NMCoNN<G,"N %N bNoc&.qN_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorage9C3=78 N N)MGHIJKLMNN*N+N,N-N.N/N0N1>?@BCDEF, "%Nqqq.qqqq'< G "%Nqqq.qqqq< H "%NSNqqq.qqqqA< I78 NaNbM, "% Nqqq.qqqqU< J "% Nqqq.qqqqU< K "%Nqqq.qqqq'< L "%Nqqq.qqqq< M "%Nqqq.qqqq'< N"N %N bNoc&.qN_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorage9o3H78 NNM}~NNNNNNNˁIJKL, "%Nqqq.qqqqG } "%Nqqq.qqqqG ~ "%Nqqq.qqqqG  "%FNqqq.qqqqMG O O O O OO OO "OO%bcO&&Oi.&cl<cO O!q_!XDBucketForOwnedAttributesordered_!XDBucketForOwnedAttributesstorage_ XDBucketForStereotypeswasEncoded_$XDBucketForOwnedAttributeswasEncoded_XDBucketForStereotypesstorage_$XDBucketForGeneralizationsduplicates_$XDBucketForGeneralizationswasEncoded_XDBucketForStereotypesordered_!XDBucketForGeneralizationsordered_!XDBucketForGeneralizationsstorage]O N 78 O%O'MvO(P,"O+ %O, bO-Fvc&.qO5_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageM3Q78 O7O@MOAOBOCODOEOFOGOHRSTUWXZ[, "%O(qqq.qqqqP  "%O(qqq.qqqqP  "%O(qqq.qqqqP  "%OyO(qqq.qqqqVP 8 O% "%O(qqq.qqqq'P  "%OO(qqq.qqqqYP 78 OOM+, "%&O(qqq.qqqq.P  "%OO(qqq.qqqq\P VMLShow78 OOMOOOOOfOց^_`ab>cOOOOOOOށd{ׁ,YtheTVDBID\shortSummaryXepisodesZartworkURL\lastSyncDate[releaseYearOO O "%&FqqO.qcqOqqOq_ XDBucketForStereotypeswasEncoded_XDBucketForStereotypesstorage_XDBucketForStereotypesorderedMfk^e΄78 OPMCDPPgr,"P %P bPOc&.qP_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstoragedC3h78 PPMGHIJKLMNPPPPPP P!P"ijkmnopq, "%Pqqq.qqqq'g G "%Pqqq.qqqqg H "%PDPqqq.qqqqlg I78 PRPSM, "%Pqqq.qqqq'g J "% Pqqq.qqqqUg K "%Pqqq.qqqq'g L "%Pqqq.qqqqg M "%Pqqq.qqqq'g N"P %P bPOc&.qP_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstoragedD3s78 PPMSTUVWXY[\]^_`aPPPPPPPtuvwxyz, "%Pqqq.qSqqqr [ "%Pqqq.qTqqq'r \ "%Pqqq.qUqqqr ] "%Pqqq.qVqqqr ^ "%Pqqq.qWqqqr _ "%Pqqq.qXqqqr ` "%Pqqq.qYqqqr aQ(Q) Q* "%&FqqQ2.qcqOqqQ:q_ XDBucketForStereotypeswasEncoded_XDBucketForStereotypesstorage_XDBucketForStereotypesorderedM}k_|ZՃ78 Q>QAMCDQBQC~,"QF %QG bQHOc&.qQP_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorage{C378 QRQ[MGHIJKLMNQ\Q]Q^Q_Q`QaQbQc, "%QBqqq.qqqq'~ G "%QBqqq.qqqq~ H "%QQBqqq.qqqq~ I78 QQM, "%QBqqq.qqqq'~ J "% QBqqq.qqqqU~ K "%QBqqq.qqqq'~ L "%QBqqq.qqqq~ M "%QBqqq.qqqq'~ N"Q %Q bQOc&.qQ_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorage{D378 QQMSTUVWXY[\]^_`aQQQQQQQ, "%QCqqq.qSqqq [ "%QCqqq.qTqqq' \ "%QCqqq.qUqqq ] "%QCqqq.qVqqq ^ "%QCqqq.qWqqq _ "%QCqqq.qXqqq ` "%QCqqq.qYqqq aRiRj Rk "%&FqqRs.qcqOqqR{q_ XDBucketForStereotypeswasEncoded_XDBucketForStereotypesstorage_XDBucketForStereotypesorderedM`v78 RRMCoRR,"R %R bROc&.qR_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageC378 RRMGHIJKLMNRRRRRRRR, "%Rqqq.qqqq' G "%Rqqq.qqqq H "%RRqqq.qqqq I78 RRM, "% Rqqq.qqqqU J "% Rqqq.qqqqU K "%Rqqq.qqqq' L "%Rqqq.qqqq M "%Rqqq.qqqq' N"S# %S$ bS%Oc&.qS-_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageo378 S/S7M}~S8S9S:S;S, "%Rqqq.qqqq } "%Rqqq.qqqq ~ "%Rqqq.qqqq  "%DRqqq.qqqq  "% Rqqq.qqqqU  "%Rqqq.qqqq'  "%oRqqq.qqqq9 SS S "%&FqqS.qcqOqqSq_ XDBucketForStereotypeswasEncoded_XDBucketForStereotypesstorage_XDBucketForStereotypesorderedMkaNH78 SSMCDSSŁ,"S %S bSOc&.qS_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageC378 SSMGHIJKLMNSSSSSSSS, "%Sqqq.qqqq' G "%Sqqq.qqqq H "%TSqqq.qqqq I78 TTM, "%Sqqq.qqqq' J "% Sqqq.qqqqU K "%Sqqq.qqqq' L "%Sqqq.qqqq M "%Sqqq.qqqq' N"Td %Te bTfOc&.qTn_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageD378 TpTxMSTUVWXY[\]^_`aTyTzT{T|T}T~T, "%Sqqq.qSqqq [ "%Sqqq.qTqqq' \ "%Sqqq.qUqqq ] "%Sqqq.qVqqq ^ "%Sqqq.qWqqq _ "%Sqqq.qXqqq ` "%Sqqq.qYqqq aTT T "%&FqqT.qcqOqqTq_ XDBucketForStereotypeswasEncoded_XDBucketForStereotypesstorage_XDBucketForStereotypesorderedMkbb78 UUMCDUUÁ΀,"U %U bU Oc&.qU_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageC378 UUMGHIJKLMNUU U!U"U#U$U%U&ŁƁǁɁʁˁ́̀, "%Uqqq.qqqq' G "%Uqqq.qqqq H "%UHUqqq.qqqqȀ I78 UVUWM, "%Uqqq.qqqq' J "% Uqqq.qqqqU K "%Uqqq.qqqq' L "%Uqqq.qqqq M "%Uqqq.qqqq' N"U %U bUOc&.qU_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageD378 UUMSTUVWXY[\]^_`aUUUUUUUЁсҁӁԁՁր, "% Uqqq.qSqqq- [ "%Uqqq.qTqqq' \ "%Uqqq.qUqqq ] "%Uqqq.qVqqq ^ "%Uqqq.qWqqq _ "%Uqqq.qXqqq ` "%Uqqq.qYqqq aV,V- V. "%&FqqV6.qcqfqqV>q_ XDBucketForStereotypeswasEncoded_XDBucketForStereotypesstorage_XDBucketForStereotypesorderedMk>l!78 VBVEMCDVFVGځ,"VJ %VK bVLOc&.qVT_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorage׀C378 VVV_MGHIJKLMNV`VaVbVcVdVeVfVg܁݁ށ, "%VFqqq.qqqq' G "%VFqqq.qqqq H "%VVFqqq.qqqq߀ I78 VVM, "% VFqqq.qqqqU J "%VFqqq.qqqq' K "%VFqqq.qqqq' L "%VFqqq.qqqq M "%VFqqq.qqqq' N"V %V bVOc&.qV_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorage׀D378 VVMSTUVWXY[\]^_`aVVVVVWW, "%VGqqq.qSqqq [ "%VGqqq.qTqqq' \ "%VGqqq.qUqqq ] "%VGqqq.qVqqq ^ "%VGqqq.qWqqq _ "%VGqqq.qXqqq ` "%VGqqq.qYqqq aWmWn Wo "%&FqqWw.qcqOqqWq_ XDBucketForStereotypeswasEncoded_XDBucketForStereotypesstorage_XDBucketForStereotypesorderedMkcO78 WWMCDWW,"W %W bWOc&.qW_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageC378 WWMGHIJKLMNWWWWWWWW, "%Wqqq.qqqq' G "%Wqqq.qqqq H "%WWqqq.qqqq I78 WWM, "%Wqqq.qqqq' J "% Wqqq.qqqqU K "%Wqqq.qqqq' L "%Wqqq.qqqq M "%Wqqq.qqqq' N"X' %X( bX)Oc&.qX1_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageD378 X3X;MSTUVWXY[\]^_`aXX?X@XAXB, "%Wqqq.qSqqq [ "%Wqqq.qTqqq' \ "%Wqqq.qUqqq ] "%Wqqq.qVqqq ^ "%Wqqq.qWqqqK _ "%Wqqq.qXqqq ` "%Wqqq.qYqqq a8 X% "%Nqqq.qqqq'G  "%Nqqq.qqqq'G  "%ONqqq.qqqqG XX X "%&DqqX.qcqdqqXq_ XDBucketForStereotypeswasEncoded_XDBucketForStereotypesstorage_XDBucketForStereotypesordered k< 3i78 XXMCDXX ,"X %X bXpc&.qY_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorage C3 78 YYMGHIJKLMNYYYYYYYY, "%Xqqq.qqqq'  G "%Xqqq.qqqq  H "%Y;Xqqq.qqqq  I78 YIYJM, "% Xqqq.qqqqU  J "% Xqqq.qqqqU  K "%Xqqq.qqqq'  L "%Xqqq.qqqq  M "%Xqqq.qqqq'  N"Y %Y bYpc&.qY_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorage D378 YYMSTUVWXY[\]^_`aYYYYYYY, "%Xqqq.qSqqq [ "%Xqqq.qTqqq' \ "%Xqqq.qUqqq ] "%Xqqq.qVqqq ^ "%Xqqq.qWqqq _ "%Xqqq.qXqqq ` "%Xqqq.qYqqq aZZ Z! "%&DqqZ).qcqeqqZ1q_ XDBucketForStereotypeswasEncoded_XDBucketForStereotypesstorage_XDBucketForStereotypesordered"k=!yd78 Z5Z8MCDZ9Z:#.,"Z= %Z> bZ?qc&.qZG_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorage C3$78 ZIZRMGHIJKLMNZSZTZUZVZWZXZYZZ%&')*+,-, "%Z9qqq.qqqq'# G "%Z9qqq.qqqq# H "%Z|Z9qqq.qqqq(# I78 ZZM, "%Z9qqq.qqqq'# J "% Z9qqq.qqqqU# K "%Z9qqq.qqqq'# L "%Z9qqq.qqqq# M "%Z9qqq.qqqq'# N"Z %Z bZqc&.qZ_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorage D3/78 ZZMSTUVWXY[\]^_`aZZZZZZZ0123456, "% Z:qqq.qSqqq-. [ "%Z:qqq.qTqqq'. \ "%Z:qqq.qUqqq. ] "%Z:qqq.qVqqq. ^ "%Z:qqq.qWqqq. _ "%Z:qqq.qXqqq. ` "%Z:qqq.qYqqq. a[`[a [b "%&Dqq[j.qcqfqq[rq_ XDBucketForStereotypeswasEncoded_XDBucketForStereotypesstorage_XDBucketForStereotypesordered9k>8;=78 [v[yMCD[z[{:E,"[~ %[ b[rc&.q[_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorage7C3;78 [[MGHIJKLMN[[[[[[[[<=>@ABCD, "%[zqqq.qqqq': G "%[zqqq.qqqq: H "%[[zqqq.qqqq?: I78 [[M, "%[zqqq.qqqq': J "% [zqqq.qqqqU: K "%[zqqq.qqqq': L "%[zqqq.qqqq: M "%[zqqq.qqqq': N"\ %\ b\rc&.q\$_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorage7D3F78 \&\.MSTUVWXY[\]^_`a\/\0\1\2\3\4\5GHIJKLM, "%[{qqq.qSqqqE [ "%[{qqq.qTqqq'E \ "%[{qqq.qUqqqE ] "%[{qqq.qVqqqE ^ "%[{qqq.qWqqqE _ "%[{qqq.qXqqqE ` "%[{qqq.qYqqqE a\\ \ "%&Dqq\.qcqgqq\q_ XDBucketForStereotypeswasEncoded_XDBucketForStereotypesstorage_XDBucketForStereotypesorderedPk?O|%p"78 \\MCD\\Q\,"\ %\ b\sc&.q\_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageNC3R78 \\MGHIJKLMN\\\\\\\\܁STUWXYZ[, "%\qqq.qqqq'Q G "%\qqq.qqqqQ H "%\\qqq.qqqqVQ I78 ] ] M, "%\qqq.qqqq'Q J "% \qqq.qqqqUQ K "%\qqq.qqqq'Q L "%\qqq.qqqqQ M "%\qqq.qqqq'Q N"][ %]\ b]]sc&.q]e_!XDBucketForOwnedAttributesordered_$XDBucketForOwnedAttributeswasEncoded_!XDBucketForOwnedAttributesstorageND3]78 ]g]oMSTUVWXY[\]^_`a]p]q]r]s]t]u]v^_`abcd, "%\qqq.qSqqq\ [ "%\qqq.qTqqq'\ \ "%\qqq.qUqqq\ ] "%\qqq.qVqqq\ ^ "%\qqq.qWqqq\ _ "%\qqq.qXqqq\ ` "%\qqq.qYqqq\ a8 ]%78 ]]M,78 ]]M,78 ]]M,]]^XDModelPackage]]]]]^XDModelPackage_XDUMLPackageImp_XDUMLNamespaceImp_XDUMLNamedElementImp_XDUMLElementImp8 ]%78 ]]M,S2.1^^YXDPMModel^^YXDPMModelWXDModel_NSKeyedArchiver^)Troot"+5:?%BT[h{!@]|#DWY\_acehkmoqsuwx| 5@X^ 3Sz !$&(+-/245:BORTWY[j   +-/13579;LNPRTVXZ\^tTZcp| 3EN579;=>?@ACEFGIJSTV_nu}!"#%&368;=?bu~5>LYg|    $9H]k!$'*-/6<I]kx}2RTVXZ\]^`acdfhijlmr-QSUWY[]^`m~)FZp            W Y [ ] _ ` a b c e g h i k l y z { } !!!!!!!!!!! !!!"!$!%!&!e!g!i!k!m!n!o!p!q!s!u!v!w!y!z!!!!!!!!!!!!!!!" """""""""""""!"""G"k""""""""""""""""""""###### # ##.#Y#s####$($*$,$.$0$1$2$3$4$6$8$9$:$<$=$@$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$%'%)%+%-%/%0%1%2%3%5%7%8%9%;%<%?%~%%%%%%%%%%%%%%%%%%%%%%%%%%%%%&&&(&*&,&.&/&0&1&2&4&6&7&8&:&;&D&R&_&m&z&&&''$'D'd'f'h'j'l'n'o'p'r's'u'v'y'{'|'}'''''''''''''(()(M(O(Q(S(U(W(Y(Z(\(i(z(|(~((((((((((((((((((((((((((((()))@)B)D)F)H)I)J)K)L)N)P)Q)R)T)U)))))))))))))))))))))))******* * * * **M*O*Q*S*U*V*W*X*Y*[*]*^*_*a*b**********************+++++++ + +I+K+M+O+Q+R+S+T+U+W+Y+Z+[+]+^+++++++++++,,,,,!,#,%,',),+,:,<,>,@,B,E,H,K,M,_,s,,,,,------ -!-"-#-%-'-(-)-+-,-k-m-o-q-s-t-u-v-w-y-{-|-}------------------........ .!.#.%.&.'.).*.m....//F/m///////////////////00 0 000080\0000000000000000000000000011111F1H1J1L1N1O1P1Q1R1T1V1W1X1Z1[1111111111111111111111111112222B2D2F2H2J2K2L2M2N2P2R2S2T2V2W2`2a2c22222222222222222222233333333 3 3333!3&3(3*3,3N3q3t33333333333333344 4 4 444444444444#404s4u4w4y4{4}44444444444444444444444444444445555 5 5555555"5%5(5+5.5154575:5=5@5C5F5I5L5O5R5U5W5^5k5q5u5555555556 666.686L6U6\6g6u6666666667"7E7e77777777777777777777777777778878[8]8_8a8c8e8g8h8j8w888888888888888888888899999999 9 9 999N9P9R9T9V9W9X9Y9Z9\9^9_9`9b9c9999999999999999999:: : : ::::::::::::[:]:_:a:c:d:e:f:g:i:k:l:m:o:p:::::::::::::::;;;; ; ; ; ;;;;;;;;;W;Y;[;];_;`;a;b;c;e;g;h;i;k;l;;;<<<<<< < < <<<+<->6>Y>>>>??2?V?X?Z?\?^?`?b?e?g?i?l?n?p?s?u?v?{????????@@(@*@,@.@0@2@4@5@7@D@U@W@Y@[@]@_@a@c@e@v@x@z@|@~@@@@@@@@@@@@@@@@@@@@AAAA!A#A$A%A&A'A)A+A,A-A/A0AoAqAsAuAwAxAyAzA{A}AAAAAAAAAAAAAAAAAAAAAAAB#B%B'B)B+B,B-B.B/B1B3B4B5B7B8BwByB{B}BBBBBBBBBBBBBBBBBBCC C C CCCCCCCCCCCC[C]C_CaCcCdCeCfCgCiCkClCmCoCpCxCCCCCCCCCCD D-DMDODQDSDUDWDXDYD[D\D^D_DaDcDdDeDgDhDmDzDDDDDDDDDDE"E$E&E(E*E,E.E/E1E>EOEQESEUEWEYE[E]E_EpErEtEvExEzE|E~EEEEEEEEEEEEEEEEEFFFFFFFF F!F#F%F&F'F)F*FiFkFmFoFqFrFsFtFuFwFyFzF{F}F~FFFFFFFFFFFFFFFFFFFG"G$G&G(G*G+G,G-G.G0G2G3G4G6G7GvGxGzG|G~GGGGGGGGGGGGGGGGGGGGGGGGGHH H"H$H&H'H(H)H*H,H.H/H0H2H3HXH|HHHHHHHHHHHHHHHHHHIIIIIIIIIII^I`IbIdIfIgIhIiIjIlInIoIpIrIsI|IIIIIIIIIIIIIIIJJJJJJJJJJJJ J!J#J$JcJeJgJiJkJlJmJnJoJqJsJtJuJwJxJ{JJJJJJJJJJJJJJJKKKKKKKKKKKKK K"K#KbKdKfKhKjKkKlKmKnKpKrKsKtKvKwKKLL%L'L)L+L-L/L0L1L4L5L7L8L;L=L>L?LALBLGLTLYL[L]LbLeLhLjLLLLMMMMMM M MMM,M.M0M2M4M6M8M:M<MMMPMSMVMYM\M_MbMeMgMMMMMMMMMMMMMMMMMMNNNNNNN N N NNNNPNRNUNWNZN[N\N]N^N`NbNcNdNfNgNtNuNvNxNNNNNNNNNNNNNNNO OOOOOOOOOOOOO!O"OaOcOeOgOjOkOlOmOnOpOrOsOtOvOwOOOOOOOOOOOOOOOP P PPPPPPPPPPPP P!PFPjPPPPPPPPPPPPPPPPPPPPQQQQ Q QQQQTQVQXQZQ]Q^Q_Q`QaQcQeQfQgQiQjQQQQQQQQQQQQQQQQRRRRRR R R R RRRRRRSRURWRYR\R]R^R_R`RbRdReRfRhRiRRRRRRRRRRRRRRRRRSSSSSS S S SSSSSSRSTSVSXS[S\S]S^S_SaScSdSeSgShSqSSSSSSSSTTTT TT'T2T@TUTiTTTTTTTTTTTTTTTTTU%U'U)U+U-U.U/U0U1U3U5U6U7U9U:UyU{U}UUUUUUUUUUUUUUVV<V>V@VBVDVFVGVHVKVLVNVOVQVSVTVUVXVYV^VkVpVrVtVyV|VVVVVWWWWWW W"W#W&W3WDWFWHWJWLWNWPWRWTWeWhWkWnWqWtWwWzW}WWWWWWWWWWWWWWWWXXXXXXXXX X"X$X%X&X(X)XhXjXmXoXrXsXtXuXvXxXzX{X|X~XXXXXXXXXXXXXXXXXXXXY$Y&Y(Y*Y-Y.Y/Y0Y1Y3Y5Y6Y7Y9Y:YyY{Y}YYYYYYYYYYYYYYYYYYYYYYYYYYYZ#Z%Z'Z)Z,Z-Z.Z/Z0Z2Z4Z5Z6Z8Z9Z^ZZZZZZZZZZZZZZZ[[[[[[[[[ [#[&[)[,[.[m[o[r[t[w[x[y[z[{[}[[[[[[[[[[[[[[[[[[[[[\\\\ \#\$\%\&\'\)\+\,\-\/\0\o\q\t\v\y\z\{\|\}\\\\\\\\\\\\\\\\\\\\\\]]]!]#]&]'](])]*],].]/]0]2]3]r]t]v]x]{]|]}]~]]]]]]]]]^^6^8^:^<^>^@^A^B^E^F^H^I^K^M^N^O^R^S^X^e^j^l^n^s^v^y^{^^^_________ _-_>_@_B_D_F_H_J_L_N___b_e_h_k_n_q_t_w_y_______________` ```````````` `"`#`b`d`g`i`l`m`n`o`p`r`t`u`v`x`y```````````````````aa a"a$a'a(a)a*a+a-a/a0a1a3a4asauawaya|a}a~aaaaaaaaaaaaaaaaaaaaaaabbb!b#b&b'b(b)b*b,b.b/b0b2b3bXb|bbbbbbbbbbbbbbbbbcccccccc c#c&c(cgcickcmcpcqcrcsctcvcxcyczc|c}cccccccccccccccdddddddddd d"d#d$d&d'dfdhdjdldodpdqdrdsdudwdxdyd{d|dddddddddddddddeeeeeeeeeee!e"e#e%e&eeegeiekeneoepeqeretevewexeze{eef f)f+f-f/f1f3f4f5f8f9f;f<f>f@fAfBfEfFfKfXf]f_fafffiflfnfffgggg g g gggg g1g3g5g7g9g;g=g?gAgRgUgXg[g^gagdgggjglggggggggggggggghhhhh h h h h hhhhhhhUhWhZh\h_h`hahbhchehghhhihkhlhyhzh{h}hhhhhhhhhhhhhhhiiiiiiiiii i"i#i$i&i'ifihijilioipiqirisiuiwixiyi{i|iiiiiiiiiiiiiiijjjjjjjjjjj!j"j#j%j&jKjojjjjjjjjjjjjjjjjjjjkkk k kkkkkkZk\k^k`kckdkekfkgkikkklkmkokpkkkkkkkkkkkkkkkllll l lllllllllllYl[l]l_lblcldlelflhljlklllnlollllllllllllllllm m m mmmmmmmmmmmmm^m`mbmdmgmhmimjmkmmmompmqmsmtmmnn"n$n&n(n*n,n-n.n1n2n4n5n7n9n:n;n>n?nDnQnVnXnZn_nbnengnnnnnoooooo o oo*o,o.o0o2o4o6o8o:oKoNoQoToWoZo]o`ocoeoooooooooooooooooooppppppp p p pppNpPpSpUpXpYpZp[p\p^p`papbpdpeprpsptpvpppppppppppppppq q qqqqqqqqqqqqq q_qaqcqeqhqiqjqkqlqnqpqqqrqtquqqqqqqqqqqqqqqqr r r rrrrrrrrrrrrrDrhrrrrrrrrrrrrrrrrrrrrssss s ssssSsUsXsZs]s^s_s`sascsesfsgsisjsssssssssssssssstttttt t t t ttttttStUtXtZt]t^t_t`tatctetftgtitjtltttttttttttttttuuuuu u u u u uuuuuuuUuWuYu[u^u_u`uaubudufuguhujukuuuvvvvv!v#v$v%v(v)v+v,v.v0v1v2v5v6v;vHvMvOvQvVvYv\v^vvvvvvvvvvwwww!w#w%w'w)w+w-w/w1wBwEwHwKwNwQwTwWwZw\wwwwwwwwwwwwwwwwwwwwwwwwwxxxxxxExGxJxLxOxPxQxRxSxUxWxXxYx[x\xixjxkxmxxxxxxxxxxxxxxxyyyyy y y y yyyyyyyyVyXyZy\y_y`yaybycyeygyhyiykylyyyyyyyyyyyyyyyzzzzz z z z z zzzzzzz;z_zzzzzzzzzzzzzzzzzzzzzzz{{{{ { {J{L{N{P{S{T{U{V{W{Y{[{\{]{_{`{{{{{{{{{{{{{{{{{{{{{{||||||| | |I|K|N|P|S|T|U|V|W|Y|[|\|]|_|`|c|||||||||||||||||||}}}}}}}} } } } }L}N}P}R}U}V}W}X}Y}[}]}^}_}a}b}}}~~~~~~~~~~ ~"~#~%~'~(~)~,~-~2~?~D~F~H~M~P~S~U~z~~~~~~~~~~~ "$&(9<?BEHKNQS<>ACFGHIJLNOPRS`abd MOQSVWXYZ\^_`bc 2V}ACEGJKLMNPRSTVW@BDFIJKLMOQRSUV?ACEHIJKLNPQRTU  )6;=?DGJLq0369<?BEHJ358:=>?@ACEFGIJWXY[DFHJMNOPQSUVWYZ)Mt8:<>ABCDEGIJKMN79<>ABCDEGIJKMNQ:<>@CDEFGIKLMOP  -246;>ACh '*-0369<?A*,/145678:<=>@ANOPR;=?ADEFGHJLMNPQ Dk/13589:;<>@ABDE.024789:;=?@ACD-/136789:<>?@BC  %').146[  #&),/24suwy|}~"$'()*+-/0134ABCE.024789:;=?@ACD7^"$'),-./0245689xz|~"$'),-./0245689xz|~"$&(+,-./134578  "'*-/Tx"%(+-lnpruvwxy{}~ !"#$&()*,-:;<>}')+-01234689:<=|~ 0W{~!$%&'(*,-.01prtvyz{|} #$%&')+,-/0oqsuxyz{|~"#$%&(*+,./z  "Gk  _acehijklnpqrtu  -./1prtvyz{|} #$%&')+,-/0oqsuxyz{|~#Jnqsuwy{| !"$%dfhjmnopqsuvwyz !"$%dfhjmnopqsuvwyz !#$o <` TVXZ]^_`acefgij "#$&egiknopqrtvwxz{ !"$%dfhjmnopqsuvwyz?cfhjlnpqt Y[]_bcdefhjklno Y[]_bcdefhjklno d 1U| IKMORSTUVXZ[\^_ Z\^`cdefgiklmop Y[]_bcdefhjklno 4X[]_acefiv MOQSVWXYZ\^_`bc LNQSVWXYZ\^_`bce Z}'Kr?ACEHIJKLNPQRTU PRTVYZ[\]_abcef OQSUXYZ[\^`abde*NQSUWY[\_l{}ƒ…‡‰˜›ž¡¤§ª­¯DFHJMNOPQSUVWYZÙÛÝßâãäåæèêëìîïDFHJMNOPQSUVWYZęěĝğĢģĤĥĦĨĪīĬĮįOrŒŲŴŶŸźżŽž@gƋƎƐƒƔƖƘƙƜƩƺƼƾ468:=>?@ACEFGIJljNjǍǏǒǓǔǕǖǘǚǛǜǞǟEGIKNOPQRTVWXZ[ȚȜȞȠȣȤȥȦȧȩȫȬȭȯȰDFHJMNOPQSUVWYZəɛɝɟɢɣɤɥɦɨɪɫɬɮɯCFHJLNPQTaprtvxz|~ʍʐʓʖʙʜʟʢʤ?ACEHIJKLNPQRTU˔˖˘˚˝˞˟ˠˡˣ˥˦˧˩˪>@BDGHIJKMOPQST̢̨̗̙̜̝̞̟̠̤̥̦̩̓̕Il͌ͬͮͰͲʹͶͷ͸ͻͼ;Ϳ:a΅ΈΊΌΎΐΒΓΖΣδζθκμξ.024789:;=?@ACDσυχωόύώϏϐϒϔϕϖϘϙ?ACEHIJKLNPQRTUДЖИКНОПРСУХЦЧЩЪ>@BDGHIJKMOPQSTѓѕїљќѝўџѠѢѤѥѦѨѩ=@BDFHJKN[jlnprtvx҇ҊҍҐғҖҙҜҞ2468;<=>?ACDEGHӇӉӋӍӐӑӒӓӔӖӘәӚӜӝ1357:;<=>@BCDFGԆԈԊԌԏԐԑԒԓԕԗԘԙԛԜ<_՟ագեէթժիծկձղմնշոջռ -Tx{}ցփօֆ։ֱֳֵַ֖֧֭֩֫֯!#%'*+,-.023467vxz|׀ׁׂ׃ׇׅ׈׉׋׌2468;<=>?ACDEGH؇؉؋؍ؘؙؚؐؑؒؓؔؖ؜؝1357:;<=>@BCDFGنويٌُِّْٕٜٓٗ٘ٙٛ 03579;=>AN]_acegikz}ڀڃچډڌڏڑ&(*,/01235789;<{}ہۄۅۆۇۈۊیۍێېۑ(*,.1234579:;=>}܁܃܆܇܈܉܊܌܎܏ܐܒܓ3Vvݖݘݚݜݞݠݡݢݥݦݨݩݫݭݮݯݲݳݸ$Kortvxz|}ހލޞޠޢޤަިުެޮ޿!"#$%')*+-.moqsvwxyz|~߀߂߃)+-/234568:;<>?~(*,.1234579:;=>}'*,.02458ETVXZ\^`bqtwz} "%&'()+-./12qsuwz{|}~!$%&'(*,-.01prtvyz{|}&Ii>begikmops  !`bdfijklmoqrsuv "%&'()+-./12qsuwz{|}~!$%&'(*,-.01prtvyz{|}!#%'(+8GIKMOQSUdgjmpsvy{ !#%&')*ikmorstuvxz{|~ "$%&()hjlnqrstuwyz{}~Aa6Z]_aceghkx XZ\^abcdegijkmn !#%&')*ikmorstuvxz{|~ "$%&()hjlnqrstuwyz{}~ #0?ACEGIKM\_behknqs ]_acfghijlnoprs \^`befghikmnoqr5Uuwy{}+ORTVXZ\]`m~ MOQSVWXYZ\^_`bc ^`bdghijkmopqst ]_acfghijlnoprs %468:<>@BQTWZ]`cfh QSUWZ[\]^`bcdfg$Hk Dhjmoqsvy{}>ACEGIKLO\moqsuwy{} IKMORSTUVXZ[\^_  UWY[^_`abdfghjkQSUWZ[\]^`bcdfg )/5; !#(+.0Uy #&),.moqsvwxyz|~!"#$%')*+-.;<=?~(*,.1234579:;=>} 1X| "%&'()+-./12qsuwz{|}~    ! $ % & ' ( * , - . 0 1 p r t v y z { | }                          # $ % & ' ) + , - / 0 {                            # % J n                             ! # b d f h k l m n o q s t u w x                             " # 0 1 2 4 s u w y | } ~                       !#&'()*,./023rtvx{|}~&Mqtvxz|~!#$%'(gikmpqrstvxyz|}!#$%'(gikmpqrstvxyz|} "#$&'r  @d XZ\^abcdegijkmn   &'(*ikmorstuvxz{|~ "$%&()hjlnqrstuwyz{}~Cgjlnprtux   \^`befghikmnoqr  []_adefghjlmnpq  f  6Z  NPRTWXYZ[]_`acd    _acehijklnpqrtu   ^`bdghijkmopqst9]`bdfhjkn{              R T V X [ \ ] ^ _ a c d e g h                 !!!!!!! ! ! !!!!!Q!S!U!W!Z![!\!]!^!`!b!c!d!f!g!!!!!!!!!!!!!!!!!""""""" " " """""]"""""""""""""""""""""""""#####-#Q#x##########################$$$$E$G$I$K$N$O$P$Q$R$T$V$W$X$Z$[$$$$$$$$$$$$$$$$$$$$$$$$$%%%%%%%%%%V%X%Z%\%_%`%a%b%c%e%g%h%i%k%l%%%%%%%%%%%%%%%&&&&& & & & & &&&&&&&U&W&Y&[&^&_&`&a&b&d&f&g&h&j&k&&&&&&&&&&&&&&&&' '0'T'W'Y'[']'_'a'b'e'r''''''''''''''''''''''''((((((( ( (I(K(M(O(R(S(T(U(V(X(Z([(\(^(_(((((((((((((((((((((())))))) ) )M)q))))*&*M*m************************++@+g+++++++++++++++++++++++++++++,4,6,9,;,>,?,@,A,B,D,F,G,H,J,K,T,U,W,,,,,,,,,,,,,,,,,,,,,,,,,,,,---@-B-E-G-J-K-L-M-N-P-R-S-T-V-W-`-a-c-------------------....... . . . ... .#.&.+.-.0.2.T.w................// /#/%/(/)/*/+/,/./0/1/2/4/5/=/J/S/V/Y/[/^/g/j/m/p/s/u/|///00#0C0E0G0I0K0N0O0P0S0T0V0W0Z0]0^0_0b0c0h0u0z0|0~000000011"1$1&1(1*1,1-101=1N1P1R1T1V1X1Z1\1^1o1r1u1x1{1~1111111111111111111222!2#2&2'2(2)2*2,2.2/2022232r2t2w2y2|2}2~2222222222222222222222222223.3032343738393:3;3=3?3@3A3C3D3333333333333333333333333333334-4/4143464748494:4<4>4?4@4B4C4h4444444444445555 5 5555!5$5'5*5-505356585w5y5{5}555555555555555555555555556!6#6%6'6*6+6,6-6.6062636466676v6x6{6}666666666666666666666666667!7#7%7'7*7+7,7-7.7072737476777v7x7{7}777777777777788;8=8?8A8C8F8G8H8K8L8N8O8Q8T8U8V8Y8Z8_8l8q8s8u8z8}88888999999!9#9$9'949E9G9I9K9M9O9Q9S9U9f9i9l9o9r9u9x9{9~9999999999999999:::::::: :!:#:%:&:':):*:i:k:n:p:s:t:u:v:w:y:{:|:}:::::::::::::::::::::;%;';);+;.;/;0;1;2;4;6;7;8;:;;;z;|;~;;;;;;;;;;;;;;;;;;;;;;;;;;;<$<&<(<*<-<.>>>>!>">#>$>%>'>)>*>+>->.>m>o>q>s>v>w>x>y>z>|>~>>>>>>>>>>>>>>>>>>>????? ?!?"?#?$?&?(?)?*?,?-?l?n?p?r?u?v?w?x?y?{?}?~?????@@0@2@4@6@8@;@<@=@@@A@C@D@F@H@I@J@M@N@S@`@e@g@i@n@q@t@v@@@A A AAAAAAAA(A9A;A=A?AAACAEAGAIAZA]A`AcAfAiAlAoArAtAAAAAAAAAAAAAAABB B BBBBBBBBBBBBB]B_BbBdBgBhBiBjBkBmBoBpBqBsBtBBBBBBBBBBBBBBBBBBBCCCCC"C#C$C%C&C(C*C+C,C.C/CnCpCrCtCwCxCyCzC{C}CCCCCCCCCCCCCCCCCCCCDDDDD!D"D#D$D%D'D)D*D+D-D.DSDwDDDDDDDDDDDDDDDDDDDE EEEEEEE!E#EbEdEfEhEkElEmEnEoEqEsEtEuEwExEEEEEEEEEEEEEEEF FFFFFFFFFFFFF!F"FaFcFeFgFjFkFlFmFnFpFrFsFtFvFwFFFFFFFFFFFFFFFG G GGGGGGGGGGGG G!G`GbGdGfGiGjGkGlGmGoGqGrGsGuGvGGHH$H&H(H*H,H/H0H1H4H5H7H8H;H>H?H@HCHDHIHVH[H]H`HeHhHkHmHHHHIIIIII I"I#I&I3IBIDIFIHIJILINIPI_IbIeIhIkInIqItIvIIIIIIIIIIIIIIIJ J JJJJJJJJJJJJJ J_JaJdJfJiJjJkJlJmJoJqJrJsJuJvJJJJJJJJJJJJJJJJJJJKKKK!K$K%K&K'K(K*K,K-K.K0K1KpKrKtKvKyKzK{K|K}KKKKKKKKKKKKKKKKKKKKKLL$LKLoLrLuLwLyL{L}L~LLLLLLLLLLLLLLMMMMMMM M M M!M4MGMOMRMUMXM[M^M|MMMMMMMNNN(N;NRNdNmNnNpNNNNNNNNNNNNNNNOOOO O OOOOOOOOOOOYO[O^O`OcOdOeOfOgOiOkOlOmOoOpOOOPP P"P$P&P)P*P+P.P/P1P2P4P7P8P9P<P=PBPOPTPVPXP]P`PcPePPPPPPQQQQQQ QQ(Q*Q,Q.Q0Q2Q4Q6Q8QIQLQOQRQUQXQ[Q^QaQcQQQQQQQQQQQQQQQQQQQRRRRRRRR R R R RLRNRQRSRVRWRXRYRZR\R^R_R`RbRcRpRqRrRtRRRRRRRRRRRRRRRSS S SSSSSSSSSSSSS]S_SaScSfSgShSiSjSlSnSoSpSrSsSSSSSSSSSSSSSSSTT T T TTTTTTTTTTTTBTfTTTTTTTTTTTTTTTTTTTTTUUUU U UUUQUSUUUWUZU[U\U]U^U`UbUcUdUfUgUUUUUUUUUUUUUUUUUUVVVVVVV V V VVVVPVRVTVVVYVZV[V\V]V_VaVbVcVeVfVVVVVVVVVVVVVVVVVVWWWWWWW W W W WWWOWQWSWUWXWYWZW[W\W^W`WaWbWdWeWnWoWqWWWWWWWWWWWWWWWXXX X XXXXXXXXXXXXZX\X_XaXdXeXfXgXhXjXlXmXnXpXqXXXYY!Y#Y%Y'Y)Y*Y+Y.Y/Y1Y2Y4Y6Y7Y8Y;Y<YAYNYSYUYWY\Y_YbYdYYYYYYYZZZZZ ZZ'Z)Z+Z-Z/Z1Z3Z5Z7ZHZKZNZQZTZWZZZ]Z`ZbZZZZZZZZZZZZZZZZZZZZ[[[[[[[[ [ [ [K[M[P[R[U[V[W[X[Y[[[][^[_[a[b[o[p[q[s[[[[[[[[[[[[[[[\\ \ \ \\\\\\\\\\\\\\^\`\b\e\f\g\h\i\k\m\n\o\q\r\\\\\\\\\\\\\\\]]] ] ]]]]]]]]]]]]A]e]]]]]]]]]]]]]]]]]]]]]^^^^ ^ ^^^P^R^U^W^Z^[^\^]^^^`^b^c^d^f^g^^^^^^^^^^^^^^^^^^_______ _ _ ____P_R_U_W_Z_[_\_]_^_`_b_c_d_f_g__________________``````` ` ` ````P`R`T`V`Y`Z`[`\`]`_`a`b`c`e`f```aaaaaaaa a#a$a&a'a)a+a,a-a0a1a6aCaHaJaLaQaTaWaYa~aaaaaaaaaaab bbb b"b$b&b(b*b,b=b@bCbFbIbLbObRbUbWbbbbbbbbbbbbbbbbbbbbbbbbbbbbccc@cBcEcGcJcKcLcMcNcPcRcScTcVcWcdcecfchcccccccccccccccccddddddd d d dddddQdSdUdWdZd[d\d]d^d`dbdcdddfdgddddddddddddddddddeeeeeee e e eeee6eZeeeeeeeeeeeeeeeeeeeeeeeeeffffEfGfJfLfOfPfQfRfSfUfWfXfYf[f\fffffffffffffffffffffffffggggggEgGgJgLgOgPgQgRgSgUgWgXgYg[g\ggggggggggggggggggggggggghhhhhhEhGhIhKhNhOhPhQhRhThVhWhXhZh[hhhi i i iiiiiiiiiii i!i"i%i&i+i8i=i?iAiFiIiLiNisiiiiiiiiiiijjjjjjjjjj!j2j5j8j;j>jAjDjGjJjLjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjk5k7k:k<k?k@kAkBkCkEkGkHkIkKkLkYkZk[k]kkkkkkkkkkkkkkkkkkkkkkkklllllllFlHlJlLlOlPlQlRlSlUlWlXlYl[l\lllllllllllllllllllllllllmmmmmm+mOmvmmmmmmmmmmmmmmmmmmmmmmmmmmmn:n<n>n@nCnDnEnFnGnInKnLnMnOnPnnnnnnnnnnnnnnnnnnnnnnnnnnnnnno9o;o=o?oBoCoDoEoFoHoJoKoLoNoOoooooooooooooooooooooooooooooop8p:p<p>pApBpCpDpEpGpIpJpKpMpNpppppqqqqqqq q qqqqqqqqqq+q0q2q4q9q<q?qAqfqqqqqqqqqqqqrrrr r rrrrr%r(r+r.r1r4r7r:r=r?r~rrrrrrrrrrrrrrrrrrrrrrrrrrrrrs(s*s-s/s2s3s4s5s6s8s:s;s<s>s?sLsMsNsPsssssssssssssssssssssssssssssst9t;t=t?tBtCtDtEtFtHtJtKtLtNtOttttttttttttttttttttttttttttttuuBuiuuuuuuuuuuuuuuuuuuuuuuuuuuuv-v/v2v4v7v8v9v:v;v=v?v@vAvCvDvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvw-w/w2w4w7w8w9w:w;w=w?w@wAwCwDwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwx-x/x1x3x6x7x8x9x:x<x>x?x@xBxCxxxxxxxxxxxyyyyyy y y yyyy!y&y(y*y/y2y5y7y\yyyyyyyyyyyyyyyzzzzzz zzz!z$z'z*z-z0z3z5ztzvzxzzz}z~zzzzzzzzzzzzzzzzzzzzzzzz{{ {#{%{({){*{+{,{.{0{1{2{4{5{B{C{D{F{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{|/|1|3|5|8|9|:|;|<|>|@|A|B|D|E||||||||||||||||||||||||||||||}}8}_}}}}}}}}}}}}}}}}}}}}}}}}}}}~#~%~'~)~,~-~.~/~0~2~4~5~6~8~9~x~z~|~~~~~~~~~~~~~~~~~~~~~~~~~~~~"$&(+,-./134578wy{}!#%'*+,-.023467#&)+Pt!$')hjlnqrstuwyz{}~ "$%&()678:y{}#%'),-./0245689xz|~,Swz|~ !"#$&()*,-lnpruvwxy{}~ !"#$&()*,-6V}3W~:^acegiklo|   \^`befghikmnoqr  &')hjlnqrstuwyz{}~PRTVYZ[\]_abcefIl<c02469:;<=?ABCEFACEGJKLMNPRSTVW@BDFIJKLMOQRSUV?BDFHJLMP]lnprtvxz468:=>?@ACEFGIJ3579<=>?@BDEFHI>a2Y}&(*,/01235789;<{}79;=@ABCDFHIJLM68:<?@ABCEGHIKL58:<>@BCFSbdfhjlnp*,.0345679;<=?@)+-/234568:;<>?~  )3<?ADGJM"Bi    -0258:_   !$'*-0368wy{}!#%'*+,-.023467vx{}-/24789:;=?@ACDQTWZ]_)+.0345679;<=?@R_dgjoruw<>@BDGHILMOPRUVWZ[`mrtv{~ "$%(5FHJLNPRTVgjmpsvy| !"$&'(*+jloqtuvwxz|}~&(*,/01235789;<{}%')+./0124678:;` "%(+.0oqtvyz{|} #$%&')+,-/0oqtvyz{|} #$%&')+,-/0oqsuxyz{|~3579;>?@CDFGILMNQRWdikmruxz,=?ACEGIKM^adgjmpsvx !"acfhklmnoqstuwx!#&'()*,./023rtvx{|}~ "%&'()+-./12W{"%'fhkmpqrstvxyz|} "#$&'fhkmpqrstvxyz|} "#$&'fhjlopqrsuwxy{|!$'*-p"Ip ?c  WY[]`abcdfhijlm    VX[]`abcdfhijlmvwy  !#$147:=?bu   2?DGJORUW]d"#%&(+,-016CHJLQTWY~  "$&(*,=@CFILORUW@BEGJKLMNPRSTVWdefh   QSUWZ[\]^`bcdfg   6ZEGJLOPQRSUWXY[\EGJLOPQRSUWXY[\›Ÿ¡¤¥¦§¨ª¬­®°±EGIKNOPQRTVWXZ[æ   "#$'(-:?ACHKNPuę!#47:=@CFILNōŏőœŖŗŘřŚŜŞşŠŢţ79<>ABCDEGIJKMN[\]_ƞƠƢƤƧƨƩƪƫƭƯưƱƳƴ HJLNQRSTUWYZ[]^ǝǟǡǣǦǧǨǩǪǬǮǯǰDzdz-QxȜȟȡȣȥȧȩȪȭȺ<>ACFGHIJLNOPRSɒɔɖɘɛɜɝɞɟɡɣɤɥɧɨ<>ACFGHIJLNOPRSʒʔʖʘʛʜʝʞʟʡʣʤʥʧʨ<>@BEFGHIKMNOQR[^ach˧˩˫˭˰˱˲˳˴˶˸˹˺˼˽   QSVX[\]^_acdegh̳ !"%&()+-./238EJLNSVY[̀ͤ  "$&(*,.?BEHKNQTWYΘΚΜΞΡ΢ΣΤΥΧΩΪΫέήBDGILMNOPRTUVXYfghjϩϫϭϯϲϳϴϵ϶ϸϺϻϼϾϿ    SUWY\]^_`bdefhiШЪЬЮбвгдезйклно   8\уѧѪѬѮѰѲѴѵѸGIKMPQRSTVXYZ\]ҜҞҠҢҥҦҧҨҩҫҭҮүұҲFHJLOPQRSUWXY[\ӛӝӟӡӤӥӦӧӨӪӬӭӮӰӱEGIKNOPQRTVWXZ[Ԧ    !"%&+8=?AFILNs՗վ!258;>ADGJL֋֍֏֑֖֚֔֕֗֘֜֝֞֠֡57:<?@ABCEGHIKLYZ[]למנעץצקרש׫׭׮ׯױײFHJLOPQRSUWXY[\؛؝؟ءؤإئابتجحخذر+Ovٟٚٝ١٣٥٧٨٫ٸ:<>@CDEFGIKLMOPڏڑړڕژڙښڛڜڞڠڡڢڤڥ9;=?BCDEFHJKLNOێېے۔ۗۘۙۚۛ۝ۣ۟۠ۡۤ8:<>ABCDEGIJKMNܙܼ  +0249<?Af݊ݱ  %(+.147:=?~ހނބއވމފދލޏސޑޓޔ(*-/234568:;<>?LMNPߏߑߓߕߘߙߚߛߜߞߠߡߢߤߥ9;=?BCDEFHJKLNOBi-/136789:<>?@BC,.0256789;=>?AB+-/145678:<=>@A  #%',/24Y}!$'*-02qsuwz{|}~ "%&'()+-./12?@AC,.0256789;=>?AB5\ "%'*+,-.023467vxz| "$&)*+,-/12356uwy{~!#%()*+,.01245>?A(*-/1234579:;=>  "$),/1Vz!$'*-/nprtwxyz{}"#$%&(*+,./<=>@)+-/234568:;<>?~2Y}!#&'()*,./023rtvx{|}~ "%&'()+-./12qsuwz{|}~!$%&'(*,-.01|"$Im  "acegjklmnprstvw  !"/013rtvx{|}~ "%&'()+-./12qsuwz{|}~%Lpsuwy{}~!"#%&egiknopqrtvwxz{ !"$%dfhjmnopqsuvwyz !#$o <`  TVXZ]^_`acefgij    "#$&egiknopqrtvwxz{ !"$%dfhjmnopqsuvwyz?cfhjlnpqt  Y[]_bcdefhjklno  Y[]_bcdefhjklno   d  1U| IKMORSTUVXZ[\^_  Z\^`cdefgiklmop                Y [ ] _ b c d e f h j k l n o                  4 X [ ] _ a c e f i v                                 N P R T W X Y Z [ ] _ ` a c d                               N P R T W X Y Z [ ] _ ` a c d                               Y |                          'Kr?ACEHIJKLNPQRTU PRTVYZ[\]_abcef    OQSUXYZ[\^`abde*NQSUWY[\_l{}CEGILMNOPRTUVXYGk Gg:a.024789:;=?@ACD-/24789:;=?@ACDMNP []_adefghjlmnpq "$.;DO\h!"#&')*,/0145:GLNPUX[] "$&(*,.0ADGJMPSVY[DFIKNOPQRTVWXZ[hijl     UWY[^_`abdfghjk    :^     I K M O R S T U V X Z [ \ ^ _                       !!!!!!! !H!J!L!N!Q!R!S!T!U!W!Y!Z![!]!^!!!!!!!!!!!!!!!!!!!!!!!!"""""""G"I"K"M"P"Q"R"S"T"V"X"Y"Z"\"]"""# # ###########!#$#%#&#)#*#/#<#A#C#E#J#M#P#R#w###########$$$$$$$$!$#$%$6$9$<$?$B$E$H$K$N$P$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$%9%;%>%@%C%D%E%F%G%I%K%L%M%O%P%]%^%_%a%%%%%%%%%%%%%%%%%%%%%&&&&&&&& & &J&L&N&P&S&T&U&V&W&Y&[&\&]&_&`&&&&&&&&&&&&&&&&&&&&&&''''''' ' '/'S'z'''''''''''''''''''''''''''(>(@(B(D(G(H(I(J(K(M(O(P(Q(S(T(((((((((((((((((((((((((((((()=)?)A)C)F)G)H)I)J)L)N)O)P)R)S))))))))))))))))))))))))))))))*<*>*@*B*E*F*G*H*I*K*M*N*O*Q*R***++++++ + + ++++++++++ +%+2+7+9+;+@+C+F+H+m++++++++++++, , ,,,,,,,,,,/,2,5,8,;,>,A,D,F,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,-/-1-4-6-9-:-;-<-=-?-A-B-C-E-F-S-T-U-W----------------------------...@.B.D.F.I.J.K.L.M.O.Q.R.S.U.V.............................//%/I/p///////////////////////////0406080:0=0>0?0@0A0C0E0F0G0I0J000000000000000000000000000000131517191<1=1>1?1@1B1D1E1F1H1I111111111111111111111111111111222427292<2=2>2?2@2B2D2E2F2H2I22222222333333 3 3 3333333(3-3/3136393<3>3c33333333333344444 4 4 444"4%4(4+4.4144474:4<4{4}44444444444444444444444444445%5'5*5,5/50515253555758595;5<5I5J5K5M55555555555555555555555555555566686:6<6?6@6A6B6C6E6G6H6I6K6L66666666666666666666666666666677?7f7777777777777777777777777778*8,8.808384858687898;8<8=8?8@8888888888888888888888888888889)9+9-9/9293949596989:9;9<9>9?9~99999999999999999999999999999:(:*:,:.:1:2:3:4:5:7:9:::;:=:>::::::::::::::;;;;;; ; ;;;";$;&;+;.;1;3;X;|;;;;;;;;;;;;;;;;<<<<<<<< <#<&<)<,=?=@=B==============================>+>->/>1>4>5>6>7>8>:><>=>>>@>A>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>??4?[???????????????????????????@@!@$@&@)@*@+@,@-@/@1@2@3@5@6@u@w@y@{@~@@@@@@@@@@@@@@@@@@@@@@@@@AA!A$A&A)A*A+A,A-A/A1A2A3A5A6AuAwAyA{A~AAAAAAAAAAAAAAAAAAAAAAAAABB!B#B%B(B)B*B+B,B.B0B1B2B4B5BBBBBBBBBBBBBBBBBBBCCCCCCCC!C$C'C)CNCrCCCCCCCCCCCCCCCCCCCCD DDDDDDD"D%D'DfDhDjDlDoDpDqDrDsDuDwDxDyD{D|DDDDDDDDDDDDDDDEEEEEEEEEE E"E#E$E&E'E4E5E6E8EwEyE{E}EEEEEEEEEEEEEEEEEEEEEEEEEEF!F#F%F'F*F+F,F-F.F0F2F3F4F6F7FvFxFzF|FFFFFFFFFFFFFFFFFFFFFFFFFFGG*GQGuGxGzG|G~GGGGGGGGGGGGGGGGGGGGGGHHHHHHH H!H"H$H&H'H(H*H+HjHlHnHpHsHtHuHvHwHyH{H|H}HHHHHHHHHHHHHHHHHIIIIIIII I!I#I%I&I'I)I*IiIkImIoIrIsItIuIvIxIzI{I|I~IIIIIIIIIIIIIIIIJJJJJJJJJ J"J$J%J&J(J)JtJJJJJJJJJJJJJJJJJJJJJKK KKKKKKKCKgKKKKKKKKKKKKKKKKKKKKLLLL LLLLLLL[L]L_LaLdLeLfLgLhLjLlLmLnLpLqLLLLLLLLLLLLLLLMMM M MMMMMMMMMMMM)M*M+M-MlMnMpMrMuMvMwMxMyM{M}M~MMMMMMMMMMMMMMMMMMNNNNNN N!N"N#N%N'N(N)N+N,NkNmNoNqNtNuNvNwNxNzN|N}N~NNNNNNNNNNNNNNNNNNOOFOjOmOoOqOsOuOwOxO{OOOOOOOOOOOOOOOOOOP P PPPPPPPPPPPPP P_PaPcPePhPiPjPkPlPnPpPqPrPtPuPPPPPPPPPPPPPPPQ Q Q QQQQQQQQQQQQQ^Q`QcQeQhQiQjQkQlQnQpQqQrQtQuQQQQQQQQQQQQQQQR R R RRRRRRRRRRRRR(R)R+RjRlRnRpRsRtRuRvRwRyR{R|R}RRRRRRRRRRRRRRRRRSSSSSSS S!S"S$S&S'S(S*S+SvSSSSSSSSSSSSSSSSSSSSSTT TTTTTTTCTgTTTTTTTTTTTTTTTTTTTTUUUU UUUUUUU[U]U_UaUdUeUfUgUhUjUlUmUnUpUqUUUUUUUUUUUUUUUVVV V VVVVVVVVVVVV)V*V+V-VlVnVpVrVuVvVwVxVyV{V}V~VVVVVVVVVVVVVVVVVVWWWWWW W!W"W#W%W'W(W)W+W,WkWmWoWqWtWuWvWwWxWzW|W}W~WWWWWWWWWWWWWWWWWWXXFXjXmXoXqXsXuXwXxX{XXXXXXXXXXXXXXXXXXY Y YYYYYYYYYYYYY Y_YaYcYeYhYiYjYkYlYnYpYqYrYtYuYYYYYYYYYYYYYYYZ Z Z ZZZZZZZZZZZZZ^Z`ZbZdZgZhZiZjZkZmZoZpZqZsZtZZZZZZZZZZZZZZZ[[ [ [[[[[[[[[[[[[i[[[[[[[[[[[[[[[[[[[[[[\\\\ \\\\:\^\\\\\\\\\\\\\\\\\\\\\\\]]]] ]]]]R]T]V]X][]\]]]^]_]a]c]d]e]g]h]]]]]]]]]]]]]]]]]^^^^^^ ^ ^ ^^^^^^ ^!^"^$^c^e^g^i^l^m^n^o^p^r^t^u^v^x^y^^^^^^^^^^^^^^^_ ____________ _"_#_b_d_f_h_k_l_m_n_o_q_s_t_u_w_x________________``=`a`d`f`h`j`l`n`o`r``````````````````aaaaa a a aaaaaaaaaWaYa[a]a`aaabacadafahaiajalamaaaaaaaaaaaaaaabbbbb b b bbbbbbbbbWbYb[b]b`babbbcbdbfbhbibjblbmbbbbbbbbbbbbbbbccccc c c c ccccccccbcccccccccccccccccccccccccdddd d/dSdzdddddddddddddddddddddddddeeeeeGeIeKeMePeQeReSeTeVeXeYeZe\e]eeeeeeeeeeeeeeeeeeeeeeeefffffffffffXfZf\f^fafbfcfdfefgfifjfkfmfnfffffffffffffffggggg g g gggggggggWgYg[g]g`gagbgcgdgfghgigjglgmggggggggggggggggh h2hVhYh[h]h_hahchdhghthhhhhhhhhhhhhhhhhhhhhhiiiiiiii i i iKiMiOiQiTiUiViWiXiZi\i]i^i`iaiiiiiiiiiiiiiiiiiiiiijjjjjjjj j jJjLjNjPjSjTjUjVjWjYj[j\j]j_j`jjjjjjjjjjjjjjjjjjjjjjkkkkkkk k kUkxkkkkkkkkkkkkkkkkkkkkkkkkkkkkl"lFlmlllllllllllllllllllllllllllllm:m<m>m@mCmDmEmFmGmImKmLmMmOmPmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmnn n n nKnMnOnQnTnUnVnWnXnZn\n]n^n`nannnnnnnnnnnnnnnnnnnnnoooooooo o oJoLoNoPoSoToUoVoWoYo[o\o]o_o`ooooooooooooooooop%pIpLpNpPpRpTpVpWpZpgpvpxpzp|p~pppppppppppppppppppppppppppq>q@qBqDqGqHqIqJqKqMqOqPqQqSqTqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqr=r?rArCrFrGrHrIrJrLrNrOrPrRrSrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrsss sssss's(s)s+s8s9s:s<sEsTsaspssssssssssssssstt tt#t(^ t*MediaLibrary.xcdatamodel/layout000066400000000000000000000650001247122470700171550ustar00rootroot00000000000000bplist00 X$versionX$objectsY$archiverT$top6"<STX`fmruy} !$(26BCGKORU`abepqrstw{ *+/37:=HIJNYZ[\]aeituy} )*+,-15?CMXY]aehkvwxyz~   !%)37BCGKORU`abcdhstuvw{ #,-.2<=FGHLUVY]bghmru{~ "+,567;DEGHMRU[^adgmvw{ "(126?@IJNWXabcgpqsty~ "&/09=GHJKPUX^adgjpyz~       ) * 3 4 5 9 C D F J | } ~  U$null WNS.keysZNS.objectsV$class 5Wstorage_hasCombinedRelationshipsXmappings !\XDDataSource_XDDiagramControllerZXDGraphicsZXDDelegate #;$%&'()*+,-./0123456789:(:M^tр&s#88=>?@ABC DEFHIJKLMNOPR_XDDiagramStorage_XDTailConnectionXXDBoundsZXDUniqueID]XDHeadLineEnd]XDTailLineEnd_XDDrawingStyles_XDHeadConnectionZXDLineType^XDGraphicFlags%  '"_{{146, 483.5}, {68, 75}} UWV  YZ[\]$_XXDShadowYXDGraphic_XDShadowStyleFlags  abcde_NSShadowBlurRadius\NSShadowVert #@ # ghijZ$classnameX$classesXNSShadowklXNSShadowXNSObjectghno]XDShadowStylepql]XDShadowStyle^XDDrawingStyleghstWNSArrayslv wxVXDUUID z{|YNS.string_$DD1536DB-EA87-4954-9B44-AB3B12EB1025gh~_NSMutableString~lXNSStringgh[XDGraphicIDl[XDGraphicID Z_$VXDName^XDLineEndFlagsXXDOrigin\XDIdentifierWXDSlopeWXDWidthUXDGapYXDLineGap\XDBezierPath"A"?"^XDArrowLineEndUArrow\{214, 558.5}V{1, 0} ZNSSegmentsO$A@@A@gh\NSBezierPathl\NSBezierPathghYXDLineEndlYXDLineEnd Z_$ "A"?"!_XDDoubleArrowsLineEnd]Double Arrows\{146, 483.5}W{-1, 0} OHA@@A@AA@@AA@ Z9$_XDTargetGraphic#$F =C?@P_XDCollapsedCompartments^XDCompartments_XDCompartmentGraphicFlags;gh\XDConnectionl\XDConnection Z1$&$F =C?@P߁9; gh]XDLineGraphicl]XDLineGraphicYXDGraphic=>?@ABC DEFNP9)-/3*'7_{{342, 495.5}, {63, 48}} W+ YZ[\%_,( abc #@ # v x. z{_$F01FF926-739B-4B33-80AA-2B16187932EB Z_    %01"A"?"(2\{405, 495.5}V{1, 0} O$A@@A@ Z_%45"A"?"(6\{342, 543.5}W{-1, 0} "OHA@@A@AA@@AA@ Z:%8$(F =C?@)-./P1; Z9%#$(=>?@ABC DEF89:;<=N?PAL;?AE<'Kp_{{146, 483.5}, {68, 75}} DWE= YZ[\I&_>: abcMN #@ # v Px@ z{T_$E65F2118-6C48-4199-A516-FCFF161B0504 Z_WZ[\]&_BC"A"?":D\{146, 483.5}W{-1, 0} cO$A@@A@ Zf_gijklm&oGHFI"A"?":J_XDStraightLineEndXStraight\{214, 558.5}V{1, 0} uOA Z1&&$: Z9&#$:=>?@ABC DEFNP]NRTXO'\`_{{342, 495.5}, {63, 48}} WP YZ[\'_QM abc #@ # v xS z{_$63B6001B-0760-479A-9DFA-12D2FB64A387 Z_'UV"A"?"MW\{342, 543.5}W{-1, 0} O$A@@A@ Zf_i'GYFZ"A"?"M[\{405, 495.5}V{1, 0} OA Z9'#$M Z:'8$M=>?@ABC DEFNPрr_cek`'q _{{146, 69.5}, {266, 459}} WՀa YZ[\(_b^ abcހ #@ # v xd z{_$33CCD5F0-42A5-497C-9898-5E3D5E02D717 Z_(ghfi"A"?"^j^XDArrowLineEndUArrow\{146, 528.5}W{-1, 0} [NSLineWidthO$A@@A@#@ Z_(mnlo"A"?"^p_XDDoubleArrowsLineEnd]Double Arrows[{412, 69.5}V{1, 0}   OHA@@A@AA@@AA@#@ Z1(&$^ Z6(s$^F =C?@P;=>?@ABC DEF !"#$%N'P)uy{v'P_{{146, 69.5}, {266, 459}} ,W-w YZ[\1)_xt abc56 #@ # v 8xz z{<_$6B0EE429-E70B-49BC-BBE0-83DEB5DCB31D Z_?BCDE)Gm|l}"A"?"t~[{412, 69.5}V{1, 0} LMOHA@@A@AA@@AA@#@ ZO_PRSTUV)X"A"?"t_XDStraightLineEndXStraight\{146, 528.5}W{-1, 0} _`OA#@ Z6)s$t Z1)&$tDFAE >=C?@jkl_Nnpqs4'_5{{476.86206896551727, 78}, {0.27586206896546628, 12}} vWw YZ[\{*_ abc #@ # v x z{_$37A993E3-3A21-4611-A291-50785EACA484 Z_*"A"?"_XDEmptyArrowLineEnd[Empty Arrow_{476.86206896551727, 78}_{-0.27586206896546628, -12} O-A@@A@#@ Z6*s$ Z7*$F =C?@P̀;DFAE >=C?@_N$'_6{{540, 38.754901960784316}, {25, 0.49019607843136725}} W YZ[\+_ abcÀ #@ # v x z{ɀ_$351DBB49-52E9-4954-BAD5-EB77AA5B98CB Z_+Ԁ"A"?"_{540, 39.245098039215684}_{-25, 0.49019607843136725} ڀO-A@@A@#@ Z6+s$ Z8+$F =C?@P;ցρ΀=>?@ABC DEFNP)'_{{335, 338.5}, {70, 29}} W YZ[\,_ abc #@ # v x z{ _$2AE9F60C-B948-4134-A6BB-A4D8A976F40D Z _ ,"A"?"^XDArrowLineEndUArrow\{405, 338.5}V{1, 0} O$A@@A@#@ Z_ "#$%&,("A"?"_XDStraightLineEndXStraight\{335, 367.5}W{-1, 0} /0OA#@ Z2,$F =C?@6:;<P>S;D=<B Z4,$F =C?@DHIJPL;xpov=>?@ABC DEFOPQRSTNVP)ЀÀɀ'π_{{146, 354.5}, {61, 159}} ZW[ YZ[\_-_ abccd #@ # v fx€ z{j_$A027925D-A479-4AAE-B3E6-B48EB98E7516 Zl_mopqrs-uŀƀĀ"A"?"^XDArrowLineEndUArrow\{207, 354.5}V{1, 0} |}O$A@@A@#@ Z_-ˀ̀ʀ"A"?"_XDStraightLineEndXStraight\{146, 513.5}W{-1, 0} OA#@ Z4-$ Z1-&$=>?@ABC DEFNPрҀր؀ހӀ'_{{146, 354.5}, {61, 159}} WԀ YZ[\._Հ abc #@ # v x׀ z{_$086D1CD5-2AE0-4907-9781-66C0FAA162FF Z_.ڀۀـ"A"?"р_XDDoubleArrowsLineEnd]Double Arrows\{146, 513.5}W{-1, 0} ɀOHA@@A@AA@@AA@#@ Zl_o.Ԁŀ߀Ā"A"?"р\{207, 354.5}V{1, 0} ڀO$A@@A@#@ Z1.&$ Z4.$=>?@ABC DEFNP'_{{146, 129.5}, {43, 369}} W YZ[\/_ abc #@ # v x z{_$D6C2A281-9EAC-4C65-9451-96EDAC2FFA20 Z_ / "A"?"_XDDoubleArrowsLineEnd]Double Arrows\{189, 129.5}V{1, 0} OHA@@A@AA@@AA@#@ Z_/"A"?"\{146, 498.5}W{-1, 0} #$OHA@@A@AA@@AA@#@ Z3/$F =C?@*./0P2n;]UT[ Z1/&$=>?@ABC DEF9:;<=>N@P ' _{{146, 129.5}, {43, 369}} DWE YZ[\I0_ abcMN #@ # v Px z{T_$05C14C76-1BE9-424C-834A-39925F07D400 ZV_WYZ[\]0_"A"?"_XDDoubleArrowsLineEnd]Double Arrows\{146, 498.5}W{-1, 0} fgOHA@@A@AA@@AA@#@ Zi_jlmnop0r "A"?" _XDStraightLineEndXStraight\{189, 129.5}V{1, 0} yzOA#@ Z10&$ Z30$_{{18, 12}, {128, 523}} W Z1[XDLineWidth]XDStrokeColor_XDStrokeStyleFlags"?& UNSRGB\NSColorSpaceO'0.5266666667 0.4207218733 0.4533202387ghWNSColorlgh]XDStrokeStylel]XDStrokeStyle^XDDrawingStyle Z1P[XDFillColor_XDGradientColor_XDGradientAngle_XDFillStyleFlags&"C O0.79 0.63108281 0.679980358 O&0.9299240239 0.8770276033 0.893220054gh_XDCompartmentGraphicFillStylel_XDCompartmentGraphicFillStyle[XDFillStyle^XDDrawingStylev x z{_$A1A53950-6EAB-4341-9B84-8A9083E728DE ;,28 1_XDCompartmentFlagsWXDLabel_XDCompartmentItemMinSize[XDIconImage_XDCompartmentGraphic_XDBackgroundColor_XDCompartmentItem@+*&_/XDPPCompartmentGraphicNameCompartmentIdentifier ]XDCompartmentZXDDataCell) _[NSCellFlags\NSCellFlags2_XDAlternateImageYNSSupport_XDCompartmentItemCellFlagsWXDImage_NSBackgroundColor[NSTextColor^XDButtonTarget@(!% VNSSizeXNSfFlagsVNSName#@& \LucidaGrandeghVNSFontl [NSColorName]NSCatalogNameWNSColor#"$VSystem_textBackgroundColor WNSWhiteB1  &"'YtextColor B0gh_XDCompartmentItemCelll_XDCompartmentItemCell_NSTextFieldCell\NSActionCellVNSCellgh_XDCompartmentIteml_XDCompartmentItemW{0, 15}gh !]XDCompartment"l]XDCompartment %&(1++.1-&/_5XDPPCompartmentGraphicAttributesCompartmentIdentifierZAttributes 1),0 3_+(!%/W{0, 15} ?@B1E+473&5_8XDPPCompartmentGraphicRelationshipsCompartmentIdentifier]Relationships K)26 3_E(!%5W{0, 15}ghWX^NSMutableArrayWslZ [\\NSRangeCount:gh^__NSMutableIndexSet`al_NSMutableIndexSetZNSIndexSetghcd_XDCompartmentGraphicefl_XDCompartmentGraphicYXDGraphic_{{405, 199}, {128, 148}} iWjk>@ Zn2q"?? sO'0.5266666667 0.4207218733 0.4533202387 Z2yzPA"C |O&0.9299240239 0.8770276033 0.893220054v xC z{_$270F9D7A-1B77-4611-8479-15CE692914EF ;EJO8 2+IF )G _ZNSContentsFH(%!PW{0, 15} %(2+.N-K )JL _3̀KM(%!TnameW{0, 15} ?B2Ł+4R3P Ɂ)OQ 3_ŀ(!%PW{0, 15}Z [\:_{{189, 63}, {128, 75}} WځVX Z3"?W O'0.5266666667 0.4207218733 0.4533202387 Z3PYZ"C O0.79 0.63108281 0.679980358 O&0.9299240239 0.8770276033 0.893220054v x\ z{_$29E8FC6E-8B91-4E6B-B147-0B6B6FB0F22B ;^ch8 3+b_`_/XDPPCompartmentGraphicNameCompartmentIdentifier  )^a _(!%`W{0, 15} %3+.gde_5XDPPCompartmentGraphicAttributesCompartmentIdentifier !)cf 3_(!%eW{0, 15} ./134+jmik_8XDPPCompartmentGraphicRelationshipsCompartmentIdentifier]Relationships :)hl 3_4(!%kW{0, 15}Z [\:_{{207, 168}, {128, 210}} IWJKqs ZN4Q"?r SO'0.5266666667 0.4207218733 0.4533202387 ZV4YZPtu"C \O0.79 0.63108281 0.679980358 _O&0.9299240239 0.8770276033 0.893220054v bxw z{f_$22ABA8CE-43F9-4BF9-9C09-A21136F81111 h;ijky~8 pr4u+}z{_/XDPPCompartmentGraphicNameCompartmentIdentifier iz)y| _u(!%{W{0, 15} %4+._5XDPPCompartmentGraphicAttributesCompartmentIdentifier j)~ 3_(!%W{0, 15} 4+_8XDPPCompartmentGraphicRelationshipsCompartmentIdentifier]Relationships k) 3_(!%W{0, 15}Z [\:=>?@ABC DEFNPр'_{{335, 338.5}, {70, 29}} WƁ YZ[\5_ abcπ #@ # v x z{Հ_$1F38AC2C-B07B-4045-947F-CC319F26B0C2 Z_5"A"?"_XDDoubleArrowsLineEnd]Double Arrows\{335, 367.5}W{-1, 0} OHA@@A@AA@@AA@#@ Z _5󀮁"A"?"\{405, 338.5}V{1, 0} O$A@@A@#@ Z45$ Z25$_{{412, 3}, {128, 75}} W Z 6 "?s O'0.5266666667 0.4207218733 0.4533202387 Z6Ps"C O0.79 0.63108281 0.679980358 O&0.9299240239 0.8770276033 0.893220054v x z{!_$046B785B-9778-40CB-BD55-333D9EAAB8A9 #;$%&8 +-60+s_/XDPPCompartmentGraphicNameCompartmentIdentifier $5) _0(!%W{0, 15} %CE6H+.s_5XDPPCompartmentGraphicAttributesCompartmentIdentifier %M) 3_H(!%W{0, 15} Z[]6`+s_8XDPPCompartmentGraphicRelationshipsCompartmentIdentifier]Relationships &f) 3_`(!%W{0, 15}Z [\:_{{414, 90}, {128, 75}} uWvw Zz7}"? O'0.5266666667 0.4207218733 0.4533202387 Z7P"C O&0.9299240239 0.8770276033 0.893220054v x z{_$06125917-E6DC-4F89-B905-B33CB035D11E ;ŁɁ8 -7+Ā ) _(!%W{0, 15} %E7+.Ȁ )Ł 3_(!%W{0, 15} Z]7́+̀ Ё) _3̀ʁH(%!W{0, 15}Z [\:_{{565, 0}, {128, 75}} WЁҀ Z8"? O'0.5266666667 0.4207218733 0.4533202387 Z8P"C O&0.9299240239 0.8770276033 0.893220054v xՀ z{_$E6DE9B3E-DFAD-4AF5-A879-1D77E834A0EE ;ׁہ߁8 -8 +ڀ  ) _ ̀؁H(%!W{0, 15} %E8!+.ހ %)ہ 3_!(!%W{0, 15} Z3]88+ <) _38̀H(%!W{0, 15}Z [\:_{{214, 432}, {128, 133}} LWMN ZQ9T"?# VO'0.5266666667 0.4207218733 0.4533202387 ZY9\]P#" _O0.79 0.63108281 0.679980358 bO'0.9299303818 0.8770276033 0.8932184645v ex z{i_$BD7DB0ED-6323-4117-8DAB-9BAACC510D59 k;lmn8 su9x+#_/XDPPCompartmentGraphicNameCompartmentIdentifier }) _x̀H(%!W{0, 15} %9+.#_5XDPPCompartmentGraphicAttributesCompartmentIdentifier ) _3̀H(%!W{0, 15} 9+#_8XDPPCompartmentGraphicRelationshipsCompartmentIdentifier]Relationships ) _3̀H(%!W{0, 15}Z [\:_{{405, 414}, {128, 116}} W Z:"?8 O'0.5266666667 0.4207218733 0.4533202387 ZY:P8" O'0.9299303818 0.8770276033 0.8932184645v x z{ڀ_$9B48C1F7-E989-4349-B4CF-7B4D3DF462DC ; 8 u:+ 8 )  _̀ H(%!W{0, 15} %: +.8  ) _3 ̀ H(%!W{0, 15}  : +8  ) _3 ̀H(%!W{0, 15}  , - /: 2+8_2"QLs;J:ցB-[yRv逌ԁc? d e f g h i j k l m n o p q r s t u v w x y z !"#$%&'()*+,-./01234hB"s iJ*fAvBou\iJQ?MR  Y_gh _NSMutableDictionary l\NSDictionarygh l_NSKeyedArchiver Troot"+5:?&;H^itvxz|/BKVdr"79;=?Lanpy  "$-79`i{   * 7 9 ; = ? A F K P R T c i v }  1 3 5 7 9 ; @ E J L N f t   1 K Z v y        . 5 C M ~      9 f h j l n p u z    (1|~ "$&(*,.3NWZ\^oqsu  ,4=df!#%'XZ\^`bdfhjlq@BDFHJOTY[]jr{  "/135BDFHy{} 5bdfhjlqv{}!#%')+05:<>Vdpw-0257:=@BEvxz|~  2_aceginsxz|!#%').38:<PYfn{}=FIKM^`bdqs|  $0Kivx  IKPRTVXZ\^` MOQSUW\afhj  >ACFHKNQSV  =jlnprty~ "$&+0579MVckxz   0 3 5 8 : = @ C E H y { }  !! !0!]!_!a!c!e!g!l!q!v!x!z!!!!!!!!""""""""#"("*","@"I"V"^"k"m"""""""""""""""""""""#### #"#3#5#7#9#F#H#Q#Z#c#e#g#p#r#############$ $$$+$-$x$$$$$$$$$$$$$$$$%%%+%-%/%1%>%@%B%D%u%w%y%{%}%%%%%%%%%%%%%%%%%%%%%%&&&,&Y&[&]&_&a&c&h&m&r&t&v&&&&&&' ''@'B'D'F'H'J'O'T'Y'[']'j'r''''''''(((((("(%(((*(-(:(<(>(@(q(s(v(x(z(|((((((((((((((((((((()))+)X)[)^)`)c)f)k)p)u)w)z))))))***E*H*K*M*P*S*X*]*b*d*g*{***************++ +++++/+;+I+^+c+f+h+k+t++++++++++++,,,-,9,K,],p,s,v,x,{,,,,,,,,---:-F-U-^-a-c-l-n----------...1.E.Y.^.a.c.f.h.k.m.o.r.......// //,/6/S/[/o/{//////////////////////000%030;0>0A0C0F0I0P0f0s0{0~00000000000000111$1+141H1M1a1i1r1111111111112222 2#2&2S2V2X2[2^2`2c2f2h2k2s22222222222333 3 393;3>3A3C3F3I3K3N3V3_3n3u3~3333333333344464?4D4G4J4L4a4f4i4k4n4{44444444455 5555!5#5J5S5Z5]5`5c5f5555555555555555555566666 666696<6?6A6D6F6H6K6X6[6^6a66666666666666666666667777476797<7>7A7D7F7I7Q7Z7]7v77777777777778888 8 888=8@8M8v8y8888888888888889999 9 99@9M9P9S9V9999999999999999999:::":%:(:U:W:Z:]:_:b:e:g:j:r:::::::::::;;;; ;8;:;=;@;B;E;H;J;M;U;^;a;|;;;;;;;;;;;;;<< < <<<<$>%>(>+>.>[>]>`>c>e>h>k>m>p>x>>>>>>>>>>>?? ???>?@?C?F?H?K?N?P?S?[?d?g????????????????????@@@@@"@%@'@0@2@Y@@@@@@@@@@@@@@@@@A>AGAtAvAyA{A}AAAAAAAAAAAAAAAAB B B BB(B1B6B9BBSBXB[B]B`BmBBBBBBBBBBBBC(C+C4C7C9CBCDCkCtC{C~CCCCCCCCCCCCCCDDDD5D7D:D=D?DBDEDGDJDRDwDzD}DDDDDDDDDDDEE E EEEEEEE$EIELEOERETEWEYE[E^EEEEEEEEEEEEEEEFFFF,F5F:F=F@FBFWF\F_FaFdFqFFFFFFFFFFGG G GGGG@GIGPGSGVGYG\GGGGGGGGGGGGGGGGGGGGGGGHHH H#H%H(H*H,H/HJ@JgJpJwJzJ}JJJJJJJJJJJJJJJKKKK K KKKKKK"KGKJKMKPKRKUKWKYK\KiKlKoKrKKKKKKKKKKKKKKKKKKKLLLL LLALDLGLILLLOLRLTL\LeLhLLLLLLLLLLLLLLMMMMMMM+MJMMMZMMMMMMMMMMMMMMNN N NNNNNNNNN[N^N`NcNNNNNNNNNNNNNNNNNNNNO&O3O6O8O;OlOnOqOtOwOyO|OOOOOOOOOOOOOPPPPP!P$PUPWPZP]P`PbPePhPkPmPuP~PPPPPPPPPPPPPQ QQ'Q*Q-Q/Q2Q7QDQnQqQzQ}QQQQQQQQQQQQQQQRRRRR RRRR RQRSRVRYR\R^RaRdRgRiRqRRRRRRRRRRRRRRRRRRRSSSS SS6S9SU@UBUDUGUJULUOUQUTUVUYU[UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUVVV VVVVV$V)V.V3V8V=VBVGVPVfVmVzVVVVV VMediaLibraryKit.xcodeproj/000077500000000000000000000000001247122470700160745ustar00rootroot00000000000000MediaLibraryKit.xcodeproj/project.pbxproj000066400000000000000000001020371247122470700211530ustar00rootroot00000000000000// !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 7D0EF4A2170883940003ED47 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7D0EF4A1170883940003ED47 /* Foundation.framework */; }; 7D0EF528170885130003ED47 /* MLCrashPreventer.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D0EF518170885130003ED47 /* MLCrashPreventer.m */; }; 7D0EF529170885130003ED47 /* MLFile.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D0EF519170885130003ED47 /* MLFile.m */; }; 7D0EF52A170885130003ED47 /* MLFileParserQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D0EF51B170885130003ED47 /* MLFileParserQueue.m */; }; 7D0EF52B170885130003ED47 /* MLLabel.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D0EF51C170885130003ED47 /* MLLabel.m */; }; 7D0EF52C170885130003ED47 /* MLMediaLibrary.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D0EF51D170885130003ED47 /* MLMediaLibrary.m */; }; 7D0EF52D170885130003ED47 /* MLMovieInfoGrabber.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D0EF51E170885130003ED47 /* MLMovieInfoGrabber.m */; }; 7D0EF52E170885130003ED47 /* MLShow.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D0EF51F170885130003ED47 /* MLShow.m */; }; 7D0EF52F170885130003ED47 /* MLShowEpisode.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D0EF520170885130003ED47 /* MLShowEpisode.m */; }; 7D0EF530170885130003ED47 /* MLThumbnailerQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D0EF522170885130003ED47 /* MLThumbnailerQueue.m */; }; 7D0EF531170885130003ED47 /* MLTitleDecrapifier.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D0EF523170885130003ED47 /* MLTitleDecrapifier.m */; }; 7D0EF532170885130003ED47 /* MLTVShowEpisodesInfoGrabber.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D0EF524170885130003ED47 /* MLTVShowEpisodesInfoGrabber.m */; }; 7D0EF533170885130003ED47 /* MLTVShowInfoGrabber.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D0EF525170885130003ED47 /* MLTVShowInfoGrabber.m */; }; 7D0EF534170885130003ED47 /* MLURLConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D0EF526170885130003ED47 /* MLURLConnection.m */; }; 7D0EF535170885130003ED47 /* NSXMLNode_Additions.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D0EF527170885130003ED47 /* NSXMLNode_Additions.m */; }; 7D0EF551170885230003ED47 /* CXMLDocument_CreationExtensions.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D0EF53A170885230003ED47 /* CXMLDocument_CreationExtensions.m */; }; 7D0EF552170885230003ED47 /* CXMLNode_CreationExtensions.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D0EF53C170885230003ED47 /* CXMLNode_CreationExtensions.m */; }; 7D0EF553170885230003ED47 /* CXMLDocument.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D0EF53E170885230003ED47 /* CXMLDocument.m */; }; 7D0EF554170885230003ED47 /* CXMLDocument_PrivateExtensions.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D0EF540170885230003ED47 /* CXMLDocument_PrivateExtensions.m */; }; 7D0EF555170885230003ED47 /* CXMLElement.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D0EF542170885230003ED47 /* CXMLElement.m */; }; 7D0EF556170885230003ED47 /* CXMLElement_CreationExtensions.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D0EF544170885230003ED47 /* CXMLElement_CreationExtensions.m */; }; 7D0EF557170885230003ED47 /* CXMLElement_ElementTreeExtensions.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D0EF546170885230003ED47 /* CXMLElement_ElementTreeExtensions.m */; }; 7D0EF558170885230003ED47 /* CXMLNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D0EF548170885230003ED47 /* CXMLNode.m */; }; 7D0EF559170885230003ED47 /* CXMLNode_PrivateExtensions.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D0EF54A170885230003ED47 /* CXMLNode_PrivateExtensions.m */; }; 7D0EF55A170885230003ED47 /* CXMLNode_XPathExtensions.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D0EF54C170885230003ED47 /* CXMLNode_XPathExtensions.m */; }; 7D0EF55B170885230003ED47 /* CTidy.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D0EF54F170885230003ED47 /* CTidy.m */; }; 7D0EF55D170885300003ED47 /* MediaLibrary.xcdatamodel in Sources */ = {isa = PBXBuildFile; fileRef = 7D0EF55C170885300003ED47 /* MediaLibrary.xcdatamodel */; }; 7D8ECFE21708FEAE00A989E9 /* CXHTMLDocument.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D8ECFE11708FEAE00A989E9 /* CXHTMLDocument.m */; }; 7D8ECFE51708FEC000A989E9 /* CXMLNamespaceNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D8ECFE41708FEC000A989E9 /* CXMLNamespaceNode.m */; }; 7D9E238617AEEA13008485E5 /* MLAlbumTrack.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D9E238517AEEA13008485E5 /* MLAlbumTrack.m */; }; 7D9E238817AEEA71008485E5 /* MLAlbum.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D9E238717AEEA71008485E5 /* MLAlbum.m */; }; 7D9E238917AF0711008485E5 /* MLAlbum.h in Copy Files */ = {isa = PBXBuildFile; fileRef = 7D9E238117AEE9F2008485E5 /* MLAlbum.h */; }; 7D9E238A17AF0711008485E5 /* MLAlbumTrack.h in Copy Files */ = {isa = PBXBuildFile; fileRef = 7D9E238417AEEA13008485E5 /* MLAlbumTrack.h */; }; A7924688170F09A30036AAF2 /* MediaLibraryKit.h in Copy Files */ = {isa = PBXBuildFile; fileRef = 7D0EF510170885130003ED47 /* MediaLibraryKit.h */; }; A7924689170F09A30036AAF2 /* MLFile.h in Copy Files */ = {isa = PBXBuildFile; fileRef = 7D0EF511170885130003ED47 /* MLFile.h */; }; A792468A170F09A30036AAF2 /* MLLabel.h in Copy Files */ = {isa = PBXBuildFile; fileRef = 7D0EF512170885130003ED47 /* MLLabel.h */; }; A792468B170F09A30036AAF2 /* MLMediaLibrary.h in Copy Files */ = {isa = PBXBuildFile; fileRef = 7D0EF513170885130003ED47 /* MLMediaLibrary.h */; }; A792468C170F09A30036AAF2 /* MLShow.h in Copy Files */ = {isa = PBXBuildFile; fileRef = 7D0EF514170885130003ED47 /* MLShow.h */; }; A792468D170F09A30036AAF2 /* MLShowEpisode.h in Copy Files */ = {isa = PBXBuildFile; fileRef = 7D0EF515170885130003ED47 /* MLShowEpisode.h */; }; A792468E170F09A30036AAF2 /* MLThumbnailerQueue.h in Copy Files */ = {isa = PBXBuildFile; fileRef = 7D0EF521170885130003ED47 /* MLThumbnailerQueue.h */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ 7D0EF49C170883940003ED47 /* Copy Files */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = "include/${PRODUCT_NAME}"; dstSubfolderSpec = 16; files = ( 7D9E238917AF0711008485E5 /* MLAlbum.h in Copy Files */, 7D9E238A17AF0711008485E5 /* MLAlbumTrack.h in Copy Files */, A7924688170F09A30036AAF2 /* MediaLibraryKit.h in Copy Files */, A7924689170F09A30036AAF2 /* MLFile.h in Copy Files */, A792468A170F09A30036AAF2 /* MLLabel.h in Copy Files */, A792468B170F09A30036AAF2 /* MLMediaLibrary.h in Copy Files */, A792468C170F09A30036AAF2 /* MLShow.h in Copy Files */, A792468D170F09A30036AAF2 /* MLShowEpisode.h in Copy Files */, A792468E170F09A30036AAF2 /* MLThumbnailerQueue.h in Copy Files */, ); name = "Copy Files"; runOnlyForDeploymentPostprocessing = 0; }; /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ 7D0EF49E170883940003ED47 /* libMediaLibraryKit.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libMediaLibraryKit.a; sourceTree = BUILT_PRODUCTS_DIR; }; 7D0EF4A1170883940003ED47 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 7D0EF4DF170883D80003ED47 /* MediaLibraryKit_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MediaLibraryKit_Prefix.pch; sourceTree = ""; }; 7D0EF508170885130003ED47 /* MLMovieInfoGrabber.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MLMovieInfoGrabber.h; sourceTree = ""; }; 7D0EF509170885130003ED47 /* MLTitleDecrapifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MLTitleDecrapifier.h; sourceTree = ""; }; 7D0EF50A170885130003ED47 /* MLTVShowEpisodesInfoGrabber.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MLTVShowEpisodesInfoGrabber.h; sourceTree = ""; }; 7D0EF50B170885130003ED47 /* MLTVShowInfoGrabber.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MLTVShowInfoGrabber.h; sourceTree = ""; }; 7D0EF50C170885130003ED47 /* MLURLConnection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MLURLConnection.h; sourceTree = ""; }; 7D0EF50D170885130003ED47 /* NSXMLNode_Additions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NSXMLNode_Additions.h; sourceTree = ""; }; 7D0EF50E170885130003ED47 /* TheTVDBGrabber.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TheTVDBGrabber.h; sourceTree = ""; }; 7D0EF510170885130003ED47 /* MediaLibraryKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MediaLibraryKit.h; sourceTree = ""; }; 7D0EF511170885130003ED47 /* MLFile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MLFile.h; sourceTree = ""; }; 7D0EF512170885130003ED47 /* MLLabel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MLLabel.h; sourceTree = ""; }; 7D0EF513170885130003ED47 /* MLMediaLibrary.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MLMediaLibrary.h; sourceTree = ""; }; 7D0EF514170885130003ED47 /* MLShow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MLShow.h; sourceTree = ""; }; 7D0EF515170885130003ED47 /* MLShowEpisode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MLShowEpisode.h; sourceTree = ""; }; 7D0EF517170885130003ED47 /* MLCrashPreventer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MLCrashPreventer.h; sourceTree = ""; }; 7D0EF518170885130003ED47 /* MLCrashPreventer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MLCrashPreventer.m; sourceTree = ""; }; 7D0EF519170885130003ED47 /* MLFile.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MLFile.m; sourceTree = ""; }; 7D0EF51A170885130003ED47 /* MLFileParserQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MLFileParserQueue.h; sourceTree = ""; }; 7D0EF51B170885130003ED47 /* MLFileParserQueue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MLFileParserQueue.m; sourceTree = ""; }; 7D0EF51C170885130003ED47 /* MLLabel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MLLabel.m; sourceTree = ""; }; 7D0EF51D170885130003ED47 /* MLMediaLibrary.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MLMediaLibrary.m; sourceTree = ""; }; 7D0EF51E170885130003ED47 /* MLMovieInfoGrabber.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MLMovieInfoGrabber.m; sourceTree = ""; }; 7D0EF51F170885130003ED47 /* MLShow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MLShow.m; sourceTree = ""; }; 7D0EF520170885130003ED47 /* MLShowEpisode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MLShowEpisode.m; sourceTree = ""; }; 7D0EF521170885130003ED47 /* MLThumbnailerQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MLThumbnailerQueue.h; path = ../../Sources/MLThumbnailerQueue.h; sourceTree = ""; }; 7D0EF522170885130003ED47 /* MLThumbnailerQueue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MLThumbnailerQueue.m; sourceTree = ""; }; 7D0EF523170885130003ED47 /* MLTitleDecrapifier.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MLTitleDecrapifier.m; sourceTree = ""; }; 7D0EF524170885130003ED47 /* MLTVShowEpisodesInfoGrabber.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MLTVShowEpisodesInfoGrabber.m; sourceTree = ""; }; 7D0EF525170885130003ED47 /* MLTVShowInfoGrabber.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MLTVShowInfoGrabber.m; sourceTree = ""; }; 7D0EF526170885130003ED47 /* MLURLConnection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MLURLConnection.m; sourceTree = ""; }; 7D0EF527170885130003ED47 /* NSXMLNode_Additions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NSXMLNode_Additions.m; sourceTree = ""; }; 7D0EF539170885230003ED47 /* CXMLDocument_CreationExtensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CXMLDocument_CreationExtensions.h; sourceTree = ""; }; 7D0EF53A170885230003ED47 /* CXMLDocument_CreationExtensions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CXMLDocument_CreationExtensions.m; sourceTree = ""; }; 7D0EF53B170885230003ED47 /* CXMLNode_CreationExtensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CXMLNode_CreationExtensions.h; sourceTree = ""; }; 7D0EF53C170885230003ED47 /* CXMLNode_CreationExtensions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CXMLNode_CreationExtensions.m; sourceTree = ""; }; 7D0EF53D170885230003ED47 /* CXMLDocument.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CXMLDocument.h; sourceTree = ""; }; 7D0EF53E170885230003ED47 /* CXMLDocument.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CXMLDocument.m; sourceTree = ""; }; 7D0EF53F170885230003ED47 /* CXMLDocument_PrivateExtensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CXMLDocument_PrivateExtensions.h; sourceTree = ""; }; 7D0EF540170885230003ED47 /* CXMLDocument_PrivateExtensions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CXMLDocument_PrivateExtensions.m; sourceTree = ""; }; 7D0EF541170885230003ED47 /* CXMLElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CXMLElement.h; sourceTree = ""; }; 7D0EF542170885230003ED47 /* CXMLElement.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CXMLElement.m; sourceTree = ""; }; 7D0EF543170885230003ED47 /* CXMLElement_CreationExtensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CXMLElement_CreationExtensions.h; sourceTree = ""; }; 7D0EF544170885230003ED47 /* CXMLElement_CreationExtensions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CXMLElement_CreationExtensions.m; sourceTree = ""; }; 7D0EF545170885230003ED47 /* CXMLElement_ElementTreeExtensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CXMLElement_ElementTreeExtensions.h; sourceTree = ""; }; 7D0EF546170885230003ED47 /* CXMLElement_ElementTreeExtensions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CXMLElement_ElementTreeExtensions.m; sourceTree = ""; }; 7D0EF547170885230003ED47 /* CXMLNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CXMLNode.h; sourceTree = ""; }; 7D0EF548170885230003ED47 /* CXMLNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CXMLNode.m; sourceTree = ""; }; 7D0EF549170885230003ED47 /* CXMLNode_PrivateExtensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CXMLNode_PrivateExtensions.h; sourceTree = ""; }; 7D0EF54A170885230003ED47 /* CXMLNode_PrivateExtensions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CXMLNode_PrivateExtensions.m; sourceTree = ""; }; 7D0EF54B170885230003ED47 /* CXMLNode_XPathExtensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CXMLNode_XPathExtensions.h; sourceTree = ""; }; 7D0EF54C170885230003ED47 /* CXMLNode_XPathExtensions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CXMLNode_XPathExtensions.m; sourceTree = ""; }; 7D0EF54E170885230003ED47 /* CTidy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CTidy.h; sourceTree = ""; }; 7D0EF54F170885230003ED47 /* CTidy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CTidy.m; sourceTree = ""; }; 7D0EF550170885230003ED47 /* TouchXML.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TouchXML.h; sourceTree = ""; }; 7D0EF55C170885300003ED47 /* MediaLibrary.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = MediaLibrary.xcdatamodel; sourceTree = SOURCE_ROOT; }; 7D8ECFE01708FEAE00A989E9 /* CXHTMLDocument.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CXHTMLDocument.h; sourceTree = ""; }; 7D8ECFE11708FEAE00A989E9 /* CXHTMLDocument.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CXHTMLDocument.m; sourceTree = ""; }; 7D8ECFE31708FEC000A989E9 /* CXMLNamespaceNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CXMLNamespaceNode.h; sourceTree = ""; }; 7D8ECFE41708FEC000A989E9 /* CXMLNamespaceNode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CXMLNamespaceNode.m; sourceTree = ""; }; 7D9E238117AEE9F2008485E5 /* MLAlbum.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MLAlbum.h; sourceTree = ""; }; 7D9E238417AEEA13008485E5 /* MLAlbumTrack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MLAlbumTrack.h; sourceTree = ""; }; 7D9E238517AEEA13008485E5 /* MLAlbumTrack.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MLAlbumTrack.m; sourceTree = ""; }; 7D9E238717AEEA71008485E5 /* MLAlbum.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MLAlbum.m; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 7D0EF49B170883940003ED47 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 7D0EF4A2170883940003ED47 /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 7D0EF495170883940003ED47 = { isa = PBXGroup; children = ( 7D0EF536170885230003ED47 /* TouchXML */, 7D0EF506170885130003ED47 /* Headers */, 7D0EF516170885130003ED47 /* Sources */, 7D0EF4A4170883940003ED47 /* Supporting Files */, 7D0EF4A0170883940003ED47 /* Frameworks */, 7D0EF49F170883940003ED47 /* Products */, ); sourceTree = ""; }; 7D0EF49F170883940003ED47 /* Products */ = { isa = PBXGroup; children = ( 7D0EF49E170883940003ED47 /* libMediaLibraryKit.a */, ); name = Products; sourceTree = ""; }; 7D0EF4A0170883940003ED47 /* Frameworks */ = { isa = PBXGroup; children = ( 7D0EF4A1170883940003ED47 /* Foundation.framework */, ); name = Frameworks; sourceTree = ""; }; 7D0EF4A4170883940003ED47 /* Supporting Files */ = { isa = PBXGroup; children = ( 7D0EF55C170885300003ED47 /* MediaLibrary.xcdatamodel */, 7D0EF4DF170883D80003ED47 /* MediaLibraryKit_Prefix.pch */, ); name = "Supporting Files"; path = MediaLibraryKit; sourceTree = ""; }; 7D0EF506170885130003ED47 /* Headers */ = { isa = PBXGroup; children = ( 7D0EF507170885130003ED47 /* Internal */, 7D0EF50F170885130003ED47 /* Public */, ); path = Headers; sourceTree = ""; }; 7D0EF507170885130003ED47 /* Internal */ = { isa = PBXGroup; children = ( 7D0EF508170885130003ED47 /* MLMovieInfoGrabber.h */, 7D0EF509170885130003ED47 /* MLTitleDecrapifier.h */, 7D0EF50A170885130003ED47 /* MLTVShowEpisodesInfoGrabber.h */, 7D0EF50B170885130003ED47 /* MLTVShowInfoGrabber.h */, 7D0EF50C170885130003ED47 /* MLURLConnection.h */, 7D0EF50D170885130003ED47 /* NSXMLNode_Additions.h */, 7D0EF50E170885130003ED47 /* TheTVDBGrabber.h */, ); path = Internal; sourceTree = ""; }; 7D0EF50F170885130003ED47 /* Public */ = { isa = PBXGroup; children = ( 7D0EF510170885130003ED47 /* MediaLibraryKit.h */, 7D0EF511170885130003ED47 /* MLFile.h */, 7D0EF512170885130003ED47 /* MLLabel.h */, 7D0EF513170885130003ED47 /* MLMediaLibrary.h */, 7D0EF514170885130003ED47 /* MLShow.h */, 7D0EF515170885130003ED47 /* MLShowEpisode.h */, 7D9E238117AEE9F2008485E5 /* MLAlbum.h */, 7D9E238417AEEA13008485E5 /* MLAlbumTrack.h */, 7D0EF521170885130003ED47 /* MLThumbnailerQueue.h */, ); path = Public; sourceTree = ""; }; 7D0EF516170885130003ED47 /* Sources */ = { isa = PBXGroup; children = ( 7D0EF517170885130003ED47 /* MLCrashPreventer.h */, 7D0EF518170885130003ED47 /* MLCrashPreventer.m */, 7D0EF519170885130003ED47 /* MLFile.m */, 7D0EF51A170885130003ED47 /* MLFileParserQueue.h */, 7D0EF51B170885130003ED47 /* MLFileParserQueue.m */, 7D0EF51C170885130003ED47 /* MLLabel.m */, 7D0EF51D170885130003ED47 /* MLMediaLibrary.m */, 7D0EF51E170885130003ED47 /* MLMovieInfoGrabber.m */, 7D0EF51F170885130003ED47 /* MLShow.m */, 7D0EF520170885130003ED47 /* MLShowEpisode.m */, 7D9E238717AEEA71008485E5 /* MLAlbum.m */, 7D9E238517AEEA13008485E5 /* MLAlbumTrack.m */, 7D0EF522170885130003ED47 /* MLThumbnailerQueue.m */, 7D0EF523170885130003ED47 /* MLTitleDecrapifier.m */, 7D0EF524170885130003ED47 /* MLTVShowEpisodesInfoGrabber.m */, 7D0EF525170885130003ED47 /* MLTVShowInfoGrabber.m */, 7D0EF526170885130003ED47 /* MLURLConnection.m */, 7D0EF527170885130003ED47 /* NSXMLNode_Additions.m */, ); path = Sources; sourceTree = ""; }; 7D0EF536170885230003ED47 /* TouchXML */ = { isa = PBXGroup; children = ( 7D0EF537170885230003ED47 /* Source */, ); name = TouchXML; path = External/TouchXML; sourceTree = ""; }; 7D0EF537170885230003ED47 /* Source */ = { isa = PBXGroup; children = ( 7D0EF538170885230003ED47 /* Creation */, 7D0EF53D170885230003ED47 /* CXMLDocument.h */, 7D0EF53E170885230003ED47 /* CXMLDocument.m */, 7D0EF53F170885230003ED47 /* CXMLDocument_PrivateExtensions.h */, 7D0EF540170885230003ED47 /* CXMLDocument_PrivateExtensions.m */, 7D0EF541170885230003ED47 /* CXMLElement.h */, 7D0EF542170885230003ED47 /* CXMLElement.m */, 7D0EF543170885230003ED47 /* CXMLElement_CreationExtensions.h */, 7D0EF544170885230003ED47 /* CXMLElement_CreationExtensions.m */, 7D0EF545170885230003ED47 /* CXMLElement_ElementTreeExtensions.h */, 7D0EF546170885230003ED47 /* CXMLElement_ElementTreeExtensions.m */, 7D0EF547170885230003ED47 /* CXMLNode.h */, 7D0EF548170885230003ED47 /* CXMLNode.m */, 7D0EF549170885230003ED47 /* CXMLNode_PrivateExtensions.h */, 7D0EF54A170885230003ED47 /* CXMLNode_PrivateExtensions.m */, 7D0EF54B170885230003ED47 /* CXMLNode_XPathExtensions.h */, 7D0EF54C170885230003ED47 /* CXMLNode_XPathExtensions.m */, 7D8ECFE01708FEAE00A989E9 /* CXHTMLDocument.h */, 7D8ECFE11708FEAE00A989E9 /* CXHTMLDocument.m */, 7D8ECFE31708FEC000A989E9 /* CXMLNamespaceNode.h */, 7D8ECFE41708FEC000A989E9 /* CXMLNamespaceNode.m */, 7D0EF54D170885230003ED47 /* Tidy */, 7D0EF550170885230003ED47 /* TouchXML.h */, ); path = Source; sourceTree = ""; }; 7D0EF538170885230003ED47 /* Creation */ = { isa = PBXGroup; children = ( 7D0EF539170885230003ED47 /* CXMLDocument_CreationExtensions.h */, 7D0EF53A170885230003ED47 /* CXMLDocument_CreationExtensions.m */, 7D0EF53B170885230003ED47 /* CXMLNode_CreationExtensions.h */, 7D0EF53C170885230003ED47 /* CXMLNode_CreationExtensions.m */, ); path = Creation; sourceTree = ""; }; 7D0EF54D170885230003ED47 /* Tidy */ = { isa = PBXGroup; children = ( 7D0EF54E170885230003ED47 /* CTidy.h */, 7D0EF54F170885230003ED47 /* CTidy.m */, ); path = Tidy; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 7D0EF49D170883940003ED47 /* MediaLibraryKit */ = { isa = PBXNativeTarget; buildConfigurationList = 7D0EF4AC170883940003ED47 /* Build configuration list for PBXNativeTarget "MediaLibraryKit" */; buildPhases = ( 7D0EF49A170883940003ED47 /* Sources */, 7D0EF49B170883940003ED47 /* Frameworks */, 7D0EF49C170883940003ED47 /* Copy Files */, ); buildRules = ( ); dependencies = ( ); name = MediaLibraryKit; productName = MediaLibraryKit; productReference = 7D0EF49E170883940003ED47 /* libMediaLibraryKit.a */; productType = "com.apple.product-type.library.static"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 7D0EF496170883940003ED47 /* Project object */ = { isa = PBXProject; attributes = { LastUpgradeCheck = 0510; ORGANIZATIONNAME = VideoLAN; }; buildConfigurationList = 7D0EF499170883940003ED47 /* Build configuration list for PBXProject "MediaLibraryKit" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, ); mainGroup = 7D0EF495170883940003ED47; productRefGroup = 7D0EF49F170883940003ED47 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 7D0EF49D170883940003ED47 /* MediaLibraryKit */, ); }; /* End PBXProject section */ /* Begin PBXSourcesBuildPhase section */ 7D0EF49A170883940003ED47 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 7D0EF528170885130003ED47 /* MLCrashPreventer.m in Sources */, 7D0EF529170885130003ED47 /* MLFile.m in Sources */, 7D0EF52A170885130003ED47 /* MLFileParserQueue.m in Sources */, 7D0EF52B170885130003ED47 /* MLLabel.m in Sources */, 7D0EF52C170885130003ED47 /* MLMediaLibrary.m in Sources */, 7D0EF52D170885130003ED47 /* MLMovieInfoGrabber.m in Sources */, 7D0EF52E170885130003ED47 /* MLShow.m in Sources */, 7D0EF52F170885130003ED47 /* MLShowEpisode.m in Sources */, 7D0EF530170885130003ED47 /* MLThumbnailerQueue.m in Sources */, 7D0EF531170885130003ED47 /* MLTitleDecrapifier.m in Sources */, 7D0EF532170885130003ED47 /* MLTVShowEpisodesInfoGrabber.m in Sources */, 7D0EF533170885130003ED47 /* MLTVShowInfoGrabber.m in Sources */, 7D0EF534170885130003ED47 /* MLURLConnection.m in Sources */, 7D9E238617AEEA13008485E5 /* MLAlbumTrack.m in Sources */, 7D9E238817AEEA71008485E5 /* MLAlbum.m in Sources */, 7D0EF535170885130003ED47 /* NSXMLNode_Additions.m in Sources */, 7D0EF551170885230003ED47 /* CXMLDocument_CreationExtensions.m in Sources */, 7D0EF552170885230003ED47 /* CXMLNode_CreationExtensions.m in Sources */, 7D0EF553170885230003ED47 /* CXMLDocument.m in Sources */, 7D0EF554170885230003ED47 /* CXMLDocument_PrivateExtensions.m in Sources */, 7D0EF555170885230003ED47 /* CXMLElement.m in Sources */, 7D0EF556170885230003ED47 /* CXMLElement_CreationExtensions.m in Sources */, 7D0EF557170885230003ED47 /* CXMLElement_ElementTreeExtensions.m in Sources */, 7D0EF558170885230003ED47 /* CXMLNode.m in Sources */, 7D0EF559170885230003ED47 /* CXMLNode_PrivateExtensions.m in Sources */, 7D0EF55A170885230003ED47 /* CXMLNode_XPathExtensions.m in Sources */, 7D0EF55B170885230003ED47 /* CTidy.m in Sources */, 7D8ECFE21708FEAE00A989E9 /* CXHTMLDocument.m in Sources */, 7D8ECFE51708FEC000A989E9 /* CXMLNamespaceNode.m in Sources */, 7D0EF55D170885300003ED47 /* MediaLibrary.xcdatamodel in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ 7D0EF4AA170883940003ED47 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = ( "$(inherited)", /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, "$(SRCROOT)/External/MobileVLCKit/include/MobileVLCKit/**", ); IPHONEOS_DEPLOYMENT_TARGET = 5.1; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; }; name = Debug; }; 7D0EF4AB170883940003ED47 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = ( "$(inherited)", /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, "$(SRCROOT)/External/MobileVLCKit/include/MobileVLCKit/**", ); IPHONEOS_DEPLOYMENT_TARGET = 5.1; SDKROOT = iphoneos; VALIDATE_PRODUCT = YES; }; name = Release; }; 7D0EF4AD170883940003ED47 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ARCHS = ( "$(ARCHS_STANDARD)", armv7s, ); CLANG_ENABLE_OBJC_ARC = YES; DSTROOT = /tmp/MediaLibraryKit.dst; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = MediaLibraryKit_Prefix.pch; HEADER_SEARCH_PATHS = ( "\"$(SRCROOT)/External/MobileVLCKit/include\"", /usr/include/libxml2, ); IPHONEOS_DEPLOYMENT_TARGET = 5.1.1; LIBRARY_SEARCH_PATHS = "\"$(SRCROOT)/External/MobileVLCKit\""; OTHER_LDFLAGS = "-ObjC"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; }; name = Debug; }; 7D0EF4AE170883940003ED47 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ARCHS = ( "$(ARCHS_STANDARD)", armv7s, ); CLANG_ENABLE_OBJC_ARC = YES; DSTROOT = /tmp/MediaLibraryKit.dst; ENABLE_NS_ASSERTIONS = NO; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = MediaLibraryKit_Prefix.pch; HEADER_SEARCH_PATHS = ( "\"$(SRCROOT)/External/MobileVLCKit/include\"", /usr/include/libxml2, ); IPHONEOS_DEPLOYMENT_TARGET = 5.1.1; LIBRARY_SEARCH_PATHS = "\"$(SRCROOT)/External/MobileVLCKit\""; OTHER_LDFLAGS = "-ObjC"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 7D0EF499170883940003ED47 /* Build configuration list for PBXProject "MediaLibraryKit" */ = { isa = XCConfigurationList; buildConfigurations = ( 7D0EF4AA170883940003ED47 /* Debug */, 7D0EF4AB170883940003ED47 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 7D0EF4AC170883940003ED47 /* Build configuration list for PBXNativeTarget "MediaLibraryKit" */ = { isa = XCConfigurationList; buildConfigurations = ( 7D0EF4AD170883940003ED47 /* Debug */, 7D0EF4AE170883940003ED47 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 7D0EF496170883940003ED47 /* Project object */; } MediaLibraryKit_Prefix.pch000066400000000000000000000037121247122470700161140ustar00rootroot00000000000000/***************************************************************************** * MobileMediaLibraryKit_Prefix.pch * MobileMediaLibraryKit ***************************************************************************** * Copyright (C) 2010 Pierre d'Herbemont * Copyright (C) 2010-2013 VLC authors and VideoLAN * $Id$ * * Authors: Pierre d'Herbemont * * 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.1 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 Lesser 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ #ifdef __OBJC__ #import #endif #import #if TARGET_OS_IPHONE // FIXME #define HAVE_BLOCK 0 #define NSXMLDocument CXMLDocument #define NSXMLNode CXMLNode #import "TouchXML.h" #import #import #else #define HAVE_BLOCK 1 #import #endif #import "NSXMLNode_Additions.h" #ifndef NDEBUG #define APLog(format, ...) NSLog(format, ## __VA_ARGS__) #else #define APLog(format, ...) #endif #define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending) #ifdef __IPHONE_7_0 #define SYSTEM_RUNS_IOS7 SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0") #else #define SYSTEM_RUNS_IOS7 NO #endif NEWS000066400000000000000000000066221247122470700115710ustar00rootroot00000000000000Version 2.4 ----------- - NEW: code was upgraded to ARC - FIX: library is no longer reset when upgrading iOS app through the store - FIX: [] pattern is correctly removed from file titles Added Public APIs: - MLMediaLibrary - new selector: documentFolderPath Version 2.3 ----------- - FIX: crash when deploying MLFile's unread property Added Public APIs: - MLFile: - new selectors: fileForURL folderTrackNumber - MLLabel: - new selector: sortedFolderItems - MLMediaLibrary: - new selector: removeObject Version 2.2.1 ------------- - FIX: incorrect return value for untitled TV shows - FIX: crash in setter/getter for lastPosition and unread in MLFile - Thumbnailer: use a special libVLC instance for thumbnails Version 2.2 ----------- - FIX: correct subitem behavior of MLShow and MLAlbum on removal - FIX: MLTitleDecrapifier handles shows with more than 99 and less than 1000 episodes correctly now - NEW: added user defaults option to disable file name display optimizations when media is newly added to the library - FIX: thumbnails are correctly purged if a media item is removed Added Public APIs: - MLShow: - new selectors: removeEpisode: removeEpisodeWithSeasonNumber:andEpisodeNumber: sortedEpisodes - MLAlbum: - new selectors: removeTrack: removeTrackWithTrackNumber: sortedTracks - MLLabel: - new selector: allLabels Version 2.1.3 ------------- - fix crash when processing files whose names are less than 6 characters long (after removing the file extension) Version 2.1.2 ------------- - fix crashes and missing exception handlings - fix memory leaks in MLFile, library and title sanitizer - prevent zombie creation and VLCMedia corruptions Version 2.1.1 ------------- - improved title decrapification with faster processing and support for older TV show naming schemes - improve notifications of some properties Version 2.1 ----------- Features: - added support for audio file detection and album organization - improved title decrapification including advanced TV Show support - overall stability improvements - updated database format including a future-proof upgrade API Added Public APIs: - MLAlbum: - New class - MLAlbumTrack: - New class - MLFile: - new properties: lastAudioTrack, lastSubtitleTrack - MLMediaLibrary: - new properties: delegate, libraryNeedsUpgrade - new selector: upgradeLibrary - new delegate protocol: libraryUpgradeComplete Version 2.0 ----------- The entire library was cleaned and relicensed to LGPL 2.1 or later. Please note that the Objective-C syntax was updated, so MediaLibraryKit may no longer compile with outdated versions of Xcode / clang. Features: - added automatic support for HiDPI thumbnails depending on the iOS device the client app is executed on Added APIs: - MediaLibraryKit: - added a generic header to include the entire framework's functionality with a single #import - MLMediaLibrary: - (void)updateMediaDatabase; Removed APIs and code: - MLMediaLibrary: - (void)updateDatabase; - NameCleaner.rb Modified behavior and misc: - use of clang instead of llvm-gcc-4.2 - updated project file for Xcode 4.3 and later - iOS Deployment target was raised to iOS 5.1 - different logging behavior: to see any debug messages, the framework needs to be compiled in debug mode. - fixed a significant number of memory leaks - updated TouchXML snapshot to current HEAD Sources/000077500000000000000000000000001247122470700125075ustar00rootroot00000000000000Sources/MLAlbum.m000066400000000000000000000072131247122470700141610ustar00rootroot00000000000000/***************************************************************************** * MLAlbum.m ***************************************************************************** * Copyright (C) 2010 Pierre d'Herbemont * Copyright (C) 2013 Felix Paul Kühne * $Id$ * * Authors: Pierre d'Herbemont * Felix Paul Kühne * * 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.1 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 Lesser 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ #import "MLAlbum.h" #import "MLAlbumTrack.h" #import "MLMediaLibrary.h" @implementation MLAlbum + (NSArray *)allAlbums { NSFetchRequest *request = [[NSFetchRequest alloc] init]; NSManagedObjectContext *moc = [[MLMediaLibrary sharedMediaLibrary] managedObjectContext]; NSEntityDescription *entity = [NSEntityDescription entityForName:@"Album" inManagedObjectContext:moc]; [request setEntity:entity]; NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:NO]; [request setSortDescriptors:@[descriptor]]; NSArray *albums = [moc executeFetchRequest:request error:nil]; return albums; } + (MLAlbum *)albumWithName:(NSString *)name { NSFetchRequest *request = [[MLMediaLibrary sharedMediaLibrary] fetchRequestForEntity:@"Album"]; [request setPredicate:[NSPredicate predicateWithFormat:@"name == %@", name]]; NSArray *dbResults = [[[MLMediaLibrary sharedMediaLibrary] managedObjectContext] executeFetchRequest:request error:nil]; NSAssert(dbResults, @"Can't execute fetch request"); if ([dbResults count] <= 0) return nil; return dbResults[0]; } @dynamic name; @dynamic releaseYear; @dynamic tracks; @dynamic unreadTracks; - (NSArray *)sortedTracks { NSArray *tracks = [[self valueForKey:@"tracks"] allObjects]; NSSortDescriptor *trackNumberDescriptor = [[NSSortDescriptor alloc] initWithKey:@"trackNumber" ascending:YES selector:@selector(compare:)]; return [tracks sortedArrayUsingDescriptors:@[trackNumberDescriptor]]; } - (void)removeTrack:(MLAlbumTrack *)track { if (!track) return; NSMutableSet *tracks = [self mutableSetValueForKey:@"tracks"]; [tracks removeObject:track]; [self willChangeValueForKey:@"tracks"]; [self setValue:tracks forKey:@"tracks"]; [self didChangeValueForKey:@"tracks"]; } - (void)removeTrackWithNumber:(NSNumber *)trackNumber { NSMutableSet *tracks = [self mutableSetValueForKey:@"tracks"]; MLAlbumTrack *track = nil; if (trackNumber) { for (MLAlbumTrack *trackIter in tracks) { if ([trackIter.trackNumber intValue] == [trackNumber intValue]) { track = trackIter; break; } } } if (!track) return; [tracks removeObject:track]; [self willChangeValueForKey:@"tracks"]; [self setValue:tracks forKey:@"tracks"]; [self didChangeValueForKey:@"tracks"]; } @end Sources/MLAlbumTrack.m000066400000000000000000000074301247122470700151470ustar00rootroot00000000000000/***************************************************************************** * MLAlbumTrack.m ***************************************************************************** * Copyright (C) 2010 Pierre d'Herbemont * Copyright (C) 2013 Felix Paul Kühne * $Id$ * * Authors: Pierre d'Herbemont * Felix Paul Kühne * * 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.1 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 Lesser 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ #import "MLMediaLibrary.h" #import "MLAlbumTrack.h" #import "MLAlbum.h" @interface MLAlbumTrack () @property (nonatomic, strong) NSNumber *primitiveUnread; @end @implementation MLAlbumTrack + (NSArray *)allTracks { NSFetchRequest *request = [[NSFetchRequest alloc] init]; NSManagedObjectContext *moc = [[MLMediaLibrary sharedMediaLibrary] managedObjectContext]; NSEntityDescription *entity = [NSEntityDescription entityForName:@"AlbumTrack" inManagedObjectContext:moc]; [request setEntity:entity]; NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:@"title" ascending:NO]; [request setSortDescriptors:@[descriptor]]; [request setPredicate:[NSPredicate predicateWithFormat:@"files.@count > 0"]]; NSArray *tracks = [moc executeFetchRequest:request error:nil]; return tracks; } + (MLAlbumTrack *)trackWithAlbum:(id)album trackNumber:(NSNumber *)trackNumber createIfNeeded:(BOOL)createIfNeeded { NSMutableSet *tracks = [album mutableSetValueForKey:@"tracks"]; MLAlbumTrack *track = nil; if (trackNumber) { for (MLAlbumTrack *trackIter in tracks) { if ([trackIter.trackNumber intValue] == [trackNumber intValue]) { track = trackIter; break; } } } if (!track && createIfNeeded) { track = [[MLMediaLibrary sharedMediaLibrary] createObjectForEntity:@"AlbumTrack"]; track.trackNumber = trackNumber; [tracks addObject:track]; } return track; } + (MLAlbumTrack *)trackWithAlbumName:(NSString *)albumName trackNumber:(NSNumber *)trackNumber createIfNeeded:(BOOL)createIfNeeded wasCreated:(BOOL *)wasCreated { MLAlbum *album = [MLAlbum albumWithName:albumName]; *wasCreated = NO; if (!album && createIfNeeded) { *wasCreated = YES; album = [[MLMediaLibrary sharedMediaLibrary] createObjectForEntity:@"Album"]; album.name = albumName ? albumName : @""; } else if (!album && !createIfNeeded) return nil; return [MLAlbumTrack trackWithAlbum:album trackNumber:trackNumber createIfNeeded:createIfNeeded]; } @dynamic primitiveUnread; @dynamic unread; - (void)setUnread:(NSNumber *)unread { [self willChangeValueForKey:@"unread"]; [self setPrimitiveUnread:unread]; [self didChangeValueForKey:@"unread"]; [[[MLMediaLibrary sharedMediaLibrary] managedObjectContext] refreshObject:[self album] mergeChanges:YES]; [[[MLMediaLibrary sharedMediaLibrary] managedObjectContext] refreshObject:self mergeChanges:YES]; } @dynamic artist; @dynamic genre; @dynamic title; @dynamic trackNumber; @dynamic album; @dynamic files; @end Sources/MLCrashPreventer.h000066400000000000000000000026441247122470700160520ustar00rootroot00000000000000/***************************************************************************** * MLCrashPreventer.h * MobileMediaLibraryKit ***************************************************************************** * Copyright (C) 2010 Pierre d'Herbemont * Copyright (C) 2010-2013 VLC authors and VideoLAN * $Id$ * * Authors: Pierre d'Herbemont * * 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.1 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 Lesser 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ @class MLFile; @interface MLCrashPreventer : NSObject + (id)sharedPreventer; - (void)cancelAllFileParse; - (void)markCrasherFiles; - (BOOL)isFileSafe:(MLFile *)file; - (void)willParseFile:(MLFile *)file; - (void)didParseFile:(MLFile *)file; @end Sources/MLCrashPreventer.m000066400000000000000000000062371247122470700160610ustar00rootroot00000000000000/***************************************************************************** * MLCrashPreventer.m * MobileMediaLibraryKit ***************************************************************************** * Copyright (C) 2010 Pierre d'Herbemont * Copyright (C) 2010-2013 VLC authors and VideoLAN * $Id$ * * Authors: Pierre d'Herbemont * * 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.1 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 Lesser 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ #import "MLCrashPreventer.h" #import "MLThumbnailerQueue.h" #import "MLFileParserQueue.h" #import "MLCrashPreventer.h" #import "MLFile.h" #import "MLMediaLibrary.h" @interface MLCrashPreventer () { NSMutableArray *_parsedFiles; } @end @implementation MLCrashPreventer + (id)sharedPreventer { static MLCrashPreventer *crashPreventer; if (!crashPreventer) crashPreventer = [[MLCrashPreventer alloc] init]; // Use the same queue for the two objects, because we wan't to track accurately // which operation causes a crash. [MLThumbnailerQueue sharedThumbnailerQueue].queue = [MLFileParserQueue sharedFileParserQueue].queue; return crashPreventer; } - (id)init { self = [super init]; if (self) _parsedFiles = [[NSMutableArray alloc] init]; return self; } - (void)dealloc { NSAssert([_parsedFiles count] == 0, @"You should call -cancelAllFileParse before releasing"); } - (void)cancelAllFileParse { APLog(@"Cancelling file parsing"); for (MLFile *file in _parsedFiles) file.isBeingParsed = NO; [_parsedFiles removeAllObjects]; [[MLMediaLibrary sharedMediaLibrary] save]; } - (void)markCrasherFiles { for (MLFile *file in [MLFile allFiles]) { if ([file isBeingParsed]) { file.isSafe = NO; file.isBeingParsed = NO; } } [[MLMediaLibrary sharedMediaLibrary] save]; } - (BOOL)isFileSafe:(MLFile *)file { return file.isSafe; } - (void)willParseFile:(MLFile *)file { NSAssert([MLThumbnailerQueue sharedThumbnailerQueue].queue == [MLFileParserQueue sharedFileParserQueue].queue, @""); NSAssert([_parsedFiles count] < 1, @"Parsing multiple files at the same time. Crash preventer can't work accurately."); file.isBeingParsed = YES; // Force to save the media library in case of crash. [[MLMediaLibrary sharedMediaLibrary] save]; [_parsedFiles addObject:file]; } - (void)didParseFile:(MLFile *)file { file.isBeingParsed = NO; [_parsedFiles removeObject:file]; } @end Sources/MLFile.m000066400000000000000000000266331247122470700140070ustar00rootroot00000000000000/***************************************************************************** * MLFile.m * Lunettes ***************************************************************************** * Copyright (C) 2010 Pierre d'Herbemont * Copyright (C) 2010-2013 VLC authors and VideoLAN * $Id$ * * Authors: Pierre d'Herbemont * Felix Paul Kühne * * 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.1 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 Lesser 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ #import "MLFile.h" #import "MLShow.h" #import "MLShowEpisode.h" #import "MLAlbum.h" #import "MLAlbumTrack.h" #import "MLMediaLibrary.h" #import "MLThumbnailerQueue.h" NSString *kMLFileTypeMovie = @"movie"; NSString *kMLFileTypeClip = @"clip"; NSString *kMLFileTypeTVShowEpisode = @"tvShowEpisode"; NSString *kMLFileTypeAudio = @"audio"; @implementation MLFile - (NSString *)description { return [NSString stringWithFormat:@"", [self title]]; } + (NSArray *)allFiles { NSFetchRequest *request = [[NSFetchRequest alloc] init]; NSManagedObjectContext *moc = [[MLMediaLibrary sharedMediaLibrary] managedObjectContext]; NSEntityDescription *entity = [NSEntityDescription entityForName:@"File" inManagedObjectContext:moc]; [request setEntity:entity]; [request setPredicate:[NSPredicate predicateWithFormat:@"isOnDisk == YES"]]; NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:@"title" ascending:YES selector:@selector(localizedCaseInsensitiveCompare:)]; [request setSortDescriptors:@[descriptor]]; NSError *error; NSArray *movies = [moc executeFetchRequest:request error:&error]; if (!movies) { APLog(@"WARNING: %@", error); } return movies; } + (NSArray *)fileForURL:(NSString *)url; { NSFetchRequest *request = [[NSFetchRequest alloc] init]; NSManagedObjectContext *moc = [[MLMediaLibrary sharedMediaLibrary] managedObjectContext]; NSEntityDescription *entity = [NSEntityDescription entityForName:@"File" inManagedObjectContext:moc]; [request setEntity:entity]; [request setPredicate:[NSPredicate predicateWithFormat:@"url == %@", url]]; NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:@"title" ascending:YES selector:@selector(localizedCaseInsensitiveCompare:)]; [request setSortDescriptors:@[descriptor]]; NSError *error; NSArray *files = [moc executeFetchRequest:request error:&error]; if (!files) APLog(@"WARNING: %@", error); return files; } - (BOOL)isKindOfType:(NSString *)type { return [self.type isEqualToString:type]; } - (BOOL)isMovie { return [self isKindOfType:kMLFileTypeTVShowEpisode]; } - (BOOL)isClip { return [self isKindOfType:kMLFileTypeTVShowEpisode]; } - (BOOL)isShowEpisode { return [self isKindOfType:kMLFileTypeTVShowEpisode]; } - (BOOL)isAlbumTrack { return [self isKindOfType:kMLFileTypeAudio]; } - (BOOL)isSupportedAudioFile { NSUInteger options = NSRegularExpressionSearch | NSCaseInsensitiveSearch; return ([[self.url lastPathComponent] rangeOfString:@"\\.(aac|aiff|aif|amr|aob|ape|axa|caf|flac|it|m2a|m4a|m4b|mka|mlp|mod|mp1|mp2|mp3|mpa|mpc|oga|oma|opus|rmi|s3m|spx|tta|voc|vqf|w64|wav|wma|wv|xa|xm)$" options:options].location != NSNotFound); } - (NSString *)artworkURL { if ([self isShowEpisode]) { return self.showEpisode.artworkURL; } return [self primitiveValueForKey:@"artworkURL"]; } - (NSString *)title { if ([self isShowEpisode]) { MLShowEpisode *episode = self.showEpisode; NSMutableString *name = [[NSMutableString alloc] init]; if (episode.show.name.length > 0) [name appendString:episode.show.name]; if ([episode.seasonNumber intValue] > 0) { if (![name isEqualToString:@""]) [name appendString:@" - "]; [name appendFormat:@"S%02dE%02d", [episode.seasonNumber intValue], [episode.episodeNumber intValue]]; } if (episode.name.length > 0) { if ([name length] > 0) [name appendString:@" - "]; [name appendString:episode.name]; } NSString *returnValue = [NSString stringWithString:name]; return returnValue; } else if ([self isAlbumTrack]) { MLAlbumTrack *track = self.albumTrack; if (track && track.title.length > 0) { NSMutableString *name = [[NSMutableString alloc] initWithString:track.title]; if (track.album.name.length > 0) [name appendFormat:@" - %@", track.album.name]; if (track.artist.length > 0) [name appendFormat:@" - %@", track.artist]; NSString *returnValue = [NSString stringWithString:name]; return returnValue; } } [self willAccessValueForKey:@"title"]; NSString *ret = [self primitiveValueForKey:@"title"]; [self didAccessValueForKey:@"title"]; return ret; } @dynamic seasonNumber; @dynamic remainingTime; @dynamic releaseYear; @dynamic lastSubtitleTrack; @dynamic lastAudioTrack; @dynamic playCount; @dynamic artworkURL; @dynamic type; @dynamic title; @dynamic shortSummary; @dynamic currentlyWatching; @dynamic episodeNumber; @dynamic hasFetchedInfo; @dynamic noOnlineMetaData; @dynamic showEpisode; @dynamic labels; @dynamic tracks; @dynamic isOnDisk; @dynamic duration; @dynamic artist; @dynamic album; @dynamic albumTrackNumber; @dynamic folderTrackNumber; @dynamic genre; @dynamic albumTrack; @dynamic unread; - (NSNumber *)lastPosition { [self willAccessValueForKey:@"lastPosition"]; NSNumber *ret = [self primitiveValueForKey:@"lastPosition"]; [self didAccessValueForKey:@"lastPosition"]; return ret; } - (void)setLastPosition:(NSNumber *)lastPosition { @try { [self willChangeValueForKey:@"lastPosition"]; [self setPrimitiveValue:lastPosition forKey:@"lastPosition"]; [self didChangeValueForKey:@"lastPosition"]; } @catch (NSException *exception) { APLog(@"setLastPosition raised exception"); } } - (NSString *)url { [self willAccessValueForKey:@"url"]; NSString *ret = [self primitiveValueForKey:@"url"]; [self didAccessValueForKey:@"url"]; /* we need to make sure that current app path is still part of the file * URL since app upgrades via iTunes or the App Store will change the * absolute URL of our files (trac #11330) */ NSString *documentFolderPath = [[MLMediaLibrary sharedMediaLibrary] documentFolderPath]; if ([ret rangeOfString:documentFolderPath].location != NSNotFound) return ret; NSArray *pathComponents = [ret componentsSeparatedByString:@"/"]; NSUInteger componentCount = pathComponents.count; if ([pathComponents[componentCount - 2] isEqualToString:@"Documents"]) ret = [NSString stringWithFormat:@"%@/%@", documentFolderPath, [ret lastPathComponent]]; else { NSUInteger firstElement = [pathComponents indexOfObject:@"Documents"] + 1; ret = documentFolderPath; for (NSUInteger x = 0; x < componentCount - firstElement; x++) ret = [ret stringByAppendingFormat:@"/%@", pathComponents[firstElement + x]]; } APLog(@"returning modified URL! will return %@", ret); return ret; } - (void)setUrl:(NSString *)url { @try { [self willChangeValueForKey:@"url"]; [self setPrimitiveValue:url forKey:@"url"]; [self didChangeValueForKey:@"url"]; } @catch (NSException *exception) { APLog(@"setUrl raised exception"); } } - (NSString *)thumbnailPath { NSString *folder = [[MLMediaLibrary sharedMediaLibrary] thumbnailFolderPath]; NSURL *url = [[self objectID] URIRepresentation]; return [[folder stringByAppendingPathComponent:[url path]] stringByAppendingString:@".png"]; } - (UIImage *)computedThumbnail { return [UIImage imageWithContentsOfFile:[self thumbnailPath]]; } - (void)setComputedThumbnail:(UIImage *)image { NSURL *url = [NSURL fileURLWithPath:[self thumbnailPath]]; NSFileManager *manager = [NSFileManager defaultManager]; [manager createDirectoryAtPath:[[self thumbnailPath] stringByDeletingLastPathComponent] withIntermediateDirectories:YES attributes:nil error:nil]; if (!image) { [manager removeItemAtURL:url error:nil]; return; } [UIImagePNGRepresentation(image) writeToURL:url atomically:YES]; } - (BOOL)isSafe { [self willAccessValueForKey:@"isSafe"]; NSNumber *ret = [self primitiveValueForKey:@"isSafe"]; [self didAccessValueForKey:@"isSafe"]; return [ret boolValue]; } - (void)setIsSafe:(BOOL)isSafe { @try { [self willChangeValueForKey:@"isSafe"]; [self setPrimitiveValue:@(isSafe) forKey:@"isSafe"]; [self didChangeValueForKey:@"isSafe"]; } @catch (NSException *exception) { APLog(@"setIsSafe raised exception"); } } - (BOOL)isBeingParsed { [self willAccessValueForKey:@"isBeingParsed"]; NSNumber *ret = [self primitiveValueForKey:@"isBeingParsed"]; [self didAccessValueForKey:@"isBeingParsed"]; return [ret boolValue]; } - (void)setIsBeingParsed:(BOOL)isBeingParsed { @try { [self willChangeValueForKey:@"isBeingParsed"]; [self setPrimitiveValue:@(isBeingParsed) forKey:@"isBeingParsed"]; [self didChangeValueForKey:@"isBeingParsed"]; } @catch (NSException *exception) { APLog(@"setIsBeingParsed raised exception"); } } - (BOOL)thumbnailTimeouted { [self willAccessValueForKey:@"thumbnailTimeouted"]; NSNumber *ret = [self primitiveValueForKey:@"thumbnailTimeouted"]; [self didAccessValueForKey:@"thumbnailTimeouted"]; return [ret boolValue]; } - (void)setThumbnailTimeouted:(BOOL)thumbnailTimeouted { @try { [self willChangeValueForKey:@"thumbnailTimeouted"]; [self setPrimitiveValue:@(thumbnailTimeouted) forKey:@"thumbnailTimeouted"]; [self didChangeValueForKey:@"thumbnailTimeouted"]; } @catch (NSException *exception) { APLog(@"setThumbnailTimeouted raised exception"); } } - (void)willDisplay { [[MLThumbnailerQueue sharedThumbnailerQueue] setHighPriorityForFile:self]; } - (void)didHide { [[MLThumbnailerQueue sharedThumbnailerQueue] setDefaultPriorityForFile:self]; } - (NSManagedObject *)videoTrack { NSSet *tracks = [self tracks]; if (!tracks) return nil; for (NSManagedObject *track in tracks) { if ([[[track entity] name] isEqualToString:@"VideoTrackInformation"]) return track; } return nil; } - (size_t)fileSizeInBytes { NSFileManager *manager = [NSFileManager defaultManager]; NSDictionary *fileAttributes = [manager attributesOfItemAtPath:[[[NSURL URLWithString:self.url] path] stringByResolvingSymlinksInPath] error:nil]; NSNumber *fileSize = fileAttributes[NSFileSize]; return [fileSize unsignedLongLongValue]; } @end Sources/MLFileParserQueue.h000066400000000000000000000027551247122470700161630ustar00rootroot00000000000000/***************************************************************************** * MLFileParserQueue.h * MobileMediaLibraryKit ***************************************************************************** * Copyright (C) 2010 Pierre d'Herbemont * Copyright (C) 2010-2013 VLC authors and VideoLAN * $Id$ * * Authors: Pierre d'Herbemont * * 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.1 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 Lesser 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ @class MLFile; @interface MLFileParserQueue : NSObject + (MLFileParserQueue *)sharedFileParserQueue; - (void)addFile:(MLFile *)file; - (void)setHighPriorityForFile:(MLFile *)file; - (void)setDefaultPriorityForFile:(MLFile *)file; - (void)stop; - (void)resume; @property (nonatomic, strong) NSOperationQueue *queue; @end Sources/MLFileParserQueue.m000066400000000000000000000164451247122470700161710ustar00rootroot00000000000000/***************************************************************************** * MLFileParserQueue.m * MobileMediaLibraryKit ***************************************************************************** * Copyright (C) 2010 Pierre d'Herbemont * Copyright (C) 2010-2013 VLC authors and VideoLAN * $Id$ * * Authors: Pierre d'Herbemont * Felix Paul Kühne * * 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.1 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 Lesser 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ #import "MLFileParserQueue.h" #import "MLFile.h" #import "MLMediaLibrary.h" #import "MLCrashPreventer.h" #import "MLAlbumTrack.h" #import "MLAlbum.h" #import "MLTitleDecrapifier.h" @interface MLFileParserQueue () { NSDictionary *_fileDescriptionToOperation; NSOperationQueue *_queue; } @end @interface MLParsingOperation : NSOperation { MLFile *_file; VLCMedia *_media; } @property (strong,readwrite) MLFile *file; @end @interface MLFileParserQueue () - (void)didFinishOperation:(MLParsingOperation *)op; @end @implementation MLParsingOperation @synthesize file=_file; - (id)initWithFile:(MLFile *)file; { if (!(self = [super init])) return nil; self.file = file; return self; } - (void)parse { NSAssert(!_media, @"We are already parsing"); APLog(@"Starting parsing %@", self.file); [[MLCrashPreventer sharedPreventer] willParseFile:self.file]; _media = [VLCMedia mediaWithURL:[NSURL URLWithString:self.file.url]]; _media.delegate = self; [_media parse]; MLFileParserQueue *parserQueue = [MLFileParserQueue sharedFileParserQueue]; [parserQueue.queue setSuspended:YES]; // Balanced in -mediaDidFinishParsing // Balanced in -mediaDidFinishParsing: } - (void)main { [self performSelectorOnMainThread:@selector(parse) withObject:nil waitUntilDone:YES]; } - (void)mediaDidFinishParsing:(VLCMedia *)media { APLog(@"Parsed %@ - %lu tracks", media, [[_media tracksInformation] count]); if (_media.delegate != self) return; _media.delegate = nil; NSArray *tracks = [_media tracksInformation]; NSMutableSet *tracksSet = [NSMutableSet setWithCapacity:[tracks count]]; for (NSDictionary *track in tracks) { NSString *type = track[VLCMediaTracksInformationType]; NSManagedObject *trackInfo = nil; if ([type isEqualToString:VLCMediaTracksInformationTypeVideo]) { trackInfo = [[MLMediaLibrary sharedMediaLibrary] createObjectForEntity:@"VideoTrackInformation"]; [trackInfo setValue:track[VLCMediaTracksInformationVideoWidth] forKey:@"width"]; [trackInfo setValue:track[VLCMediaTracksInformationVideoHeight] forKey:@"height"]; } else if ([type isEqualToString:VLCMediaTracksInformationTypeAudio]) { trackInfo = [[MLMediaLibrary sharedMediaLibrary] createObjectForEntity:@"AudioTrackInformation"]; [trackInfo setValue:track[VLCMediaTracksInformationAudioRate] forKey:@"bitrate"]; [trackInfo setValue:track[VLCMediaTracksInformationAudioChannelsNumber] forKey:@"channelsNumber"]; } if (trackInfo) [tracksSet addObject:trackInfo]; } [self.file setTracks:tracksSet]; [self.file setDuration:[[_media length] numberValue]]; if ([self.file isAlbumTrack]) { NSDictionary *audioContentInfo = [_media metaDictionary]; if (audioContentInfo && audioContentInfo.count > 0) { NSString *title = audioContentInfo[VLCMetaInformationTitle]; NSString *artist = audioContentInfo[VLCMetaInformationArtist]; NSString *albumName = audioContentInfo[VLCMetaInformationAlbum]; NSString *releaseYear = audioContentInfo[VLCMetaInformationDate]; NSString *genre = audioContentInfo[VLCMetaInformationGenre]; NSString *trackNumber = audioContentInfo[VLCMetaInformationTrackNumber]; MLAlbum *album = nil; BOOL wasCreated = NO; MLAlbumTrack *track = [MLAlbumTrack trackWithAlbumName:albumName trackNumber:@([trackNumber integerValue]) createIfNeeded:YES wasCreated:&wasCreated]; if (track) { album = track.album; track.title = title ? title : @""; track.artist = artist ? artist : @""; track.genre = genre ? genre : @""; album.releaseYear = releaseYear ? releaseYear : @""; if (!track.title || [track.title isEqualToString:@""]) track.title = [MLTitleDecrapifier decrapify:self.file.title]; [track addFilesObject:self.file]; self.file.albumTrack = track; } } } MLFileParserQueue *parserQueue = [MLFileParserQueue sharedFileParserQueue]; [[MLCrashPreventer sharedPreventer] didParseFile:self.file]; [parserQueue.queue setSuspended:NO]; [parserQueue didFinishOperation:self]; _media = nil; } @end @implementation MLFileParserQueue @synthesize queue=_queue; + (MLFileParserQueue *)sharedFileParserQueue { static MLFileParserQueue *shared = nil; if (!shared) { shared = [[MLFileParserQueue alloc] init]; } return shared; } - (id)init { self = [super init]; if (self != nil) { _fileDescriptionToOperation = [[NSMutableDictionary alloc] init]; _queue = [[NSOperationQueue alloc] init]; [_queue setMaxConcurrentOperationCount:1]; } return self; } static inline NSString *hashFromFile(MLFile *file) { return [NSString stringWithFormat:@"%p", [[file objectID] URIRepresentation]]; } - (void)didFinishOperation:(MLParsingOperation *)op { [_fileDescriptionToOperation setValue:nil forKey:hashFromFile(op.file)]; } - (void)addFile:(MLFile *)file { if (_fileDescriptionToOperation[hashFromFile(file)]) return; if (![[MLCrashPreventer sharedPreventer] isFileSafe:file]) { APLog(@"%@ is unsafe and will crash, ignoring", file); return; } MLParsingOperation *op = [[MLParsingOperation alloc] initWithFile:file]; [_fileDescriptionToOperation setValue:op forKey:hashFromFile(file)]; [self.queue addOperation:op]; } - (void)stop { [_queue setMaxConcurrentOperationCount:0]; } - (void)resume { [_queue setMaxConcurrentOperationCount:1]; } - (void)setHighPriorityForFile:(MLFile *)file { MLParsingOperation *op = _fileDescriptionToOperation[hashFromFile(file)]; [op setQueuePriority:NSOperationQueuePriorityHigh]; } - (void)setDefaultPriorityForFile:(MLFile *)file { MLParsingOperation *op = _fileDescriptionToOperation[hashFromFile(file)]; [op setQueuePriority:NSOperationQueuePriorityNormal]; } @end Sources/MLLabel.m000066400000000000000000000044431247122470700141420ustar00rootroot00000000000000/***************************************************************************** * MLLabel.m * Lunettes ***************************************************************************** * Copyright (C) 2010 Pierre d'Herbemont * Copyright (C) 2010-2013 VLC authors and VideoLAN * $Id$ * * Authors: Pierre d'Herbemont * Felix Paul Kühne * * 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.1 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 Lesser 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ #import "MLLabel.h" #import "MLMediaLibrary.h" #import "MLFile.h" @implementation MLLabel + (NSArray *)allLabels { NSFetchRequest *request = [[NSFetchRequest alloc] init]; NSManagedObjectContext *moc = [[MLMediaLibrary sharedMediaLibrary] managedObjectContext]; NSEntityDescription *entity = [NSEntityDescription entityForName:@"Label" inManagedObjectContext:moc]; [request setEntity:entity]; NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:NO]; [request setSortDescriptors:@[descriptor]]; NSArray *labels = [moc executeFetchRequest:request error:nil]; return labels; } @dynamic name; @dynamic files; - (NSArray *)sortedFolderItems { NSArray *folderItems = [[self valueForKey:@"files"] allObjects]; NSSortDescriptor *folderItemDescriptor = [[NSSortDescriptor alloc] initWithKey:@"folderTrackNumber" ascending:YES selector:@selector(compare:)]; NSArray *items = [folderItems sortedArrayUsingDescriptors:@[folderItemDescriptor]]; return items; } @end Sources/MLMediaLibrary.m000066400000000000000000001067721247122470700154770ustar00rootroot00000000000000/***************************************************************************** * MLMediaLibrary.m * MobileMediaLibraryKit ***************************************************************************** * Copyright (C) 2010 Pierre d'Herbemont * Copyright (C) 2010-2014 VLC authors and VideoLAN * $Id$ * * Authors: Pierre d'Herbemont * Felix Paul Kühne * * 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.1 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 Lesser 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ #import "MLMediaLibrary.h" #import "MLTitleDecrapifier.h" #import "MLMovieInfoGrabber.h" #import "MLTVShowInfoGrabber.h" #import "MLTVShowEpisodesInfoGrabber.h" #import "MLFile.h" #import "MLLabel.h" #import "MLShowEpisode.h" #import "MLShow.h" #import "MLThumbnailerQueue.h" #import "MLAlbumTrack.h" #import "MLAlbum.h" #import "MLFileParserQueue.h" #import "MLCrashPreventer.h" @interface MLMediaLibrary () { NSManagedObjectContext *_managedObjectContext; NSManagedObjectModel *_managedObjectModel; BOOL _allowNetworkAccess; NSString *_thumbnailFolderPath; NSString *_databaseFolderPath; NSString *_documentFolderPath; } @end #define DEBUG 1 // To debug #define DELETE_LIBRARY_ON_EACH_LAUNCH 0 // Pref key static NSString *kLastTVDBUpdateServerTime = @"MLLastTVDBUpdateServerTime"; static NSString *kUpdatedToTheGreatSharkHuntDatabaseFormat = @"upgradedToDatabaseFormat 2.3"; static NSString *kDecrapifyTitles = @"MLDecrapifyTitles"; #if HAVE_BLOCK @interface MLMediaLibrary () #else @interface MLMediaLibrary () #endif - (NSManagedObjectContext *)managedObjectContext; - (NSString *)databaseFolderPath; @end @implementation MLMediaLibrary + (void)initialize { NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; [defaults registerDefaults:@{kUpdatedToTheGreatSharkHuntDatabaseFormat : @NO, kDecrapifyTitles : @YES}]; } + (id)sharedMediaLibrary { static id sharedMediaLibrary = nil; if (!sharedMediaLibrary) { sharedMediaLibrary = [[[self class] alloc] init]; APLog(@"Initializing db in %@", [sharedMediaLibrary databaseFolderPath]); // Also force to init the crash preventer // Because it will correctly set up the parser and thumbnail queue [MLCrashPreventer sharedPreventer]; } return sharedMediaLibrary; } - (void)dealloc { if (_managedObjectContext) [_managedObjectContext removeObserver:self forKeyPath:@"hasChanges"]; } - (NSFetchRequest *)fetchRequestForEntity:(NSString *)entity { NSFetchRequest *request = [[NSFetchRequest alloc] init]; NSManagedObjectContext *moc = [self managedObjectContext]; NSEntityDescription *entityDescription = [NSEntityDescription entityForName:entity inManagedObjectContext:moc]; NSAssert(entityDescription, @"No entity"); [request setEntity:entityDescription]; return request; } - (id)createObjectForEntity:(NSString *)entity { NSManagedObjectContext *moc = [self managedObjectContext]; return [NSEntityDescription insertNewObjectForEntityForName:entity inManagedObjectContext:moc]; } - (void)removeObject:(NSManagedObject *)object { [[self managedObjectContext] deleteObject:object]; } #pragma mark - #pragma mark Media Library - (NSManagedObjectModel *)managedObjectModel { if (_managedObjectModel) return _managedObjectModel; _managedObjectModel = [NSManagedObjectModel mergedModelFromBundles:nil]; return _managedObjectModel; } - (NSString *)databaseFolderPath { if (_databaseFolderPath) { if (_databaseFolderPath.length > 0) return _databaseFolderPath; } int directory = NSLibraryDirectory; NSArray *paths = NSSearchPathForDirectoriesInDomains(directory, NSUserDomainMask, YES); NSString *directoryPath = paths[0]; #if DELETE_LIBRARY_ON_EACH_LAUNCH [[NSFileManager defaultManager] removeItemAtPath:directoryPath error:nil]; #endif _databaseFolderPath = directoryPath; return _databaseFolderPath; } - (NSString *)thumbnailFolderPath { if (_thumbnailFolderPath) { if (_thumbnailFolderPath.length > 0) return _thumbnailFolderPath; } int directory = NSLibraryDirectory; NSArray *paths = NSSearchPathForDirectoriesInDomains(directory, NSUserDomainMask, YES); NSString *directoryPath = paths[0]; #if DELETE_LIBRARY_ON_EACH_LAUNCH [[NSFileManager defaultManager] removeItemAtPath:directoryPath error:nil]; #endif _thumbnailFolderPath = [directoryPath stringByAppendingPathComponent:@"Thumbnails"]; return _thumbnailFolderPath; } - (NSString *)documentFolderPath { if (_documentFolderPath) { if (_documentFolderPath.length > 0) return _documentFolderPath; } int directory = NSDocumentDirectory; NSArray *paths = NSSearchPathForDirectoriesInDomains(directory, NSUserDomainMask, YES); _documentFolderPath = [NSString stringWithFormat:@"file://%@", paths[0]]; return _documentFolderPath; } - (NSURL *)persistentStoreURL { NSString *databaseFolderPath = [self databaseFolderPath]; NSString *path = [databaseFolderPath stringByAppendingPathComponent: @"MediaLibrary.sqlite"]; return [NSURL fileURLWithPath:path]; } - (NSPersistentStoreCoordinator *)persistentStoreCoordinator { NSPersistentStoreCoordinator *coordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]]; NSNumber *yes = @YES; NSDictionary *options = @{NSMigratePersistentStoresAutomaticallyOption : yes, NSInferMappingModelAutomaticallyOption : yes}; NSError *error; NSPersistentStore *persistentStore = [coordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:self.persistentStoreURL options:options error:&error]; if (!persistentStore) { #if! TARGET_OS_IPHONE // FIXME: Deal with versioning NSInteger ret = NSRunAlertPanel(@"Error", @"The Media Library you have on your disk is not compatible with the one Lunettes can read. Do you want to create a new one?", @"No", @"Yes", nil); if (ret == NSOKButton) [NSApp terminate:nil]; [[NSFileManager defaultManager] removeItemAtPath:self.persistentStoreURL.path error:nil]; #else [[NSFileManager defaultManager] removeItemAtPath:self.persistentStoreURL.path error:nil]; #endif persistentStore = [coordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:self.persistentStoreURL options:options error:&error]; if (!persistentStore) { #if! TARGET_OS_IPHONE NSRunInformationalAlertPanel(@"Corrupted Media Library", @"There is nothing we can apparently do about it...", @"OK", nil, nil); #else UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Corrupted Media Library" message:@"There is nothing we can apparently do about it..." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; [alert show]; #endif // Probably assert instead. return nil; } } return coordinator; } - (NSManagedObjectContext *)managedObjectContext { if (_managedObjectContext) return _managedObjectContext; _managedObjectContext = [[NSManagedObjectContext alloc] init]; [_managedObjectContext setPersistentStoreCoordinator:self.persistentStoreCoordinator]; [_managedObjectContext setUndoManager:nil]; [_managedObjectContext addObserver:self forKeyPath:@"hasChanges" options:NSKeyValueObservingOptionInitial context:nil]; return _managedObjectContext; } - (void)savePendingChanges { [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(savePendingChanges) object:nil]; NSError *error = nil; BOOL success = [[self managedObjectContext] save:&error]; NSAssert1(success, @"Can't save: %@", error); #if !TARGET_OS_IPHONE && MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5 NSProcessInfo *process = [NSProcessInfo processInfo]; if ([process respondsToSelector:@selector(enableSuddenTermination)]) [process enableSuddenTermination]; #endif } - (void)save { NSError *error = nil; BOOL success = [[self managedObjectContext] save:&error]; NSAssert1(success, @"Can't save: %@", error); } - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if ([keyPath isEqualToString:@"hasChanges"] && object == _managedObjectContext) { #if !TARGET_OS_IPHONE && MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5 NSProcessInfo *process = [NSProcessInfo processInfo]; if ([process respondsToSelector:@selector(disableSuddenTermination)]) [process disableSuddenTermination]; #endif if ([[self managedObjectContext] hasChanges]) { [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(savePendingChanges) object:nil]; [self performSelector:@selector(savePendingChanges) withObject:nil afterDelay:1.]; } return; } [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; } #pragma mark - #pragma mark No meta data fallbacks - (void)computeThumbnailForFile:(MLFile *)file { if (!file.computedThumbnail) { APLog(@"Computing thumbnail for %@", file.title); [[MLThumbnailerQueue sharedThumbnailerQueue] addFile:file]; } } - (void)errorWhenFetchingMetaDataForFile:(MLFile *)file { APLog(@"Error when fetching for '%@'", file.title); [self computeThumbnailForFile:file]; } - (void)errorWhenFetchingMetaDataForShow:(MLShow *)show { for (MLShowEpisode *episode in show.episodes) { for (MLFile *file in episode.files) [self errorWhenFetchingMetaDataForFile:file]; } } - (void)noMetaDataInRemoteDBForFile:(MLFile *)file { file.noOnlineMetaData = @YES; [self computeThumbnailForFile:file]; } - (void)noMetaDataInRemoteDBForShow:(MLShow *)show { for (MLShowEpisode *episode in show.episodes) { for (MLFile *file in episode.files) [self noMetaDataInRemoteDBForFile:file]; } } #pragma mark - #pragma mark Getter - (void)addNewLabelWithName:(NSString *)name { MLLabel *label = [self createObjectForEntity:@"Label"]; label.name = name; } /** * TV MLShow Episodes */ #pragma mark - #pragma mark Online meta data grabbing #if !HAVE_BLOCK - (void)tvShowEpisodesInfoGrabberDidFinishGrabbing:(MLTVShowEpisodesInfoGrabber *)grabber { MLShow *show = grabber.userData; NSArray *results = grabber.episodesResults; [show setValue:(grabber.results)[@"serieArtworkURL"] forKey:@"artworkURL"]; for (id result in results) { if ([result[@"serie"] boolValue]) { continue; } MLShowEpisode *showEpisode = [MLShowEpisode episodeWithShow:show episodeNumber:result[@"episodeNumber"] seasonNumber:result[@"seasonNumber"] createIfNeeded:YES]; showEpisode.name = result[@"title"]; showEpisode.theTVDBID = result[@"id"]; showEpisode.shortSummary = result[@"shortSummary"]; showEpisode.artworkURL = result[@"artworkURL"]; if (!showEpisode.artworkURL) { for (MLFile *file in showEpisode.files) [self computeThumbnailForFile:file]; } showEpisode.lastSyncDate = [MLTVShowInfoGrabber serverTime]; } show.lastSyncDate = [MLTVShowInfoGrabber serverTime]; } - (void)tvShowEpisodesInfoGrabber:(MLTVShowEpisodesInfoGrabber *)grabber didFailWithError:(NSError *)error { MLShow *show = grabber.userData; [self errorWhenFetchingMetaDataForShow:show]; } - (void)tvShowInfoGrabberDidFinishGrabbing:(MLTVShowInfoGrabber *)grabber { MLShow *show = grabber.userData; NSArray *results = grabber.results; if ([results count] > 0) { NSDictionary *result = results[0]; NSString *showId = result[@"id"]; show.theTVDBID = showId; show.name = result[@"title"]; show.shortSummary = result[@"shortSummary"]; show.releaseYear = result[@"releaseYear"]; // Fetch episodes info MLTVShowEpisodesInfoGrabber *grabber = [[MLTVShowEpisodesInfoGrabber alloc] init]; grabber.delegate = self; grabber.userData = show; [grabber lookUpForShowID:showId]; } else { // Not found. [self noMetaDataInRemoteDBForShow:show]; show.lastSyncDate = [MLTVShowInfoGrabber serverTime]; } } - (void)tvShowInfoGrabber:(MLTVShowInfoGrabber *)grabber didFailWithError:(NSError *)error { MLShow *show = grabber.userData; [self errorWhenFetchingMetaDataForShow:show]; } - (void)tvShowInfoGrabberDidFetchServerTime:(MLTVShowInfoGrabber *)grabber { MLShow *show = grabber.userData; [[NSUserDefaults standardUserDefaults] setInteger:[[MLTVShowInfoGrabber serverTime] integerValue] forKey:kLastTVDBUpdateServerTime]; // First fetch the MLShow ID MLTVShowInfoGrabber *showInfoGrabber = [[MLTVShowInfoGrabber alloc] init]; showInfoGrabber.delegate = self; showInfoGrabber.userData = show; APLog(@"Fetching show information on %@", show.name); [showInfoGrabber lookUpForTitle:show.name]; } #endif - (void)fetchMetaDataForShow:(MLShow *)show { if (!_allowNetworkAccess) return; APLog(@"Fetching show server time"); // First fetch the serverTime, so that we can update each entry. #if HAVE_BLOCK [MLTVShowInfoGrabber fetchServerTimeAndExecuteBlock:^(NSNumber *serverDate) { [[NSUserDefaults standardUserDefaults] setInteger:[serverDate integerValue] forKey:kLastTVDBUpdateServerTime]; APLog(@"Fetching show information on %@", show.name); // First fetch the MLShow ID MLTVShowInfoGrabber *grabber = [[[MLTVShowInfoGrabber alloc] init] autorelease]; [grabber lookUpForTitle:show.name andExecuteBlock:^{ NSArray *results = grabber.results; if ([results count] > 0) { NSDictionary *result = [results objectAtIndex:0]; NSString *showId = [result objectForKey:@"id"]; show.theTVDBID = showId; show.name = [result objectForKey:@"title"]; show.shortSummary = [result objectForKey:@"shortSummary"]; show.releaseYear = [result objectForKey:@"releaseYear"]; APLog(@"Fetching show episode information on %@", showId); // Fetch episode info MLTVShowEpisodesInfoGrabber *grabber = [[[MLTVShowEpisodesInfoGrabber alloc] init] autorelease]; [grabber lookUpForShowID:showId andExecuteBlock:^{ NSArray *results = grabber.episodesResults; [show setValue:[grabber.results objectForKey:@"serieArtworkURL"] forKey:@"artworkURL"]; for (id result in results) { if ([[result objectForKey:@"serie"] boolValue]) { continue; } MLShowEpisode *showEpisode = [MLShowEpisode episodeWithShow:show episodeNumber:[result objectForKey:@"episodeNumber"] seasonNumber:[result objectForKey:@"seasonNumber"] createIfNeeded:YES]; showEpisode.name = [result objectForKey:@"title"]; showEpisode.theTVDBID = [result objectForKey:@"id"]; showEpisode.shortSummary = [result objectForKey:@"shortSummary"]; showEpisode.artworkURL = [result objectForKey:@"artworkURL"]; showEpisode.lastSyncDate = serverDate; } show.lastSyncDate = serverDate; }]; } else { // Not found. show.lastSyncDate = serverDate; } }]; }]; #else MLTVShowInfoGrabber *grabber = [[MLTVShowInfoGrabber alloc] init]; grabber.delegate = self; grabber.userData = show; [grabber fetchServerTime]; #endif } - (void)addTVShowEpisodeWithInfo:(NSDictionary *)tvShowEpisodeInfo andFile:(MLFile *)file { file.type = kMLFileTypeTVShowEpisode; NSNumber *seasonNumber = tvShowEpisodeInfo[@"season"]; NSNumber *episodeNumber = tvShowEpisodeInfo[@"episode"]; NSString *tvShowName = tvShowEpisodeInfo[@"tvShowName"]; NSString *tvEpisodeName = tvShowEpisodeInfo[@"tvEpisodeName"]; BOOL hasNoTvShow = NO; if (!tvShowName) { tvShowName = @""; hasNoTvShow = YES; } BOOL wasInserted = NO; MLShow *show = nil; MLShowEpisode *episode = [MLShowEpisode episodeWithShowName:tvShowName episodeNumber:episodeNumber seasonNumber:seasonNumber createIfNeeded:YES wasCreated:&wasInserted]; if (episode) { show = episode.show; [show addEpisode:episode]; } if (wasInserted && !hasNoTvShow) { show.name = tvShowName; [self fetchMetaDataForShow:show]; } episode.name = tvEpisodeName; if (episode.name.length < 1) episode.name = file.title; file.seasonNumber = seasonNumber; file.episodeNumber = episodeNumber; episode.shouldBeDisplayed = @YES; [episode addFilesObject:file]; file.showEpisode = episode; // The rest of the meta data will be fetched using the MLShow file.hasFetchedInfo = @YES; } - (void)addAudioContentWithInfo:(NSDictionary *)audioContentInfo andFile:(MLFile *)file { file.type = kMLFileTypeAudio; file.title = audioContentInfo[VLCMetaInformationTitle]; /* all further meta data is set by the FileParserQueue */ file.hasFetchedInfo = @YES; } /** * MLFile auto detection */ #if !HAVE_BLOCK - (void)movieInfoGrabber:(MLMovieInfoGrabber *)grabber didFailWithError:(NSError *)error { MLFile *file = grabber.userData; [self errorWhenFetchingMetaDataForFile:file]; } - (void)movieInfoGrabberDidFinishGrabbing:(MLMovieInfoGrabber *)grabber { NSNumber *yes = @YES; NSArray *results = grabber.results; MLFile *file = grabber.userData; if ([results count] > 0) { NSDictionary *result = results[0]; file.artworkURL = result[@"artworkURL"]; file.title = result[@"title"]; file.shortSummary = result[@"shortSummary"]; file.releaseYear = result[@"releaseYear"]; } else { [self noMetaDataInRemoteDBForFile:file]; } file.hasFetchedInfo = yes; } #endif - (void)fetchMetaDataForFile:(MLFile *)file { APLog(@"Fetching meta data for %@", file.title); [[MLFileParserQueue sharedFileParserQueue] addFile:file]; if (!_allowNetworkAccess) { // Automatically compute the thumbnail [self computeThumbnailForFile:file]; } NSDictionary *tvShowEpisodeInfo = [MLTitleDecrapifier tvShowEpisodeInfoFromString:file.title]; if (tvShowEpisodeInfo) { [self addTVShowEpisodeWithInfo:tvShowEpisodeInfo andFile:file]; return; } if ([file isSupportedAudioFile]) { NSDictionary *audioContentInfo = [MLTitleDecrapifier audioContentInfoFromFile:file]; if (audioContentInfo && ![file videoTrack]) { [self addAudioContentWithInfo:audioContentInfo andFile:file]; return; } } if (!_allowNetworkAccess) return; // Go online and fetch info. // We don't care about keeping a reference to track the item during its life span // because we are a singleton MLMovieInfoGrabber *grabber = [[MLMovieInfoGrabber alloc] init]; APLog(@"Looking up for Movie '%@'", file.title); #if HAVE_BLOCK [grabber lookUpForTitle:file.title andExecuteBlock:^(NSError *err){ if (err) { [self errorWhenFetchingMetaDataForFile:file]; return; } NSArray *results = grabber.results; if ([results count] > 0) { NSDictionary *result = [results objectAtIndex:0]; file.artworkURL = [result objectForKey:@"artworkURL"]; if (!file.artworkURL) [self computeThumbnailForFile:file]; file.title = [result objectForKey:@"title"]; file.shortSummary = [result objectForKey:@"shortSummary"]; file.releaseYear = [result objectForKey:@"releaseYear"]; } else [self noMetaDataInRemoteDBForFile:file]; file.hasFetchedInfo = [NSNumber numberWithBool:YES]; }]; #else grabber.userData = file; grabber.delegate = self; [grabber lookUpForTitle:file.title]; #endif } #pragma mark - #pragma mark Adding file to the DB - (void)addFilePath:(NSString *)filePath { APLog(@"Adding Path %@", filePath); NSURL *url = [NSURL fileURLWithPath:filePath]; NSDictionary *attributes = [[NSFileManager defaultManager] attributesOfItemAtPath:filePath error:nil]; NSString *title = [filePath lastPathComponent]; #if !TARGET_OS_IPHONE NSDate *openedDate = nil; // FIXME kMDItemLastUsedDate NSDate *modifiedDate = nil; // FIXME [result valueForAttribute:@"kMDItemFSContentChangeDate"]; #endif NSNumber *size = attributes[NSFileSize]; // FIXME [result valueForAttribute:@"kMDItemFSSize"]; MLFile *file = [self createObjectForEntity:@"File"]; file.url = [url absoluteString]; // Yes, this is a negative number. VLCTime nicely display negative time // with "XX minutes remaining". And we are using this facility. NSNumber *no = @NO; NSNumber *yes = @YES; file.currentlyWatching = no; file.lastPosition = @0.0; file.remainingTime = @0.0; file.unread = yes; #if !TARGET_OS_IPHONE if ([openedDate isGreaterThan:modifiedDate]) { file.playCount = [NSNumber numberWithDouble:1]; file.unread = no; } #endif if ([[[NSUserDefaults standardUserDefaults] objectForKey:kDecrapifyTitles] boolValue] == YES) file.title = [MLTitleDecrapifier decrapify:[title stringByDeletingPathExtension]]; else file.title = [title stringByDeletingPathExtension]; if ([size longLongValue] < 150000000) /* 150 MB */ file.type = kMLFileTypeClip; else file.type = kMLFileTypeMovie; [self fetchMetaDataForFile:file]; } - (void)addFilePaths:(NSArray *)filepaths { NSUInteger count = [filepaths count]; NSMutableArray *fetchPredicates = [NSMutableArray arrayWithCapacity:count]; NSMutableDictionary *urlToObject = [NSMutableDictionary dictionaryWithCapacity:count]; NSString *documentFolderPath = [[MLMediaLibrary sharedMediaLibrary] documentFolderPath]; // Prepare a fetch request for all items NSArray *pathComponents; NSUInteger componentCount; for (NSString *path in filepaths) { #if TARGET_OS_IPHONE NSString *urlString; NSString *componentString = @""; pathComponents = [path componentsSeparatedByString:@"/"]; componentCount = pathComponents.count; if ([pathComponents[componentCount - 2] isEqualToString:@"Documents"]) componentString = [path lastPathComponent]; else { NSUInteger firstElement = [pathComponents indexOfObject:@"Documents"] + 1; for (NSUInteger x = 0; x < componentCount - firstElement; x++) { if (x == 0) componentString = [componentString stringByAppendingFormat:@"%@", pathComponents[firstElement + x]]; else componentString = [componentString stringByAppendingFormat:@"/%@", pathComponents[firstElement + x]]; } } /* compose and escape string */ urlString = [[NSString stringWithFormat:@"%@/%@", documentFolderPath, componentString] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; /* check for the end of the paths */ [fetchPredicates addObject:[NSPredicate predicateWithFormat:@"url CONTAINS %@", [urlString lastPathComponent]]]; [urlToObject setObject:path forKey:urlString]; #else [fetchPredicates addObject:[NSPredicate predicateWithFormat:@"url == %@", path]]; #endif } NSFetchRequest *request = [self fetchRequestForEntity:@"File"]; [request setPredicate:[NSCompoundPredicate orPredicateWithSubpredicates:fetchPredicates]]; APLog(@"Fetching"); NSArray *dbResults = [[self managedObjectContext] executeFetchRequest:request error:nil]; APLog(@"Done"); NSMutableArray *filePathsToAdd = [NSMutableArray arrayWithArray:filepaths]; // Remove objects that are already in db. for (MLFile *dbResult in dbResults) { NSString *urlString = dbResult.url; [filePathsToAdd removeObject:[urlToObject objectForKey:urlString]]; } // Add only the newly added items for (NSString* path in filePathsToAdd) [self addFilePath:path]; } #pragma mark - #pragma mark DB Updates #if !HAVE_BLOCK - (void)tvShowInfoGrabber:(MLTVShowInfoGrabber *)grabber didFetchUpdates:(NSArray *)updates { NSFetchRequest *request = [self fetchRequestForEntity:@"Show"]; [request setPredicate:[NSComparisonPredicate predicateWithLeftExpression:[NSExpression expressionForKeyPath:@"theTVDBID"] rightExpression:[NSExpression expressionForConstantValue:updates] modifier:NSDirectPredicateModifier type:NSInPredicateOperatorType options:0]]; NSArray *results = [[self managedObjectContext] executeFetchRequest:request error:nil]; for (MLShow *show in results) [self fetchMetaDataForShow:show]; } #endif - (BOOL)libraryNeedsUpgrade { if (![[[NSUserDefaults standardUserDefaults] objectForKey:kUpdatedToTheGreatSharkHuntDatabaseFormat] boolValue]) return YES; return NO; } - (void)upgradeLibrary { if (![[[NSUserDefaults standardUserDefaults] objectForKey:kUpdatedToTheGreatSharkHuntDatabaseFormat] boolValue]) [self _upgradeLibraryToGreatSharkHuntDatabaseFormat]; } - (void)_upgradeLibraryToGreatSharkHuntDatabaseFormat { [self libraryDidDisappear]; NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; NSFileManager *fileManager = [NSFileManager defaultManager]; /* remove potential empty albums left over by previous releases */ NSArray *collection = [MLAlbum allAlbums]; NSUInteger count = collection.count; MLAlbum *album; MLAlbumTrack *track; NSArray *secondaryCollection; NSURL *fileURL; NSUInteger secondaryCount = 0; NSArray *tertiaryCollection; NSUInteger tertiaryCount = 0; NSUInteger emptyAlbumCounter = 0; for (NSUInteger x = 0; x < count; x++) { album = collection[x]; if (album.tracks.count < 1) [[self managedObjectContext] deleteObject:album]; else { secondaryCollection = album.tracks.allObjects; secondaryCount = secondaryCollection.count; emptyAlbumCounter = 0; for (NSUInteger y = 0; y < secondaryCount; y++) { track = secondaryCollection[y]; tertiaryCollection = track.files.allObjects; tertiaryCount = tertiaryCollection.count; for (NSUInteger z = 0; z < tertiaryCount; z++) { fileURL = [NSURL URLWithString:[(MLFile *)tertiaryCollection[z] url]]; BOOL exists = [fileManager fileExistsAtPath:[fileURL path]]; if (exists) emptyAlbumCounter++; else [album removeTrack:track]; } } if (emptyAlbumCounter == 0) [[self managedObjectContext] deleteObject:album]; } } album = nil; /* remove potential empty shows left over by previous releases */ collection = [MLShow allShows]; MLShow *show; MLShowEpisode *showEpisode; count = collection.count; for (NSUInteger x = 0; x < count; x++) { show = collection[x]; if (show.episodes.count < 1) [[self managedObjectContext] deleteObject:show]; else { secondaryCollection = show.episodes.allObjects; secondaryCount = secondaryCollection.count; emptyAlbumCounter = 0; for (NSUInteger y = 0; y < secondaryCount; y++) { showEpisode = secondaryCollection[y]; tertiaryCollection = showEpisode.files.allObjects; tertiaryCount = tertiaryCollection.count; for (NSUInteger z = 0; z < tertiaryCount; z++) { fileURL = [NSURL URLWithString:[(MLFile *)tertiaryCollection[z] url]]; BOOL exists = [fileManager fileExistsAtPath:[fileURL path]]; if (exists) emptyAlbumCounter++; else [show removeEpisode:showEpisode]; } } if (emptyAlbumCounter == 0) [[self managedObjectContext] deleteObject:show]; } } /* remove duplicates */ NSArray *allFiles = [MLFile allFiles]; NSUInteger allFilesCount = allFiles.count; NSMutableArray *seenFiles = [[NSMutableArray alloc] initWithCapacity:allFilesCount]; MLFile *currentFile; NSString *currentFilePath; for (NSUInteger x = 0; x < allFilesCount; x++) { currentFile = allFiles[x]; currentFilePath = [currentFile.url stringByReplacingOccurrencesOfString:@"/localhost/" withString:@"//"]; if ([seenFiles containsObject:currentFilePath]) [[self managedObjectContext] deleteObject:currentFile]; else [seenFiles addObject:currentFilePath]; } [defaults setBool:YES forKey:kUpdatedToTheGreatSharkHuntDatabaseFormat]; [defaults synchronize]; [self libraryDidAppear]; if ([self.delegate respondsToSelector:@selector(libraryUpgradeComplete)]) [self.delegate libraryUpgradeComplete]; } - (void)updateMediaDatabase { [self libraryDidDisappear]; // Remove no more present files NSFetchRequest *request = [self fetchRequestForEntity:@"File"]; NSArray *results = [[self managedObjectContext] executeFetchRequest:request error:nil]; NSFileManager *fileManager = [NSFileManager defaultManager]; unsigned int count = (unsigned int)results.count; for (unsigned int x = 0; x < count; x++) { MLFile *file = results[x]; NSString *urlString = [file url]; NSURL *fileURL = [NSURL URLWithString:urlString]; BOOL exists = [fileManager fileExistsAtPath:[fileURL path]]; if (!exists) { APLog(@"Marking - %@", [fileURL absoluteString]); file.isSafe = YES; // It doesn't exist, it's safe. if (file.isAlbumTrack) { MLAlbum *album = file.albumTrack.album; if (album.tracks.count <= 1) { @try { [[self managedObjectContext] deleteObject:album]; } @catch (NSException *exception) { APLog(@"failed to nuke object because it disappeared in front of us"); } } else [album removeTrack:file.albumTrack]; } if (file.isShowEpisode) { MLShow *show = file.showEpisode.show; if (show.episodes.count <= 1) { @try { [[self managedObjectContext] deleteObject:show]; } @catch (NSException *exception) { APLog(@"failed to nuke object because it disappeared in front of us"); } } else [show removeEpisode:file.showEpisode]; } #if TARGET_OS_IPHONE NSString *thumbPath = [file thumbnailPath]; bool thumbExists = [fileManager fileExistsAtPath:thumbPath]; if (thumbExists) [fileManager removeItemAtPath:thumbPath error:nil]; [[self managedObjectContext] deleteObject:file]; #endif } #if !TARGET_OS_IPHONE file.isOnDisk = @(exists); #endif } [self libraryDidAppear]; // Get the file to parse request = [self fetchRequestForEntity:@"File"]; [request setPredicate:[NSPredicate predicateWithFormat:@"isOnDisk == YES && tracks.@count == 0"]]; results = [[self managedObjectContext] executeFetchRequest:request error:nil]; for (MLFile *file in results) [[MLFileParserQueue sharedFileParserQueue] addFile:file]; if (!_allowNetworkAccess) { // Always attempt to fetch request = [self fetchRequestForEntity:@"File"]; [request setPredicate:[NSPredicate predicateWithFormat:@"isOnDisk == YES"]]; results = [[self managedObjectContext] executeFetchRequest:request error:nil]; for (MLFile *file in results) { if (!file.computedThumbnail) [self computeThumbnailForFile:file]; } return; } // Get the thumbnails to compute request = [self fetchRequestForEntity:@"File"]; [request setPredicate:[NSPredicate predicateWithFormat:@"isOnDisk == YES && hasFetchedInfo == 1 && artworkURL == nil"]]; results = [[self managedObjectContext] executeFetchRequest:request error:nil]; for (MLFile *file in results) if (!file.computedThumbnail && ![file isAlbumTrack]) [self computeThumbnailForFile:file]; // Get to fetch meta data request = [self fetchRequestForEntity:@"File"]; [request setPredicate:[NSPredicate predicateWithFormat:@"isOnDisk == YES && hasFetchedInfo == 0"]]; results = [[self managedObjectContext] executeFetchRequest:request error:nil]; for (MLFile *file in results) [self fetchMetaDataForFile:file]; // Get to fetch show info request = [self fetchRequestForEntity:@"Show"]; [request setPredicate:[NSPredicate predicateWithFormat:@"lastSyncDate == 0"]]; results = [[self managedObjectContext] executeFetchRequest:request error:nil]; for (MLShow *show in results) [self fetchMetaDataForShow:show]; // Get updated TV Shows NSNumber *lastServerTime = @([[NSUserDefaults standardUserDefaults] integerForKey:kLastTVDBUpdateServerTime]); #if HAVE_BLOCK [MLTVShowInfoGrabber fetchUpdatesSinceServerTime:lastServerTime andExecuteBlock:^(NSArray *updates){ NSFetchRequest *request = [self fetchRequestForEntity:@"Show"]; [request setPredicate:[NSComparisonPredicate predicateWithLeftExpression:[NSExpression expressionForKeyPath:@"theTVDBID"] rightExpression:[NSExpression expressionForConstantValue:updates] modifier:NSDirectPredicateModifier type:NSInPredicateOperatorType options:0]]; NSArray *results = [[self managedObjectContext] executeFetchRequest:request error:nil]; for (MLShow *show in results) [self fetchMetaDataForShow:show]; }]; #else MLTVShowInfoGrabber *grabber = [[MLTVShowInfoGrabber alloc] init]; grabber.delegate = self; [grabber fetchUpdatesSinceServerTime:lastServerTime]; #endif /* Update every hour - FIXME: Preferences key */ [self performSelector:@selector(updateMediaDatabase) withObject:nil afterDelay:60 * 60]; } - (void)applicationWillExit { [[MLCrashPreventer sharedPreventer] cancelAllFileParse]; } - (void)applicationWillStart { [[MLCrashPreventer sharedPreventer] markCrasherFiles]; } - (void)libraryDidDisappear { // Stop expansive work [[MLThumbnailerQueue sharedThumbnailerQueue] stop]; } - (void)libraryDidAppear { // Resume our work [[MLThumbnailerQueue sharedThumbnailerQueue] resume]; } @end Sources/MLMovieInfoGrabber.m000066400000000000000000000131051247122470700162760ustar00rootroot00000000000000/***************************************************************************** * MLMovieInfoGrabber.m * Lunettes ***************************************************************************** * Copyright (C) 2010 Pierre d'Herbemont * Copyright (C) 2010-2013 VLC authors and VideoLAN * $Id$ * * Authors: Pierre d'Herbemont * * 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.1 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 Lesser 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ #import "MLMovieInfoGrabber.h" #define TMDB_HOSTNAME "api.themoviedb.org" #define TMDB_API_KEY "5401cd030990fba60e1c23d2832de62e" #define TMDB_QUERY_SEARCH @"http://%s/2.0/Movie.search?title=%@&api_key=%s" #define TMDB_QUERY_INFO @"http://%s/2.0/Movie.getInfo?id=%@&api_key=%s" @interface MLMovieInfoGrabber () @property (readwrite, strong) NSArray *results; @end @implementation MLMovieInfoGrabber @synthesize delegate=_delegate; @synthesize results=_results; #if !HAVE_BLOCK @synthesize userData=_userData; #endif - (void)lookUpForTitle:(NSString *)title { NSString *escapedString = [title stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:TMDB_QUERY_SEARCH, TMDB_HOSTNAME, escapedString, TMDB_API_KEY]]; NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:4]; [_connection cancel]; _data = [[NSMutableData alloc] init]; // Keep a reference to ourself while we are alive. _connection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES]; NSAssert(_connection, @"Can't create connection"); } #if HAVE_BLOCK - (void)lookUpForTitle:(NSString *)title andExecuteBlock:(void (^)(NSError *))block { Block_release(_block); _block = Block_copy(block); [self lookUpForTitle:title]; } #endif - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { APLog(@"Did Fail %@", _delegate); if ([_delegate respondsToSelector:@selector(movieInfoGrabber:didFailWithError:)]) { APLog(@"Did Fail Calling %@", _delegate); [_delegate movieInfoGrabber:self didFailWithError:error]; } #if HAVE_BLOCK if (_block) { _block(error); // Release the eventual block. This prevents ref cycle. Block_release(_block); _block = NULL; } #endif } - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { [_data appendData:data]; } - (void)connectionDidFinishLoading:(NSURLConnection *)connection { NSXMLDocument *xmlDoc = [[NSXMLDocument alloc] initWithData:_data options:0 error:nil]; _data = nil; NSError *error = nil; NSArray *nodes = [xmlDoc nodesForXPath:@"./results/moviematches/movie" error:&error]; if ([nodes count] > 0 ) { NSMutableArray *array = [NSMutableArray arrayWithCapacity:[nodes count]]; for (NSXMLNode *node in nodes) { NSString *id = [node stringValueForXPath:@"./id"]; if (!id) continue; NSString *title = [node stringValueForXPath:@"./title"]; NSString *release = [node stringValueForXPath:@"./release"]; NSString *releaseYear = nil; if (release) { NSDateFormatter *inputFormatter = [[NSDateFormatter alloc] init]; [inputFormatter setDateFormat:@"yyyy-MM-dd"]; NSDateFormatter *outputFormatter = [[NSDateFormatter alloc] init]; [outputFormatter setDateFormat:@"yyyy"]; NSDate *releaseDate = [inputFormatter dateFromString:release]; releaseYear = releaseDate ? [outputFormatter stringFromDate:releaseDate] : nil; } //APLog(@"%@", title); //APLog(TMDB_QUERY_INFO, TMDB_HOSTNAME, id, TMDB_API_KEY); NSString *artworkURL = [node stringValueForXPath:@"./poster[size='cover']"]; if (!artworkURL) artworkURL = [node stringValueForXPath:@"./poster"]; if (!artworkURL) artworkURL = [node stringValueForXPath:@"./backdrop[@size='cover']"]; if (!artworkURL) artworkURL = [node stringValueForXPath:@"./backdrop"]; NSString *shortSummary = [node stringValueForXPath:@"./short_overview"]; [array addObject:@{@"title": title, @"shortSummary": shortSummary ?: @"", @"releaseYear": releaseYear ?: @"", @"artworkURL": artworkURL}]; } self.results = array; } else { self.results = nil; } #if HAVE_BLOCK if (_block) { _block(nil); Block_release(_block); _block = NULL; } #endif if ([_delegate respondsToSelector:@selector(movieInfoGrabberDidFinishGrabbing:)]) [_delegate movieInfoGrabberDidFinishGrabbing:self]; } @end Sources/MLShow.m000066400000000000000000000117651247122470700140500ustar00rootroot00000000000000/***************************************************************************** * MLShow.m * Lunettes ***************************************************************************** * Copyright (C) 2010 Pierre d'Herbemont * Copyright (C) 2010-2013 VLC authors and VideoLAN * $Id$ * * Authors: Pierre d'Herbemont * Felix Paul Kühne * * 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.1 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 Lesser 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ #import "MLShow.h" #import "MLShowEpisode.h" #import "MLMediaLibrary.h" @implementation MLShow + (NSArray *)allShows { NSFetchRequest *request = [[NSFetchRequest alloc] init]; NSManagedObjectContext *moc = [[MLMediaLibrary sharedMediaLibrary] managedObjectContext]; NSEntityDescription *entity = [NSEntityDescription entityForName:@"Show" inManagedObjectContext:moc]; [request setEntity:entity]; NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:NO]; [request setSortDescriptors:@[descriptor]]; NSArray *shows = [moc executeFetchRequest:request error:nil]; return shows; } + (MLShow *)showWithName:(NSString *)name { NSFetchRequest *request = [[MLMediaLibrary sharedMediaLibrary] fetchRequestForEntity:@"Show"]; [request setPredicate:[NSPredicate predicateWithFormat:@"name == %@", name]]; NSArray *dbResults = [[[MLMediaLibrary sharedMediaLibrary] managedObjectContext] executeFetchRequest:request error:nil]; NSAssert(dbResults, @"Can't execute fetch request"); if ([dbResults count] <= 0) return nil; return dbResults[0]; } @dynamic theTVDBID; @dynamic shortSummary; @dynamic artworkURL; @dynamic name; @dynamic lastSyncDate; @dynamic releaseYear; @dynamic episodes; - (NSSet *)unreadEpisodes { NSArray *episodes = [[self valueForKey:@"episodes"] allObjects]; NSMutableSet *set = [NSMutableSet set]; NSUInteger count = episodes.count; for (NSUInteger x = 0; x < count; x++) { NSSet *files = [episodes[x] valueForKey:@"files"]; for (id file in files) { if ([[file valueForKey:@"unread"] boolValue]) { [set addObject:episodes[x]]; break; } } } return set; } - (NSArray *)sortedEpisodes { NSArray *episodes = [[self valueForKey:@"episodes"] allObjects]; NSSortDescriptor *seasonDescriptor = [[NSSortDescriptor alloc] initWithKey:@"seasonNumber" ascending:YES selector:@selector(compare:)]; NSSortDescriptor *episodesDescriptor = [[NSSortDescriptor alloc] initWithKey:@"episodeNumber" ascending:YES selector:@selector(compare:)]; NSArray *descriptors = @[seasonDescriptor, episodesDescriptor]; return [episodes sortedArrayUsingDescriptors:descriptors]; } - (void)addEpisode:(MLShowEpisode*)episode { if (!episode) return; NSMutableSet *episodes = [self mutableSetValueForKey:@"episodes"]; [episodes addObject:episode]; [self willChangeValueForKey:@"episodes"]; [self setValue:episodes forKey:@"episodes"]; [self didChangeValueForKey:@"episodes"]; } - (void)removeEpisode:(MLShowEpisode*)episode { if (!episode) return; NSMutableSet *episodes = [self mutableSetValueForKey:@"episodes"]; [episodes removeObject:episode]; [self willChangeValueForKey:@"episodes"]; [self setValue:episodes forKey:@"episodes"]; [self didChangeValueForKey:@"episodes"]; } - (void)removeEpisodeWithSeasonNumber:(NSNumber *)seasonNumber andEpisodeNumber:(NSNumber *)episodeNumber { NSMutableSet *episodes = [self mutableSetValueForKey:@"episodes"]; MLShowEpisode *episode = nil; if (seasonNumber && episodeNumber) { for (MLShowEpisode *episodeIter in episodes) { if ([episodeIter.seasonNumber intValue] == [seasonNumber intValue] && [episodeIter.episodeNumber intValue] == [episodeNumber intValue]) { episode = episodeIter; break; } } } if (!episode) return; [episodes removeObject:episode]; [self willChangeValueForKey:@"episodes"]; [self setValue:episodes forKey:@"episodes"]; [self didChangeValueForKey:@"episodes"]; } @end Sources/MLShowEpisode.m000066400000000000000000000114041247122470700153470ustar00rootroot00000000000000/***************************************************************************** * MLShowEpisode.m * Lunettes ***************************************************************************** * Copyright (C) 2010 Pierre d'Herbemont * Copyright (C) 2010-2013 VLC authors and VideoLAN * $Id$ * * Authors: Pierre d'Herbemont * Felix Paul Kühne * * 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.1 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 Lesser 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ #import "MLMediaLibrary.h" #import "MLShowEpisode.h" #import "MLShow.h" @interface MLShowEpisode () @property (nonatomic, strong) NSNumber *primitiveUnread; @property (nonatomic, strong) NSString *primitiveArtworkURL; @end @implementation MLShowEpisode + (NSArray *)allEpisodes { NSFetchRequest *request = [[NSFetchRequest alloc] init]; NSManagedObjectContext *moc = [[MLMediaLibrary sharedMediaLibrary] managedObjectContext]; NSEntityDescription *entity = [NSEntityDescription entityForName:@"ShowEpisode" inManagedObjectContext:moc]; [request setEntity:entity]; NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:NO]; [request setSortDescriptors:@[descriptor]]; [request setPredicate:[NSPredicate predicateWithFormat:@"files.@count > 0"]]; NSArray *episodes = [moc executeFetchRequest:request error:nil]; return episodes; } + (MLShowEpisode *)episodeWithShow:(MLShow *)show episodeNumber:(NSNumber *)episodeNumber seasonNumber:(NSNumber *)seasonNumber createIfNeeded:(BOOL)createIfNeeded { if (!show) return NULL; NSSet *episodes = [show valueForKey:@"episodes"]; MLShowEpisode *episode = nil; if (seasonNumber && episodeNumber) { for (MLShowEpisode *episodeIter in episodes) { if ([episodeIter.seasonNumber intValue] == [seasonNumber intValue] && [episodeIter.episodeNumber intValue] == [episodeNumber intValue]) { episode = episodeIter; break; } } } if (!episode && createIfNeeded) { episode = [[MLMediaLibrary sharedMediaLibrary] createObjectForEntity:@"ShowEpisode"]; episode.episodeNumber = episodeNumber; episode.seasonNumber = seasonNumber; episode.show = show; } return episode; } + (MLShowEpisode *)episodeWithShowName:(NSString *)showName episodeNumber:(NSNumber *)episodeNumber seasonNumber:(NSNumber *)seasonNumber createIfNeeded:(BOOL)createIfNeeded wasCreated:(BOOL *)wasCreated { MLShow *show = [MLShow showWithName:showName]; *wasCreated = NO; if (!show && createIfNeeded) { *wasCreated = YES; show = [[MLMediaLibrary sharedMediaLibrary] createObjectForEntity:@"Show"]; show.name = showName; } else if (!show && !createIfNeeded) return nil; return [MLShowEpisode episodeWithShow:show episodeNumber:episodeNumber seasonNumber:seasonNumber createIfNeeded:createIfNeeded]; } @dynamic primitiveUnread; @dynamic unread; - (void)setUnread:(NSNumber *)unread { [self willChangeValueForKey:@"unread"]; [self setPrimitiveUnread:unread]; [self didChangeValueForKey:@"unread"]; [[[MLMediaLibrary sharedMediaLibrary] managedObjectContext] refreshObject:[self show] mergeChanges:YES]; [[[MLMediaLibrary sharedMediaLibrary] managedObjectContext] refreshObject:self mergeChanges:YES]; } @dynamic theTVDBID; @dynamic shortSummary; @dynamic shouldBeDisplayed; @dynamic episodeNumber; @dynamic seasonNumber; @dynamic lastSyncDate; @dynamic artworkURL; @dynamic primitiveArtworkURL; - (void)setArtworkURL:(NSString *)artworkURL { [self willChangeValueForKey:@"artworkURL"]; NSSet *files = self.files; for (id file in files) [file willChangeValueForKey:@"artworkURL"]; [self setPrimitiveArtworkURL:artworkURL]; for (id file in files) [file didChangeValueForKey:@"artworkURL"]; [self didChangeValueForKey:@"artworkURL"]; } @dynamic name; @dynamic show; @dynamic files; @end Sources/MLTVShowEpisodesInfoGrabber.m000066400000000000000000000120031247122470700201010ustar00rootroot00000000000000/***************************************************************************** * MLTVShowEpisodesInfoGrabber.m * Lunettes ***************************************************************************** * Copyright (C) 2010 Pierre d'Herbemont * Copyright (C) 2010-2013 VLC authors and VideoLAN * $Id$ * * Authors: Pierre d'Herbemont * Felix Paul Kühne * * 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.1 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 Lesser 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ #import "MLTVShowEpisodesInfoGrabber.h" #import "TheTVDBGrabber.h" #import "MLURLConnection.h" @interface MLTVShowEpisodesInfoGrabber () #if !HAVE_BLOCK #endif @property (readwrite, strong) NSDictionary *results; @property (readwrite, strong) NSArray *episodesResults; - (void)didReceiveData:(NSData *)data; @end @implementation MLTVShowEpisodesInfoGrabber @synthesize delegate=_delegate; @synthesize episodesResults=_episodesResults; @synthesize results=_results; #if !HAVE_BLOCK @synthesize userData=_userData; #endif #if !HAVE_BLOCK - (void)urlConnection:(MLURLConnection *)connection didFinishWithError:(NSError *)error { if (error) { _connection = nil; return; } [self didReceiveData:connection.data]; } #endif - (void)lookUpForShowID:(NSString *)showId { [_connection cancel]; NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:TVDB_QUERY_EPISODE_INFO, TVDB_HOSTNAME, TVDB_API_KEY, showId, TVDB_DEFAULT_LANGUAGE]]; // Balanced below #if HAVE_BLOCK _connection = [[MLURLConnection runConnectionWithURL:url andBlock:^(MLURLConnection *connection, NSError * error) { if (error) { [_connection release]; _connection = nil; [self autorelease]; return; } [self didReceiveData:connection.data]; [self autorelease]; }] retain]; #else _connection = [MLURLConnection runConnectionWithURL:url delegate:self userObject:nil]; #endif } #if HAVE_BLOCK - (void)lookUpForShowID:(NSString *)id andExecuteBlock:(void (^)())block { Block_release(_block); _block = Block_copy(block); [self lookUpForShowID:id]; } #endif - (void)didReceiveData:(NSData *)data { NSXMLDocument *xmlDoc = [[NSXMLDocument alloc] initWithData:data options:0 error:nil]; NSError *error = nil; NSArray *nodesSerie = [xmlDoc nodesForXPath:@"./Data/Series" error:&error]; NSArray *nodesEpisode = [xmlDoc nodesForXPath:@"./Data/Episode" error:&error]; NSString *serieArtworkURL = nil; if ([nodesSerie count] == 1) { NSXMLNode *node = nodesSerie[0]; serieArtworkURL = [node stringValueForXPath:@"./poster"]; } if ([nodesEpisode count] > 0 ) { NSMutableArray *array = [NSMutableArray arrayWithCapacity:[nodesEpisode count]]; for (NSXMLNode *node in nodesEpisode) { NSString *episodeId = [node stringValueForXPath:@"./id"]; if (!episodeId) continue; NSString *title = [node stringValueForXPath:@"./EpisodeName"]; NSNumber *seasonNumber = [node numberValueForXPath:@"./SeasonNumber"]; NSNumber *episodeNumber = [node numberValueForXPath:@"./EpisodeNumber"]; NSString *artworkURL = [node stringValueForXPath:@"./filename"]; NSString *shortSummary = [node stringValueForXPath:@"./Overview"]; [array addObject:@{@"id": episodeId, @"title": title ?: @"", @"shortSummary": shortSummary ?: @"", @"episodeNumber": episodeNumber, @"seasonNumber": seasonNumber, @"artworkURL": [NSString stringWithFormat:TVDB_COVERS_URL, TVDB_IMAGES_HOSTNAME, artworkURL]}]; } self.episodesResults = array; self.results = @{@"serieArtworkURL": [NSString stringWithFormat:TVDB_COVERS_URL, TVDB_IMAGES_HOSTNAME, serieArtworkURL]}; } else { self.episodesResults = nil; self.results = nil; } #if HAVE_BLOCK if (_block) { _block(); Block_release(_block); _block = NULL; } #endif if ([_delegate respondsToSelector:@selector(movieInfoGrabberDidFinishGrabbing:)]) [_delegate tvShowEpisodesInfoGrabberDidFinishGrabbing:self]; } @end Sources/MLTVShowInfoGrabber.m000066400000000000000000000242141247122470700164140ustar00rootroot00000000000000/***************************************************************************** * MLTVShowInfoGrabber.m * Lunettes ***************************************************************************** * Copyright (C) 2010 Pierre d'Herbemont * Copyright (C) 2010-2013 VLC authors and VideoLAN * $Id$ * * Authors: Pierre d'Herbemont * * 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.1 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 Lesser 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ #import "MLTVShowInfoGrabber.h" #import "TheTVDBGrabber.h" #import "MLURLConnection.h" @interface MLTVShowInfoGrabber () #if !HAVE_BLOCK #endif @property (readwrite, strong) NSArray *results; @end @implementation MLTVShowInfoGrabber @synthesize delegate=_delegate; @synthesize results=_results; #if !HAVE_BLOCK @synthesize userData=_userData; #endif static NSDate *gLastFetch = nil; static NSNumber *gServerTime = nil; #if !HAVE_BLOCK - (void)urlConnection:(MLURLConnection *)connection didFinishWithError:(NSError *)error { if ([connection.userObject isEqualToString:@"fetchUpdatesSinceServerTime"]) { // We are coming form -fetchUpdatesSinceServerTime if (error) return; NSXMLDocument *xmlDoc = [[NSXMLDocument alloc] initWithData:connection.data options:0 error:nil]; NSNumber *serverTime = [[xmlDoc rootElement] numberValueForXPath:@"./Time"]; gServerTime = serverTime; gLastFetch = [NSDate dateWithTimeIntervalSinceNow:0]; NSArray *nodes = [xmlDoc nodesForXPath:@"./Items/Series" error:&error]; NSMutableArray *array = [NSMutableArray arrayWithCapacity:[nodes count]]; for (NSXMLNode *node in nodes) { NSNumber *id = [node numberValueForXPath:@"."]; [array addObject:id]; } [_delegate tvShowInfoGrabber:self didFetchUpdates:array]; } else { NSAssert([connection.userObject isEqualToString:@"fetchServerTime"], @"Unkown callback emitter"); if (error) { [_delegate tvShowInfoGrabberDidFetchServerTime:self]; return; } NSXMLDocument *xmlDoc = [[NSXMLDocument alloc] initWithData:connection.data options:0 error:nil]; NSNumber *serverTime = [[xmlDoc rootElement] numberValueForXPath:@"./Time"]; gServerTime = serverTime; gLastFetch = [NSDate dateWithTimeIntervalSinceNow:0]; [_delegate tvShowInfoGrabberDidFetchServerTime:self]; } } - (void)fetchUpdatesSinceServerTime:(NSNumber *)serverTime { NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:TVDB_QUERY_UPDATES, TVDB_HOSTNAME, serverTime]]; [MLURLConnection runConnectionWithURL:url delegate:self userObject:@"fetchUpdatesSinceServerTime"]; } #else + (void)fetchUpdatesSinceServerTime:(NSNumber *)serverTime andExecuteBlock:(void (^)(NSArray *))block { NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:TVDB_QUERY_UPDATES, TVDB_HOSTNAME, serverTime]]; [MLURLConnection runConnectionWithURL:url andBlock:^(MLURLConnection *connection, NSError *error) { if (error) { return; } NSXMLDocument *xmlDoc = [[NSXMLDocument alloc] initWithData:connection.data options:0 error:nil]; NSNumber *serverTime = [[xmlDoc rootElement] numberValueForXPath:@"./Time"]; [gServerTime release]; [gLastFetch release]; gServerTime = [serverTime retain]; gLastFetch = [[NSDate dateWithTimeIntervalSinceNow:0] retain]; NSArray *nodes = [xmlDoc nodesForXPath:@"./Items/Series" error:&error]; NSMutableArray *array = [NSMutableArray arrayWithCapacity:[nodes count]]; for (NSXMLNode *node in nodes) { NSNumber *id = [node numberValueForXPath:@"."]; [array addObject:id]; } block(array); }]; } #endif #if !HAVE_BLOCK + (NSNumber *)serverTime { return gServerTime; } - (void)fetchServerTime { if (gLastFetch && gServerTime) { // Only fetch the serverTime every hour // FIXME: Have a default for that? NSDate *oneHourAgo = [NSDate dateWithTimeIntervalSinceNow:5 * 60 /* Every 5 mins */]; if ([oneHourAgo earlierDate:gLastFetch] == gLastFetch) { [_delegate tvShowInfoGrabberDidFetchServerTime:self]; return; } } NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:TVDB_QUERY_SERVER_TIME, TVDB_HOSTNAME]]; [MLURLConnection runConnectionWithURL:url delegate:self userObject:@"fetchServerTime"]; } #else + (void)fetchServerTimeAndExecuteBlock:(void (^)(NSNumber *))block { if (gLastFetch && gServerTime) { // Only fetch the serverTime every hour // FIXME: Have a default for that? NSDate *oneHourAgo = [NSDate dateWithTimeIntervalSinceNow:5 * 60 /* Every 5 mins */]; if ([oneHourAgo earlierDate:gLastFetch] == gLastFetch) { block(gServerTime); return; } } NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:TVDB_QUERY_SERVER_TIME, TVDB_HOSTNAME]]; [MLURLConnection runConnectionWithURL:url andBlock:^(MLURLConnection *connection, NSError *error) { if (error) { block(nil); return; } [gServerTime release]; [gLastFetch release]; NSXMLDocument *xmlDoc = [[NSXMLDocument alloc] initWithData:connection.data options:0 error:nil]; NSNumber *serverTime = [[xmlDoc rootElement] numberValueForXPath:@"./Time"]; gServerTime = [serverTime retain]; gLastFetch = [[NSDate dateWithTimeIntervalSinceNow:0] retain]; block(gServerTime); }]; } #endif - (void)lookUpForTitle:(NSString *)title { NSString *escapedString = [title stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:TVDB_QUERY_SEARCH, TVDB_HOSTNAME, escapedString]]; NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:15]; [_connection cancel]; _data = [[NSMutableData alloc] init]; // Keep a reference to ourself while we are alive. _connection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES]; } - (void)lookUpForShowID:(NSString *)showId { NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:TVDB_QUERY_EPISODE_INFO, TVDB_HOSTNAME, TVDB_API_KEY, showId, TVDB_DEFAULT_LANGUAGE]]; NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:15]; [_connection cancel]; _data = [[NSMutableData alloc] init]; // Keep a reference to ourself while we are alive. _connection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES]; } #if HAVE_BLOCK - (void)lookUpForTitle:(NSString *)title andExecuteBlock:(void (^)())block { Block_release(_block); _block = Block_copy(block); [self lookUpForTitle:title]; } #endif - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { if ([_delegate respondsToSelector:@selector(movieInfoGrabber:didFailWithError:)]) [_delegate tvShowInfoGrabber:self didFailWithError:error]; #if HAVE_BLOCK // Release the eventual block. This prevents ref cycle. if (_block) { Block_release(_block); _block = NULL; } #endif } - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { [_data appendData:data]; } - (void)connectionDidFinishLoading:(NSURLConnection *)connection { NSXMLDocument *xmlDoc = [[NSXMLDocument alloc] initWithData:_data options:0 error:nil]; _data = nil; NSError *error = nil; NSArray *nodes = [xmlDoc nodesForXPath:@"./Data/Series" error:&error]; if ([nodes count] > 0 ) { NSMutableArray *array = [NSMutableArray arrayWithCapacity:[nodes count]]; for (NSXMLNode *node in nodes) { NSString *id = [node stringValueForXPath:@"./seriesid"]; if (!id) continue; NSString *title = [node stringValueForXPath:@"./SeriesName"]; NSString *release = [node stringValueForXPath:@"./FirstAired"]; NSString *releaseYear = nil; if (release) { NSDateFormatter *inputFormatter = [[NSDateFormatter alloc] init]; [inputFormatter setDateFormat:@"yyyy-MM-dd"]; NSDateFormatter *outputFormatter = [[NSDateFormatter alloc] init]; [outputFormatter setDateFormat:@"yyyy"]; NSDate *releaseDate = [inputFormatter dateFromString:release]; releaseYear = releaseDate ? [outputFormatter stringFromDate:releaseDate] : nil; } NSString *artworkURL = [node stringValueForXPath:@"./banner"]; NSString *shortSummary = [node stringValueForXPath:@"./Overview"]; [array addObject:@{@"title": title, @"id": id, @"shortSummary": shortSummary ?: @"", @"releaseYear": releaseYear ?: @"", @"banner": [NSString stringWithFormat:TVDB_COVERS_URL, TVDB_IMAGES_HOSTNAME, artworkURL]}]; } self.results = array; } else self.results = nil; #if HAVE_BLOCK if (_block) { _block(); Block_release(_block); _block = NULL; } #endif if ([_delegate respondsToSelector:@selector(movieInfoGrabberDidFinishGrabbing:)]) [_delegate tvShowInfoGrabberDidFinishGrabbing:self]; } @end Sources/MLThumbnailerQueue.h000066400000000000000000000030251247122470700163700ustar00rootroot00000000000000/***************************************************************************** * MLThumbnailerQueue.h * MobileMediaLibraryKit ***************************************************************************** * Copyright (C) 2010 Pierre d'Herbemont * Copyright (C) 2010-2013 VLC authors and VideoLAN * $Id$ * * Authors: Pierre d'Herbemont * * 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.1 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 Lesser 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ #import @class MLFile; @interface MLThumbnailerQueue : NSObject + (MLThumbnailerQueue *)sharedThumbnailerQueue; - (void)addFile:(MLFile *)file; - (void)setHighPriorityForFile:(MLFile *)file; - (void)setDefaultPriorityForFile:(MLFile *)file; - (void)stop; - (void)resume; @property (nonatomic, strong) NSOperationQueue *queue; @end Sources/MLThumbnailerQueue.m000066400000000000000000000173701247122470700164050ustar00rootroot00000000000000/***************************************************************************** * MLThumbnailerQueue.m * MobileMediaLibraryKit ***************************************************************************** * Copyright (C) 2010 Pierre d'Herbemont * Copyright (C) 2010-2014 VLC authors and VideoLAN * $Id$ * * Authors: Pierre d'Herbemont * Felix Paul Kühne * * 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.1 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 Lesser 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ #import "MLThumbnailerQueue.h" #import "MLFile.h" #import "MLCrashPreventer.h" #import // for sysctlbyname @interface ThumbnailOperation : NSOperation { MLFile *_file; VLCMedia *_media; VLCLibrary *_internalLibrary; } @property (strong,readwrite) MLFile *file; @end @interface MLThumbnailerQueue () { VLCLibrary *_internalLibrary; NSDictionary *_fileDescriptionToOperation; NSOperationQueue *_queue; } - (void)didFinishOperation:(ThumbnailOperation *)op; @end @implementation ThumbnailOperation @synthesize file=_file; - (id)initWithFile:(MLFile *)file andVLCLibrary:(VLCLibrary *)library; { if (!(self = [super init])) return nil; self.file = file; _internalLibrary = library; return self; } - (void)fetchThumbnail { APLog(@"Starting THUMB %@", self.file); [[MLCrashPreventer sharedPreventer] willParseFile:self.file]; _media = [VLCMedia mediaWithURL:[NSURL URLWithString:self.file.url]]; VLCMediaThumbnailer *thumbnailer = [VLCMediaThumbnailer thumbnailerWithMedia:_media delegate:self andVLCLibrary:_internalLibrary]; /* optimize thumbnails for the device */ if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { if ([UIScreen mainScreen].scale==2.0) { thumbnailer.thumbnailWidth = 540.; thumbnailer.thumbnailHeight = 405.; } else { thumbnailer.thumbnailWidth = 272.; thumbnailer.thumbnailHeight = 204.; } } else { if (SYSTEM_RUNS_IOS7) { if ([UIScreen mainScreen].scale==2.0) { thumbnailer.thumbnailWidth = 480.; thumbnailer.thumbnailHeight = 270.; } else { thumbnailer.thumbnailWidth = 720.; thumbnailer.thumbnailHeight = 405.; } } else { if ([UIScreen mainScreen].scale==2.0) { thumbnailer.thumbnailWidth = 480.; thumbnailer.thumbnailHeight = 270.; } else { thumbnailer.thumbnailWidth = 240.; thumbnailer.thumbnailHeight = 135.; } } } [thumbnailer fetchThumbnail]; [[MLThumbnailerQueue sharedThumbnailerQueue].queue setSuspended:YES]; // Balanced in -mediaThumbnailer:didFinishThumbnail // Balanced in -mediaThumbnailer:didFinishThumbnail: } - (void)main { [self performSelectorOnMainThread:@selector(fetchThumbnail) withObject:nil waitUntilDone:YES]; } - (void)endThumbnailing { [[MLCrashPreventer sharedPreventer] didParseFile:self.file]; MLThumbnailerQueue *thumbnailer = [MLThumbnailerQueue sharedThumbnailerQueue]; [thumbnailer.queue setSuspended:NO]; [thumbnailer didFinishOperation:self]; } - (void)mediaThumbnailer:(VLCMediaThumbnailer *)mediaThumbnailer didFinishThumbnail:(CGImageRef)thumbnail { mediaThumbnailer.delegate = nil; APLog(@"Finished thumbnail for %@", self.file.title); self.file.computedThumbnail = [UIImage imageWithCGImage:thumbnail]; [self endThumbnailing]; } - (void)mediaThumbnailerDidTimeOut:(VLCMediaThumbnailer *)mediaThumbnailer { self.file.thumbnailTimeouted = YES; [self endThumbnailing]; } @end @implementation MLThumbnailerQueue @synthesize queue=_queue; + (MLThumbnailerQueue *)sharedThumbnailerQueue { static MLThumbnailerQueue *shared = nil; if (!shared) { shared = [[MLThumbnailerQueue alloc] init]; } return shared; } - (id)init { self = [super init]; if (self != nil) { int speedCategory = [self _deviceSpeedCategory]; APLog(@"running on a category %i device", speedCategory); if (speedCategory < 2) _internalLibrary = [VLCLibrary sharedLibrary]; else _internalLibrary = [[VLCLibrary alloc] initWithOptions:@[@"--avcodec-threads=1", @"--avcodec-skip-idct=4", @"--deinterlace=-1", @"--avcodec-skiploopfilter=3", @"--no-interact", @"--avi-index=3"]]; _fileDescriptionToOperation = [[NSMutableDictionary alloc] init]; _queue = [[NSOperationQueue alloc] init]; [_queue setMaxConcurrentOperationCount:1]; } return self; } static inline NSString *hashFromFile(MLFile *file) { return [NSString stringWithFormat:@"%p", [[file objectID] URIRepresentation]]; } - (void)didFinishOperation:(ThumbnailOperation *)op { [_fileDescriptionToOperation setValue:nil forKey:hashFromFile(op.file)]; } - (void)addFile:(MLFile *)file { if (_fileDescriptionToOperation[hashFromFile(file)]) return; if (![[MLCrashPreventer sharedPreventer] isFileSafe:file]) { APLog(@"'%@' is unsafe and will crash, ignoring", file.title); return; } if ([file isAlbumTrack]) { APLog(@"'%@' is an audio file, ignoring", file.title); return; } ThumbnailOperation *op = [[ThumbnailOperation alloc] initWithFile:file andVLCLibrary:_internalLibrary]; [_fileDescriptionToOperation setValue:op forKey:hashFromFile(file)]; [self.queue addOperation:op]; } - (void)stop { [_queue setMaxConcurrentOperationCount:0]; } - (void)resume { [_queue setMaxConcurrentOperationCount:1]; } - (void)setHighPriorityForFile:(MLFile *)file { ThumbnailOperation *op = _fileDescriptionToOperation[hashFromFile(file)]; [op setQueuePriority:NSOperationQueuePriorityHigh]; } - (void)setDefaultPriorityForFile:(MLFile *)file { ThumbnailOperation *op = _fileDescriptionToOperation[hashFromFile(file)]; [op setQueuePriority:NSOperationQueuePriorityNormal]; } - (int)_deviceSpeedCategory { size_t size; sysctlbyname("hw.machine", NULL, &size, NULL, 0); char *answer = malloc(size); sysctlbyname("hw.machine", answer, &size, NULL, 0); NSString *currentMachine = @(answer); free(answer); if ([currentMachine hasPrefix:@"iPhone2"] || [currentMachine hasPrefix:@"iPhone3"] || [currentMachine hasPrefix:@"iPhone4"] || [currentMachine hasPrefix:@"iPod3"] || [currentMachine hasPrefix:@"iPod4"] || [currentMachine hasPrefix:@"iPad2"]) { // iPhone 3GS, iPhone 4, 3rd and 4th generation iPod touch, iPad 2, iPad mini (1st gen) return 1; } else if ([currentMachine hasPrefix:@"iPad3,1"] || [currentMachine hasPrefix:@"iPad3,2"] || [currentMachine hasPrefix:@"iPad3,3"] || [currentMachine hasPrefix:@"iPod5"]) { // iPod 5, iPad 3 return 2; } else if ([currentMachine hasPrefix:@"iPhone5"] || [currentMachine hasPrefix:@"iPhone6"] || [currentMachine hasPrefix:@"iPad4"]) { // iPhone 5 + 5S, iPad 4, iPad Air, iPad mini 2G return 3; } else // iPhone 6, 2014 iPads return 4; } @end Sources/MLTitleDecrapifier.m000066400000000000000000000176641247122470700163530ustar00rootroot00000000000000/***************************************************************************** * MLTitleDecrapifier.m * Lunettes ***************************************************************************** * Copyright (C) 2010 Pierre d'Herbemont * Copyright (C) 2010-2013 VLC authors and VideoLAN * $Id$ * * Authors: Pierre d'Herbemont * Felix Paul Kühne * * 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.1 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 Lesser 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ #import "MLTitleDecrapifier.h" @implementation MLTitleDecrapifier + (NSString *)decrapify:(NSString *)string { static NSArray *ignoredWords = nil; if (!ignoredWords) ignoredWords = [[NSArray alloc] initWithObjects: @"xvid", @"h264", @"dvd", @"rip", @"divx", @"[fr]", @"720p", @"1080i", @"1080p", @"x264", @"hdtv", @"aac", @"bluray", nil]; NSMutableString *mutableString = [NSMutableString stringWithString:string]; for (NSString *word in ignoredWords) [mutableString replaceOccurrencesOfString:word withString:@"" options:NSCaseInsensitiveSearch range:NSMakeRange(0, [mutableString length])]; [mutableString replaceOccurrencesOfString:@"." withString:@" " options:NSCaseInsensitiveSearch range:NSMakeRange(0, [mutableString length])]; [mutableString replaceOccurrencesOfString:@"_" withString:@" " options:NSCaseInsensitiveSearch range:NSMakeRange(0, [mutableString length])]; [mutableString replaceOccurrencesOfString:@"+" withString:@" " options:NSCaseInsensitiveSearch range:NSMakeRange(0, [mutableString length])]; [mutableString replaceOccurrencesOfString:@"-" withString:@" " options:NSCaseInsensitiveSearch range:NSMakeRange(0, [mutableString length])]; NSString *staticString = [NSString stringWithString:mutableString]; mutableString = nil; while ([staticString rangeOfString:@" "].location != NSNotFound) staticString = [staticString stringByReplacingOccurrencesOfString:@" " withString:@" "]; if (staticString.length > 2) { @try { if ([staticString characterAtIndex:0] == 0x20) staticString = [staticString substringFromIndex:1]; } @catch (NSException *exception) { } } return staticString; } static inline BOOL isDigit(char c) { return c >= '0' && c <= '9'; } // Shortcut to ease reading static inline unichar c(NSString *string, unsigned index) { @try { return [string characterAtIndex:index]; } @catch (NSException *exception) { return 0x00; } } + (BOOL)isTVShowEpisodeTitle:(NSString *)string { NSString *str = [string lowercaseString]; // Search for s01e10. for (int i = 0; i < (int)[str length] - 5; i++) { if (c(str, i) == 's' && isDigit(c(str, i+1)) && isDigit(c(str, i+2)) && c(str, i+3) == 'e' && isDigit(c(str, i+4)) && isDigit(c(str, i+5))) { return YES; } } return NO; } static inline int intFromChar(char n) { return n - '0'; } static inline NSNumber *numberFromTwoChars(char high, char low) { return @(intFromChar(high) * 10 + intFromChar(low)); } static inline NSNumber *numberFromThreeChars(char high, char mid, char low) { return @(intFromChar(high) * 100 + intFromChar(mid) * 10 + intFromChar(low)); } + (NSDictionary *)tvShowEpisodeInfoFromString:(NSString *)string { if (!string) return nil; NSString *str = [string lowercaseString]; BOOL successfulSearch = NO; NSMutableDictionary *mutableDict; NSUInteger stringLength = [str length]; if (stringLength < 6) return nil; // Search for s01e10. for (unsigned int i = 0; i < stringLength - 5; i++) { if (c(str, i) == 's' && isDigit(c(str, i+1)) && isDigit(c(str, i+2)) && c(str, i+3) == 'e' && isDigit(c(str, i+4)) && isDigit(c(str, i+5))) { NSNumber *season = numberFromTwoChars(c(str,i+1), c(str,i+2)); NSNumber *episode; if (isDigit(c(str, i+6))) episode = numberFromThreeChars(c(str,i+4), c(str,i+5), c(str,i+6)); else episode = numberFromTwoChars(c(str,i+4), c(str,i+5)); NSString *tvShowName = i > 0 ? [str substringToIndex:i] : NSLocalizedString(@"UNTITLED_SHOW", @""); tvShowName = tvShowName ? [[MLTitleDecrapifier decrapify:tvShowName] capitalizedString] : nil; NSString *episodeName = stringLength > i + 4 ? [str substringFromIndex:i+6] : nil; episodeName = episodeName ? [MLTitleDecrapifier decrapify:episodeName] : nil; mutableDict = [[NSMutableDictionary alloc] initWithCapacity:4]; if (season) mutableDict[@"season"] = season; if (episode) mutableDict[@"episode"] = episode; if (tvShowName && ![tvShowName isEqualToString:@" "]) mutableDict[@"tvShowName"] = tvShowName; if (episodeName.length > 0 && ![episodeName isEqualToString:@" "]) mutableDict[@"tvEpisodeName"] = [episodeName capitalizedString]; successfulSearch = YES; } } // search for 0x00 if (!successfulSearch) { for (unsigned int i = 0; i < stringLength - 4; i++) { if (isDigit(c(str, i)) && c(str, i+1) == 'x' && isDigit(c(str, i+2)) && isDigit(c(str, i+3))) { NSNumber *season = @(intFromChar(c(str,i))); NSNumber *episode = numberFromTwoChars(c(str,i+2), c(str,i+3)); NSString *tvShowName = i > 0 ? [str substringToIndex:i] : NSLocalizedString(@"UNTITLED_SHOW", @""); tvShowName = tvShowName ? [[MLTitleDecrapifier decrapify:tvShowName] capitalizedString] : nil; NSString *episodeName = stringLength > i + 4 ? [str substringFromIndex:i+4] : nil; episodeName = episodeName ? [MLTitleDecrapifier decrapify:episodeName] : nil; mutableDict = [[NSMutableDictionary alloc] initWithCapacity:3]; if (season) mutableDict[@"season"] = season; if (episode) mutableDict[@"episode"] = episode; if (tvShowName && ![tvShowName isEqualToString:@" "]) mutableDict[@"tvShowName"] = tvShowName; if (episodeName.length > 0 && ![episodeName isEqualToString:@" "]) mutableDict[@"tvEpisodeName"] = [episodeName capitalizedString]; successfulSearch = YES; } } } if (successfulSearch) { NSDictionary *dict = [NSDictionary dictionaryWithDictionary:mutableDict]; return dict; } return nil; } + (NSDictionary *)audioContentInfoFromFile:(MLFile *)file { if (!file) return nil; NSString *title = file.title; NSArray *components = [title componentsSeparatedByString:@" "]; if (components.count > 0) { if ([components[0] intValue] > 0) title = [self decrapify:[title stringByReplacingOccurrencesOfString:components[0] withString:@""]]; } else title = [self decrapify:title]; return @{VLCMetaInformationTitle: title}; } @end Sources/MLURLConnection.m000066400000000000000000000070321247122470700156020ustar00rootroot00000000000000/***************************************************************************** * MLURLConnection.m * MobileMediaLibraryKit ***************************************************************************** * Copyright (C) 2010 Pierre d'Herbemont * Copyright (C) 2010-2013 VLC authors and VideoLAN * $Id$ * * Authors: Pierre d'Herbemont * * 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.1 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 Lesser 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ #import "MLURLConnection.h" #if HAVE_BLOCK @interface MLURLConnection () - (void)loadURL:(NSURL *)url andPerformBlock:(void (^)(MLURLConnection *connection, NSError *error))block; @end #endif @implementation MLURLConnection @synthesize data=_data; @synthesize delegate=_delegate; @synthesize userObject=_userObject; #if HAVE_BLOCK + (id)runConnectionWithURL:(NSURL *)url andBlock:(void (^)(MLURLConnection *connection, NSError *error))block { id obj = [[[[self class] alloc] init] autorelease]; [obj loadURL:url andPerformBlock:block]; return obj; } #else + (id)runConnectionWithURL:(NSURL *)url delegate:(id)delegate userObject:(id)userObject { MLURLConnection *obj = [[[self class] alloc] init]; obj.delegate = delegate; obj.userObject = userObject; [obj loadURL:url]; return obj; } #endif - (void)loadURL:(NSURL *)url { _data = [[NSMutableData alloc] init]; NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:15]; [_connection cancel]; _connection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES]; // Make sure we are around during the request } #if HAVE_BLOCK - (void)loadURL:(NSURL *)url andPerformBlock:(void (^)(MLURLConnection *connection, NSError *error))block { if (_block) Block_release(_block); _block = block ? Block_copy(block) : NULL; [self loadURL:url]; } #endif - (void)cancel { [_connection cancel]; _connection = nil; } - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { #if HAVE_BLOCK // Call the call back with the error. _block(self, error); // Release the eventual block. This prevents ref cycle. if (_block) { Block_release(_block); _block = NULL; } #endif [_delegate urlConnection:self didFinishWithError:error]; } - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { [_data appendData:data]; } - (void)connectionDidFinishLoading:(NSURLConnection *)connection { #if HAVE_BLOCK // Call the call back with the data. _block(self, nil); // Release the eventual block. This prevents ref cycle. if (_block) { Block_release(_block); _block = NULL; } #endif [_delegate urlConnection:self didFinishWithError:nil]; } @end Sources/NSXMLNode_Additions.m000066400000000000000000000033571247122470700164020ustar00rootroot00000000000000/***************************************************************************** * NSXMLNode_Additions.m * MobileMediaLibraryKit ***************************************************************************** * Copyright (C) 2010 Pierre d'Herbemont * Copyright (C) 2010-2013 VLC authors and VideoLAN * $Id$ * * Authors: Pierre d'Herbemont * * 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.1 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 Lesser 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ @implementation NSXMLNode (MLAdditions) - (NSString *)stringValueForXPath:(NSString *)string { NSArray *nodes = [self nodesForXPath:string error:nil]; if ([nodes count] == 0) return nil; return [nodes[0] stringValue]; } - (NSNumber *)numberValueForXPath:(NSString *)string { NSArray *nodes = [self nodesForXPath:string error:nil]; if ([nodes count] == 0) return nil; NSScanner *scanner = [NSScanner scannerWithString:[nodes[0] stringValue]]; NSInteger i; if ([scanner scanInteger:&i]) return @(i); return nil; } @end