vdr-plugin-epgsearch/0000755000175000017500000000000013145412721014430 5ustar tobiastobiasvdr-plugin-epgsearch/recstatus.c0000644000175000017500000001105113145412721016607 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #include "epgsearchtools.h" #include "recstatus.h" #include "recdone_thread.h" #include "conflictcheck_thread.h" #include "epgsearchcfg.h" #include #define ALLOWED_BREAK_INSECS 2 extern int gl_InfoConflict; cTimersRecording TimersRecording; cRecdoneThread RecdoneThread; cRecStatusMonitor* gl_recStatusMonitor = NULL; cRecStatusMonitor::cRecStatusMonitor() { } void cRecStatusMonitor::Recording(const cDevice *Device, const char *Name, const char* Filename, bool On) { time_t now = time(NULL); // insert new timers currently recording in TimersRecording if (On && Name) { if (EPGSearchConfig.checkTimerConflOnRecording) cConflictCheckThread::Init((cPluginEpgsearch*)cPluginManager::GetPlugin("epgsearch"), true); LOCK_TIMERS_READ; for (const cTimer *ti = Timers->First(); ti; ti = Timers->Next(ti)) if (ti->Recording()) { // check if this is a new entry cRecDoneTimerObj *tiRFound = NULL; cMutexLock TimersRecordingLock(&TimersRecording); for (cRecDoneTimerObj *tiR = TimersRecording.First(); tiR; tiR = TimersRecording.Next(tiR)) if (tiR->timer == ti) { tiRFound = tiR; break; } if (tiRFound) // already handled, perhaps a resume { if (tiRFound->lastBreak > 0 && now - tiRFound->lastBreak <= ALLOWED_BREAK_INSECS) { LogFile.Log(1,"accepting resume of '%s' on device %d", Name, Device->CardIndex()); tiRFound->lastBreak = 0; } continue; } cRecDoneTimerObj* timerObj = new cRecDoneTimerObj(ti, Device->DeviceNumber()); TimersRecording.Add(timerObj); cSearchExt* search = TriggeredFromSearchTimer(ti); if (!search || (search->avoidRepeats == 0 && search->delMode == 0)) // ignore if not avoid repeats and no auto-delete continue; bool vpsUsed = ti->HasFlags(tfVps) && ti->Event() && ti->Event()->Vps(); LogFile.Log(1,"recording started '%s' on device %d (search timer '%s'); VPS used: %s", Name, Device->CardIndex(), search->search, vpsUsed ? "Yes": "No"); const cEvent* event = ti->Event(); if (!event) { event = GetEvent(ti); if (event) LogFile.Log(3,"timer had no event: assigning '%s'", event->Title()); } if (!event) { LogFile.Log(1,"no event for timer found! will be ignored in done list"); continue; } time_t now = time(NULL); if (vpsUsed || now < ti->StartTime() + 60) // allow a delay of one minute { timerObj->recDone = new cRecDone(ti, event, search); return; } else LogFile.Log(1,"recording started too late! will be ignored"); } } if (!On) { // must be done in a different thread because we hold timer and scheduling lock here while (RecdoneThread.Active()) cCondWait::SleepMs(100); // wait before changing filename RecdoneThread.SetFilename(Filename); RecdoneThread.Start(); } } int cRecStatusMonitor::TimerRecDevice(const cTimer* timer) { if (!timer) return 0; cMutexLock TimersRecordingLock(&TimersRecording); for (cRecDoneTimerObj *tiR = TimersRecording.First(); tiR; tiR = TimersRecording.Next(tiR)) if (tiR->timer == timer && timer->Recording()) return tiR->deviceNr+1; return 0; } vdr-plugin-epgsearch/epgsearchcats.c0000644000175000017500000001025013145412721017406 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #include #include "epgsearchcats.h" #include "log.h" #include "epgsearchtools.h" #include using std::string; // -- cSearchExtCat ----------------------------------------------------------------- cSearchExtCat::cSearchExtCat(void) { id = 0; name = NULL; format = NULL; menuname = NULL; searchmode = 1; // default: all substrings must exist values = NULL; nvalues = 0; } cSearchExtCat::~cSearchExtCat(void) { free(name); free(menuname); for(int i=0; i MAXVALUELEN) { LogFile.eSysLog("entry '%s' is too long. Will be truncated!", pos); valuelen = MAXVALUELEN; } strn0cpy(value, pos, valuelen); pos = pos_next; switch (parameter) { case 1: id = atoi(value); break; case 2: { name = strdup(value); format=strchr(name,','); if (format) { *format=0; format++; char cset[]="%0123456789di"; if (strspn(format,cset)!=strlen(format)) format=NULL; } break; } case 3: menuname = strdup(value); break; case 4: { char* szBuffer = strdup(value); char* pptr; char* pstrToken=strtok_r(szBuffer, ",", &pptr); while(pstrToken) { nvalues++; char **tmp = (char**) realloc(values, nvalues * sizeof(char*)); if (tmp) { values=tmp; values[nvalues-1] = strdup(pstrToken); } pstrToken=strtok_r(NULL, ",", &pptr); } free(szBuffer); break; } case 5: searchmode = atoi(value); break; default: break; } //switch } parameter++; } if (*pos) pos++; } //while free(line); return (parameter >= 3) ? true : false; } const char *cSearchExtCat::ToText(void) { char* buffer = NULL; string sValues = ""; for(int i=0; iid == id) break; index++; SearchExtCat = SearchExtCats.Next(SearchExtCat); } if (!SearchExtCat && index == 0) return -1; else return index; } vdr-plugin-epgsearch/COPYING0000644000175000017500000004310613145412721015467 0ustar tobiastobias GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. vdr-plugin-epgsearch/docsrc2html.sh0000755000175000017500000000150213145412721017211 0ustar tobiastobias#!/bin/bash # # Creates the html pages # # Needs: pod2html # # Mike Constabel # # Version 0.1 - 24.09.2006 # DOCSRC="doc-src" if [ ! -s "epgsearch.c" ]; then echo "Cannot find epgsearch.c. Call this script from epgsearch source directory." exit fi VERSION="$(awk -F\" '/VERSION/ {print $2; exit;}' epgsearch.c)" for LANGUAGE in $(ls "$DOCSRC"/); do [ ! -d ""$DOCSRC"/$LANGUAGE" ] && continue mkdir -p html/$LANGUAGE rm html/$LANGUAGE/* 2>/dev/null for i in "$DOCSRC"/$LANGUAGE/*.txt; do echo -ne "create html page: ($LANGUAGE) $(basename "$i" ".txt")..." pod2html --infile="$i" --outfile="html/$LANGUAGE/$(basename "$i" ".txt").html" --norecurse --title="Epgsearch Version $VERSION" if [ $? -eq 0 ]; then echo " done." else echo " failed." fi done rm "$DOCSRC"/$LANGUAGE/*~ 2>/dev/null done echo #EOF vdr-plugin-epgsearch/HISTORY.DE0000644000175000017500000021013113145412721016001 0ustar tobiastobiasVDR Plugin 'epgsearch' Revision History --------------------------------------- 2017-05-xx; Version 2.3.1 - development release neu: - Anwenden vdr-2.3.2-epgsearch-1.0.1.beta5~git20150715_v2.diff von fnu@vdr-portal.de basierend auf Eingaben von kamel5, mini73 & TomJoad @ vdr-portal.de => http://www.vdr-portal.de/board17-developer/board97-vdr-core/p1284612-produktive-problem-und-pluginl%C3%B6sungen-f%C3%BCr-vdr-2-3-2-und-h%C3%B6her/#post1284612 - Anwenden 0004-Added-patches-vdr.epgsearch-exttimeredit-2.3.3.diff.diff von jasminj@vdr-portal.de => http://www.vdr-portal.de/board17-developer/board21-vdr-plugins/p1289938-epgsearch-f%C3%BCr-vdr-2-3-x/#post1289938 - Anwenden 0005-epgsearch-inactive-records-v2.diff von jasminj@vdr-portal.de => http://www.vdr-portal.de/board17-developer/board21-vdr-plugins/p1289983-epgsearch-f%C3%BCr-vdr-2-3-x/#post1289983 - Anwenden 0001-Fix-warning-in-pending_notifications.c.diff von jasminj@vdr-portal.de - Anwenden 0002-Fixed-warnings-in-man-page-generation.diff von jasminj@vdr-portal.de => http://www.vdr-portal.de/board17-developer/board21-vdr-plugins/p1289704-epgsearch-f%C3%BCr-vdr-2-3-x/#post1289704 - Anwenden 0003-Use-HandleRemoteTimerModifications-instead-of-Handle.diff von jasminj@vdr-portal.de => http://www.vdr-portal.de/board17-developer/board21-vdr-plugins/p1289764-epgsearch-f%C3%BCr-vdr-2-3-x/#post1289764 - Anwenden menu_category_recsdone.diff von tomas & louis @vdr-portal.de http://www.vdr-portal.de/board1-news/board2-vdr-news/p1271995-skindesigner-1-0-0-neuer-default-skin-estuary4vdr/#post1271995 - Anwenden 0001-revert-seperate-status-thread.diff von TomJoad@vdr-portal.de - Anwenden 0002-fix-incorrect-lock-sequences.diff von TomJoad@vdr-portal.de - Anwenden 0003-revert-now-obsolete-pointer-params.diff von TomJoad@vdr-portal.de - Anwenden 0004-some-small-fixes.diff von TomJoad@vdr-portal.de http://www.vdr-portal.de/board17-developer/board21-vdr-plugins/p1291452-epgsearch-f%C3%BCr-vdr-2-3-x/#post1291452 - Löschen Alt-Code vor VDR 2.3.x - Anwenden 0001-fixed-unresponsive-vdr.diff von TomJoad@vdr-portal.de - Anwenden 0002-removed-variableduplications.diff von TomJoad@vdr-portal.de - Anwenden 0003-more-cleanups.diff von TomJoad@vdr-portal.de - Anwenden 0004-Remote-timers-in-menu-myedittimer.diff von TomJoad@vdr-portal.de http://www.vdr-portal.de/board17-developer/board21-vdr-plugins/p1291771-epgsearch-f%C3%BCr-vdr-2-3-x/#post1291771 - Anwenden fixblacklist_handling.diff von TomJoad@vdr-portal.de http://www.vdr-portal.de/board16-video-disk-recorder/board99-distributionen/board107-mld/p1292085-epgsearch-in-verbindung-mit-epgd-epg2vdr-live-absturz-unter-vdr-2-3-4/#post1292085 - Anwenden epgsearch_min_max_from_stl.diff von jasminj@vdr-portal.de http://www.vdr-portal.de/board17-developer/board21-vdr-plugins/p1292145-epgsearch-f%C3%BCr-vdr-2-3-x/#post1292145 2013-03-xx: Version 1.0.1 - Maintenance Release neu: - neuer Stil für das Makefile wie in vdr-1.7.36 eingeführt. Das alte Makefile gibt es noch als Makefile.before.1.7.36 für frühere VDR-Versionen. Vielen Dank an Copperhead, Stefan Hofmann und Christopher Reimer für deren Arbeit. - device bonding in der Timer-Konflikt-Prüfung implementiert, Danke an Joachim Wilke für den Path - Neue Service-Schnittstelle "Epgsearch-enablesearchtimers-v1.0" zum Ein- und Ausschalten des Suchtimer-Updates im Hintergrund. Das Beispiel in source/vdr-epgsearchclient-0.0.2.tgz wurde aktualisiert und nutzt die neue Schnittstelle. - Neuer Format-Eintrag wie z.B. %02i in der epgsearchcats.conf, Danke an Joe_D für den Patch ('man 5 epgsearchcats.conf' für mehr Information). - Im Menu 'Erledigte Aufnahmen' kann nun mit der blauen Taste zu 'Verwaiste' umgeschaltet werden, um Aufnahmen anzuzeigen, zu denen es keine Suchtimer mehr gibt. - Wenn Kanalseparatoren angezeigt werden, kann das in der Ausgabe von graphlcd Probleme machen. Um das zu vermeiden, bitte PLUGIN_EPGSEARCH_SEP_ITEMS=--- in der Make.config setzen. Die meisten Skins (ausser classic, st:tng) ersetzen '---' ohnehin in eine durch- gehende Linie. (Feature #857, Danke an 'KeineAhnung' für den Patch) - Suchtimer werden jetzt anhand absteigender Timer-Priorität abgearbeitet. Bei gleicher Priorität wird nach dem Suchbegriff sortiert. Danke an Anonym für den Patch. - Neuer Bugtracker unter http://projects.vdr-developer.org/projects/plg-epgsearch - Danke an Tobias Grimm - alten Code für vdr < 1.6.0 entfernt, Danke an Ville Skyttä für einen ganzen Haufen Patches - MainMenuHooks-Patch auf 1.0.1 aktualisiert - tschechische Übersetzung, Danke an Radek Stastny fixes: - Speicherleck behoben, Danke an Sundararaj Reel für den Patch - Crash beim Editieren von Ausschlusslisten korrigiert 2011-09-11: Version 1.0.0 neu: - unterstützt vdr-1.6.0 bis vdr-1.7.21 - Vermeide Wiederholungen mit 'Vergleiche Zeitpunkt': dabei werden 2 Sendungen anhand des Zeitpunkts der Ausstrahlung verglichen, um z.B. Wiederholungen innerhalb des gleichen Tages, der Woche oder des Monats zu ignorieren. - Globale Ausschlusslisten: Ausschlusslisten für Suchtimer können nun als global markiert werden, um unerwünschte Sendungen generell auszuschliessen (wie z.B auf doppelten SD/HD- Kanälen). Vorbelegung für Suchtimer ist nun "nur globale", kann aber auch auf "keine" gesetzt werden, um auch globale Ausschlusslisten zu ignorieren. - neue Setup-Option epgsearch.ConflCheckCmd (keine GUI dazu, also nur per setup.conf zu setzen!), mit der man je Konflikt-Timer einen Befehl ausführen kann, mehr dazu im MANUAL. - vdr-1.7.15 benutzt einen anderen SVDRP Standard-Port (6419), bitte im Setupmenü von epgsearch ebenfalls anpassen! - Es gibt nun ein offizielles git repository für epgsearch, das die neueste Entwicklung enthält. Zuerst: git clone git://projects.vdr-developer.org/vdr-plugin-epgsearch.git Auf den aktuellen Stand kommt man einfach mit: git pull Web-git: http://projects.vdr-developer.org/git/?p=vdr-plugin-epgsearch.git Vielen Dank an die Leute von projects.vdr-developer.org, besonders an Tobias Grimm - Verzeichnis-Einträge in VDR's folders.conf werden nun ausgelesen und in der Verzeichnis- auswahl der Timerprogrammierung angeboten. - Suchtimer unterstützen nun content descriptors, die in vdr-1.7.11 eingeführt wurden. Damit können Sendungen nach ihrem Typ gesucht werden, z.B. "Film/Drama", "Dokumentation",... - Suchtimer haben nun eine neue Aktion "Ankündigen und Umschalten". Damit wird eine Sendung via OSD kurz vor ihrem Start angekündigt. Mit 'Ok' kann zum entsprechenden Kanal gewechselt werden. Umschalttimer haben die gleiche Option erhalten. - Zusätzlich zur Ankündigung per OSD können neue Sendungen nun auch per Mail bekannt- gegeben werden. Dazu gibt es eine neue Suchtimeraktion "Per Mail ankündigen". Man muss ausserdem das Mail-Templatefile epgsearchupdmail.templ anpassen (s. aktualisiertes HTML-Beispiel im conf-Verzeichnis bzw. MANUAL '13. Email notification'). - Die Zeit in Stunden zwischen den Suchtimer-Emails kann nun im Setup eingestellt werden um eine Überflutung des Posteingangs zu vermeiden. epgsearch puffert den Inhalt ausstehender Mails in der neuen Datei pendingnotifications.conf. - Neue Setup-Option zur Prüfung, ob es EPG für die nächsten x Stunden gibt. Falls nicht, kann man per OSD und/oder Mail gewarnt werden. (Setup -> Suche und Suchtimer), vorgeschlagen von Andreas Mair. - neue interne Variablen: * %day%, %month% und %year% liefern den numerische Tag, das Monat und das Jahr (mit Jahrhundert) einer Sendung * %chgrp% liefert die VDR Kanalgruppe einer Sendung * %liveeventid% liefert die kodierte Event-ID wie sie im Frontend 'live' benutzt wird. Damit können nun z.B. in den Suchtimer-Mails direkte Links angegeben werden. (s. Beispiel conf/epgsearchupdmail-html.templ) * %timer.liveid% liefert die kodierte Timer-ID wie sie im Frontend 'live' benutzt wird. Damit können nun z.B. in den Suchtimer-Mails direkte Links angegeben werden. * %date_iso% und %date_iso_now% ergeben das (aktuelle) Datum im Format 'YYYY-MM-DD', vorgeschlagen von Andreas Mair. * %search.series% liefert 1 oder 0 abhängig vom Flag "Serienaufnahme" der Suche und kann im Verzeichniseintrag einer Suche oder in deren abhängigen Variablen benutzt werden. - neues Kommando 'connect' innerhalb interner Variablen: damit kann eine Verbindung zu einem TCP-Dienst aufgebaut werden, Daten übergeben und das Ergebnis einer Variable zugewiesen werden. S. MANUAL für Details. - neues Kommando 'length' innerhalb interner Variablen: liefert die Länge des Arguments zurück. - Im Gedenken an pat: Update der französischen Übersetzung, Danke an Patrice Staudt - Update der italienischen Übersetzung, Danke an Diego Pierotto - Update der finnischen Übersetzung, Danke an Rolf Ahrenberg und Ville Skyttä - Neue litauische Übersetzung, Danke an Valdemaras Pipiras - Neue slowakische Übersetzung, Danke an Milan Hrala - neues SVDRP-Kommando 'MENU [NOW|PRG|SUM]' zum Aufruf eines der OSD-Hauptmenüs oder der Inhaltsangabe der aktuellen Sendung. Falls irgendein epgsearch-Menü geöffnet ist, schließt ein weiteres SVDRP-Kommando dieses wieder. - Die maximale Anzahl von Tagen für eine Timerkonfliktprüfung ist nun von 99 auf 14 geändert. - Patch von Jörg Wendel für neuen graphtft-Patch - Zwei Episoden mit leerem Untertitel innerhalb 'Vermeide Wiederholung' werden jetzt als unterschiedlich gewertet. Damit ergeben sich mehr Aufnahmen, aber es wird verhindert, dass man eine Folge nur wegen eines fehlerhaften EPGs verpasst. - Suchtimer: Falls der Datei-Eintrag eines Timers leer ist oder "!^invalid^!" enthält, wird er für die Programmierung übersprungen. - Wiederholung vermeiden: Die Option 'ja' bei 'Vergleiche Untertitel' wurde durch 'falls vorhanden' ersetzt. Damit stuft epgsearch zwei Sendungen nur dann als identisch ein, wenn die Episodennamen gleich sind und nicht leer. - epgsearch verwendet nun den shutdown handler (eingeführt in vdr 1.5.1) um die Unter- brechung eines Suchtimerupdates zu verhindern. - das SVDRP-Kommando UPDS zum Auslösen von Suchtimer-Updates hat nun eine neue Option 'SCAN' mit der vor dem eigentlichen Update noch ein EPG-Scan ausgeführt wird. - beim Löschen eines Suchtimers wird nun auch dessen Liste erstellter Timer gelöscht, vorgeschlagen von Sundararaj Reel - 'Datei' und 'Verzeichnis' an den Anfang des Timeredit-Menüs verlegt, da es zumindest bei mir das am meisten editierte Feld ist, z.B. bei wegen der Auswahl eines Ordners für die Aufnahme. - Wareagle Icons werden bei Verwendung des VDRSymbols-Font nun automatisch aktiv (kann aber mit WarEagleIcons=0 in epgsearchmenu.conf überschrieben werden), vorgeschlagen von Ronny Kornexl - Das korrekte Encoding für Email-Benachrichtigungen wird nun automatisch erkannt. - Es wird nun automatisch erkannt, ob Pin-Plugin oder Graphtft installiert sind, ebenso die optionalen Libs libpcre und libtre (läßt sich im Makefile mit Kommentieren von AUTOCONFIG abschalten) - neuer Patch vdr.epgsearch-exttimeredit.diff: Dieser VDR-Patch integriert epgsearch's Timer-Edit-Menü in VDR's Timer-Menü, Danke dafür an S:oren@vdr-portal. - einige Geschwindigkeitsverbesserungen, Danke an Tobias Bratfisch für die Patches - falls die VPS-Zeit von der Startzeit einer Sendung abweicht, wird die VPS-Kennung nun mit 'v' statt 'V' angezeigt. - Der erste Lauf der Hintergrund-Threads (Suchtimer, Umschalttimer, Konfliktprüfung) wird nun durch den ersten Aufruf von cPlugin::MainThreadHook ausgelöst, anstatt 20s nach dem VDR-Start. - Die Überwachung manueller Timer ignoriert nun Timer, deren Start- oder Stopzeit vom Anwender geändert wurde. - Der Default-Pfad zu sendmail ist nun '/usr/sbin/sendmail' und kann per Makefile konfiguriert werden, Danke an Ville Skyttä für den Patch. - Externe Suchtimer-Updates (via service interface oder SVDRP) aktivieren nun automatisch die Option "Suchtimer verw." im Setup. - epgsearch prüft nun neben korrekter Start- und Stopzeit des Timers auch die Aufnahmelänge bei der Prüfung auf vollständige Aufnahmen. 98% und mehr gelten als vollständig. - Umschalttimer sind nun ebenfalls in alle EPG-Menüs mit Suchergebnissen sichtbar. - Vermeide Wiederholung: Bei 'Vergleiche Beschreibung' kann nun angegeben werden wie hoch die Übereinstimmung sein muss, Default ist 90%. - falls kein Episodenname existiert, wird nun als Dateiname YYYY.MM.DD-HH.MM-Weekday verwendet, um die Sortierung in manchen Frontends zu erleichtern. Danke an Dominic Evans für einen Patch. - sollte nun auch unter FreeBSD compilieren, Danke an Juergen Lock für einen Patch - neuer SVDRP-Befehl UPDT zum Neuladen der Suchtimer aus der Datei epgsearch.conf fixes: - Absturz beim Drücken von 'Ok' in leerem Menü erledigter Timer behoben - Absturz bei Verwendung des Fortschrittsbalkens in Verbindung mit Sendungen der Länge 0 behoben. Danke an egal@vdrportal - Wenn eine unvollständige Aufnahme ein Suchtimer-Update für einen Suchtimer mit 'Wiederholung vermeiden' auslöst, werden nun bereits laufende Sendungen als Wieder- holung ignoriert. - Es wird nun cCondWait::Wait anstelle von cCondWait:SleepMs verwendet um Probleme beim Beenden zu vermeiden, danke e9hack@vdrportal für den Patch - Zeilenumbrüche im SVDRP-Befehl LSTT korrigiert, Danke an Andreas Mair für einen Patch - Antwortzeit beim Abbruch des Suchtimer-Threads verbessert - Absturz beim Navigieren zu benutzerdef. EPG-Menüs behoben, die zwischenzeitlich schon in der Vergangenheit lagen, Danke an Mike Constabel für den Hinweis - Im Timer-Edit-Menu war das Menu zur Tagesauswahl nicht mehr sichtbar - Wurde eine Sendung von mehreren Suchtimern mit "Nur ankündigen" gefunden, wurde sie auch mehrfach gelistet, Danke an Andreas Mair für den Hinweis. - Fehler bei "Nur ankündigen"-Suchtimer im Zusammenhang mit der Anzeige des zugehörigen Such- timernamens korrigiert. - Einige Speicherlecks korrigiert, Danke an Bittor Corl für einen Patch - Einige Korrekturen damit es mit gcc-4.4 compiliert, Danke an firefly@vdrportal für einen Patch. - Falsche Man-Sektion einiger Man-Pages korrigiert, Danke an Ville Skyttä für den Patch. - Einige Korrekturen bzgl. libtre-Includes, Danke an Ville Skyttä für den Patch. - Korrektur beim UTF8-Zeichensatz-Handling bei Timer-Filenamen, Danke an Rolf Ahrenberg für den Patch. - Absturz beim Hinzufügen sehr langer Episodentexte zum Verzeichnis eines Timers behoben, Danke an Lari Tuononen für den Hinweis. - Sichergestellt, dass nur noch ein Library für reguläre Ausdrücke von epgsearch benutzt wird, Danke an Ville Skyttä für den Patch. - Einige Provider haben seltsame Änderungen in den EPG-Zeiten von nur wenigen Sekunden. epgsearch ignoriert nun Änderungen von weniger als 60s und ändert den zugehörigen Timer nicht. Es erfolgt auch keine Emailbenachrichtigung. Danke an cmichel@mantis für den Hinweis. - möglicher Fix für das alte Problem mit dem crash in libpcre, Danke an Andreas Cz. für den Patch und an Stefan Bauer für den Hinweis darauf. - Fix für einen Absturz beim Hin- und Herschalten von mit/ohne Untertitel bei Timern mit mit sehr langen Episodennamen, Danke an Ville Skyttä für den Patch. - Korrektur beim file descriptor handling bei fehlerhafter SVDRP-Verbindung, Danke an Teemu Rantanen für einen Patch. - Service-Schnittstelle für Umschalttimer wegen falschem Parameterhandling korrigiert, Danke an gnapheus@vdrportal für den Hinweis. - Korrektur der Suche ohne Unterscheidung von Groß-/Kleinschreibung in Verbindung mit Utf-8-Zeichen, danke an Ville Skyttä für den Hinweis. - Prüfung auf Vollständigkeit von VPS-Aufnahmen korrigiert, Danke an durchflieger@vdr-portal für einen Patch. 2008-04-29: Version 0.9.24 neu: - Unterstützung von vdr-1.6.x/1.7.x - Die Suche und damit das Suchtimer-Update sind nun etwa 25% schneller - Schnellere EPG-Menüs, danke an die Patch-Authoren von http://www.open7x0.org - Unterstützung des VDRSymbols-Font (aktivieren mit 'WarEagle=1' in epgsearchmenu.conf) - der EPG-Befehl 'Suche in Aufnahmen' wertet nun die info.vdr anstelle des Aufnahmepfades aus und macht zusätzlich eine fuzzy-Suche, vorgeschlagen von Mase@vdrportal - Suchtimer mit Aktion 'Nur umschalten' und Switchtimer haben jetzt eine weitere Option 'Ton anschalten', wodurch der Ton beim Umschalten aktiviert wird, falls er aus war, vorgeschlagen von Michael Brückner - Die Timer-Benachrichtigungsmail unterstützt nun eine weitere Variable %timer.modreason%, in der im Klartext der Grund einer Timeränderung steht (s. epgsearchupdmail(-html).templ für ein Beispiel) - Unterstützung für einen conf.d-Mechanismus (s. MANUAL -> 14. The conf.d subdirectory), vorgeschlagen von Mike Constabel - neuer SVDRP-Befehl 'LSCC', der das Ergebnis einer Timerkonfliktprüfung zurückgibt. Zum Format der Ergebnisliste bitte ins MANUAL schauen. - Neuer Patch für VDR (vdr-1.5.17-progressbar-support-0.0.1.diff), der die Unter- stützung eines grafischen Fortschrittsbalkens in den Skins classic und st:tng einbaut, Danke an zulu@vdrportal. - '0' im Menü der erledigten Aufnahmen schaltet nun die Anzeige zwischen '~Episode' und 'Titel~Episode' um. - Das Favoriten-Menü kann jetzt auch per Setup nach 'Übersicht - Jetzt' angezeigt werden, vorgeschlagen von Bittor Corl - Im Menü "erledigte Aufnahmen" wird nun beim Datum absteigend sortiert. - Unterstützung für das neue Info-Key-Verhalten in vdr-1.5.13 - Änderungen für den eingebauten graphtft-patch (bei Verwendung von VDR-extension-patch ist > v.37 notwendig) - Update des timercmd-patches für vdr-1.5.12 (patches/timercmd-0.1_1.5.12.diff) - Neue Datei patches/README.patches für eine Beschreibung der vorhandenen Patches - Update von 'undoneepgsearch.sh', einem Skript zum Entfernen einer Aufnahme aus dem done-File über die reccmds.conf, Danke an Viking@vdrportal. - Update der finnischen Übersetzung, Danke an Rolf Ahrenberg - Spanische Übersetzung, vielen Dank an agusmir, dragondefuego, GenaroL, lopezm und nachofr von todopvr.com, und ein besonderer Dank an bittor - Update der italienischen Übersetzung, Danke an Diego Pierotto - Update der niederländischen Übersetzung, Danke an carel@bugtracker - Die Setup-Option "Keine Ankündigungen bei Wiedergabe" wird jetzt ignoriert, wenn das Suchtimer-Update manuell gestartet wurde, vorgeschlagen von Andreas Mair. fixes: - Shiften der Uhrzeit: die Startzeit wird jetzt nur noch dann anstelle des Fortschrittsbalken angezeigt, wenn in der Menüvorlage nicht bereits eine Startzeit enthalten ist ("%time%"), so wie in der Standardvorlage. Danke an Getty@vdrportal für den Hinweis. - einige Punkte bzgl. GPL korrigiert, Danke an Thomas Günther für den Hinweis. - Crash behoben bei nicht vorhandenem EPG, Danke an Petri Helin für einen Patch. - Der Standardwert für die maximale Dauer ist nun '23:59' um Probleme mit externen Tools zu vermeiden, Danke an ralf-naujokat@bugtracker für den Hinweis (bug-id #371) - bei EPG-Änderungen mit weniger als 10 Minuten hat epgsearch bisher einen Timer modifiziert anstatt einen neuen anzulegen. Das verursachte jedoch Probleme mit Sendungen unter 10 Minuten Länge. Die Toleranz ist deshalb nun min(, 10 min). Danke an Janne Liimatainen für den Hinweis. - einige Übersetzungen korrigiert, Danke an ramirez@vdrportal für den Hinweis. - Scrollgeschwindigkeit in den EPG-Menüs verbessert, Danke an ramirez@vdrportal für den Hinweis. - Absturz behoben, wenn SIGINT während des Startens der Background-Threads signalisiert wird. - Kanalgruppen-Separatoren in 'Übersicht Jetzt/Nächste/...' werden nun ausgeblendet, wenn sie leer sind, wie in ':@30', Danke an Ulf Kiener für einen entspr. Patch. - Absturz beim Aufruf des Setups der Addon-Plugins behoben, wenn VDR mit dem ext-Patch und aktivem LIEMIKUUTIO versehen wurde. - 'Wiederholung vermeiden' kombiniert mit 'Pause, wenn ... Aufnahmen existieren' hat zu wenige Timer erzeugt, Danke an spockele@vdrportal für den Hinweis - einige Compilerwarnungen von g++ 4.3 behoben - fine-tuning beim fuzzy-Vergleich von Inhaltsangaben, Danke an Alf Fahland für einen Patch - Problem mit Pipes im Suchbegriff einer Blacklist behoben, Danke anAndreas Mair für den Hinweis. - Beschriftung der grünen/gelben Taste nach Umschalten im Menü "Schedule" korrigiert. Danke an Andreas Mair für den Hinweis. - Auswertung von Compiler-Flags wie WITHOUT_EPGSEARCHONLY,... korrigiert. 2007-09-02: Version 0.9.23 neu: - unterstützt das neue i18n-System in vdr>=1.5.7, ist aber weiterhin abwärtskompatibel - bei den erweiterten EPG-Kategorien kann nun auch wertmäßig verglichen werden, z.B. um nach Sendungen nach einem bestimmten Jahr zu suchen. Dazu wurden neue Suchmodi für die epgsearchcats.conf eingeführt (10 entspricht '<', 11 entspricht '<=', ...) Beispiel: # 'bis Jahr' 3|Year|bis Jahr||11 # 'ab Jahr' 12|Year|ab Jahr||13 Denkbar wäre auch die Suche nach einer bestimmten Staffel einer Serie, falls dies im EPG enthalten ist. Eine vollständige Liste der Suchmodi ist im Bereich in der Dokumentation aufgeführt - Neuer Schalter "Ignoriere fehlende Kategorien" im Edit-Menü eines Suchtimers bei den erweiterten EPG-Kategorien: Wenn 'Ja' gewählt ist, verhindert das, dass eine Sendung aus dem Suchergebnis ausgeschlossen wird, falls die entsprechende Kategorie nicht im EPG vorhanden ist. Vorsicht: Ohne weitere Suchkriterien kann das zu einer Flut von Timern führen. - Suchtimer können jetzt automatisch gelöscht werden. Im Edit-Menü gibt es dafür: * nach x Aufnahmen, oder * nach x Tagen nach erster Aufnahme gezählt werden nur erfolgreiche Aufnahmen. Das Löschen erfolgt direkt nach dem Ende der entsprechenden Aufnahme. - Neue Aktion "Kopie anlegen" im Menü Suche/Aktionen zum Anlegen und Editieren einer Kopie der aktuellen Suche, vorgeschlagen von Michael Brückner. - Die Option "Verw. als Suchtimer" hat nun einen dritten Wert 'benutzerdef.' neben 'Ja' und 'Nein', mit dem man über die Taste 'Blau' ein Zeitfenster angeben kann, in dem der Suchtimer aktiv sein soll. Vorgeschlagen von jo01@vdrportal. - Der Fortschrittsbalken zeigt nun die Startzeit anstelle eines leeren Balkens an, wenn man zu einer noch nicht laufenden Sendung shiftet, Danke an zulu@vdrportal für den Patch. - Das Menü "Zeige erstellte Timer" zeigt nun mit 'Ok' die Inhaltsangabe der erstellten Timer. Ebenfalls funktionieren die Kurztasten '1..9' für die EPG- Befehle. - eingebauter pin-plugin patch (epgsearch muss nicht mehr gepatcht werden) Zum Aktivieren bitte mit 'USE_PINPLUGIN' in VDR's Make.config kompilieren (ist mit VDR extension patch bereits automatisch der Fall) - eingebauter graphtft-plugin patch (epgsearch muss nicht mehr gepatcht werden) Zum Aktivieren bitte mit 'USE_GRAPHTFT' in VDR's Make.config kompilieren (ist mit VDR extension patch bereits automatisch der Fall) - Update der finnischen Übersetzung, Danke an Rolf Ahrenberg - Update der französischen Übersetzung, Danke an Patrice Staudt fixes: - Fehler beim Anlegen eines Timers korrigiert, nachdem man durch die Inhalts- angabe navigiert hat, danke an Rolf Ahrenberg für den Hinweis. - Beschriftung "Aufnehmen" bzw. "Timer" im Menü Inhaltsangabe je nach vorhandenem Timer korrigiert. - Fehler bei Umschalttimern und geändertem EPG behoben, Danke an Juergen Urban für einen Patch - einige Compiler-Warnungen in g++-4.2 gefixed, Danke an Michael Brückner für den Hinweis. - "," als erlaubtes Zeichen für Suchtimer hinzugefügt, Danke an Mike Constabel für den Hinweis. 2007-05-27: Version 0.9.22 neu: - neue Option in der Timerkonflikt-Prüfung "Beim Beginn einer Aufnahme": Dadurch wird beim Start einer Aufnahme eine Konfliktprüfung durchgeführt und per OSD über Konflikte informiert, wenn der Konflikt innerhalb der nächsten 2h auftritt. Somit werden also auch Timer überwacht, die nicht innerhalb epgsearch programmiert wurden, ebenso Sofortaufnahmen. - Neues Service-Interface "Epgsearch-services-v1.0": Damit können andere Plugins auf viele Komponenten von epgsearch wie z.B. Suchtimer, Setup-Werte, ... zugreifen, diese verwalten und Aufgaben wie 'Nach Wiederholung suchen' ausführen (Mehr dazu in services.h). - Neue Projekt-Homepage: http://winni.vdr-developer.org/epgsearch, vielen Dank an Thomas Keil - Update der finnischen Übersetzung, Danke an Rolf Ahrenberg. fixes: - vollständige Neuentwicklung des Menüs zur Inhaltsangabe und dessen Navi- gation, um Probleme mit Skins zu vermeiden und andere Bugs zu beheben. - beim Test auf Wiederholungen wird nun auch im Vergleich mit dem Done-File nur der alphanumerische Teil von Titel und Episode verwendet. - weiteres Problem mit Anführungszeichen beim Aufrunf von EPG-Befehlen korrigiert. - Lizenzänderungen und -ergänzungen für den Einzug ins Debian-Repository - Fehler in der Zeitanzeige bei benutzerdef. Zeiten in Verbindung mit Zeit- sprung mit FRew/FFwd behoben, Danke an Torsten Weigelt für den Hinweis - Die Zusatzinfo über den Kanal wurde bei 'Timer mit 'Aufnehmen' sofort anlegen' nicht erzeugt. Danke an Rolf Ahrenberg für den Patch. 2007-04-29: Version 0.9.21 neu: - Unterstützung für den MainMenuHooksPatch. Dieser löst den vdr-replace-schedulemenu-Patch ab. Der neue Patch wird auch von anderen Plugins verwendet. Somit ist dafür nur noch ein Patch notwendig. Der alte Patch wird vorübergehend ebenfalls noch unterstützt. - Die Sendungs-Ankündigungen per OSD wurden vollständig überarbeitet. Statt einer Anzeige jeder einzelnen Sendung erhält man nun "x neue Sendungen gefunden! Anzeigen?". Mit 'Ok' wird ein Menü aller Sendungen eingeblendet, das die üblichen Funktionen anderer EPG-Menüs hat. Mit "Editieren" kann man die Ankündigungs-Einstellungen verändern (z.B. "Erneut ankündigen: ja/nein" oder erst wieder nach Tag x ankündigen). - Timer-Konflikt-Benachrichtigungen per OSD können nun während einer Wieder- gabe unterdrückt werden. Die Benachrichtigung erfolgt aber trotzdem, wenn der nächste Konflikt innerhalb der nächsten 2 Stunden liegt. - alle sub-Plugins (epgsearchonly, quickepgsearch, conflictcheckonly) haben nun eine Setupoption zum Ein-/Ausschalten des Hauptmenüeintrags. Danke an Tobias Grimm für den Patch. - Kanalname in der Aux-Info von manuellen Timern, Danke an Rolf Ahrenberg für den Patch. - neues Skript undoneepgsearch.sh zum Rücksetzen eines Timers im Aufnahmemenü. Mehr dazu unter: http://www.vdr-portal.de/board/thread.php?postid=574109#post574109 Danke an den Author Christian Jacobsen - Update der französischen Übersetzung, Danke an Patrice Staudt. - Update der finnischen Übersetzung, Danke an Rolf Ahrenberg. - Im Menü 'Timer-Konflikt-Details' wird im Titel nun auch das Datum des Konflikts angezeigt, vorgeschlagen von Rusk@vdrportal. - Das Passwort für die Mail-Authentifizierung wird im OSD nun versteckt angezeigt, d.h. mit '***...' - Das Setup für Mail-Benachrichtigungen hat nun auch ein "Senden an"-Feld, weil einige Provider keine Mails mit gleichem Sender/Empfänger akzeptieren. Falls das Feld nicht besetzt ist, benutzt epgsearch automatisch den Sender als Empfänger. - Beim Prüfen auf Wiederholung (beim Feature "Wiederholung vermeiden") vergleicht epgsearch nun nur noch die alphanumerischen Teile von Titel und Episode und ignoriert dabei auch die Groß-/Kleinschreibung. Vorschlag von chello@vdrportal. - Danke an Rolf Ahrenberg für das Update der finnischen Übersetzung - '&' zu den erlaubten Zeichen eines Suchbegriffs hinzugefügt fixes: - Die Tags in der Aux-Info von Timern, die per Suchtimer erzeugt wurden, sind nun XML-konform (keine Großbuchstaben oder Leerzeichen). Z.B. wird aus "Search timer" nun "searchtimer". Also nicht wundern, wenn beim ersten Suchtimer-Update alle Timer aktualisiert werden, die von Suchtimern angelegt wurden. Danke an Rolf Ahrenberg für den Hinweis. - Update von recordingdone.sh wegen der vorherigen Änderung, Danke an Mike Constabel für einen entsprechenden Patch. - segfault bei falsch konfigurierten erw. EPG-Kategorien behoben. - Scrollende Menütexte funktionieren nun wieder, wenn der gewählte Skin das unterstützt. Danke an ufauser@vdrportal für den Hinweis. - Die Setup-Option "Verw. Suchtimer" wird nun automatisch aktiv, wenn ein Suchtimer aktiv gesetzt wird oder ein manuelles Suchtimer-Update gestartet wird. - Behandlung von Anführungszeichen in Titel/Untertitel bei Übergabe an benutzerdef. EPG-Befehle korrigiert, Danke an Mike Constabel für den Hinweis. - Handling im Suchtimer-Vorlagenmenü korrigiert, Danke an wombel@vdrportal für den Hinweis. 2007-01-30: Version 0.9.20 neu: - Unterstützung von vdr-1.5.0: Hinweis: Der CA-Support im Timerkonflikt-Check ist ziemlich experimentell, weil ich es mangels CAMs nicht testen kann. - epgsearch kann nun auch manuell programmierte Timer auf EPG-Änderungen überwachen. Wenn epgsearch's eigenes Timer-Edit-Menü benutzt wird, stehen folgende Methoden zur Auswahl: * ohne Überwachung * anhand Sendungskennung * anhand Kanal/Uhrzeit Mehr dazu in der README.DE (unter 1.4.4 Setup/Timer-Programmierung/Standard-Timer-Prüfmethode) - die im Favoritenmenü verwendete Zeitspanne kann jetzt über das Setup angepaßt werden. Standard sind 24h. - Sendungs-Ankündigungen: Wenn während der Ankündigung einer Sendung eine der Tasten '0', ... '9' oder 'Ok' gedrückt wird, wird nachgefragt, ob zukünftige Ankündigungen vollständig (bei den Tasten '0' oder 'Ok') oder nur für die nächsten x Tage (bei den Tasten '1' bis '9') unterdrückt werden sollen. Bestätigt man diese Abfrage durch ein erneutes 'Ok', wird die Einstellung entsprechend übernommen. - Mit der neuen Setup-Option "Keine Ankündigungen bei Wiedergabe" können Ankündigungen von Sendungen während einer Wiedergabe nun abgeschaltet werden. Vorgeschlagen von Andreas Mair. - Neben der Erledigt-Liste für Aufnahmen gibt es nun auch eine für Timer (timersdone.conf). Damit können nun Timer gelöscht werden, ohne dass diese mit dem nächsten Suchtimer-Update wieder neu angelegt werden. Mit dem neuen Menü 'Zeige erzeugte Timer' unter Suche/Aktionen kann diese Liste bearbeitet werden. Das ganze Verfahren kann im Suchtimer-Setup auch abgeschaltet werden. Achtung: Diese Timer-Erledigungsliste wird nur mit Timern gefüllt, die ab dieser Version neu angelegt wurden. - neues Zusatzplugin 'quickepgsearch': Dieses erstellt einen Hauptmenüeintrag "Schnellsuche", der dazu dient einfach nach einem beliebigen Begriff im EPG zu suchen. Mit '-Pquickepgsearch' einbinden. Vorgeschlagen von SurfaceCleanerZ@vdrportal. - neue Setup-Option "Kanäle begrenzen von 1 bis" zur Beschleunigung von epgsearch's Aufruf. Ist der aktuelle Kanal über dem Limit werden alle Kanäle angezeigt. Vorgeschlagen von Uwe@vdrportal. - neue SVDRP-Befehle: * 'LSRD' liefert eine Liste aller Verzeichnisse zurück, die aktuell bei Aufnahmen, Timern, Suchtimern oder in epgsearchdirs.conf verwendet werden. * 'LSTT [ID]' liefert alle Such-Vorlagen, oder die Vorlage mit der angegebeenen ID (Format wie in epgsearch.conf). * 'NEWT ' zum Anlegen einer neuen Suchvorlage. * 'DELT ' zum Löschen der Suchvorlage mit der angegebenen ID. * 'EDIT ' zum Ändern einer Suchvorlage. * 'DEFT [ID]' liefert die aktuelle Standard-Suchvorlage. Wird eine ID übergeben wird die zugehörige Suchvorlage zur Standard-Suchvorlage. - geänderte SVDRP-Befehle: * 'DELS [ID] [DELT]' löscht nun neben der Suche auch zugehörige Timer, wenn das optionale 'DELT' mitübergeben wird. - man kann nun neben dem Skript sendemail.pl auch sendmail für den Mailversand verwenden (->Setup), vorgeschlagen von Patrick Cernko - Neue Variablen: * '%timespan%' zur Verwendung in Menüs oder Mails. Zurückgegeben wird die Zeitspanne von Jetzt bis zum Beginn einer Sendung (z.B. 'in 15m'). Die Variable wird nun im Standard-Menütemplate des Favoritenmenüs verwendet, in dem das Datumsfeld entfernt wurde. * '%length%' für die Länge einer Sendung in Sekunden. - Danke an Rolf Ahrenberg für das Update der finnischen Übersetzung fixes: - manuell programmierte Timer werden durch Suchtimer nun weder gelöscht noch geändert. - das Zusatzplugin conflictcheckonly wurde kompiliert auch wenn WITHOUT_CONFLICTCHECKONLY im Makefile gesetzt war, Danke an Ronny Kornexl für den Hinweis. - Für Suchbegriff und Verzeichnis gibt es nun auch die Zeichen 'ß' (nur bei Sprache Deutsch) und '@'. - Bei Verwendung von 'Wiederholung verm.' war es in bestimmten Fällen möglich, dass nicht die Erstausstrahlung, sondern eine Wiederholung programmiert wurde. - Eine Suche mit "Verw. Wochentag" UND "Verw. Uhrzeit", bei der "Start vor:" nach Mitternacht liegt, findet nun auch Sendungen des nächsten Tages bis "Start vor:", z.B. "Start nach 22:00" und "Start vor 03:00" am Montag findet nun auch eine Sendung um 01:00 am Dienstag. - bereits aufnehmende Timer werden nun nur noch aktualisiert, falls sich die Stopzeit des Timers (z.B. wegen EPG-Update) ändert, Danke an Mike Constabel für den Hinweis. - Fehler beim Auswerten von Uservariablen behoben, Danke an Mike Constabel für den Hinweis und für's remote debugging. - Fehler bei Timerkonflikt-Mails im Zusammenhang mit Timern ohne zugeordneten Event behoben. 2006-10-27: Version 0.9.19 - neu: wenn sich die Suchergebnisse unterschiedlicher Suchen überschneiden, wird der zugehörige Timer nun nur noch von der Suche aktualisiert, die ihn ursprünglich angelegt hat. - neue Variablen: * '%search.query%' für die Verwendung im Aufnahmeverzeichnis eines Suchtimers. Diese wird mit dem Suchbegriff eines Suchtimers ersetzt. * '%videodir%' VDR Videoverzeichnis (z.B. /video) * '%plugconfdir%' VDR plugin Konfigurationsverzeichnis (z.B. /etc/vdr/plugins) * '%epgsearchdir%' epgsearchs Konfigurationsverzeichnis (z.B. /etc/vdr/plugins/epgsearch) - die Syntax des 'system'-Kommandos innerhalb einer Uservariable hat sich geändert, um die Parameter flexibler übergeben zu können. Sie lautet nun: %uservar%=system(/path/to/script[, parameters]) wobei das optionale 'parameters' ein beliebiger Ausdruck unter Verwendung weiterer Uservariablen sein kann. Ausnahme: es dürfen nicht direkt weitere system-Calls oder bedingte Ausdrücke verwendet werden. - Update der französischen Übersetzung, Danke an Patrice Staudt fixes: - VPS-Timer, die von Suchtimern angelegt wurden, werden nun immer auf Ihre VPS-Zeit aktualisiert, selbst wenn der Anwender Start- und/oder Stopzeit verändert hat. - nach Änderungen im Setup wurden Menü-Templates aus epgsearchmenu.conf wieder auf den Standard zurückgesetzt, Danke an s.krueger@vdrportal für den Hinweis. - vorhandene VDR-Wiederholungstimer werden durch das Suchtimer-Update nicht mehr zu normalen Timern abgeändert. 2006-10-01: Version 0.9.18 neu: - WICHTIG!!! BITTE LESEN!: epgsearch erwartet seine conf-Dateien nun in einem eigenen Konfig-Verzeichnis 'epgsearch' innerhalb des Plugin-Konfig-Verzeichnis und nicht mehr wie bisher direkt im Plugin-Konfig-Verzeichnis. Bitte legt dieses Verzeichnis an und verschiebt alle epgsearch-Dateien dorthin, bevor Ihr diese Version verwendet. Etwa so: mkdir /etc/vdr/plugins/epgsearch mv /etc/vdr/plugins/epgsearch*.* /etc/vdr/plugins/epgsearch mv /etc/vdr/plugins/.epgsearch* /etc/vdr/plugins/epgsearch Wer bereits epgsearch's '--config' oder '-c' Parameter verwendet hat, für den ist das nicht weiter wichtig. - 'Favoriten-Menü' neben 'Jetzt' and 'Nächste': Dieses Menü kann eine Liste der Lieblingssendungen der nächsten 24h zeigen. Dazu zunächst im Setup 'Zeige Favoriten-Menü' aktivieren. Um epgsearch zu sagen, was die Lieblingssendungen sind, dann Suchen anlegen/editieren und dort 'In Favoritenmenü verw.' auswählen. - neue Setup-Option für den Timer-Konflikt-Check: 'Nach jeder Timer-Programmierung'. Das bewirkt eine Konfliktprüfung nach jeder manuellen Timer-Programmierung und erzeugt sofort eine OSD-Nachricht, falls der neue/geänderte Timer in einen Konflikt verwickelt ist. - neue Email-Benachrichtigungen über Suchtimer-Updates oder Timer-Konflikte. Der Inhalt der Mails kann beliebig gestaltet werden. Bitte im MANUAL-Abschnitt 'Email notification' für weitere Details nachlesen. - epgsearch hat jetzt einen Satz von man-Pages. Ein GROSSES Danke an Mike Constabel (vejoun@vdrportal), der die ganze Arbeit des Umschreibens, Korrigierens und Formattieren gemacht hat. Die man-Pages enthalten die README's, das MANUAL, sowie eine Beschreibung aller conf's, die epgsearch verwendet. Das alles auf DE/EN. Einfach mit 'make install-doc' im epgsearch-src-Verzeichnis einrichten. - man kann jetzt eigene Variablen definieren um diese im Standard-Aufnahme-Verzeichnis, im Suchtimer-Aufnahme-Verzeichnis oder in den Menü-Templates zu verwenden. Nachdem das Ganze etwas komplex ist, bitte den Abschnitt 'User defined variables' im MANUAL lesen. Hier nur ein Beispiel was möglich ist: # Weekday, Date, Time %DateStr%=%time_w% %date% %time% # Themes or Subtitle or Date %ThemesSubtitleDate1%=%Subtitle% ? %Subtitle% : %DateStr% %ThemesSubtitleDate%=%Themes% ? %Themes% : %ThemesSubtitleDate1% # Calls this script to get a recording path %DocuScript%=system(doku.pl,%Title%,%Subtitle%,%Episode%,%Themes%,%Category%,%Genre%) %Docu%=%DocuScript% - Taste 'Ok' kann jetzt auch so konfiguriert werden, dass der Kanal gewechselt wird anstelle der Anzeige der Inhaltsanzeige. Vorschlag von malachay@vdrportal - wenn ein Timer von einem Suchtimer erzeugt wurde, wird nun in epgsearch's eigenem Timer-Edit-Menü der Name der Suche am Ende in einem nicht selektierbaren Feld angezeigt. - wenn eine Sendung via Suchtimer angekündigt wird, kann man nun dafür einen Timer erzeugen, wenn man während der Ankündigung die rote Taste drückt, vorgeschlagen von Andreas Mair. - Wenn Suchtimer im Setup abgeschaltet sind, dann bewirkt ein Anlegen/Ändern eines Suchtimers nun auch eine automatische Aktivierung im Setup, vorgeschlagen von Andreas Mair. - man kann jetzt mehr als ein Menü-Template für die Suchergebnisse verwenden. (s. MANUAL, Abschnitt "Customizing the EPG menus") - die Prüfung auf Vollständigkeit einer Aufnahme erlaubt nun auch kurze Unterbrechungen (unter 2s, z.B. bei einem Kanal-PID-Wechsel). - neue SVDRP-Befehle: * LSTC [channel group name] zeigt alle Kanalgruppen an oder nur die optional angegebene * NEWC erstellt eine neue Kanalgruppe, Format wie in epgsearchchangrps.conf * EDIC ändert eine vorhandene Kanalgruppe, Format wie in epgsearchchangrps.conf * DELC löscht eine vorhandene Kanalgruppe * RENC benennt eine Kanalgruppe um * LSTB [ID] zeigt alle Ausschlusslisten an, oder nur diejenige mit der angegebenen ID (Format ist dasgleiche wie in epgsearchblacklists.conf, s. MANUAL) * NEWB zum Anlegen einer neuen Blacklist Anmerkung: der Wert ID wird ignoriert und von epgsearch automatisch vergeben. * DELB zum Löschen einer Blacklist mit der angegebenen ID * EDIB zum Ändern einer Blacklist * 'QRYS < ID(s) >' liefert die Ergebnisse einer Suche mit der angegebenen ID zurück. Es können auch mehrere IDs übergeben werden, getrennt durch '|'. (s. MANUAL) * 'QRYS ' liefert die Ergebnisse einer Suche mit den angegebenen Werten zurück. * 'QRYF [hours]' liefert die Ergebnisse des Favoriten-Menüs (s. MANUAL). Der optionale Parameter gibt die Anzahl der auszuwertenden Stunden an. Standardwert ist 24h. * 'LSTE [ID] liefert die erweiterten EPG-Kategorien, wie sie in epgsearchcats.conf definiert sind, oder nur diejenige mit der angegebenen ID. * 'MODS ID ON|OFF' schaltet die Option 'als Suchtimer verw.' ein/aus. * 'SETP option' liefert den aktuellen Wert einer Setup-Option (s. MANUAL). - epgsearch hat jetzt ein Bug-Tracking-System (deutsch) und eine Mailinglist (englisch): http://www.vdr-developer.org/mantisbt http://www.vdr-developer.org/mailman/listinfo/epgsearch Danke an die Betreiber von developer.org - neues Service-Interface "Epgsearch-switchtimer-v1.0" zum Zugriff und zur Verwaltung der Umschaltlisten (switch timer). Danke an Dirk Leber für die Erweiterung. - Update für die französische Übersetzung (mit Setup-Hilfe!), Danke an Patrice Staudt - Danke an Rolf Ahrenberg für das Update der finnischen Übersetzung fixes: - der erste Tag eines Wiederholungstimers wird nun beim Timer-Konflikt-Check berücksichtigt, Danke an zimuland@vdrportal für den Hinweis - Suchtimer-Update für VPS-Timer korrigiert, Danke an Chello und oholler@vdrportal für den Hinweis - Behandlung des Zeichens '|' beim Wechsel des Suchmodus einer Suche korrigiert, Danke an Chello@vdrportal für den Hinweis - einige Suchmodi in den epgsearchcats.conf-Beispielen für die Mehrfachauswahl geändert. - zusätzliche Linefeeds in der SVDRP-Antwort von LSTS entfernt, Danke an Andreas Mair für den Hinweis - Kanal-Kriterium 'ohne Pay-TV' wurde ignoriert, Danke an Andreas Mair für den Hinweis - Min/Max-Initial-Werte für Suchkriterium "Dauer" korrigiert, Danke an Mike Constabel für den Hinweis - einen Bug bei der Auswahl der Konfliktprüfung nach jedem Suchtimer-Update behoben, Danke an Ronny Kornexl für den Hinweis - '--remove-destination' ins Makefile integriert, wie in vdr-1.4.2-3 eingeführt. 2006-08-07: Version 0.9.17d (maintenance release) fixes: - falsche Verwendung von 'cPlugin::ConfigDirectory' im Suchtimer-Thread korrigiert, Danke an Udo Richter und Petri Hintukainen für den Hinweis 2006-06-12: Version 0.9.17c fixes: - Problem mit Mehrfachauswahl bei erweiterten EPG-Kategorie-Werten behoben, Danke an Christian Jacobsen für den Hinweis - Nochmal ein Fix für den gcc unter linvdr, Danke an toxic-tonic@vdrportal 2006-06-10: Version 0.9.17b fixes: - einige Probleme mit Wiederholungstimer im Timer-Konflit-Check behoben, Danke an Peter Juenger für den Hinweis - Crash beim Konflikt-Check behoben bei einer aktiven Aufnahme auf einem Gerät, das über ein Plugin zur Verfügung gestellt wird (z.B. pvr, streamdev), Danke an Gerhard Steiner für den Hinweis. 2006-06-06: Version 0.9.17a (bug fix release) - Menü 'Timer-Konlfikte' wurde automatisch geschlossen, wenn Wiederholungstimer existierten, Danke an lostinspc@vdrportal - einige Compiler-Probleme mit gcc-2.95 und gcc-4.1.0 behoben, Danke an ferdi03@vdrportal, smudo81@vdrportal, toxic-tonic@vdrportal 2006-06-05: Version 0.9.17 - Kein Support mehr für vdr < 1.3.46 :-( - Die Logik beim Springen durch die benutzerdef. EPG-Zeiten hat sich geändert: Es können jetzt auch Zeiten des nächsten Tages erreicht werden, wenn diese nicht mehr als 20 Stunden in der Zukunft liegen. Danke an egal@vdrportal und CKone@vdrportal. - epgsearch hat jetzt einen eigenen Timer-Konflikt-Check, der über das Setup angepasst werden kann. Einstellbar sind relevante Prioritäten, die Zeitspanne der Prüfung und die relevante Dauer eines Konflikts. Begleitet wird dieser Check von einem "Konflikt-Manager" unter Suchen/Aktionen, der bei der Auflösung von Konflikten hilft. Vielen Dank an Mike Constabel für seine ausführlichen Tests. - Falls über einen Konflikt per OSD eine Nachricht erfolgt, kann nun mit 'Ok' direkt in die Konflikt-Übersicht des Konflikt-Managers gewechselt werden. - Falls jemand für die Konfliktprüfung einen eigenen Hauptmenü-Eintrag opfern will, kann dazu das Mini-Plugin 'conflictcheckonly' verwenden, das automatisch mitkompiliert wird. Wie üblich mit '-Pconflictcheckonly' einbinden. conflictcheckonly hat eine Setup-Option, mit der Informationen über den letzten Check direkt im Hauptmenü angezeigt werden. - Das Setup ist nun vollständig umgekrempelt (in Kategorien) und hat nun soetwas wie eine 'Online'-Hilfe, die die einzelnen Punkte näher erklärt. - Im Menü 'Umschalttimer' wird nun auch die Kanalnummer angezeigt. - Die Eingabe-Logik bei den erweiterten EPG-Kategorien für eine Suche hat sich geändert um eine Mehrfachauswahl von Kategorien zu erlauben. - Neues Skript 'timercmds-auxinfo.sh' zur Anzeige der Aux-Infos (z.B. welcher Suchtimer hat diesen Timer erzeugt?) im VDR-Timer-Menü (erfordert den timercmd-Patch), Danke an den Author Mike Constabel. - bei benutzer-def. EPG-Zeiten mit leerer Beschreibung wird nun die Uhrzeit als Beschreibung verwendet, vorgeschlagen von Thiemo Gehrke - Neues Service-Interface "Epgsearch-conflictmenu-v1.0" zum Aufruf der Timer-Konlfikt-Übersicht durch andere Plugins - Neues Service-Interface "Epgsearch-lastconflictinfo-v1.0" zur Abfrage der Ergebnisse des letzten Konfliktchecks durch andere Plugins. - epgsearchmenu.conf wird nun nicht mehr bei jedem Plugin-Aufruf neu geladen, weil das nur zum Testen eines conf-Files sinnvoll ist. Um das permanente Neuladen trotzdem zu aktivieren, kann man als Plugin-Parameter '-r' oder '--reloadmenuconf' in der runvdr angeben. - Danke an Rolf Ahrenberg für das Update der finnischen Übersetzung - HISTORY.DE hinzugefügt fixes: - Beim Laden der epgsearchmenu.conf wird im Fehlerfall nun auf ein Default-Menü geschaltet. - Behandlung von '%' in LSTS für SVDRP bei vdr > 1.3.44 korrigiert, Danke an Mike Constabel - Rechtzeitiges Laden der epgsearchmenu.conf für epgsearchonly und das Service-Interface "Epgsearch-searchmenu-v1.0", Danke an Daniel Dorau für den Hinweis. - Menü-Anzeigefehler in 'Suchvorlagen' korrigiert, Danke an Mike Constabel - Bug beim Löschen zugehöriger Timer eines Suchtimers behoben, wenn es überhaupt keine Timer gibt, Danke an Patrick Koppen für den Hinweis. - hoffentlich :-) einen Bug beim Übernehmen einer Suche in die Vorlagen behoben, Danke an Patrick Koppen für den Hinweis. 2006-04-18: Version 0.9.16 (maintenance release) fixes: - Die Anzeige in 'Übersicht - Jetzt' war fehlerhaft, wenn Fortschrittsbalken und Kanalnummern im Standard-Menü-Look aktiv waren. Danke an Gerhard Steiner. - Bei Verwendung von kleinen OSD-Fonts hat der Fortschrittsbalken geflimmert, weil er nur 1 Pixel hoch war. Danke an holymoly und TomG@vdrportal. - support für das APIVERSION-Define, das mit vdr-1.3.47 eingeführt wurde. 2006-04-14: Version 0.9.15 neu: - die EPG-Menüs können nun über die Datei epgsearchmenu.conf in Aussehen und Inhalt konfiguriert werden (Beispiel im 'conf'-Unterverzeichnis), z.B. erzeugt der Eintrag: MenuWhatsOnNow=%chnr%:3|%progrt2s%:5| %time% %t_status%:8|%category%:6| %title% ~ %subtitle%:35 im Menü 'Übersicht Jetzt' Einträge die mit der Kanalnummer beginnen, gefolgt von einem Fortschrittsbalken im text2skin-Stil, der Startzeit, dem Timerstatus, der EPG-Kategorie (z.B. 'Spielfilm') sowie schließlich Titel und Untertitel. Jedes Menü ('Übersicht Jetzt', 'Nächste', benutzerdef. Zeiten, 'Programm' und 'Suchergebnisse' kann mit einer eigenen Zeile angepaßt werden. Weitere Infos dazu im MANUAL. - WICHTIGE Änderung bei Suchtimern: epgsearch entfernt nun Timer, die nicht mehr notwendig sind (ab vdr >= 1.3.44). Darunter fallen: * Timers, die aufgrund von EPG-Änderungen nicht mehr gültig sind. Damit sollten die doppelten Aufnahmen vermieden werden, die es bisher evtl. bei einer EPG-Änderung gab * Timers, bei denen die Suchkriterien nicht mehr stimmen, z.B. nach Änderung im Suchtimer. Derartige Timer müssen also nicht mehr manuell gelöscht werden. Ausnahme: Timer, deren Start/Stop-Zeit manuell geändert wurde. Diese werden nicht gelöscht oder verändert. - Neuer Such-Modus 'unscharf': Damit wird eine 'Fuzzy'-Suche durchgeführt, die einen Algorithmus verwendet, wie er auch bei agrep benutzt wird. Die Fehler-Toleranz kann im Feld 'Toleranz' eingestellt werden. - Neue Setup-Option "Timer mit 'Aufnehmen' sofort anlegen", wie in vdr-1.3.38 eingeführt. Bei Drücken von 'Aufnehmen' wird damit sofort ein Timer angelegt. Kleine Abweichung zur VDR-Logik: Wenn die Sendung bereits läuft oder innerhalb der nächsten Vorlauf-Puffer-Minuten +2 beginnt, wird trotzdem das Timer-Edit-Menü angezeigt, damit man noch Änderungen z.B. beim Verzeichnis vornehmen kann, was bei einer lfd. Aufnahme ja nicht mehr geht. Die ganze Logik kann per Setup auch wieder abgeschaltet werden, zumindest mir ist die alte lieber ;-) - Bei Verwendung von epgsearch Timer-Edit-Menü gibts nun auch einen Löschen-Button, um einen Timer ohne Umweg über das Timer-Menü löschen zu können, vorgeschlagen von Rolf Ahrenberg. - Wenn der Hauptmenüeintrag von epgsearch nicht ausgeblendet ist, kann der anzuzeigende Name nun per Setup eingestellt werden. (Anmerkung: ändert man den Eintrag abweichend zur Standard-Vorgabe, ist dieser nicht mehr sprachabhängig) - Der Standard-Menü-Eintrag lautet jetzt nicht mehr 'Suche' sondern 'Programmführer' - einige Leute wollten einen eigenen Hauptmenü-Eintrag für epgsearch's Suchen-Menü. Deshalb gibt's nun ein Mini-Plugin names 'epgsearchonly' das einfach dieses Menü aufruft. Sein Hauptmenu-Eintrag lautet 'Suche'. Übersetzt wird es automatisch mit epgsearch. Man kann das aber auch im Makefile abschalten, indem man #WITHOUT_EPGSEARCHONLY=1 auskommentiert. Zur Verwendung einfach '-P epgsearchonly' ins VDR-Startskript eintragen (ab vdr-1.3.30) - Neues Service-Interface "Epgsearch-searchmenu-v1.0" um epgsearch's Suchmenu aufzurufen (genau das macht epgsearchonly ;-) ) - Neue Aktion 'Erstellte Timer löschen?' um alle Timer eines Suchtimers zu entfernen. Betrifft nicht aufnehmende Timer. - Beim Löschen einer Suche erfolgt nun eine Abfrage, ob alle zugehörigen Timer ebenfalls gelöscht werden sollen. - Wenn die Start/Stop-Zeit eines Timers, der per Suchtimer angelegt wurde, manuell verändert wird, wird dieser Timer von epgsearch nicht mehr angefaßt (ab vdr-1.3.44 ) - Eine Sendung, die gerade aufgenommen wird, hat in den EPG-Menüs nun ein 'R' statt eines 'T'. - Unterstützung des wareagle-icon-patch (kann in der epgsearchmenu.conf mit 'WarEagleIcons=1' aktiviert werden) - Fortschrittsbalken in Jetzt/Nächste 'verschönert' (bei Verwendung der Setup-Option 'graphisch'), angelehnt an Nordlichts-EPG-Plugin - Neue Setup-Option um Radio-Kanäle in den EPG-Menüs zu unterdrücken, vorgeschlagen von Patrice Staudt. - Neues Service-Interface "Epgsearch-searchresults-v1.0", das die Suchergebnisse einer übergebenen Suche zurückliefert, vorgeschlagen von Andreas Brugger - Damit das Setup nicht platzt, wurden einige Optionen entfernt, weil diese mit dem konfigurierbaren Menü nun genauso machbar sind: * "Zeige Fortschrittsbalen in 'Nächste', default ist 'nein' * "Anzeigenbreite für Fortschrittsbalken", default ist 4 * "Zeige kurze Kanalnamen", default ist 'ja' * "Zeige Untertitel in EPG-Menüs', default ist 'ja' - Update der finnischen Übesetzung, Danke an Rolf Ahrenberg - Das Aux-Feld eines Timers wird nun komplett im XML-Stil gefüllt (ab vdr-1.3.44). Deshalb gibt es auch ein Update für die recordingdone.sh im 'scripts'-Unterverzeichnis. Danke an Mike Constabel für den Patch des Skripts. - Das Suchtimer-Update läuft nun immer mit niedriger Priorität, vorgeschlagen von Christian Jacobsen - neues SVDRP-Kommando 'FIND'. Damit kann ein Sendung gesucht werden. Zurückgeliefert wird eine Ergebnisliste bestehend aus 'NEWT'-Zeilen, die somit direkt zum Programmieren des Timers verwendet werden können. Vorgeschlagen ovn Lari Tuononen. fixes: - Danke an Darren Salt für einige Patches im Zusammenhang mit g++ 4.1, Thread safeness und code review - einige Speicherlecks geflickt. - Korrektur für Aufruf von benutzerdef. EPG-Befehlen, Danke an rzndl@vdrportal - Korrektur für blacklist-Suche bei Suchtimern, Danke an Christian Jacobsen - der Episoden-Name eines Timer ist nun max. MAX_SUBTITLE_LENGTH lang, Danke an Mike Constabel - Geschwindigkeit des Suchtimer-Updates etwas verbessert (~15%) 2006-03-05: Version 0.9.14a fixes: - EPG-Befehl 'als bereits aufgezeichnet markieren' hat einen Absturz verursacht, Danke an Mike Constabel für den Hinweis 2006-03-04: Version 0.9.14 neu: - beim Aktivieren/Deaktivieren eines Suchtimers kann man nun angeben, ob die zugehörigen Timer ebenfalls aktiviert/deaktiviert werden sollen. - Neuer EPG-Befehl 'Ausschlussliste anlegen' zum Anlegen einer Ausschlussliste aus einem EPG-Menü. - Die Inhaltsangabe eines Eintrags im Menü 'Erledigte Aufnahmen' hat nun einen zusätzlichen Button 'Zusatzinfo', der den Inhalt des Aux-Feld (in vdr-1.3.44 eingeführt) anzeigt, falls verfügbar. - Update für das Skript recordingdone.sh, funktioniert nun auch mit vdr-1.3.44, Danke an Mike Constabel für die Anpassungen. - Konvertierungsskripts für das Upgrade auf vdr-1.3.44: Aufgrund der geänderten Behandlung der Zusatzinfos in der Inhaltsangabe (summary -> aux) funktionieren einige Suchtimer-Features nicht mit Aufnahmen die vor dem Umstieg auf vdr-1.3.44 gemacht wurden. Das betrifft das done-Feature und das automatische Löschen von Aufnahmen. Wer die Skripts nicht anwendet, hat einfach einige überflüssige Aufnahmen mehr ;-). Muss also nicht unbedingt gemacht werden, aber mit den Skripts läuft alles wie gewohnt. Danke an Mike Constabel, der die Skripts gebaut hat. * neues Skript convert_info_vdr.pl. Dieses konvertiert das Info-File von Aufnahmen und verschiebt die Zusatzinfo von epgsearch in das aux-Feld. * neues Skript convert_epgsearchdone_data.pl. Dieses konvertiert die Datei epgsearchdone.data, indem es einen Aux-Abschnitt hinzufügt. - Update für das Skript mtdone2epgsearchdone.sh, Danke an Christian Jacobsen. - Update der französischen Übersetzung, Danke an Patrice Staudt - Update der finnischen Übersetzung, Danke an Rolf Ahrenberg fixes: - Das done-Feature funktioniert nun auch mit vdr-1.3.44, Danke an Mike Constabel - fix für hohe CPU-Last durch Suchtimer-Thread im 30sek-Abstand, Danke an sledgehammer@vdrportal - Das automatische Verlinken des Tarballs wurde wieder entfernt, gewünscht von Distri-Maintainern - einige Compiler-Warnings gefixed bei Verwendung von -Wformat=2, Danke an Darren Salt für den Hinweis und einen Patch 2006-02-28: Version 0.9.13 neu: - Unterstützung für vdr-1.3.44: funktioniert nun, aber: wegen der Änderung summary -> aux in vdr-1.3.44 sind die Zusatzinfo über den Suchtimer, der den Timer/die Aufnahme erzeugt hat, im Moment nicht mehr verfügbar. Diese werden jetzt im neuen Aux-Feld des Timers/der Aufnahme gespeichert. - Ausschlusslisten: man kann nun eine oder mehrere Ausschlusslisten anlegen und diese innerhalb einer Suche oder eines Suchtimers auswählen. Eine Ausschlussliste arbeitet wie eine normale Suche und legt die Sendungen fest, die in einer Suche oder einem Suchtimer ignoriert werden sollen. Ausschlusslisten können im Setup oder in der neuen Such-Aktion 'Ausschlusslisten anzeigen' sowie direkt beim Editieren einer Suche verwaltet werden. In der Suche selbst können eine, mehrere oder alle Ausschlusslisten ausgewählt werden. Falls ein Suchergebnis auch in einer der gewählten Ausschlusslisten enthalten ist, wird es ignoriert. - Der Hintergrund-Thread für die Umschalttimer läuft jetzt nur noch, wenn auch ein Umschalttimer aktiv ist. - Beim entpacken des tar-Files wird der Link zu epgsearch-x.x.x nun automatisch erzeugt (wie bei text2skin) - Die Ergebnisliste bei "Wiederholungen anzeigen" zeigt nun nicht mehr auch die laufende Sendung an, Vorschlag von Ronny Kornexl - Danke fürs Betatesten an Mike Constabel - Danke fürs Update der finnischen Übersetzung an Rolf Ahrenberg fixes: - die Setup-Option 'Untertitel in manuellen Timern' wurde nicht gespeichert. 2006-02-12: Version 0.9.12 neu: - Neues Feature 'Pause, wenn ... Aufnahmen exist." für Suchtimer. Sobald die angegebene Anzahl (>0) von Aufnahmen existiert, erzeugt epgsearch keine weiteren Timer mehr für diesen Suchtimer. Erst wenn eine oder mehrere Auf- nahmen gelöscht wurden, werden erneut Timer angelegt. fixes: - Absturz beim Navigieren zu einem Kanal ohne EPG im Programme-Menü behoben 2006-02-08: Version 0.9.11a fixes: - hohe CPU-Last im 5 Sekunden-Takt beseitigt 2006-02-07: Version 0.9.11 neu: - Unterstützung von vdr-1.3.42 - Neues Feature 'Umschalttimer': mit dem neuen EPG-Befehl 'In/Aus Umschalt- liste' kann eine Sendung in eine Umschaltliste aufgenommen werden. VDR schaltet dann kurz (einstellbar) vor Beginn zu dieser Sendung um. Der Inhalt der Umschaltliste kann über 'Suche/Aktionen/Umschaltliste anzeigen' kontrolliert und geändert werden. Falls eine Sendung in der Umschaltliste ist, wird Sie in den Menüs mit einem 'S' markiert (falls kein echter Timer dafür existiert). - Umschalttimer auch für Suchtimer: Ein Suchtimer kann ebenfalls als Umschalt- timer verwendet werden (Aktion: nur umschalten). Sobald Suchergenisse vorliegen werden diese in die Umschaltliste aufgenommen. Es wird kein echter Timer erzeugt. - Suchkriterium 'Verwende Kanal' hat nun einen weiteren Wert 'nur FTA', um die Suche auf alle nicht verschlüsselten Programme einzuschränken. - Neue Setup-Option 'Zeige Tagesseparatoren', zur Anzeige von Trennlinien zwischen den Tagen im Menu Programm - epgsearch hat jetzt ein SVDRP-Interface mit folgenden Befehlen (ab vdr > 1.3.30): * 'LSTS [ID]' zeigt alle Suchen an, oder nur diejenige mit der angegebenen ID (Format ist dasgleiche wie in epgsearch.conf, s. MANUAL) * 'NEWS ' zum Anlegen einer neuen Suche Anmerkung: der Wert ID wird ignoriert und von epgsearch automatisch vergeben. * 'DELS ' zum Löschen einer Suche mit der angegebenen ID * 'EDIS ' zum Ändern einer Suche * 'UPDS [OSD]' zum Starten eines Suchtimer-Updates. Wird der optionale Parameter 'OSD' angegeben, informiert das OSD, wann das Update beendet ist. * 'UPDD' zum Nachladen der epgsearchdone.data in den Speicher, z.B. nach einer Änderung durch ein externes Tool * 'SETS ' zum Ein-/Ausschalten der Suchtimersuche im Hintergrund - weil das Setup allmählich zu groß wird, gibt es dort jetzt die Modi "Standard" und "Erweitert" (umschaltbar über Taste rot), vorgeschlagen von Rolf Ahrenberg - Update der finnischen Übersetzung, Danke an Rolf Ahrenberg - Update der italienischen Übersetzung, Danke an Reelbox User - Update der französischen Übersetzung, Danke an Patrice Staudt - Neue holländische Übersetzung, Danke an Reelbox User - Verwendung von '127.0.0.1' anstatt der Auflösung von 'localhost' für SVDRP, vorgeschlagen von Thiemo Gehrke - neues Skript recordingdone.sh für die reccmds.conf, um eine Aufnahme als erlegigt zu kennzeichnen (für epgsearch's done-Feature), Danke an Patrice Staudt, Christian Jacobsen und Mike Constabel - neues Skript mtdone2epgsearchdone.sh zur Übernahme von erledigten Aufnahmen von mastertimer in epgsearch's done-Datei, Danke an Christian Jacobsen. - Danke an Mike Constabel und Andreas Brugger fürs Testen und die Bug Reports fixes: - Fehler bei der Verwendung von Vorlagen behoben, Danke an Christian Jacobsen 2006-01-15: Version 0.9.10 neu: - Aktualisierung aller Programm- und Suchergebnismenüs nach dem Anlegen oder Ändern eines Timers, wie in vdr-1.3.38 eingeführt - Die Taste 'Aufnehmen' wird jetzt mit 'Aufnehmen' oder 'Timer' beschriftet, abhängig davon, ob für die Sendung ein Timer existiert, wie in vdr-1.3.38 eingeführt - Im Timer-Edit-Menu von epgsearch (Setup-Einstellung beachten!) wird nun bei einer laufenden Aufnahme angezeigt, über welche Karte der Timer aufnimmt - Neue Setup-Option: 'Untertitel in manuellen Timern' Betrifft das autom. Ergänzen des Untertitels bei einem manuell angelegten Timer. Die Einstellung 'intelligent' verwirft den Untertitel, falls die Sendung länger als 80min ist. Ist noch nicht sooo intelligent ;-) - Das Menü zum Editieren der Suche wurde für zukünftige Erweiterungen geändert: 'Aktion' bestimmt nun, was mit den Suchergebnissen gemacht werden soll, im Moment gibts 'Aufnehmen' als Standard und 'Nur Ankündigen' - Danke an Rolf Ahrenberg für das Update der finnischen Übersetzung fixes: - in vdr-1.3.38 waren einige Übersetzungen defekt - timercmds-patches für vdr-1.3.38 aktualisiert 2006-01-08: Version 0.9.9 neu: - Unterstützung für vdr-1.3.38 - Suchvorlagen: da die Einstellungen zu einer Suche oft die gleichen sind, gibt es nun Vorlagen, die beim Anlegen/Ändern einer Suche mit der Taste 'Blau' verwendet werden können. Eine Vorlage kann auch als "Standard" definiert werden, wodurch deren Einträge beim Anlegen einer Suche auto- matisch übernommen werden. - Setup um 'Suchvorlagen' erweitert (zur Verwaltung der Vorlagen) - Neue Aktion 'Als Vorlage verwenden', um eine Suche in die Vorlagen zu kopieren - Neue Setup-Option, um die Anzeige der Untertitel in der Übersicht zu steuern, danke an Darren Salt für den Patch - Erweiterung des Features 'Aufnahmen nach ... Tagen löschen' um 'Erhalte ... Aufnahmen'. Dadurch werden die letzten x Aufnahmen immer erhalten, auch wenn diese bereits das Zeitlimit überschritten haben. fixes: - Das Feature 'Aufnahmen nach ... Tagen löschen' hat auch editierte/ge- schnittene Aufnahmen gelöscht. Behoben. 2005-11-27: Version 0.9.8 neu: ACHTUNG!: diese Version konvertiert die epgsearch.conf (die Datei, in der die Sucheinträge gespeichert werden) in ein NEUES FORMAT. Es wird ein Backup der alten Datei unter epgsearch.conf.bak angelegt.Geht man also auf eine alte Version zurück, muss das Backup nach epgsearch.conf zurückkopiert werden. - Neues Feature 'Wiederholungen vermeiden' (aka done-Feature) für Suchtimer (bitte die README.DE vor dem ersten Gebrauch lesen!). Ein besonderer Dank an Mike Constable (vejoun@vdrportal) für viele viele Test-Stunden und Bug- Reports. * Vorschau von geplanten Timern * Erkennung unvollständiger Aufnahmen * Fuzzy-Vergleich von Sendungen - Das Menü der Suchergebnisse hat bei Suchtimern mit 'Wiederh. vermeiden' nun eine zusätzliche Belegung für die Taste 'Blau', um sich die geplanten Timer anzeigen zu lassen, die mit dem nächsten Suchtimer-Update programmiert werden. - Neue Setup-Option zur Anzeige von Sendern ohne EPG in 'Was läuft jetzt?', Idee von 'Nordlicht's EPG plugin' übernommen - Neue Setup-Option 'Zeige Kanal-Separatoren' in 'Was läuft jetzt?' Idee von 'Nordlicht's EPG plugin' übernommen - Neues Suchtimer-Feature 'Lösche Aufnahmen nach ... Tagen'. Damit werden Auf- nahmen nach den eingestellen Tagen automatisch gelöscht. Praktisch z.B. für Nachrichtensendungen wie Tagesschau, die nur für einige Tage interessieren. - Die Inhaltsangabe von Timern (über ok im Timermenu), die epgsearch erzeugt hat, enthalten nun zusätzliche Infos: Titel und Untertitel (falls vorhanden) am Anfang, sowie Name und ID des Suchtimers und den Sender am Ende - Die Inhaltsangabe von manuell programmierten Timern enthält nun: Titel und Untertitel (falls vorhanden) am Anfang, sowie Sender am Ende - 'Ausführen' im Suchmenu wurde ersetzt durch 'Aktionen' und listet: * Suche ausführen (wie zuvor auch mit ok) * 'Als Suchtimer verwenden' an/aus * Suchtimer-Update ausführen * Erledigte Aufnahmen anzeigen Es können natürlich genauso die Tasten als Abkürzung verwendet werden, ohne das Menu aufzurufen. '0' ruft das Menü auf. - Einführung eines Logfiles (Standard ist plugin-configdir/epgsearch.log, kann aber über den Startparameter '-l /path/to/logfile' geändert werden. Der Para- meter '-v n' bestimmt das Log-Level. n=0 bedeutet kein Logging (default), 1 (eingeschränktes Logging),2(detailliert),3(umfangreich). - Im Setup gibts nun ein Standard-Aufnahmeverzeichnis, das beim manuellen Pro- grammieren von Timern vorgegeben wird. Unterstützt werden auch Einträge der Form '%Category%~%Genre%'. - abhängig vom aufrufenden Menu sind nun die Tasten 'Grün/Geld' im Event-Menu (also der Inhaltsangabe) nun mit dem vorh./nächsten Sender bzw. der vorh./ nächsten Startzeit beschriftet, danke an Andreas Brugger (brougs78@vdrportal) - Sendernummern werden nun auch im Menü Suchergebnisse gelistet, falls die Option im Setup geschaltet ist, danke an Gerhard Steiner (gestein@vdrportal). - Kurztasten (1,2,...) für EPG-Befehle sind nun auch im Menu der Inhaltsangabe verfügbar, danke an Frank Krömmelbein (frank99@vdrportal) - Ab VDR version >= 1.3.31 kann im Setup nun eingestellt werden, ob man für die manuelle Timerprogrammierung das Timer-Editmenü von epgsearch oder von VDR ver- wenden will.(evtl. sinnvoll, wenn man einen gepatchten VDR benutzt). Danke an Frank Krömmelbein (frank99@vdrportal) - Falls ein Untertitel existiert wird er beim manuellen Timer-Programmieren nun automatisch ans Verzeichnis angehängt. Danke an Gerhard Steiner (gestein@vdrportal) - Aufteilung von Verzeichnis und File beim erneuten Bearbeiten von Timern opti- miert, Danke Andreas Brugger (brougs78@vdrportal) - In den Hauptmenus werden Untertitel nun immer angezeigt, in der Form 'Titel ~ Untertitel', falls vorhanden - Neue service-Funktion 'Epgsearch-updatesearchtimers-v1.0' zum Aufruf eines Suchtimer-Updates - Falls ein Suchtimer-Update über das Aktionenmenu aufgerufen wird, gibt es nun im OSD eine Nachricht, sobald das Update fertig ist. (Ebenso bei Verwendung von des Services 'Epgsearch-updatesearchtimers-v1.0' - Das Such-Menü zeigt nun die Anzahl der (aktiven) Suchen im Titel an - Danke an Rolf Ahrenberg für die Aktualisierung der finnischen Übersetzung. - Danke an Mike Constabel für die Überarbeitung der READMEs und des MANUALs. fixes: - epgsearch springt nun zum Hauptmenu zurück, falls es nicht über eine Kurztaste aufgerufen wurde. Danke an Andreas Brugger (brougs78@vdrportal) - Eingabe von Suchbegriffen bei englischem OSD korrigiert - Sortierung von Suchtimern nach dem Editieren einer Suche korrigiert, Danke an Mike Constabel (vejoun@vdrportal) - Menü-Navigation bei leerem EPG korrigiert, Danke an Darren Salt für den Patch - Falsche optische Ausrichtung von Sucheinträgen im Suchmenü korrigiert, Danke an Andreas Brugger (brougs78@vdrportal) 2005-09-04: Version 0.9.7 neu: - Änderungen in der Beschreibung einer Sendung bewirken jetzt auch ein Update eines Timers fixes: - bei der Verwendung von reg. Ausdrücken in Suchtimern gab es ein böses Speicherleck, Danke an TomG@vdrportal - Kanalanzeige in den Farbtasten funktionierte nicht wenn es Kanaltrenner gab. Danke an viking@vdrportal 2005-08-27: Version 0.9.6 neu: - Suchkriterium 'Verw. Kanal' um 'Kanalgruppen' erweitert. Diese Kanalgruppen können über ein eigenes Menu verwaltet werden (im Suchtimer oder im Setup) und erlauben eine flexiblere Kanalauswahl für Suchtimer als bisher. (s. Screenshot) - epgsearch stellt das erweiterte Timer-Editmenu und die Suche im EPG jetzt als 'Service' anderen Plugins zur Verfügung (ab 1.3.30 oder mit Udo Richters backport, s. MANUAL oder mail an mich, falls jemand Interesse hat) - Beim Programmieren eines Timers (manuell oder per Suchtimer) wird nun die Inhaltsangabe an den Timer übergeben (damit kann im VDR-Timermenu mit 'ok' die Inhaltsangabe angezeigt werden), Danke an TomG - Nach dem Umschalten der Farbtasten mit '0' im Menu 'Programm' kann mit den Farbtasten Grün/Gelb zum Programm des vorherigen/nächsten Senders gewechselt werden (s. Farbtasten im Screenshot) - patch von Uwe/egal hinzugefügt, der es erlaubt, das VDR-Programmmenu durch epgsearch zu ersetzen. Danke an Uwe auch für die Anpassungen in epgsearch (Nach dem Patchen von VDR muss der patch noch im epgsearch-Setup aktiviert werden!) - Nach dem Anlegen einer neuen Suche wird diese jetzt im Suchmenu korrekt einsortiert, Danke an Mike Constabel - Gerhard Steiner's timercmd patch für vdr >= 1.3.25 hinzugefügt - ein 'back' im Anfangsmenu schließt nun immer das OSD (sollte Probleme mit dem submenu-Patch lösen) - Events ohne Titel (ja, sowas gibts) werden in der Suche nun immer ignoriert, Danke an Mike Constabel - neue EPG-Variable '%channel%', die im Verzeichnis-Eintrag verwendet werden kann und durch den Sendernamen ersetzt wird - Anfangs- und Endpuffer einer Aufnhame dürfen jetzt auch negativ sein (das erlaubt ein absichtliches Abschneiden einer Sendung am Anfang oder Ende), Danke an Mike Constabel - Groß-/Kleinschreibung wird nun in erweiterten EPG-Kategorien ignoriert - Finnische Übersetzung aktualisiert, Danke an Rolf Ahrenberg fixes: - Beim Laden von '.epgsearchrc' wird jetzt auch ein evtl. angegebener Config-Pfad (-c) berücksichtigt, Danke an Ronny Kornexl - Programmierung von Suchtimern mit leerem Verzeichnis oder Namen korrigiert, Danke an Andreas Brugger - Programmierung von Suchtimern korrigiert, bei denen Mitternacht zwischen Start und Ende liegt - Menu Verzeichnisauswahl machte Probleme, wenn keine Verzeichnisse existierten, Danke an harvey@vdrportal - (De)Aktivieren von Suchtimern mit '0' speichert nun sofort, Danke an Mike Constabel - Menu Navigation (Grüm-Gelb-Gelb-Grün) zeigt nun korrekterweise 'Was läuft jetzt' und nicht mehr Inhaltsangabe, Danke an Mike Constabel vdr-plugin-epgsearch/recdone.h0000644000175000017500000000523113145412721016221 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #ifndef __RECDONE_H #define __RECDONE_H #include #include #include #include "epgsearchext.h" class cSearchExt; // --- cRecDone -------------------------------------------------------- class cRecDone : public cListObject { public: char *title; // Title of this event char *shortText; // Short description of this event char *description; // Description of this event char *aux; // Aux info time_t startTime; // Start time of the timer int duration; int searchID; // ID of the search, that triggered this recording tChannelID channelID; char* rawdescription; static char *buffer; cRecDone(); cRecDone(const cTimer*, const cEvent* event, cSearchExt* search); ~cRecDone(); static bool Read(FILE *f); bool Parse(char *s); const char *ToText(void); bool Save(FILE *f); int ChannelNr(); }; class cRecsDone : public cList, public cMutex { private: char *fileName; public: void Clear(void) { free(fileName); fileName = NULL; cList::Clear(); } cRecsDone(void) { fileName = NULL; } int GetCountRecordings(const cEvent* event, cSearchExt* search, cRecDone** first = NULL, int matchLimit = 90); int GetCountRecordings(const cEvent*, bool compareTitle, int compareSubtitle, bool compareSummary, int compareDate, unsigned long, cRecDone** first = NULL, int matchLimit = 90); int GetTotalCountRecordings(cSearchExt* search, cRecDone** first); void RemoveSearchID(int ID); bool Load(const char *FileName = NULL); bool Save(void); }; extern cRecsDone RecsDone; #endif vdr-plugin-epgsearch/md5.h0000644000175000017500000001060713145412721015272 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ ///////////////////////////////////////////////////////////////////////// // MD5.cpp // Implementation file for MD5 class // // This C++ Class implementation of the original RSA Data Security, Inc. // MD5 Message-Digest Algorithm is copyright (c) 2002, Gary McNickle. // All rights reserved. This software is a derivative of the "RSA Data // Security, Inc. MD5 Message-Digest Algorithm" // // You may use this software free of any charge, but without any // warranty or implied warranty, provided that you follow the terms // of the original RSA copyright, listed below. // // Original RSA Data Security, Inc. Copyright notice ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All // rights reserved. // // License to copy and use this software is granted provided that it // is identified as the "RSA Data Security, Inc. MD5 Message-Digest // Algorithm" in all material mentioning or referencing this software // or this function. // License is also granted to make and use derivative works provided // that such works are identified as "derived from the RSA Data // Security, Inc. MD5 Message-Digest Algorithm" in all material // mentioning or referencing the derived work. // RSA Data Security, Inc. makes no representations concerning either // the merchantability of this software or the suitability of this // software for any particular purpose. It is provided "as is" // without express or implied warranty of any kind. // These notices must be retained in any copies of any part of this // documentation and/or software. ///////////////////////////////////////////////////////////////////////// typedef unsigned int uint4; typedef unsigned short int uint2; typedef unsigned char uchar; char* PrintMD5(uchar md5Digest[16]); char* MD5String(char* szString); class md5 { // Methods public: md5() { Init(); m_Buffer[0]=0; m_Digest[0]=0; m_Finalized=0; } void Init(); void Update(uchar* chInput, uint4 nInputLen); void Finalize(); uchar* Digest() { return m_Digest; } private: void Transform(uchar* block); void Encode(uchar* dest, uint4* src, uint4 nLength); void Decode(uint4* dest, uchar* src, uint4 nLength); inline uint4 rotate_left(uint4 x, uint4 n) { return ((x << n) | (x >> (32-n))); } inline uint4 F(uint4 x, uint4 y, uint4 z) { return ((x & y) | (~x & z)); } inline uint4 G(uint4 x, uint4 y, uint4 z) { return ((x & z) | (y & ~z)); } inline uint4 H(uint4 x, uint4 y, uint4 z) { return (x ^ y ^ z); } inline uint4 I(uint4 x, uint4 y, uint4 z) { return (y ^ (x | ~z)); } inline void FF(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) { a += F(b, c, d) + x + ac; a = rotate_left(a, s); a += b; } inline void GG(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) { a += G(b, c, d) + x + ac; a = rotate_left(a, s); a += b; } inline void HH(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) { a += H(b, c, d) + x + ac; a = rotate_left(a, s); a += b; } inline void II(uint4& a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) { a += I(b, c, d) + x + ac; a = rotate_left(a, s); a += b; } // Data private: uint4 m_State[4]; uint4 m_Count[2]; uchar m_Buffer[64]; uchar m_Digest[16]; uchar m_Finalized; }; vdr-plugin-epgsearch/menu_quicksearch.h0000644000175000017500000000256413145412721020136 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #ifndef __MENU_QUICKSEARCH_H #define __MENU_QUICKSEARCH_H #include "menu_searchedit.h" #include "epgsearchtools.h" // --- cMenuQuickSearch -------------------------------------------------------- class cMenuQuickSearch : public cMenuEditSearchExt { int editmode; virtual void Set(); public: cMenuQuickSearch(cSearchExt*); virtual eOSState ProcessKey(eKeys Key); }; #endif vdr-plugin-epgsearch/changrp.c0000644000175000017500000003301213145412721016215 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #include "changrp.h" #include "epgsearchtools.h" #include "epgsearchcfg.h" #include "epgsearchext.h" #include // -- cChannelGroup ----------------------------------------------------------------- cChannelGroup::cChannelGroup(void) { strcpy(name, ""); channels.Clear(); } cChannelGroup::~cChannelGroup(void) { channels.Clear(); } bool cChannelGroup::Parse(const char *s) { char *line; char *pos; char *pos_next; int parameter = 1; int valuelen; #define MAXVALUELEN (10 * MaxFileName) char value[MAXVALUELEN]; pos = line = strdup(s); pos_next = pos + strlen(pos); if (*pos_next == '\n') *pos_next = 0; while (*pos) { while (*pos == ' ') pos++; if (*pos) { if (*pos != '|') { pos_next = strchr(pos, '|'); if (!pos_next) pos_next = pos + strlen(pos); valuelen = pos_next - pos + 1; if (valuelen > MAXVALUELEN) { LogFile.eSysLog("entry '%s' is too long. Will be truncated!", pos); valuelen = MAXVALUELEN; } strn0cpy(value, pos, valuelen); pos = pos_next; switch (parameter) { case 1: strcpy(name,value); break; default: { #ifdef __FreeBSD__ char *channelbuffer = MALLOC(char, 32); int numChannels = sscanf(value, "%31[^|]", channelbuffer); #else char *channelbuffer = NULL; int numChannels = sscanf(value, "%m[^|]", &channelbuffer); #endif if (numChannels == 1) { LOCK_CHANNELS_READ; const cChannel* channel = Channels->GetByChannelID(tChannelID::FromString(channelbuffer), true, true); if (channel) { cChannelGroupItem* channelitem = new cChannelGroupItem(channel); channels.Add(channelitem); } } free(channelbuffer); } break; } //switch } parameter++; } if (*pos) pos++; } //while free(line); return (parameter >= 1) ? true : false; } const char *cChannelGroup::ToText(void) { char* channelbuffer = NULL; cChannelGroupItem* ChannelGroupItem = channels.First(); int index = 0; while (ChannelGroupItem) { const cChannel* channel = ChannelGroupItem->channel; if (index++ == 0) channelbuffer = strdup(CHANNELSTRING(channel)); else { char* temp = channelbuffer; msprintf(&channelbuffer, "%s|%s", channelbuffer, CHANNELSTRING(channel)); free(temp); } ChannelGroupItem = channels.Next(ChannelGroupItem); } char* buffer = NULL; msprintf(&buffer, "%s|%s", name, channelbuffer); free(channelbuffer); return buffer; } int* cChannelGroup::CreateChannelSel() { LOCK_CHANNELS_READ; int* channelSel = (int*) malloc(Channels->Count() * sizeof(int)); const cChannel* channel = Channels->First(); int index = 0; while (channel) { if (channel->GroupSep()) { channel = Channels->Next(channel); continue; } channelSel[index] = 0; cChannelGroupItem* channelInGroup = channels.First(); while (channelInGroup) { if (channel == channelInGroup->channel) { channelSel[index] = 1; break; } channelInGroup = channels.Next(channelInGroup); } index++; channel = Channels->Next(channel); } return channelSel; } void cChannelGroup::CreateChannelList(int* channelSel) { channels.Clear(); LOCK_CHANNELS_READ; const cChannel* channel = Channels->First(); int index = 0; while (channel) { if (!channel->GroupSep()) { if (channelSel[index] == 1) channels.Add(new cChannelGroupItem(channel)); index++; } channel = Channels->Next(channel); } } bool cChannelGroup::Save(FILE *f) { return fprintf(f, "%s\n", ToText()) > 0; } bool cChannelGroup::ChannelInGroup(const cChannel* channel) { cChannelGroupItem* channelInGroup = channels.First(); while (channelInGroup) { if (channel == channelInGroup->channel) return true; channelInGroup = channels.Next(channelInGroup); } return false; } // -- cChannelGroups ----------------------------------------------------------------- int cChannelGroups::GetIndex(char* channelGroup) { if (!channelGroup) return -1; cChannelGroup* ChannelGroup = First(); int index = 0; while (ChannelGroup) { if (strcmp(channelGroup, ChannelGroup->name) == 0) return index; index++; ChannelGroup = Next(ChannelGroup); } return -1; } cChannelGroup* cChannelGroups::GetGroupByName(const char* channelGroup) { if (!channelGroup) return NULL; cChannelGroup* ChannelGroup = First(); while (ChannelGroup) { if (strcmp(channelGroup, ChannelGroup->name) == 0) return ChannelGroup; ChannelGroup = Next(ChannelGroup); } return NULL; } cSearchExt* cChannelGroups::Used(cChannelGroup* group) { if (!group) return NULL; if (SearchExts.Count() == 0) SearchExts.Load(AddDirectory(CONFIGDIR, "epgsearch.conf")); cMutexLock SearchExtsLock(&SearchExts); cSearchExt *SearchExt = SearchExts.First(); while (SearchExt) { if (SearchExt->useChannel == 2 && strcmp(SearchExt->channelGroup, group->name) == 0) return SearchExt; SearchExt = SearchExts.Next(SearchExt); } return NULL; } char** cChannelGroups::CreateMenuitemsList() { char** menuitemsChGr = new char*[ChannelGroups.Count()+1]; cChannelGroup* ChannelGroup = First(); menuitemsChGr[0] = strdup(""); int index = 1; while (ChannelGroup) { menuitemsChGr[index++] = ChannelGroup->name; ChannelGroup = Next(ChannelGroup); } return menuitemsChGr; } // -- cMenuChannelGroupItem ----------------------------------------------------------------- cMenuChannelGroupItem::cMenuChannelGroupItem(cChannelGroup* Group) { group = Group; Set(); } void cMenuChannelGroupItem::Set(void) { cString channelbuffer; cChannelGroupItem* channelInGroup = group->channels.First(); int channelNr, chIntBegin = -1, chIntEnd = -1, chLast = -1; while (channelInGroup) { channelNr = channelInGroup->channel->Number(); if (chIntBegin == -1) chIntBegin = channelNr; if (chIntEnd == -1) chIntEnd = channelNr; if (chLast == channelNr-1) chIntEnd = channelNr; else { chIntEnd = chLast; if(chIntBegin == chIntEnd) channelbuffer = cString::sprintf("%s %d", *channelbuffer?*channelbuffer:"", chIntBegin); else if (chIntEnd != -1) channelbuffer = cString::sprintf("%s %d-%d", *channelbuffer?*channelbuffer:"", chIntBegin, chIntEnd); chIntBegin = chIntEnd = channelNr; } chLast = channelNr; channelInGroup = group->channels.Next(channelInGroup); if (!channelInGroup) { if(chLast == chIntBegin) channelbuffer = cString::sprintf("%s %d", *channelbuffer?*channelbuffer:"", chIntBegin); else channelbuffer = cString::sprintf("%s %d-%d", *channelbuffer?*channelbuffer:"", chIntBegin, chLast); } } SetText(cString::sprintf("%s\t%s", group->name, *channelbuffer?*channelbuffer:"")); } // --- cMenuChannelGroups ---------------------------------------------------------- cMenuChannelGroups::cMenuChannelGroups(char** GroupName) :cOsdMenu(tr("Channel groups"),20) { SetMenuCategory(mcSetupPlugins); groupSel = -1; groupName = GroupName; if (groupName && *groupName) groupSel = ChannelGroups.GetIndex(*groupName); cChannelGroup* ChannelGroup = ChannelGroups.First(); int index = 0; while (ChannelGroup) { Add(new cMenuChannelGroupItem(ChannelGroup), (index == groupSel?true:false)); ChannelGroup = ChannelGroups.Next(ChannelGroup); index++; } if (groupName && *groupName) SetHelp(trVDR("Button$Edit"), trVDR("Button$New"), trVDR("Button$Delete"), tr("Button$Select")); else SetHelp(trVDR("Button$Edit"), trVDR("Button$New"), trVDR("Button$Delete"), NULL); Sort(); Display(); } cChannelGroup *cMenuChannelGroups::CurrentGroup(void) { cMenuChannelGroupItem *item = (cMenuChannelGroupItem *)Get(Current()); return item ? item->group : NULL; } eOSState cMenuChannelGroups::New(void) { if (HasSubMenu()) return osContinue; return AddSubMenu(new cMenuEditChannelGroup(new cChannelGroup, true)); } eOSState cMenuChannelGroups::Delete(void) { cChannelGroup *curGroup = CurrentGroup(); if (curGroup) { cSearchExt* search = ChannelGroups.Used(curGroup); if (search) { cString Message = cString::sprintf("%s %s", tr("Channel group used by:"), search->search); INFO(Message); return osContinue; } if (Interface->Confirm(tr("Edit$Delete group?"))) { ChannelGroups.Del(curGroup); ChannelGroups.Save(); cOsdMenu::Del(Current()); Display(); } } return osContinue; } eOSState cMenuChannelGroups::ProcessKey(eKeys Key) { int GroupNumber = HasSubMenu() ? Count() : -1; eOSState state = cOsdMenu::ProcessKey(Key); if (state == osUnknown) { if (HasSubMenu()) return osContinue; switch (Key) { case kRed: if (CurrentGroup()) state = AddSubMenu(new cMenuEditChannelGroup(CurrentGroup())); else state = osContinue; break; case kGreen: state = New(); break; case kYellow: state = Delete(); break; case kOk: case kBlue: if (groupName && *groupName) { free(*groupName); *groupName = strdup(CurrentGroup()->name); return osBack; } default: break; } } if (GroupNumber >= 0 && !HasSubMenu() && ChannelGroups.Get(GroupNumber)) { // a newly created group was confirmed with Ok cChannelGroup* group = ChannelGroups.Get(GroupNumber); Add(new cMenuChannelGroupItem(group), true); Display(); } return state; } // --- cMenuEditChannelGroup -------------------------------------------------------- cMenuEditChannelGroup::cMenuEditChannelGroup(cChannelGroup *Group, bool New) :cOsdMenu(tr("Edit channel group"),30) { SetMenuCategory(mcSetupPlugins); group = Group; channelSel = group->CreateChannelSel(); strcpy(name, group->name); addIfConfirmed = New; if (group) Set(); } cMenuEditChannelGroup::~cMenuEditChannelGroup() { free(channelSel); } void cMenuEditChannelGroup::Set() { int current = Current(); Clear(); Add(new cMenuEditStrItem( tr("Group name"), name, sizeof(group->name), trVDR(FileNameChars))); LOCK_CHANNELS_READ; // TODO THIS MAY LOCK Channels A LONG TIME! const cChannel* channel = Channels->First(); int index = 0; while (channel) { if (channel->GroupSep()) { channel = Channels->Next(channel); continue; } Add(new cMenuEditBoolItem( CHANNELNAME(channel), &channelSel[index++], trVDR("no"), trVDR("yes"))); channel = Channels->Next(channel); } SetCurrent(Get(current)); } eOSState cMenuEditChannelGroup::ProcessKey(eKeys Key) { eOSState state = cOsdMenu::ProcessKey(Key); const char* ItemText = Get(Current())->Text(); if (strlen(ItemText) > 0 && strstr(ItemText, tr("Group name")) != ItemText) SetHelp(tr("Button$Invert selection"), tr("Button$All yes"), tr("Button$All no"), NULL); else if (!InEditMode(ItemText, tr("Group name"), name)) SetHelp(NULL, NULL, NULL, NULL); if (state == osUnknown) { switch (Key) { case kOk: if (strlen(name) == 0) { ERROR(tr("Group name is empty!")); return osContinue; } if (addIfConfirmed && ChannelGroups.GetGroupByName(name)) { ERROR(tr("Group name already exists!")); return osContinue; } { bool saveSearchExts = false; if (strcmp(group->name, name) != 0 && !addIfConfirmed) // if group name changed, update searches { cMutexLock SearchExtsLock(&SearchExts); cSearchExt *SearchExt = SearchExts.First(); while (SearchExt) { if (SearchExt->useChannel == 2 && SearchExt->channelGroup && strcmp(SearchExt->channelGroup, group->name) == 0) { free(SearchExt->channelGroup); SearchExt->channelGroup = strdup(name); } SearchExt = SearchExts.Next(SearchExt); } saveSearchExts = true; // save them after groups are saved! } strcpy(group->name, name); group->CreateChannelList(channelSel); if (addIfConfirmed) ChannelGroups.Add(group); ChannelGroups.Save(); if (saveSearchExts) SearchExts.Save(); } addIfConfirmed = false; return osBack; break; case kRed: case kGreen: case kYellow: { LOCK_CHANNELS_READ; const cChannel* channel = Channels->First(); int index = 0; while (channel) { if (channel->GroupSep()) { channel = Channels->Next(channel); continue; } channelSel[index] = (Key == kGreen?1:(Key == kRed?1-channelSel[index]:0)); index++; channel = Channels->Next(channel); } Set(); Display(); return osContinue; } default: break; } } return state; } vdr-plugin-epgsearch/conf/0000755000175000017500000000000013145412721015355 5ustar tobiastobiasvdr-plugin-epgsearch/conf/epgsearchmenu.conf0000644000175000017500000000303313145412721021051 0ustar tobiastobias######################################################### # sample file for epgsearchmenu.conf # # The following variables exist: # # %time% - start time in format HH:MM # %date% - start date in format TT.MM.YY # %datesh% - start date in format TT.MM. # %time_w% - weekday name # %time_d% - start day in format TT # %title% - title # %subtitle% - subtitle # %t_status% - timer status ('T', 't', 'R') # %v_status% - VPS status # %r_status% - running status # %status% - complete status, the same as # '%t_status%%v_status%%r_status%' # %colon% - the sign ':' # %% - a value from the extended EPG categories, specified in # epgsearchcats.conf, like %genre% or %category% # # for the 'Whats on...' menus there is also: # # %chnr% - channel number # %chsh% - the short channel name # %chlng% - the 'normal' channel name # %progr% - graphical progress bar # %progrT2S% - progress bar in text2skin style # ######################################################### MenuWhatsOnNow= %chnr%:4|%progrt2s%:5| %time% %t_status%:8|%category%:6| %title% ~ %subtitle%:35 MenuWhatsOnNext=%chnr%:4|%time% %t_status%:8|%category%:8| %title% ~ %subtitle%:35 MenuWhatsOnElse=%chnr%:4|%time% %t_status%:8|%category%:8| %title% ~ %subtitle%:35 MenuSchedule=%time% %t_status%:8|%genre%:14| %title% ~ %subtitle%:35 MenuSearchResults=%chsh%:12|%datesh%:6|%time%:6|%t_status%:2|%title% ~ %subtitle%:35 # WarEagleIcons=1 vdr-plugin-epgsearch/conf/epgsearchupdmail.templ0000644000175000017500000001017713145412721021743 0ustar tobiastobias######################################################################### # This is a sample template for email notifications about timer changes # and/or events announcements # (NOTE: This is a sample for a text mail, but you could use HTML as well) # # There are 3 sections that have to be defined: # - "subject" to be used as mail subject # - "mailbody" the body of the mail: # put %update.newtimers% in the place where the list of new timers should # appear. The same for %update.modtimers%, %update.deltimers% and # %update.newevents& for the list of changed or deleted timers and event # announcements. # - "timer" the description of one timer and "event" with the description of # one event. This section is used to display one timer within a timer list, # e.g. in %update.newtimers%. The same for "event". # # All sections are optional, e.g. if you don't use event announcements you # can drop "%update.newevents%" in the mailbody and the "event" section. But # of course you should have at least a mailbody ;-) # # close each section with the correspondig end tag! # Please have a look at the MANUAL for the available variables. ######################################################################### ######################################################################### # here's the mail's subject definition (no CR!) ######################################################################### [epgsearch] update info: %update.countnewtimers% new / %update.countmodtimers% modified / %update.countdeltimers% deleted timers / %update.countnewevents% new events ######################################################################### # here's the mail's body definition ######################################################################### information about search timer update ---------------------------------------------------------------------- update at: %datenow% %timenow% new timers: %update.countnewtimers% modified timers: %update.countmodtimers% deleted timers: %update.countdeltimers% new events: %update.countnewevents% the following timers have been added: ---------------------------------------------------------------------- %update.newtimers% the following timers have been modified: ---------------------------------------------------------------------- %update.modtimers% the following timers have been deleted: ---------------------------------------------------------------------- %update.deltimers% the following events where found: ---------------------------------------------------------------------- %update.newevents% Have fun! ############################################################################## # here's the timer definition, which is used to display information about # a timer within one of the timer lists. You can use any variables that refer # to an event or timer. (Please note, that a timer may have no event assigned # to it, resulting in an empty variable substitution!). You can also use 'user # defined' variables from epgsearchuservars.conf. ############################################################################## Title: %title% ~ %subtitle% Start/End: %time_w% %date% %time%-%timeend% (Timer: %timer.start%-%timer.stop%) Channel: %timer.chlng% (%timer.chnr%) File: %timer.file% Modification: %timer.modreason% Search: %timer.search% (%timer.searchid%) Summary: %summary% ---------------------------------------------------------------------- ############################################################################## # here's the event definition, which is used to display information about # an event within the list of event announcements. You can use any variables # that refer to an event. You can also use 'user defined' variables from # epgsearchuservars.conf. ############################################################################## Title: %title% ~ %subtitle% Start/End: %time_w% %date% %time%-%timeend% Channel: %chlng% (%chnr%) Search: %search% (%searchid%) Summary: %summary% ---------------------------------------------------------------------- vdr-plugin-epgsearch/conf/epgsearchupdmail-html.templ0000644000175000017500000001604113145412721022701 0ustar tobiastobias######################################################################### # This is a sample template for email notifications about timer changes # (NOTE: This is a sample for a HTML mail, but you could use only text # as well) # # There are 3 sections that have to be defined: # - "subject" to be used as mail subject # - "mailbody" the body of the mail: # put %update.newtimers% in the place where the list of new timers should # appear. The same for %update.modtimers%, %update.deltimers% and # %update.newevents& for the list of changed or deleted timers and event # announcements. # - "timer" the description of one timer and "event" with the description of # one event. This section is used to display one timer within a timer list, # e.g. in %update.newtimers%. The same for "event". # # All sections are optional, e.g. if you don't use event announcements you # can drop "%update.newevents%" in the mailbody and the "event" section. But # of course you should have at least a mailbody ;-) # # close each section with the correspondig end tag! # Please have a look at the MANUAL for the available variables. ######################################################################### # # Version: 0.4 Date: 20.09.2009 # # Author: Mike Constabel # Christian Wieninger # ######################################################################### ######################################################################### # here's the mail's subject definition (no CR!) ######################################################################### [epgsearch] update info: %update.countnewtimers% new / %update.countmodtimers% modified / %update.countdeltimers% deleted timers / %update.countnewevents% new events / ######################################################################### # here's the mail's body definition ######################################################################### Information about search timer update
Information about search timer update
update at:%datenow% %timenow%
new timers:%update.countnewtimers%
modified timers:%update.countmodtimers%
deleted timers:%update.countdeltimers%
new events to report:%update.countnewevents%

Top New timers
%update.newtimers%

Top Modified timers
%update.modtimers%

Top Deleted timers
%update.deltimers%

Top New events to report
%update.newevents%

Have fun!

############################################################################## # here's the timer definition, which is used to display information about # a timer within one of the timer lists. You can use any variables that refer # to an event or timer. (Please note, that a timer may have no event assigned # to it, resulting in an empty variable substitution!). You can also use 'user # defined' variables from epgsearchuservars.conf. ##############################################################################
Title:
Subtitle:%subtitle%
Start/End:%time_w% %date% %time%-%timeend% (Timer: %timer.start%-%timer.stop%)
Channel:%timer.chlng% (%timer.chnr%)
File:%timer.file%
Search:%timer.search% (%timer.searchid%)
Modification:%timer.modreason%
Summary:%htmlsummary%

############################################################################## # here's the event definition, which is used to display information about # an event in the announcement list. You can use any variables that refer # to an event. You can also use 'user defined' variables from # epgsearchuservars.conf. ##############################################################################
Title:
Subtitle:%subtitle%
Start/End:%time_w% %date% %time%-%timeend%
Channel:%chlng% (%chnr%)
Search:%search% (%searchid%)
Summary:%htmlsummary%

vdr-plugin-epgsearch/conf/epgsearchcats.conf-tvm2vdr-tvmovie0000644000175000017500000001020013145412721024122 0ustar tobiastobias# ----------------------------------------------------------------------------- # This is just a template based on your current epg.data. Please edit! # Perhaps a category or its value list should be removed. Also the # 'name in menu' should be adjusted to your language. # The order of items determines the order listed in epgsearch. It does not # depend on the ID, which is used by epgsearch. # Format: # ID|category name|name in menu|values separated by ',' (option)|searchmode (option) # - 'ID' should be a unique positive integer # (changing the id later on will force you to reedit your search timers!) # - 'category name' is the name in your epg.data # - 'name in menu' is the name displayed in epgsearch. # - 'values' is an optional list of possible values # - 'searchmode' is an optional parameter specifying the mode of search: # text comparison: # 0 - the whole term must appear as substring # 1 - all single words (delimiters are ',', ';', '|' or '~') # must exist as substrings. This is the default search mode. # 2 - at least one word (delimiters are ',', ';', '|' or '~') # must exist as substring. # 3 - matches exactly # 4 - regular expression # numerical comparison: # 10 - less # 11 - less or equal # 12 - greater # 13 - greater or equal # 14 - equal # 15 - not equal # ----------------------------------------------------------------------------- 1|Category|Category|Film,Kultur,Serie,Show,Spielfilm,Sport|2 2|Genre|Genre|Abenteuer,Abenteuerkomdie,Action,Actiondrama,Action-Fantasy,Actionkomdie,Actionkrimi,Actionthriller,Animations,Anime,Ansprache,Arzt,Auslandsmagazin,Auslandsreportage,Automagazin,Ballett,Bericht,Bibelverfilmung,Bildungsprogramm,Biographie,Boulevardmagazin,Boxen,Bchermagazin,Brgersendung,Chart,Chronik,Clip,Clips,Comedy,Daily Soap,Dauerwerbesendung,Detektiv,Diskussion,Doku,Dokudrama,Doku-Drama,Dokumentar,Dokumentation,Doku-Soap,Drama,Dramedy,Ehedrama,Ehekomdie,Erotik,Erotikthriller,Familien,Familienchronik,Familiendrama,Familienkomdie,Fantasy,Fantasyabenteuer,Fantasykomdie,Fernseh,Festakt,Frauenmagazin,Frhmagazin,Fuball,Gala,Gehrlosenmagazin,Gerichts,Gesellschaftsdrama,Gesellschaftskomdie,Gesellschaftssatire,Gesprch,Gesundheitsmagazin,Gottesdienst,Groteske,Gruselkomdie,Heimat,Heimatmelodram,Historien,Historiendrama,Horror,Horrorkomdie,Horrorthriller,Impressionen,Informationen,Interview,Jazz,Jugend,Jugenddrama,Jugendmagazin,Jugendmemoiren,Justizdrama,Kabarett,Kammermusik,Katastrophen,Kinder,Kinderabenteuer,Kinder<80><94>Magazin,Kinderkomdie,Kinderkrimi,Kindermagazin,Kinder-Magazin,Kinomagazin,Klassik,Koch,Komdie,Konzert,Kriegs,Kriegsdrama,Krimi,Krimiabenteuer,Krimidrama,Krimikomdie,Kriminalmagazin,Kriminal-Magazin,Kulinarisches,Kulturmagazin,Kurz,Liebes,Liebeskomdie,Lifestylemagazin,Literaturverfilmung,Lotterie,Lustspiel,Magazin,Mrchen,Medienmagazin,Melodram,Militrsatire,Mittagsmagazin,Motorsport,Musical,Musicalverfilmung,Musik,Musikkomdie,Musikmagazin,Mystery,Mythen-Doku,Nachrichten,Nachrichtenmagazin,Naturdokumentation,nn,kokrimi,Oper,Politdrama,Politmagazin,Polit-Report,Politthriller,Polizei,Portrt,Prsentation,Predigt,Preisverleihung,Programminformation,Psychothriller,Puppen,Puppentrick,Quiz,Ratgeber,Reisedokumentation,Reisemagazin,Reisereportage,Reitsport,Religion,Reportage,Rock,Romanze,Sammelsendung,Satire,Satiremagazin,Schwank,schwarze Komdie,Science-fiction,Science-fiction-Film,Science-Fiction-Horror,Science-fiction-Komdie,Sitcom,Sitzung,Sketch,Slapstickkomdie,Sonstiges,Spiel,Sport,Sportmagazin,Sportsendung,Sprachkurs,Talk,Teenagerkomdie,Telenovela,Tennis,Theater,Thriller,Tier,Tier-doku,Tierdokumentation,Tiermagazin,Tragikomdie,Trick,Turnen,Umzug,Unterhaltung,Unterhaltungs,Unterhaltungsmusik,Verkaufs,Verkehrsmagazin,Volksmusik,Volkstheater,Vortrag,Weltmusik,Werbung,Western,Westerndrama,Wetter,Wirtschaftsmagazin,Wissenschaftsmagazin,Wochenmagazin,Zeichentrick,Zusammenfassung|2 3|Format|Format|4:3,16:9|3 4|Audio|Audio|Dolby,DolbyDigital, - O-Ton,Stereo,Stereo - O-Ton,Surround,Zweikanal|3 5|Year|Jahr||0 6|Cast|Darsteller||2 7|Director|Regisseur||2 8|Rating|Bewertung|TagesTipp,Tipp,TopTipp|2 9|FSK|FSK|3,4,5,6,7,8,9,12,16,18|3 vdr-plugin-epgsearch/conf/epgsearchcats.conf-tvm2vdr-hoerzu0000644000175000017500000000470113145412721023756 0ustar tobiastobias# ----------------------------------------------------------------------------- # This is just a template based on your current epg.data. Please edit! # Perhaps a category or its value list should be removed. Also the # 'name in menu' should be adjusted to your language. # The order of items determines the order listed in epgsearch. It does not # depend on the ID, which is used by epgsearch. # Format: # ID|category name|name in menu|values separated by ',' (option)|searchmode (option) # - 'ID' should be a unique positive integer # (changing the id later on will force you to reedit your search timers!) # - 'category name' is the name in your epg.data # - 'name in menu' is the name displayed in epgsearch. # - 'values' is an optional list of possible values # - 'searchmode' is an optional parameter specifying the mode of search: # text comparison: # 0 - the whole term must appear as substring # 1 - all single words (delimiters are ',', ';', '|' or '~') # must exist as substrings. This is the default search mode. # 2 - at least one word (delimiters are ',', ';', '|' or '~') # must exist as substring. # 3 - matches exactly # 4 - regular expression # numerical comparison: # 10 - less # 11 - less or equal # 12 - greater # 13 - greater or equal # 14 - equal # 15 - not equal # ----------------------------------------------------------------------------- 1|Category|Kategorie|Information,Kinder,Musik,Serie,Show,Spielfilm,Sport|3 2|Genre|Genre|Abenteuer,Action,Boxen,Comedy,Dokumentarfilm,Drama,Erotik,Familien-Show,Fantasy,Fussball,Geschichte,Gesellschaft,Gesundheit,Gymnastik,Handball,Heimat,Humor,Jazz,Kinderfilme,Kindernachrichten,Kinderserien,Klassik,Krankenhaus,Krimi,Kultur,Kurzfilm,Motor+Verkehr,Motorsport,Musik,Mystery,Nachrichten,Natur,Politik,Radsport,Ratgeber,Reise,Rock,Romantik/Liebe,Science Fiction,Soap,Spielshows,Talkshows,Tennis,Thriller,Verschiedenes,Volksmusik,Wassersport,Western,Wintersport,Wirtschaft,Wissen,Zeichentrick|2 3|Format|Video-Format|16:9,4:3|2 4|Audio|Audio|Dolby Surround,Dolby,Hoerfilm,Stereo|2 5|Year|Jahr||0 6|Cast|Besetzung||2 7|Director|Regisseur||2 8|Moderation|Moderation||2 9|Rating|Bewertung|Groartig besonders wertvoll,Groartig wertvoll,Groartig,Gelungen besonders wertvoll,Gelungen wertvoll,Gelungen,Annehmbar besonders wertvoll,Annehmbar wertvoll,besonders wertvoll,Annehmbar,Schwach|3 10|FSK|FSK|6,12,16,18|3 11|Country|Land||0 12|Episode|Episode||0 vdr-plugin-epgsearch/conf/epgsearchcats.conf-epgdata0000644000175000017500000000431613145412721022447 0ustar tobiastobias# ----------------------------------------------------------------------------- # This is just a template based on your current epg.data. Please edit! # Perhaps a category or its value list should be removed. Also the # 'name in menu' should be adjusted to your language. # The order of items determines the order listed in epgsearch. It does not # depend on the ID, which is used by epgsearch. # Format: # ID|category name|name in menu|values separated by ',' (option)|searchmode (option) # - 'ID' should be a unique positive integer # (changing the id later on will force you to reedit your search timers!) # - 'category name' is the name in your epg.data # - 'name in menu' is the name displayed in epgsearch. # - 'values' is an optional list of possible values # - 'searchmode' is an optional parameter specifying the mode of search: # text comparison: # 0 - the whole term must appear as substring # 1 - all single words (delimiters are ',', ';', '|' or '~') # must exist as substrings. This is the default search mode. # 2 - at least one word (delimiters are ',', ';', '|' or '~') # must exist as substring. # 3 - matches exactly # 4 - regular expression # numerical comparison: # 10 - less # 11 - less or equal # 12 - greater # 13 - greater or equal # 14 - equal # 15 - not equal # ----------------------------------------------------------------------------- 1|Category|Kategorie|Information,Kinder,Musik,Serie,Show,Spielfilm,Sport|3 2|Genre|Genre|Abenteuer,Action,Boxen,Comedy,Dokumentarfilm,Drama,Erotik,Familien-Show,Fantasy,Fussball,Geschichte,Gesellschaft,Gesundheit,Gymnastik,Handball,Heimat,Humor,Jazz,Kinderfilme,Kindernachrichten,Kinderserien,Klassik,Krankenhaus,Krimi,Kultur,Kurzfilm,Motor+Verkehr,Motorsport,Musik,Mystery,Nachrichten,Natur,Politik,Radsport,Ratgeber,Reise,Rock,Romantik/Liebe,Science Fiction,Soap,Spielshows,Talkshows,Tennis,Thriller,Verschiedenes,Volksmusik,Wassersport,Western,Wintersport,Wirtschaft,Wissen,Zeichentrick|2 3|Format|Video-Format|16:9,4:3|2 4|Audio|Audio|Dolby Surround,Stereo|2 5|Year|Jahr||0 6|Cast|Besetzung||2 7|Director|Regisseur||2 8|Moderation|Moderation||2 9|Rating|Bewertung|Tagestip,Tip|2 10|FSK|FSK|6,12,16,18|2 vdr-plugin-epgsearch/conf/epgsearchconflmail.templ0000644000175000017500000000437313145412721022255 0ustar tobiastobias######################################################################### # This is a sample template for email notifications about timer conflicts. # # There are 4 sections to be defined: # - "subject" to be used as mail subject # - "mailbody" the body of the mail (put %conflicts% in the place where the # list of conflicts should appear!) # - "conflictsat" the description of one time where one or more conflicts # exists (put %confltimers% in the place where the list of conflict # timers should appear!) # - "confltimer" the description of one conflicting timer # # close each section with the correspondig end tag! ######################################################################### ######################################################################### # here's the subject definition (no CR!) ######################################################################### [epgsearch] timer conflict info: %conflict.count% conflicting timers! ######################################################################### # here's the body definition ######################################################################### information about conflicting timers ---------------------------------------------------------------------- check at: %datenow% %timenow% conflicts: %conflict.count% ---------------------------------------------------------------------- %conflict.conflicts% Have fun! ######################################################################### # here's the conflictsat definition ######################################################################### the following timers have a conflict at: %conflict.date% %conflict.time% %conflict.confltimers% ######################################################################### # here's the definition of a conflict timer ######################################################################### Title: %title% ~ %subtitle% Start/End: %time_w% %date% %time%-%timeend% (Timer: %timer.start%-%timer.stop%) Channel: %chlng% (%chnr%) File: %timer.file% Search: %timer.search% (%timer.searchid%) ---------------------------------------------------------------------- vdr-plugin-epgsearch/mainmenushortcut.h0000644000175000017500000000403613145412721020211 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #ifndef __MAINMENUSHORTCUT_H #define __MAINMENUSHORTCUT_H #include static const char I18nEpgsearch[] = "vdr-epgsearch"; class cMainMenuShortcutSetupPage : public cMenuSetupPage { private: const char* _setupEntry; int* const _setupValue; int dummy; // don't know why, but this is necessary to avoid a crash with ext-patch and active USE_LIEMIKUUTIO public: cMainMenuShortcutSetupPage(const char* setupText, const char* setupEntry, int* const setupValue); protected: virtual void Store(void); }; class cMainMenuShortcut : public cPlugin { private: int _mainMenuEntryEnabled; public: cMainMenuShortcut(); virtual ~cMainMenuShortcut(); virtual bool Initialize(); virtual bool SetupParse(const char* Name, const char* Value); virtual cMenuSetupPage* SetupMenu(); virtual const char* MainMenuEntry(); protected: cOsdMenu* GetEpgSearchMenu(const char* serviceName); virtual const char* SetupText() = 0; virtual const char* MainMenuText() = 0; }; #endif vdr-plugin-epgsearch/epgsearch.h0000644000175000017500000000417313145412721016547 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #ifndef VDR_EPGSEARCH_H #define VDR_EPGSEARCH_H #include "epgsearchext.h" class cPluginEpgsearch : public cPlugin { public: bool showConflicts; bool showAnnounces; static bool VDR_readyafterStartup; cPluginEpgsearch(void); virtual ~cPluginEpgsearch(); virtual const char *Version(void); virtual const char *Description(void); virtual const char *CommandLineHelp(void); virtual bool ProcessArgs(int argc, char *argv[]); virtual bool Initialize(void); virtual bool Start(void); virtual void Stop(void); virtual void MainThreadHook(void); virtual const char *MainMenuEntry(void); virtual cOsdObject *MainMenuAction(void); virtual cMenuSetupPage *SetupMenu(void); virtual bool SetupParse(const char *Name, const char *Value); cOsdObject *DoInitialSearch(char* rcFilename); void LoadMenuTemplates(); bool Service(const char *Id, void *Data); virtual const char **SVDRPHelpPages(void); virtual cString SVDRPCommand(const char *Cmd, const char *Option, int &ReplyCode); void LoadUserVars(); void LoadConfD(); void CheckUTF8(); virtual cString Active(void); }; #endif vdr-plugin-epgsearch/menu_favorites.c0000644000175000017500000001413313145412721017624 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #include #include "menu_favorites.h" #include "menu_whatson.h" #include "menu_commands.h" using std::set; extern const char* ButtonBlue[3]; extern int exitToMainMenu; cMenuFavorites::cMenuFavorites() : cMenuSearchResults(cTemplFile::GetTemplateByName("MenuFavorites")) { BuildList(); } #ifdef USE_GRAPHTFT const char* cMenuFavorites::MenuKind() { return "MenuEpgsFavorites"; } void cMenuFavorites::Display(void) { cOsdMenu::Display(); if (Count() > 0) { int i = 0; for (cOsdItem *item = First(); item; item = Next(item)) cStatus::MsgOsdEventItem(!item->Selectable() ? 0 : ((cMenuSearchResultsItem*)item)->event, item->Text(), i++, Count()); } } #endif /* GRAPHTFT */ bool cMenuFavorites::BuildList() { Clear(); eventObjects.Clear(); cSearchResults* pCompleteSearchResults = NULL; cMutexLock SearchExtsLock(&SearchExts); cSearchExt *SearchExt = SearchExts.First(); int timespan = EPGSearchConfig.FavoritesMenuTimespan*60; while (SearchExt) { if (SearchExt->useInFavorites) pCompleteSearchResults = SearchExt->Run(modeBlue == showNoPayTV?1:0, false, timespan, pCompleteSearchResults, true); SearchExt = SearchExts.Next(SearchExt); } if (pCompleteSearchResults) { set foundEvents; pCompleteSearchResults->SortBy(CompareEventTime); for (cSearchResult* pResultObj = pCompleteSearchResults->First(); pResultObj; pResultObj = pCompleteSearchResults->Next(pResultObj)) { if (foundEvents.find(pResultObj->event) == foundEvents.end()) { foundEvents.insert(pResultObj->event); Add(new cMenuSearchResultsItem(pResultObj->event, modeYellow == showEpisode, false, menuTemplate)); eventObjects.Add(pResultObj->event); } } delete pCompleteSearchResults; } SetHelpKeys(); cString szTitle = cString::sprintf("%s: %d %s", tr("Favorites"), Count(), tr("Search results")); SetTitle(szTitle); Display(); return true; } eOSState cMenuFavorites::OnGreen() { eOSState state = osUnknown; if(!HasSubMenu()) { toggleKeys = 0; cMenuWhatsOnSearch::currentShowMode = cMenuWhatsOnSearch::GetNextMode(); return osUnknown; } return state; } eOSState cMenuFavorites::OnYellow() { eOSState state = osUnknown; if(!HasSubMenu()) { cMenuSearchResultsItem *item = (cMenuSearchResultsItem *)Get(Current()); if (item && item->event) { LOCK_CHANNELS_READ; const cChannel *channel = Channels->GetByChannelID(item->event->ChannelID(), true, true); cMenuWhatsOnSearch::scheduleChannel = channel; cMenuWhatsOnSearch::currentShowMode = showNow; } toggleKeys = 0; return osBack; } return state; } eOSState cMenuFavorites::ProcessKey(eKeys Key) { exitToMainMenu = 0; if (!HasSubMenu() && Key == kBack) { exitToMainMenu = 1; return osBack; } eOSState state = cMenuSearchResults::ProcessKey(Key); if (state == osUnknown) { switch (Key) { case kRecord: case kRed: state = OnRed(); break; case k0: if(!HasSubMenu()) { toggleKeys = 1 - toggleKeys; SetHelpKeys(true); } state = osContinue; break; case k1...k9: state = HasSubMenu()?osContinue:Commands(Key); break; case kBlue: return EPGSearchConfig.useOkForSwitch?ShowSummary():Switch(); break; case kOk: if(HasSubMenu()) { state = cOsdMenu::ProcessKey(Key); break; } if (Count()) state = EPGSearchConfig.useOkForSwitch?Switch():ShowSummary(); else state = osBack; break; default: break; } } return state; } void cMenuFavorites::SetHelpKeys(bool Force) { cMenuSearchResultsItem *item = (cMenuSearchResultsItem *)Get(Current()); int NewHelpKeys = 0; if (item) { if (item->Selectable() && item->timerMatch == tmFull) NewHelpKeys = 2; else NewHelpKeys = 1; } bool hasTimer = (NewHelpKeys == 2); if (NewHelpKeys != helpKeys || Force) { showMode nextShowMode = cMenuWhatsOnSearch::GetNextMode(); cShowMode* mode = cMenuWhatsOnSearch::GetShowMode(nextShowMode); const char* szButtonGreen = NULL; if (mode) szButtonGreen = mode->GetDescription(); if (toggleKeys==0) SetHelp((EPGSearchConfig.redkeymode==0?(hasTimer?trVDR("Button$Timer"):trVDR("Button$Record")):tr("Button$Commands")), szButtonGreen,trVDR("Button$Schedule"), EPGSearchConfig.useOkForSwitch?trVDR("Button$Info"):trVDR("Button$Switch")); else SetHelp((EPGSearchConfig.redkeymode==1?(hasTimer?trVDR("Button$Timer"):trVDR("Button$Record")):tr("Button$Commands")), szButtonGreen,trVDR("Button$Schedule"), EPGSearchConfig.useOkForSwitch?trVDR("Button$Info"):trVDR("Button$Switch")); helpKeys = NewHelpKeys; } } vdr-plugin-epgsearch/changrp.h0000644000175000017500000000633413145412721016231 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #ifndef __EPGSEARCHCHANGRP_H #define __EPGSEARCHCHANGRP_H #include #include #include class cSearchExt; // --- cChannelGroupItem -------------------------------------------------------- class cChannelGroupItem : public cListObject { public: const cChannel* channel; public: cChannelGroupItem(const cChannel* ch) : channel(ch) {} }; // --- cChannelGroup -------------------------------------------------------- class cChannelGroup : public cListObject { public: char name[MaxFileName]; cList channels; public: cChannelGroup(void); virtual ~cChannelGroup(void); bool Parse(const char *s); const char *ToText(void); bool Save(FILE *f); int* CreateChannelSel(); void CreateChannelList(int*); bool ChannelInGroup(const cChannel*); }; // --- cChannelGroups -------------------------------------------------------- class cChannelGroups : public cConfig { private: public: cChannelGroups(void) {} ~cChannelGroups(void) {} int GetIndex(char* channelGroup); cChannelGroup* GetGroupByName(const char* channelGroup); cSearchExt* Used(cChannelGroup*); char** CreateMenuitemsList(); }; extern cChannelGroups ChannelGroups; // --- cMenuChannelGroupItem ---------------------------------------------------------- class cMenuChannelGroupItem : public cOsdItem { private: public: cChannelGroup* group; cMenuChannelGroupItem(cChannelGroup*); void Set(void); }; // --- cMenuChannelGroups -------------------------------------------------------- class cMenuChannelGroups : public cOsdMenu { private: cChannelGroup *CurrentGroup(void); eOSState New(void); eOSState Delete(void); int groupSel; char** groupName; protected: virtual eOSState ProcessKey(eKeys Key); public: cMenuChannelGroups(char** groupName = NULL); }; // --- cMenuEditChannelGroup -------------------------------------------------------- class cMenuEditChannelGroup : public cOsdMenu { private: cChannelGroup *group; bool addIfConfirmed; char name[MaxFileName]; int* channelSel; public: cMenuEditChannelGroup(cChannelGroup *group, bool New = false); ~cMenuEditChannelGroup(); void Set(); virtual eOSState ProcessKey(eKeys Key); }; #endif vdr-plugin-epgsearch/menu_event.c0000644000175000017500000001623713145412721016752 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #include #include #include "menu_event.h" #include "menu_commands.h" #include "epgsearchcfg.h" #include "epgsearchtools.h" // --- cMenuEventSearch ------------------------------------------------------------ cMenuEventSearch::cMenuEventSearch(const cEvent* Event, cEventObjects& EventObjects, MenuEventSurfMode SurfMode) :cOsdMenu(tr("Event")), eventObjects(EventObjects), surfMode(SurfMode) { SetMenuCategory(mcEvent); eventObjects.SetCurrent(Event); szGreen = szYellow = NULL; Set(); } cEventObj* cMenuEventSearch::GetPrev(const cEvent* Event) { cEventObj* prevEventObj = NULL; cEventObjects::iterator i; for(i = eventObjects.begin(); i != eventObjects.end(); ++i) { if (*i && (*i)->Event() == Event) return prevEventObj; else prevEventObj = *i; } return NULL; } cEventObj* cMenuEventSearch::GetNext(const cEvent* Event) { cEventObjects::iterator i; for(i = eventObjects.begin(); i != eventObjects.end(); ++i) if (*i && (*i)->Event() == Event) { cEventObjects::iterator nexti = i; ++nexti; return nexti != eventObjects.end() ? *nexti : NULL; } return NULL; } void cMenuEventSearch::Set() { cEventObj* eventObj = eventObjects.GetCurrent(); if (!eventObj) return; event = eventObj->Event(); if (!event) return; if (szGreen) free(szGreen); if (szYellow) free(szYellow); szGreen = szYellow = NULL; if (event) { LOCK_TIMERS_READ; LOCK_CHANNELS_READ; const cChannel *channel = Channels->GetByChannelID(event->ChannelID(), true, true); bool canSwitch = false; if (channel) { SetTitle(channel->Name()); canSwitch = channel->Number() != cDevice::CurrentChannel(); } cEventObj* eventObjPrev = GetPrev(event); cEventObj* eventObjNext = GetNext(event); eTimerMatch timerMatch = tmNone; Timers->GetMatch(event, &timerMatch); const char* szRed = trVDR("Button$Record"); if (timerMatch == tmFull) szRed = trVDR("Button$Timer"); if (surfMode == SurfModeUnknown) SetHelp(szRed, eventObjPrev ? "<<":NULL, eventObjNext ? ">>":NULL, canSwitch ? trVDR("Button$Switch") : NULL); else if (surfMode == SurfModeTime) { if (eventObjPrev && eventObjPrev->Event()) szGreen = strdup(GETTIMESTRING(eventObjPrev->Event())); if (eventObjNext && eventObjNext->Event()) szYellow = strdup(GETTIMESTRING(eventObjNext->Event())); SetHelp(szRed, szGreen, szYellow, canSwitch ? trVDR("Button$Switch") : NULL); } else if (surfMode == SurfModeChannel) { if (eventObjPrev && eventObjPrev->Event()) szGreen = strdup(CHANNELNAME(Channels->GetByChannelID(eventObjPrev->Event()->ChannelID(), true, true))); if (eventObjNext && eventObjNext->Event()) szYellow = strdup(CHANNELNAME(Channels->GetByChannelID(eventObjNext->Event()->ChannelID(), true, true))); SetHelp(szRed, szGreen, szYellow, canSwitch ? trVDR("Button$Switch") : NULL); } } } cMenuEventSearch::~cMenuEventSearch() { if (szGreen) free(szGreen); if (szYellow) free(szYellow); } void cMenuEventSearch::Display(void) { cOsdMenu::Display(); #ifdef USE_GRAPHTFT cStatus::MsgOsdSetEvent(event); #endif if (event) { DisplayMenu()->SetEvent(event); cStatus::MsgOsdTextItem(event->Description()); } } eOSState cMenuEventSearch::Commands(eKeys Key) { if (HasSubMenu()) return osContinue; if (event) { cMenuSearchCommands *menu; eOSState state = AddSubMenu(menu = new cMenuSearchCommands(tr("EPG Commands"), event, true)); if (Key != kNone) state = menu->ProcessKey(Key); return state; } return osContinue; } eOSState cMenuEventSearch::ProcessKey(eKeys Key) { if (!HasSubMenu()) { switch ((int)Key) { case kUp|k_Repeat: case kUp: case kDown|k_Repeat: case kDown: case kLeft|k_Repeat: case kLeft: case kRight|k_Repeat: case kRight: DisplayMenu()->Scroll(NORMALKEY(Key) == kUp || NORMALKEY(Key) == kLeft, NORMALKEY(Key) == kLeft || NORMALKEY(Key) == kRight); cStatus::MsgOsdTextItem(NULL, NORMALKEY(Key) == kUp); return osContinue; case k1...k9: if (!HasSubMenu()) return Commands(Key); else return osContinue; break; case kInfo: return osBack; default: break; } } eOSState state = cOsdMenu::ProcessKey(Key); if (state == osUnknown) { switch (Key) { case kOk: return osBack; case kGreen: case kFastRew: { cEventObj* eventObjPrev = GetPrev(event); if (eventObjPrev && eventObjPrev->Event()) { eventObjects.SetCurrent(eventObjPrev->Event()); Set(); Display(); } state = osContinue; } break; case kFastFwd: case kYellow: { cEventObj* eventObjNext = GetNext(event); if (eventObjNext && eventObjNext->Event()) { eventObjects.SetCurrent(eventObjNext->Event()); Set(); Display(); } state = osContinue; } break; default: break; } } return state; } cMenuEventSearchSimple::cMenuEventSearchSimple(const cEvent* Event, cEventObjects& EventObjects) :cMenuEventSearch(Event, EventObjects) { Set(); } void cMenuEventSearchSimple::Set() { cEventObj* eventObj = eventObjects.GetCurrent(); if (!eventObj) return; event = eventObj->Event(); if (!event) return; if (szGreen) free(szGreen); if (szYellow) free(szYellow); szGreen = szYellow = NULL; if (event) { LOCK_CHANNELS_READ; const cChannel *channel = Channels->GetByChannelID(event->ChannelID(), true, true); if (channel) { SetTitle(channel->Name()); } cEventObj* eventObjPrev = GetPrev(event); cEventObj* eventObjNext = GetNext(event); SetHelp(NULL, eventObjPrev ? "<<":NULL, eventObjNext ? ">>":NULL, NULL); } Display(); } vdr-plugin-epgsearch/timerdone.c0000644000175000017500000001372313145412721016570 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #include #include "timerdone.h" #include "epgsearchtools.h" using std::string; cTimersDone TimersDone; // -- cTimerDone ----------------------------------------------------------------- cTimerDone::cTimerDone(void) { start = stop = 0; searchID = -1; } cTimerDone::cTimerDone(const time_t Start, const time_t Stop, const cEvent* pEvent, const int SearchID) { start = Start; stop = Stop; if (pEvent) { channelID = pEvent->ChannelID(); title = pEvent->Title()?pEvent->Title():""; shorttext = pEvent->ShortText()?pEvent->ShortText():""; } searchID = SearchID; } bool cTimerDone::operator== (const cTimerDone &arg) const { if (start == arg.start && stop == arg.stop && channelID == arg.channelID) { if (title != arg.title) return false; if (shorttext != "" && arg.shorttext != "" && shorttext != arg.shorttext) return false; if (searchID > -1 && arg.searchID > -1) return searchID == arg.searchID; else return true; } else return false; } bool cTimerDone::Parse(const char *s) { char *line; char *pos; char *pos_next; int parameter = 1; int valuelen; #define MAXVALUELEN (10 * MaxFileName) char value[MAXVALUELEN]; pos = line = strdup(s); pos_next = pos + strlen(pos); if (*pos_next == '\n') *pos_next = 0; while (*pos) { while (*pos == ' ') pos++; if (*pos) { if (*pos != ':') { pos_next = strchr(pos, ':'); if (!pos_next) pos_next = pos + strlen(pos); valuelen = pos_next - pos + 1; if (valuelen > MAXVALUELEN) { LogFile.eSysLog("entry '%s' is too long. Will be truncated!", pos); valuelen = MAXVALUELEN; } strn0cpy(value, pos, valuelen); pos = pos_next; switch (parameter) { case 1: channelID = tChannelID::FromString(value); break; case 2: start = atol(value); break; case 3: stop = atol(value); break; case 4: searchID = atol(value); break; case 5: title = value; break; case 6: shorttext = value; break; default: break; } //switch } parameter++; } if (*pos) pos++; } //while title = ReplaceAll(title, "|", ":"); shorttext = ReplaceAll(shorttext, "|", ":"); free(line); return (parameter >= 6) ? true : false; } cString cTimerDone::ToText(void) const { LOCK_CHANNELS_READ; const cChannel *channel = Channels->GetByChannelID(channelID, true, true); string info = string(DAYDATETIME(start)) + " - " + string(channel?channel->Name():""); cString buffer = cString::sprintf("%s:%ld:%ld:%d:%s:%s:%s", *channelID.ToString(), start, stop, searchID, ReplaceAll(title, ":", "|").c_str(), ReplaceAll(shorttext, ":", "|").c_str(), ReplaceAll(info, ":", "|").c_str()); return buffer; } bool cTimerDone::Save(FILE *f) { return fprintf(f, "%s\n", *ToText()) > 0; } const cEvent* cTimerDone::GetEvent() const { LOCK_SCHEDULES_READ; if (!Schedules) return NULL; const cSchedule *Schedule = Schedules->GetSchedule(channelID); if (!Schedule) return NULL; const cEvent* Event = Schedule->GetEventAround(start + (stop - start)/2); return Event; } // -- cTimerDones ----------------------------------------------------------------- cTimerDone* cTimersDone::InList(const time_t Start, const time_t Stop, const cEvent* pEvent, const int SearchID) { cTimerDone td(Start, Stop, pEvent, SearchID); cTimerDone* timerdone = First(); while (timerdone) { if (*timerdone == td) return timerdone; timerdone = Next(timerdone); } return NULL; } void cTimersDone::ClearOutdated(void) { // remove outdated items cTimerDone* timerdone = First(); while (timerdone) { cTimerDone* timerdoneNext = Next(timerdone); if (timerdone->stop < time(NULL)) Del(timerdone); timerdone = timerdoneNext; } } void cTimersDone::Update(const time_t Start, const time_t Stop, const cEvent* pEvent, const int SearchID, cTimerDone* Timerdone) { cTimerDone* timerdone = InList(Start, Stop, pEvent, SearchID); if(timerdone) { timerdone->start = Timerdone->start; timerdone->stop = Timerdone->stop; timerdone->channelID = Timerdone->channelID; timerdone->searchID = Timerdone->searchID; timerdone->title = Timerdone->title; timerdone->shorttext = Timerdone->shorttext; delete Timerdone; } else Add(Timerdone); } void cTimersDone::RemoveEntriesOfSearch(const int SearchID) { cTimerDone* timerdone = First(); while (timerdone) { cTimerDone* timerdoneNext = Next(timerdone); if (timerdone->searchID == SearchID) Del(timerdone); timerdone = timerdoneNext; } } vdr-plugin-epgsearch/INSTALL0000644000175000017500000000273413145412721015467 0ustar tobiastobiasTheres nothing special about it. Install it like any other standard plugin (unpack, soft link, make plugins). Optional libraries: ------------------- libpcre ------- For support of Perl compatible regular expressions in a search you have to use libpcre: simply edit the plugins Makefile and uncomment '#REGEXLIB = pcre' to 'REGEXLIB = pcre' or append 'REGEXLIB=pcre' to your 'make plugins' call. (you will need pcreposix installed, comes with libpcre from www.pcre.org, but it's already part of most distributions HINT: if all compiles well, but after starting VDR you get: ERROR: /usr/lib/libpcreposix.so.0: undefined symbol: pcre_free). update libpcre from www.pcre.org and recompile the plugin. There seems to be a problem with PCRE on some systems, that produce a crash when using regexp. Til now, I could not find the reason. So perhaps dont use REGEXLIB=pcre, if you don't really need it. libtre ------ epgsearch has a fuzzy search algorithm. Unfortunately it's restricted to search patterns with a maximum of 31 characters. This results in empty results if more than 31 characters are used. To avoid this limitation you can use the TRE package (http://laurikari.net/tre/). Install tre (on debian: apt-get install tre-agrep libtre4 libtre-dev) and activate epgsearch's support for it in the Makefile by uncommenting '#REGEXLIB = pcre' to 'REGEXLIB = tre' or append it to your 'make plugins' call. After recompiling epgsearch will now use an algorithm similar to 'agrep' with no limits. vdr-plugin-epgsearch/menu_dirselect.h0000644000175000017500000000413213145412721017603 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #ifndef __EPGSEARCHDIRSELECT_H #define __EPGSEARCHDIRSELECT_H #include #include #include using std::string; using std::set; class cDirExt : public cListObject { private: char name[MaxFileName]; public: cDirExt(void){ name[0]=0; } bool Parse(const char *s) {strcpy(name,s); return true;} char* Name() {return name;} }; class cDirExts : public cConfig {}; class cConfDDirExts : public cList {}; extern cDirExts DirExts; extern cConfDDirExts ConfDDirExts; // --- cMenuDirSelect --------------------------------------------------------- class cMenuDirSelect : public cOsdMenu { private: int CurLevel; int MaxLevel; char* Directory; char* yellow; public: static set directorySet; cMenuDirSelect(char*); ~cMenuDirSelect(); void Load(); void AddDistinct(const char* szText); static void AddVDRFolders(cNestedItem* folder, string parentDirectory = ""); virtual eOSState ProcessKey(eKeys Key); int Level(const char* szDir); void ReplaceDirVars(); static void CreateDirSet(bool extraDirs=true); }; #endif vdr-plugin-epgsearch/epgsearchsetup.c0000644000175000017500000013106213145412721017621 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #include #include #include "epgsearchsetup.h" #include "epgsearchcfg.h" #include "searchtimer_thread.h" #include "epgsearchtools.h" #include "changrp.h" #include "menu_dirselect.h" #include "menu_searchtemplate.h" #include "menu_blacklists.h" #include "templatefile.h" #include "conflictcheck_thread.h" #include "mail.h" #include "menu_deftimercheckmethod.h" const char *OkKeyMode[2]; const char *RedKeyMode[2]; const char *BlueKeyMode[2]; const char *StartMenuMode[2]; const char *AddSubtitleMode[3]; const char *FavoritesMenuMode[4]; const char *MailMethod[2]; const char *cMenuSetupMailNotification::HostNameChars = " abcdefghijklmnopqrstuvwxyz0123456789-._~:"; const char *cMenuSetupMailNotification::UserNameChars = " abcdefghijklmnopqrstuvwxyz0123456789-+.,:;?!$&#@~{}[]()_/"; const char *cMenuSetupMailNotification::PasswordChars = " abcdefghijklmnopqrstuvwxyz0123456789-+.,:;?!$&#@~{}[]()_/"; const char *cMenuSetupMailNotification::MailBoxChars = " abcdefghijklmnopqrstuvwxyz0123456789-.#@~{}[]_/"; // ------------------ // cMenuSetupSubMenu cMenuSetupSubMenu::cMenuSetupSubMenu(const char* Title, cEPGSearchConfig* Data) :cOsdMenu(Title, 33) { SetMenuCategory(mcSetupPlugins); data = Data; } eOSState cMenuSetupSubMenu::ProcessKey(eKeys Key) { eOSState state = cOsdMenu::ProcessKey(Key); if (state == osUnknown) { switch (Key) { case kInfo: case kYellow: state = Help(); break; default: break; } } return state; } void cMenuSetupSubMenu::AddHelp(const char* helpText) { helpTexts.push_back(helpText); } eOSState cMenuSetupSubMenu::Help() { const char* ItemText = Get(Current())->Text(); eOSState state = osContinue; if(Current() < (int) helpTexts.size()) { char* title = NULL; if (msprintf(&title, "%s - %s", tr("Button$Help"), ItemText)!=-1) { if (strchr(title, ':')) *strchr(title, ':') = 0; state = AddSubMenu(new cMenuText(title, helpTexts[Current()])); free(title); } } return state; } // ------------------ // cMenuEPGSearchSetup cMenuEPGSearchSetup::cMenuEPGSearchSetup(void) { OkKeyMode[0] = trVDR("Button$Info"); OkKeyMode[1] = trVDR("Button$Switch"); RedKeyMode[0] = tr("Standard"); RedKeyMode[1] = tr("Button$Commands"); BlueKeyMode[0] = tr("Standard"); BlueKeyMode[1] = tr("Button$Search"); StartMenuMode[0] = trVDR("Button$Schedule"); StartMenuMode[1] = trVDR("Button$Now"); AddSubtitleMode[0] = tr("never"); AddSubtitleMode[1] = tr("always"); AddSubtitleMode[2] = tr("smart"); FavoritesMenuMode[0] = trVDR("no"); FavoritesMenuMode[1] = tr("before user-def. times"); FavoritesMenuMode[2] = tr("after user-def. times"); FavoritesMenuMode[3] = tr("before 'next'"); MailMethod[0] = "sendmail"; MailMethod[1] = "sendEmail.pl"; Setup(); } void cMenuEPGSearchSetup::Setup(void) { data = EPGSearchConfig; if (isempty(EPGSearchConfig.mainmenuentry)) strcpy(data.mainmenuentry,tr("Program guide")); Set(); SetHelp(NULL, NULL, NULL, trVDR("Button$Open")); } void cMenuEPGSearchSetup::Set() { int current = Current(); Clear(); Add(new cOsdItem(tr("General"))); Add(new cOsdItem(tr("EPG menus"))); Add(new cOsdItem(tr("User-defined EPG times"))); Add(new cOsdItem(tr("Timer programming"))); Add(new cOsdItem(tr("Search and search timers"))); Add(new cOsdItem(tr("Timer conflict checking"))); Add(new cOsdItem(tr("Email notification"))); SetCurrent(Get(current)); Display(); } void cMenuEPGSearchSetup::Store(void) { bool RestartSearchTimerThread = false; if (EPGSearchConfig.useSearchTimers != data.useSearchTimers) { RestartSearchTimerThread = true; cSearchTimerThread::Exit(); } bool RestartConflictCheckThread = false; if (EPGSearchConfig.checkTimerConflictsAfterUpdate != data.checkTimerConflictsAfterUpdate || EPGSearchConfig.conflictCheckIntervall != data.conflictCheckIntervall) { RestartConflictCheckThread = true; cConflictCheckThread::Exit(); } EPGSearchConfig = data; if (strcmp(EPGSearchConfig.mainmenuentry, tr("Program guide")) == 0) strcpy(EPGSearchConfig.mainmenuentry,""); if (isempty(EPGSearchConfig.MailAddressTo)) strcpy(EPGSearchConfig.MailAddressTo, EPGSearchConfig.MailAddress); SetupStore("HideMenu", EPGSearchConfig.hidemenu); SetupStore("MainMenuEntry", EPGSearchConfig.mainmenuentry); SetupStore("ReplaceOrgSchedule", EPGSearchConfig.ReplaceOrgSchedule); SetupStore("StartMenu", EPGSearchConfig.StartMenu); SetupStore("RedKeyMode", EPGSearchConfig.redkeymode); SetupStore("BlueKeyMode", EPGSearchConfig.bluekeymode); SetupStore("ShowProgress", EPGSearchConfig.showProgress); SetupStore("ShowChannelNr", EPGSearchConfig.showChannelNr); SetupStore("OnePressTimerCreation", EPGSearchConfig.onePressTimerCreation); SetupStore("ShowFavoritesMenu", EPGSearchConfig.showFavoritesMenu); SetupStore("FavoritesMenuTimespan", EPGSearchConfig.FavoritesMenuTimespan); SetupStore("UseOkForSwitch", EPGSearchConfig.useOkForSwitch); SetupStore("MaxChannelMenuNow", EPGSearchConfig.maxChannelMenuNow); SetupStore("UserMode1UseIt", EPGSearchConfig.ShowModes[showUserMode1].GetUsage()); SetupStore("UserMode1Description", EPGSearchConfig.ShowModes[showUserMode1].GetDescription()); SetupStore("UserMode1Time", EPGSearchConfig.ShowModes[showUserMode1].GetTime()); SetupStore("UserMode2UseIt", EPGSearchConfig.ShowModes[showUserMode2].GetUsage()); SetupStore("UserMode2Description", EPGSearchConfig.ShowModes[showUserMode2].GetDescription()); SetupStore("UserMode2Time", EPGSearchConfig.ShowModes[showUserMode2].GetTime()); SetupStore("UserMode3UseIt", EPGSearchConfig.ShowModes[showUserMode3].GetUsage()); SetupStore("UserMode3Description", EPGSearchConfig.ShowModes[showUserMode3].GetDescription()); SetupStore("UserMode3Time", EPGSearchConfig.ShowModes[showUserMode3].GetTime()); SetupStore("UserMode4UseIt", EPGSearchConfig.ShowModes[showUserMode4].GetUsage()); SetupStore("UserMode4Description", EPGSearchConfig.ShowModes[showUserMode4].GetDescription()); SetupStore("UserMode4Time", EPGSearchConfig.ShowModes[showUserMode4].GetTime()); SetupStore("UseSearchTimers", EPGSearchConfig.useSearchTimers); SetupStore("UpdateIntervall", EPGSearchConfig.UpdateIntervall); SetupStore("SVDRPPort", EPGSearchConfig.SVDRPPort); SetupStore("CheckTimerConflicts", EPGSearchConfig.checkTimerConflictsAfterUpdate); SetupStore("CheckTimerConflictsPriority", EPGSearchConfig.checkMinPriority); SetupStore("CheckTimerConflictsDays", EPGSearchConfig.checkMaxDays); SetupStore("CheckConflictsIntervall", EPGSearchConfig.conflictCheckIntervall); SetupStore("CheckConflictsWithinLimit", EPGSearchConfig.conflictCheckWithinLimit); SetupStore("CheckConflictsIntervall2", EPGSearchConfig.conflictCheckIntervall2); SetupStore("CheckConflictsMinDuration", EPGSearchConfig.checkMinDuration); SetupStore("CheckConflictsAfterTimerProg", EPGSearchConfig.checkTimerConflAfterTimerProg); SetupStore("CheckConflictsOnRecording", EPGSearchConfig.checkTimerConflOnRecording); SetupStore("NoConflMsgWhileReplay", EPGSearchConfig.noConflMsgWhileReplay); SetupStore("RemoteConflictCheck", EPGSearchConfig.RemoteConflictCheck); SetupStore("CheckEPGHours", EPGSearchConfig.checkEPGHours); SetupStore("CheckEPGWarnByOSD", EPGSearchConfig.checkEPGWarnByOSD); SetupStore("CheckEPGWarnByMail", EPGSearchConfig.checkEPGWarnByMail); SetupStore("CheckEPGChannelgroup", EPGSearchConfig.checkEPGchannelGroupNr); SetupStore("NoAnnounceWhileReplay", EPGSearchConfig.noAnnounceWhileReplay); SetupStore("TimerProgRepeat", EPGSearchConfig.TimerProgRepeat); SetupStore("TimeIntervallFRFF", EPGSearchConfig.timeShiftValue); SetupStore("ToggleGreenYellow", EPGSearchConfig.toggleGreenYellow); SetupStore("ShowRadioChannels", EPGSearchConfig.showRadioChannels); SetupStore("DefPriority", EPGSearchConfig.DefPriority); SetupStore("DefLifetime", EPGSearchConfig.DefLifetime); SetupStore("DefMarginStart", EPGSearchConfig.DefMarginStart); SetupStore("DefMarginStop", EPGSearchConfig.DefMarginStop); SetupStore("IgnorePayTV", EPGSearchConfig.ignorePayTV); SetupStore("DefRecordingDir", EPGSearchConfig.defrecdir); SetupStore("UseVDRTimerEditMenu", EPGSearchConfig.useVDRTimerEditMenu); SetupStore("ShowChannelGroups", EPGSearchConfig.showChannelGroups); SetupStore("ShowDaySeparators", EPGSearchConfig.showDaySeparators); SetupStore("ShowEmptyChannels", EPGSearchConfig.showEmptyChannels); SetupStore("DefSearchTemplateID", EPGSearchConfig.DefSearchTemplateID); SetupStore("AddSubtitleToTimerMode", EPGSearchConfig.addSubtitleToTimer); SetupStore("MailNotificationSearchtimers", EPGSearchConfig.sendMailOnSearchtimers); SetupStore("MailNotificationSearchtimersHours", EPGSearchConfig.sendMailOnSearchtimerHours); SetupStore("MailNotificationConflicts", EPGSearchConfig.sendMailOnConflicts); SetupStore("MailAddress", EPGSearchConfig.MailAddress); SetupStore("MailAddressTo", EPGSearchConfig.MailAddressTo); SetupStore("MailServer", EPGSearchConfig.MailServer); SetupStore("MailUseAuth", EPGSearchConfig.MailUseAuth); SetupStore("MailAuthUser", EPGSearchConfig.MailAuthUser); SetupStore("MailAuthPass", EPGSearchConfig.MailAuthPass); SetupStore("MailViaScript", EPGSearchConfig.mailViaScript); cTemplFile::Reset(); char* templateFilename = strdup(AddDirectory(CONFIGDIR, "epgsearchmenu.conf")); if (access(templateFilename, F_OK) == 0) { cTemplFile templFile; if (!templFile.Load(templateFilename)) LogFile.eSysLog("could not load '%s'", templateFilename); } cTemplFile::PrepareDefaultTemplates(); free(templateFilename); cPluginEpgsearch *p = (cPluginEpgsearch*) cPluginManager::GetPlugin("epgsearch"); if (RestartSearchTimerThread) cSearchTimerThread::Init(p); if (RestartConflictCheckThread) cConflictCheckThread::Init(p); } eOSState cMenuEPGSearchSetup::ProcessKey(eKeys Key) { bool hadSubMenu = HasSubMenu(); eOSState state = cMenuSetupPage::ProcessKey(Key); const char* ItemText = Get(Current())->Text(); int iOnGeneral = 0; int iOnEPGMenus = 0; int iOnUserdefTimes = 0; int iOnTimers = 0; int iOnSearchtimers = 0; int iOnTimerConflicts = 0; int iOnEmailNotification = 0; if (!HasSubMenu()) { if (strstr(ItemText, tr("General")) == ItemText) iOnGeneral = 1; else if (strstr(ItemText, tr("EPG menus")) == ItemText) iOnEPGMenus = 1; else if (strstr(ItemText, tr("User-defined EPG times")) == ItemText) iOnUserdefTimes = 1; else if (strstr(ItemText, tr("Timer programming")) == ItemText) iOnTimers = 1; else if (strstr(ItemText, tr("Search and search timers")) == ItemText) iOnSearchtimers = 1; else if (strstr(ItemText, tr("Timer conflict checking")) == ItemText) iOnTimerConflicts = 1; else if (strstr(ItemText, tr("Email notification")) == ItemText) iOnEmailNotification = 1; } if (!HasSubMenu() && (state == osUnknown || Key == kOk)) { if ((Key == kOk && !hadSubMenu) || Key == kBlue) { if (iOnGeneral == 1) state = AddSubMenu(new cMenuSetupGeneral(&data)); else if (iOnEPGMenus == 1) state = AddSubMenu(new cMenuSetupEPGMenus(&data)); else if (iOnUserdefTimes == 1) state = AddSubMenu(new cMenuSetupUserdefTimes(&data)); else if (iOnTimers == 1) state = AddSubMenu(new cMenuSetupTimers(&data)); else if (iOnSearchtimers == 1) state = AddSubMenu(new cMenuSetupSearchtimers(&data)); else if (iOnTimerConflicts == 1) state = AddSubMenu(new cMenuSetupTimerConflicts(&data)); else if (iOnEmailNotification == 1) state = AddSubMenu(new cMenuSetupMailNotification(&data)); } } if (!HasSubMenu() && hadSubMenu) Store(); return state; } // ------------------ // cMenuSetupGeneral cMenuSetupGeneral::cMenuSetupGeneral(cEPGSearchConfig* Data) : cMenuSetupSubMenu(tr("General"), Data) { Set(); } void cMenuSetupGeneral::Set() { int current = Current(); Clear(); helpTexts.clear(); Add(new cMenuEditBoolItem(tr("Hide main menu entry"), &data->hidemenu, trVDR("no"), trVDR("yes"))); AddHelp(tr("Help$Hides the main menu entry and may be useful if this plugin is used to replace the original 'Schedule' entry.")); if (!data->hidemenu) { Add(new cMenuEditStrItem(IndentMenuItem(tr("Main menu entry")), data->mainmenuentry, sizeof(data->mainmenuentry), tr(AllowedChars))); AddHelp(tr("Help$The name of the main menu entry which defaults to 'Programm guide'.")); } Add(new cMenuEditBoolItem(tr("Replace original schedule"), &data->ReplaceOrgSchedule, trVDR("no"), trVDR("yes"))); AddHelp(tr("Help$When VDR is patched to allow this plugin to replace the original 'Schedule' entry, you can de/activate this replacement here.")); Add(new cMenuEditStraItem(tr("Start menu"), &data->StartMenu, 2, StartMenuMode)); AddHelp(tr("Help$Choose between 'Overview - Now' and 'Schedule' as start menu when this plugin is called.")); SetCurrent(Get(current)); Display(); SetHelp(NULL, NULL, tr("Button$Help"), NULL); } eOSState cMenuSetupGeneral::ProcessKey(eKeys Key) { int iTemp_hidemenu = data->hidemenu; eOSState state = cMenuSetupSubMenu::ProcessKey(Key); if (iTemp_hidemenu != data->hidemenu) { Set(); Display(); } if (state == osUnknown) { switch (Key) { case kOk: return osBack; default: break; } } return state; } // ------------------ // cMenuSetupEPGMenus cMenuSetupEPGMenus::cMenuSetupEPGMenus(cEPGSearchConfig* Data) : cMenuSetupSubMenu(tr("EPG menus"), Data) { Set(); } void cMenuSetupEPGMenus::Set() { int current = Current(); Clear(); helpTexts.clear(); Add(new cMenuEditStraItem( tr("Ok key"), &data->useOkForSwitch, 2, OkKeyMode)); AddHelp(tr("Help$Choose here the behaviour of key 'Ok'. You can use it to display the summary or to switch to the corresponding channel.\nNote: the functionality of key 'blue' (Switch/Info/Search) depends on this setting.")); Add(new cMenuEditStraItem(tr("Red key"), &data->redkeymode, 2, RedKeyMode)); AddHelp(tr("Help$Choose which standard function ('Record' or 'Commands') you like to have on the red key.\n(Can be toggled with key '0')")); Add(new cMenuEditStraItem(tr("Blue key"), &data->bluekeymode, 2, BlueKeyMode)); AddHelp(tr("Help$Choose which standard function ('Switch'/'Info' or 'Search') you like to have on the blue key.\n(Can be toggled with key '0')")); Add(new cMenuEditBoolItem(tr("Show progress in 'Now'"), &data->showProgress, trVDR("no"), trVDR("yes"))); AddHelp(tr("Help$Shows a progressbar in 'Overview - Now' that informs about the remaining time of the current event.")); Add(new cMenuEditBoolItem( tr("Show channel numbers"), &data->showChannelNr, trVDR("no"), trVDR("yes"))); AddHelp(tr("Help$Display channel numbers in 'Overview - Now'.\n\n(To completely define your own menu look please inspect the MANUAL)")); Add(new cMenuEditBoolItem( tr("Show channel separators"), &data->showChannelGroups, trVDR("no"), trVDR("yes"))); AddHelp(tr("Help$Display VDR channel groups as separators between your channels in 'Overview - Now'.")); Add(new cMenuEditBoolItem( tr("Show day separators"), &data->showDaySeparators, trVDR("no"), trVDR("yes"))); AddHelp(tr("Help$Display a separator line at day break in 'Schedule'.")); Add(new cMenuEditBoolItem( tr("Show radio channels"), &data->showRadioChannels, trVDR("no"), trVDR("yes"))); AddHelp(tr("Help$Show also radio channels.")); Add(new cMenuEditIntItem(tr("Limit channels from 1 to"), &data->maxChannelMenuNow, 0, 9999)); AddHelp(tr("Help$If you have a large channel set you can speed up things when you limit the displayed channels with this setting. Use '0' to disable the limit.")); Add(new cMenuEditBoolItem( tr("'One press' timer creation"), &data->onePressTimerCreation, trVDR("no"), trVDR("yes"))); AddHelp(tr("Help$When a timer is created with 'Record' you can choose between an immediate creation of the timer or the display of the timer edit menu.")); Add(new cMenuEditBoolItem( tr("Show channels without EPG"), &data->showEmptyChannels, trVDR("no"), trVDR("yes"))); AddHelp(tr("Help$Choose 'yes' here if you want to display channels without EPG in 'Overview - Now'. 'Ok' on these entries switches the channel.")); Add(new cMenuEditIntItem(tr("Time interval for FRew/FFwd [min]"), &data->timeShiftValue, 1, 9999)); AddHelp(tr("Help$Choose here the time interval which should be used for jumping through the EPG by pressing FRew/FFwd.\n\n(If you don't have those keys, you can toggle to this functionality pressing '0' and get '<<' and '>>' on the keys green and yellow)")); Add(new cMenuEditBoolItem( tr("Toggle Green/Yellow"), &data->toggleGreenYellow, trVDR("no"), trVDR("yes"))); AddHelp(tr("Help$Specify if green and yellow shall also be switched when pressing '0'.")); Add(new cMenuEditStraItem( tr("Show favorites menu"), &data->showFavoritesMenu, 4, FavoritesMenuMode)); AddHelp(tr("Help$A favorites menu can display a list of your favorite broadcasts. Enable this if you want an additional menu besides 'Now' and 'Next'\nAny search can be used as a favorite. You only have to set the option 'Use in favorites menu' when editing a search.")); if (data->showFavoritesMenu) { Add(new cMenuEditIntItem( IndentMenuItem(tr("for the next ... hours")), &data->FavoritesMenuTimespan, 1, 9999)); AddHelp(tr("Help$This value controls the timespan used to display your favorites.")); } SetCurrent(Get(current)); Display(); SetHelpKeys(); } void cMenuSetupEPGMenus::SetHelpKeys() { SetHelp(NULL, NULL, tr("Button$Help"), NULL); } // ------------------ // cMenuSetupUsedefTimes cMenuSetupUserdefTimes::cMenuSetupUserdefTimes(cEPGSearchConfig* Data) : cMenuSetupSubMenu(tr("User-defined EPG times"), Data) { Set(); } void cMenuSetupUserdefTimes::Set() { int current = Current(); Clear(); helpTexts.clear(); cString szUseUserTime = cString::sprintf("%s %d", tr("Use user-defined time"), 1); Add(new cMenuEditBoolItem(szUseUserTime, &data->ShowModes[showUserMode1].useIt, trVDR("no"), trVDR("yes"))); AddHelp(tr("Help$Besides 'Now' and 'Next' you can specify up to 4 other times in the EPG which can be used by repeatedly pressing the green key, e.g. 'prime time', 'late night',...")); if (data->ShowModes[showUserMode1].GetUsage()) { Add(new cMenuEditStrItem(IndentMenuItem(tr("Description")), data->ShowModes[showUserMode1].description, sizeof(data->ShowModes[showUserMode1].description), trVDR(FileNameChars))); AddHelp(tr("Help$This is the description for your user-defined time as it will appear as label on the green button.")); Add(new cMenuEditTimeItem(IndentMenuItem(tr("Time")), &data->ShowModes[showUserMode1].itime)); AddHelp(tr("Help$Specify the user-defined time here in 'HH:MM'.")); } szUseUserTime = cString::sprintf("%s %d", tr("Use user-defined time"), 2); Add(new cMenuEditBoolItem( szUseUserTime, &data->ShowModes[showUserMode2].useIt, trVDR("no"), trVDR("yes"))); AddHelp(tr("Help$Besides 'Now' and 'Next' you can specify up to 4 other times in the EPG which can be used by repeatedly pressing the green key, e.g. 'prime time', 'late night',...")); if (data->ShowModes[showUserMode2].GetUsage()) { Add(new cMenuEditStrItem(IndentMenuItem(tr("Description")), data->ShowModes[showUserMode2].description, sizeof(data->ShowModes[showUserMode2].description), trVDR(FileNameChars))); AddHelp(tr("Help$This is the description for your user-defined time as it will appear as label on the green button.")); Add(new cMenuEditTimeItem(IndentMenuItem(tr("Time")), &data->ShowModes[showUserMode2].itime)); AddHelp(tr("Help$Specify the user-defined time here in 'HH:MM'.")); } szUseUserTime = cString::sprintf("%s %d", tr("Use user-defined time"), 3); Add(new cMenuEditBoolItem(szUseUserTime, &data->ShowModes[showUserMode3].useIt, trVDR("no"), trVDR("yes"))); AddHelp(tr("Help$Besides 'Now' and 'Next' you can specify up to 4 other times in the EPG which can be used by repeatedly pressing the green key, e.g. 'prime time', 'late night',...")); if (data->ShowModes[showUserMode3].GetUsage()) { Add(new cMenuEditStrItem(IndentMenuItem(tr("Description")), data->ShowModes[showUserMode3].description, sizeof(data->ShowModes[showUserMode3].description), trVDR(FileNameChars))); AddHelp(tr("Help$This is the description for your user-defined time as it will appear as label on the green button.")); Add(new cMenuEditTimeItem(IndentMenuItem(tr("Time")), &data->ShowModes[showUserMode3].itime)); AddHelp(tr("Help$Specify the user-defined time here in 'HH:MM'.")); } szUseUserTime = cString::sprintf("%s %d", tr("Use user-defined time"), 4); Add(new cMenuEditBoolItem(szUseUserTime, &data->ShowModes[showUserMode4].useIt, trVDR("no"), trVDR("yes"))); AddHelp(tr("Help$Besides 'Now' and 'Next' you can specify up to 4 other times in the EPG which can be used by repeatedly pressing the green key, e.g. 'prime time', 'late night',...")); if (data->ShowModes[showUserMode4].GetUsage()) { Add(new cMenuEditStrItem(IndentMenuItem(tr("Description")), data->ShowModes[showUserMode4].description, sizeof(data->ShowModes[showUserMode4].description), trVDR(FileNameChars))); AddHelp(tr("Help$This is the description for your user-defined time as it will appear as label on the green button.")); Add(new cMenuEditTimeItem(IndentMenuItem(tr("Time")), &data->ShowModes[showUserMode4].itime)); AddHelp(tr("Help$Specify the user-defined time here in 'HH:MM'.")); } SetCurrent(Get(current)); Display(); SetHelp(NULL, NULL, tr("Button$Help"), NULL); } eOSState cMenuSetupUserdefTimes::ProcessKey(eKeys Key) { int iTemp_useUserTime1 = data->ShowModes[showUserMode1].GetUsage(); int iTemp_useUserTime2 = data->ShowModes[showUserMode2].GetUsage(); int iTemp_useUserTime3 = data->ShowModes[showUserMode3].GetUsage(); int iTemp_useUserTime4 = data->ShowModes[showUserMode4].GetUsage(); eOSState state = cMenuSetupSubMenu::ProcessKey(Key); if (iTemp_useUserTime1 != data->ShowModes[showUserMode1].GetUsage() || iTemp_useUserTime2 != data->ShowModes[showUserMode2].GetUsage() || iTemp_useUserTime3 != data->ShowModes[showUserMode3].GetUsage() || iTemp_useUserTime4 != data->ShowModes[showUserMode4].GetUsage()) { Set(); Display(); } if (state == osUnknown) { switch (Key) { case kOk: return osBack; default: break; } } return state; } // ------------------ // cMenuSetupTimers cMenuSetupTimers::cMenuSetupTimers(cEPGSearchConfig* Data) : cMenuSetupSubMenu(tr("Timer programming"), Data) { Set(); } void cMenuSetupTimers::Set() { int current = Current(); Clear(); helpTexts.clear(); Add(new cMenuEditBoolItem( tr("Use VDR's timer edit menu"), &data->useVDRTimerEditMenu, trVDR("no"), trVDR("yes"))); AddHelp(tr("Help$This plugin has its own timer edit menu extending the original one with some extra functionality like\n- an additional directory entry\n- user-defined days of week for repeating timers\n- adding an episode name\n- support for EPG variables (see MANUAL)")); Add(new cMenuEditStrItem(tr("Default recording dir"), data->defrecdir, sizeof(data->defrecdir), tr(AllowedChars))); AddHelp(tr("Help$When creating a timer you can specify here a default recording directory.")); Add(new cMenuEditStraItem(tr("Add episode to manual timers"), &data->addSubtitleToTimer, 3, AddSubtitleMode)); AddHelp(tr("Help$If you create a timer for a series, you can automatically add the episode name.\n\n- never: no addition\n- always: always add episode name if present\n- smart: add only if event lasts less than 80 mins.")); Add(new cOsdItem(tr("Default timer check method"))); AddHelp(tr("Help$Manual timers can be checked for EPG changes. Here you can setup the default check method for each channel. Choose between\n\n- no checking\n- by event ID: checks by an event ID supplied by the channel provider.\n- by channel and time: check by the duration match.")); SetCurrent(Get(current)); Display(); SetHelpKeys(); } void cMenuSetupTimers::SetHelpKeys() { const char* ItemText = Get(Current())->Text(); if (!HasSubMenu()) { if (strstr(ItemText, tr("Default recording dir")) == ItemText) { if (!InEditMode(ItemText, tr("Default recording dir"), data->defrecdir)) SetHelp(NULL, NULL, tr("Button$Help"), tr("Button$Select")); } else if (strstr(ItemText, tr("Default timer check method")) == ItemText) SetHelp(NULL, NULL, tr("Button$Help"), tr("Button$Setup")); else SetHelp(NULL, NULL, tr("Button$Help"), NULL); } } eOSState cMenuSetupTimers::ProcessKey(eKeys Key) { eOSState state = cMenuSetupSubMenu::ProcessKey(Key); const char* ItemText = Get(Current())->Text(); int iOnDefRecDir = 0; int iOnDefTimerCheck = 0; if (!HasSubMenu()) { if (strstr(ItemText, tr("Default recording dir")) == ItemText) iOnDefRecDir = 1; if (strstr(ItemText, tr("Default timer check method")) == ItemText) iOnDefTimerCheck = 1; } SetHelpKeys(); if (state == osUnknown) { switch (Key) { case kBlue: if (!HasSubMenu()) { if (iOnDefRecDir == 1) state = AddSubMenu(new cMenuDirSelect(data->defrecdir)); if (iOnDefTimerCheck == 1) state = AddSubMenu(new cMenuDefTimerCheckMethod()); } break; case kOk: return osBack; default: break; } } return state; } // ------------------ // cMenuSetupSearchtimers cMenuSetupSearchtimers::cMenuSetupSearchtimers(cEPGSearchConfig* Data) : cMenuSetupSubMenu(tr("Search and search timers"), Data) { menuitemsChGr = NULL; Set(); } cMenuSetupSearchtimers::~cMenuSetupSearchtimers() { if (menuitemsChGr) free(menuitemsChGr); } void cMenuSetupSearchtimers::Set() { int current = Current(); Clear(); helpTexts.clear(); Add(new cMenuEditBoolItem(tr("Use search timers"), &data->useSearchTimers, trVDR("no"), trVDR("yes"))); AddHelp(tr("Help$'Search timers' can be used to automatically create timers for events that match your search criterions.")); if (data->useSearchTimers) { Add(new cMenuEditIntItem(tr(" Update interval [min]"), &data->UpdateIntervall, 1, 9999)); AddHelp(tr("Help$Specify here the time intervall to be used when searching for events in the background.")); Add(new cMenuEditIntItem(tr(" SVDRP port"), &data->SVDRPPort, 1, 99999)); AddHelp(tr("Help$Programming of new timers or timer changes is done with SVDRP. The default value should be correct, so change it only if you know what you are doing.")); Add(new cMenuEditIntItem(IndentMenuItem(trVDR("Setup.Recording$Default priority")), &data->DefPriority, 0, MAXPRIORITY)); AddHelp(tr("Help$Specify here the default priority of timers created with this plugin. This value can also be adjusted for each search itself.")); Add(new cMenuEditIntItem(IndentMenuItem(trVDR("Setup.Recording$Default lifetime (d)")), &data->DefLifetime, 0, MAXLIFETIME)); AddHelp(tr("Help$Specify here the default lifetime of timers/recordings created with this plugin. This value can also be adjusted for each search itself.")); Add(new cMenuEditIntItem(IndentMenuItem(trVDR("Setup.Recording$Margin at start (min)")), &data->DefMarginStart)); AddHelp(tr("Help$Specify here the default start recording margin of timers/recordings created with this plugin. This value can also be adjusted for each search itself.")); Add(new cMenuEditIntItem(IndentMenuItem(trVDR("Setup.Recording$Margin at stop (min)")), &data->DefMarginStop)); AddHelp(tr("Help$Specify here the default stop recording margin of timers/recordings created with this plugin. This value can also be adjusted for each search itself.")); Add(new cMenuEditBoolItem(IndentMenuItem(tr("No announcements when replaying")), &data->noAnnounceWhileReplay, trVDR("no"), trVDR("yes"))); AddHelp(tr("Help$Set this to 'yes' if you don't like to get any announcements of broadcasts if you currently replay anything.")); Add(new cMenuEditBoolItem(IndentMenuItem(tr("Recreate timers after deletion")), &data->TimerProgRepeat, trVDR("no"), trVDR("yes"))); AddHelp(tr("Help$Set this to 'yes' if you want timers to be recreated with the next search timer update after deleting them.")); Add(new cMenuEditIntItem(IndentMenuItem(tr("Check if EPG exists for ... [h]")), &data->checkEPGHours, 0, 999)); AddHelp(tr("Help$Specify how many hours of future EPG there should be and get warned else after a search timer update.")); if (data->checkEPGHours > 0) { Add(new cMenuEditBoolItem(IndentMenuItem(tr("Warn by OSD"),2), &data->checkEPGWarnByOSD, trVDR("no"), trVDR("yes"))); AddHelp(tr("Help$Set this to 'yes' if you want get warnings from the EPG check via OSD.")); Add(new cMenuEditBoolItem(IndentMenuItem(tr("Warn by mail"),2), &data->checkEPGWarnByMail, trVDR("no"), trVDR("yes"))); AddHelp(tr("Help$Set this to 'yes' if you want get warnings from the EPG check by mail.")); // create the char array for the menu display if (menuitemsChGr) delete [] menuitemsChGr; menuitemsChGr = ChannelGroups.CreateMenuitemsList(); Add(new cMenuEditStraItem(IndentMenuItem(tr("Channel group to check"),2), &data->checkEPGchannelGroupNr, ChannelGroups.Count()+1, menuitemsChGr)); AddHelp(tr("Help$Specify the channel group to check.")); } } Add(new cMenuEditBoolItem( tr("Ignore PayTV channels"), &data->ignorePayTV, trVDR("no"), trVDR("yes"))); AddHelp(tr("Help$Set this to 'yes' if don't want to see events on PayTV channels when searching for repeats.")); Add(new cOsdItem(tr("Search templates"))); AddHelp(tr("Help$Here you can setup templates for your searches.")); Add(new cOsdItem(tr("Blacklists"))); AddHelp(tr("Help$Here you can setup blacklists which can be used within a search to exclude events you don't like.")); Add(new cOsdItem(tr("Channel groups"))); AddHelp(tr("Help$Here you can setup channel groups which can be used within a search. These are different to VDR channel groups and represent a set of arbitrary channels, e.g. 'FreeTV'.")); SetCurrent(Get(current)); Display(); SetHelpKeys(); } void cMenuSetupSearchtimers::SetHelpKeys() { const char* ItemText = Get(Current())->Text(); if (!HasSubMenu()) { if (strstr(ItemText, tr("Channel groups")) == ItemText) SetHelp(NULL, NULL, tr("Button$Help"), tr("Button$Setup")); else if (strstr(ItemText, tr("Search templates")) == ItemText) SetHelp(NULL, NULL, tr("Button$Help"), tr("Button$Setup")); else if (strstr(ItemText, tr("Blacklists")) == ItemText) SetHelp(NULL, NULL, tr("Button$Help"), tr("Button$Setup")); else SetHelp(NULL, NULL, tr("Button$Help"), NULL); } } eOSState cMenuSetupSearchtimers::ProcessKey(eKeys Key) { int iTemp_useSearchTimers = data->useSearchTimers; int iTemp_checkEPGHours = data->checkEPGHours; int iOnSearchTemplates = 0; int iOnBlacklists = 0; int iOnChannelGroups = 0; eOSState state = cMenuSetupSubMenu::ProcessKey(Key); if (iTemp_useSearchTimers != data->useSearchTimers || iTemp_checkEPGHours != data->checkEPGHours) { Set(); Display(); } const char* ItemText = Get(Current())->Text(); if (!HasSubMenu()) { if (strstr(ItemText, tr("Search templates")) == ItemText) iOnSearchTemplates = 1; else if (strstr(ItemText, tr("Blacklists")) == ItemText) iOnBlacklists = 1; if (strstr(ItemText, tr("Channel groups")) == ItemText) iOnChannelGroups = 1; } SetHelpKeys(); if (state == osUnknown) { switch (Key) { case kBlue: if (!HasSubMenu()) { if (iOnSearchTemplates == 1) state = AddSubMenu(new cMenuEPGSearchTemplate(NULL, NULL, false)); else if (iOnBlacklists == 1) state = AddSubMenu(new cMenuBlacklists); else if (iOnChannelGroups == 1) state = AddSubMenu(new cMenuChannelGroups); } break; case kOk: return osBack; default: break; } } return state; } // ------------------------ // cMenuSetupTimerConflicts cMenuSetupTimerConflicts::cMenuSetupTimerConflicts(cEPGSearchConfig* Data) : cMenuSetupSubMenu(tr("Timer conflict checking"), Data) { Set(); } void cMenuSetupTimerConflicts::Set() { int current = Current(); Clear(); helpTexts.clear(); Add(new cMenuEditIntItem(tr("Ignore below priority"), &data->checkMinPriority, 0, MAXPRIORITY)); AddHelp(tr("Help$If a timer with priority below the given value will fail it will not be classified as important. Only important conflicts will produce an OSD message about the conflict after an automatic conflict check.")); Add(new cMenuEditIntItem(tr("Ignore conflict duration less ... min."), &data->checkMinDuration, 0, 999)); AddHelp(tr("Help$If a conflicts duration is less then the given number of minutes it will not be classified as important. Only important conflicts will produce an OSD message about the conflict after an automatic conflict check.")); Add(new cMenuEditIntItem(tr("Only check within next ... days"), &data->checkMaxDays, 1, 14)); AddHelp(tr("Help$This value reduces the conflict check to the given range of days. All other conflicts are classified as 'not yet important'.")); Add(new cMenuEditBoolItem(tr("Check also remote conflicts"), &data->RemoteConflictCheck, trVDR("no"), trVDR("yes"))); AddHelp(tr("Help$Set this to 'yes' if the conflict check should be done for timers set on remote hosts. This needs SVDRPPeering to be set in vdr and Plugin epgsearch running on the remote host.")); cOsdItem* sep = new cOsdItem(tr("--- Automatic checking ---")); sep->SetSelectable(false); Add(sep); AddHelp("dummy"); Add(new cMenuEditBoolItem(tr("After each timer programming"), &data->checkTimerConflAfterTimerProg, trVDR("no"), trVDR("yes"))); AddHelp(tr("Help$Set this to 'yes' if the conflict check should be performed after each manual timer programming. In the case of a conflict you get immediately a message that informs you about it. The message is only displayed if this timer is involved in any conflict.")); Add(new cMenuEditBoolItem(tr("When a recording starts"), &data->checkTimerConflOnRecording, trVDR("no"), trVDR("yes"))); AddHelp(tr("Help$Set this to 'yes' if the conflict check should be performed when a recording starts. In the case of a conflict you get immediately a message that informs you about it. The message is only displayed if the conflict is within the next 2 hours.")); Add(new cMenuEditBoolItem(tr("After each search timer update"), &data->checkTimerConflictsAfterUpdate, trVDR("no"), trVDR("yes"))); AddHelp(tr("Help$Set this to 'yes' if the conflict check should be performed after each search timer update.")); if (!data->checkTimerConflictsAfterUpdate) { Add(new cMenuEditIntItem(IndentMenuItem(tr("every ... minutes")), &data->conflictCheckIntervall, 0, 999)); AddHelp(tr("Help$Specify here the time intervall to be used for an automatic conflict check in the background.\n('0' disables an automatic check)")); Add(new cMenuEditIntItem(IndentMenuItem(tr("if conflicts within next ... minutes")), &data->conflictCheckWithinLimit, 0, 9999)); AddHelp(tr("Help$If the next conflict will appear in the given number of minutes you can specify here a shorter check intervall to get more OSD notifications about it.")); if (data->conflictCheckWithinLimit) { Add(new cMenuEditIntItem(IndentMenuItem(IndentMenuItem(tr("every ... minutes"))), &data->conflictCheckIntervall2, 1, 999)); AddHelp(tr("Help$If the next conflict will appear in the given number of minutes you can specify here a shorter check intervall to get more OSD notifications about it.")); } } Add(new cMenuEditBoolItem(tr("Avoid notification when replaying"), &data->noConflMsgWhileReplay, trVDR("no"), trVDR("yes"))); AddHelp(tr("Help$Set this to 'yes' if the don't want to get OSD messages about conflicts if you currently replay something. Nevertheless messages will be displayed if the first upcoming conflict is within the next 2 hours.")); SetCurrent(Get(current)); Display(); SetHelp(NULL, NULL, tr("Button$Help"), NULL); } eOSState cMenuSetupTimerConflicts::ProcessKey(eKeys Key) { int iTemp_checkTimerConflictsAfterUpdate = data->checkTimerConflictsAfterUpdate; int iTemp_conflictCheckWithinLimit = data->conflictCheckWithinLimit; eOSState state = cMenuSetupSubMenu::ProcessKey(Key); if (iTemp_checkTimerConflictsAfterUpdate != data->checkTimerConflictsAfterUpdate || (iTemp_conflictCheckWithinLimit != data->conflictCheckWithinLimit && (iTemp_conflictCheckWithinLimit == 0 || data->conflictCheckWithinLimit == 0))) { Set(); Display(); } if (state == osUnknown) { switch (Key) { case kOk: return osBack; default: break; } } return state; } // -------------------------- // cMenuSetupMailNotification cMenuSetupMailNotification::cMenuSetupMailNotification(cEPGSearchConfig* Data) : cMenuSetupSubMenu(tr("Email notification"), Data) { string strHidden(strlen(data->MailAuthPass), '*'); strcpy(tmpMailAuthPass, strHidden.c_str()); Set(); } void cMenuSetupMailNotification::Set() { int current = Current(); Clear(); helpTexts.clear(); Add(new cMenuEditBoolItem(tr("Search timer notification"), &data->sendMailOnSearchtimers, trVDR("no"), trVDR("yes"))); AddHelp(tr("Help$Set this to 'yes' if you want to get an email notification about the search timers that where programmed automatically in the background.")); if (data->sendMailOnSearchtimers) { Add(new cMenuEditIntItem(IndentMenuItem(tr("Time between mails [h]")), &data->sendMailOnSearchtimerHours, 0, 999999, "")); AddHelp(tr("Help$Specifiy how much time in [h] you would\nlike to have atleast between two mails.\nWith '0' you get a new mail after each\nsearch timer update with new results.")); } Add(new cMenuEditBoolItem(tr("Timer conflict notification"), &data->sendMailOnConflicts, trVDR("no"), trVDR("yes"))); AddHelp(tr("Help$Set this to 'yes' if you want to get an email notification about the timer conflicts.")); Add(new cMenuEditStrItem(tr("Send to"), data->MailAddressTo, sizeof(data->MailAddressTo), MailBoxChars)); AddHelp(tr("Help$Specify the email address where notifications should be sent to.")); Add(new cMenuEditStraItem(tr("Mail method"), &data->mailViaScript, 2, MailMethod)); AddHelp(tr("Help$Specify here the method to use when sending mails.\nYou can choose between\n - 'sendmail': requires a properly configured email system\n - 'SendEmail.pl': simple script for mail delivery")); if (data->mailViaScript) { cOsdItem* sep = new cOsdItem(tr("--- Email account ---")); sep->SetSelectable(false); Add(sep); AddHelp(" dummy"); Add(new cMenuEditStrItem(tr("Email address"), data->MailAddress, sizeof(data->MailAddress), MailBoxChars)); AddHelp(tr("Help$Specify the email address where notifications should be sent from.")); Add(new cMenuEditStrItem(tr("SMTP server"), data->MailServer, sizeof(data->MailServer), HostNameChars)); AddHelp(tr("Help$Specify the SMTP server that should deliver the notifications. If it's using a port different from the default(25) append the port with \":port\".")); Add(new cMenuEditBoolItem(tr("Use SMTP authentication"), &data->MailUseAuth, trVDR("no"), trVDR("yes"))); AddHelp(tr("Help$Set this to 'yes' if your account needs authentication to send mails.")); if (data->MailUseAuth) { Add(new cMenuEditStrItem(IndentMenuItem(tr("Auth user")), data->MailAuthUser, sizeof(data->MailAuthUser), UserNameChars)); AddHelp(tr("Help$Specify the auth user, if this account needs authentication for SMTP.")); Add(new cMenuEditStrItem(IndentMenuItem(tr("Auth password")), tmpMailAuthPass, sizeof(tmpMailAuthPass), PasswordChars)); AddHelp(tr("Help$Specify the auth password, if this account needs authentication for SMTP.")); } } SetCurrent(Get(current)); Display(); SetHelpKeys(); } eOSState cMenuSetupMailNotification::TestMailAccount() { if (strlen(data->MailAddress) == 0 || strlen(data->MailServer) == 0) return osContinue; cMailNotifier M; if (M.TestMailAccount(data->MailAddressTo, data->MailAddress, data->MailServer, data->MailAuthUser, data->MailAuthPass)) return AddSubMenu(new cMenuText("", M.scriptReply.c_str(), fontSml)); else ERROR(tr("Mail account check failed!")); return osContinue; } void cMenuSetupMailNotification::SetHelpKeys() { bool showTestButton = strlen(data->MailAddress) > 0 && strlen(data->MailServer) > 0 && data->mailViaScript; const char* ItemText = Get(Current())->Text(); if (!HasSubMenu()) { if (strstr(ItemText, tr("Email address")) == ItemText) { if (!InEditMode(ItemText, tr("Email address"), data->MailAddress)) SetHelp(NULL, NULL, tr("Button$Help"), showTestButton?tr("Button$Test"):NULL); } else if (strstr(ItemText, tr("SMTP server")) == ItemText) { if (!InEditMode(ItemText, tr("SMTP server"), data->MailServer)) SetHelp(NULL, NULL, tr("Button$Help"), showTestButton?tr("Button$Test"):NULL); } else if (strstr(ItemText, tr("Use SMTP authentication")) == ItemText) SetHelp(NULL, NULL, tr("Button$Help"), showTestButton?tr("Button$Test"):NULL); else if (strstr(ItemText, IndentMenuItem(tr("Auth user"))) == ItemText) { if (!InEditMode(ItemText, IndentMenuItem(tr("Auth user")), data->MailAuthUser)) SetHelp(NULL, NULL, tr("Button$Help"), showTestButton?tr("Button$Test"):NULL); } else if (strstr(ItemText, IndentMenuItem(tr("Auth password"))) == ItemText) { if (!InEditMode(ItemText, IndentMenuItem(tr("Auth password")), tmpMailAuthPass)) SetHelp(NULL, NULL, tr("Button$Help"), showTestButton?tr("Button$Test"):NULL); } else SetHelp(NULL, NULL, tr("Button$Help"), NULL); } } eOSState cMenuSetupMailNotification::ProcessKey(eKeys Key) { int iTemp_MailUseAuth = data->MailUseAuth; int iTemp_sendMailOnSearchtimers = data->sendMailOnSearchtimers; int iTemp_mailViaScript = data->mailViaScript; const char* ItemText = Get(Current())->Text(); bool bAuthPassWasInEditMode = false; if (ItemText && strlen(ItemText) > 0 && strstr(ItemText, IndentMenuItem(tr("Auth password"))) == ItemText) bAuthPassWasInEditMode = InEditMode(ItemText, IndentMenuItem(tr("Auth password")), tmpMailAuthPass); eOSState state = cMenuSetupSubMenu::ProcessKey(Key); ItemText = Get(Current())->Text(); bool bAuthPassIsInEditMode = false; if (ItemText && strlen(ItemText) > 0 && strstr(ItemText, IndentMenuItem(tr("Auth password"))) == ItemText) bAuthPassIsInEditMode = InEditMode(ItemText, IndentMenuItem(tr("Auth password")), tmpMailAuthPass); if (bAuthPassWasInEditMode && !bAuthPassIsInEditMode) { strcpy(data->MailAuthPass, tmpMailAuthPass); string strHidden(strlen(data->MailAuthPass), '*'); strcpy(tmpMailAuthPass, strHidden.c_str()); Set(); Display(); } if (!bAuthPassWasInEditMode && bAuthPassIsInEditMode) { strcpy(tmpMailAuthPass, ""); Set(); Display(); state = cMenuSetupSubMenu::ProcessKey(Key); } if (iTemp_MailUseAuth != data->MailUseAuth || iTemp_mailViaScript != data->mailViaScript || iTemp_sendMailOnSearchtimers != data->sendMailOnSearchtimers) { Set(); Display(); } SetHelpKeys(); if (state == osUnknown) { switch (Key) { case kOk: return osBack; case kBlue: if (data->mailViaScript) return TestMailAccount(); else return osContinue; default: break; } } return state; } vdr-plugin-epgsearch/README0000777000175000017500000000000013145412721021452 2./doc/en/epgsearch.1.txtustar tobiastobiasvdr-plugin-epgsearch/INSTALL.DE0000644000175000017500000000200613145412721015746 0ustar tobiastobiasHier gibt es nichts besonderes. Bitte wie jedes andere Standard-Plugin installieren (entpacken, soft link, make plugins). Eine kleine Besonderheit: Wer lieber mit Perl compatible regular expressions in der Suche arbeitet, sollte einfach im Makefile des Plugins '#REGEXLIB = pcre' in 'REGEXLIB = pcre' ändern oder einfach REGEXLIB=pcre an den 'make plugins'-Aufruf anhängen. Hierzu muss pcreposix installiert sein, das in der libpcre von www.pcre.org enthalten ist. Dies sollte aber in den meisten Distributionen bereits enthalten sein. HINWEIS: wenn alles normal kompiliert, aber beim Start von VDR folgendes kommt: ERROR: /usr/lib/libpcreposix.so.0: undefined symbol: pcre_free). dann bitte libpcre von www.pcre.org updaten und das Plugin neu kompilieren. Scheinbar gibt es auf manchen Systemen Probleme mit PCRE, die sich in einem Crash äußern, wenn man reg. Ausdrücke benutzt. Da ich die Ursache bisher nicht finden konnte, empfehle ich deshalb auf REGEXLIB=pcre zu verzichten, wenn es nicht unbedingt notwendig ist. vdr-plugin-epgsearch/templatefile.c0000644000175000017500000002300513145412721017247 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #include #include "templatefile.h" #include "epgsearchcfg.h" #include "epgsearchtools.h" std::set cTemplFile::menuTemplates; char** cTemplFile::SearchTemplates = NULL; bool cMenuTemplate::PrepareTemplate(const char* templateLine) { if (!templateLine || strlen(templateLine) == 0) return true; char *pstrSearchToken, *pptr; char *pstrSearch=strdup(templateLine); pstrSearchToken=strtok_r(pstrSearch, "|", &pptr); cString stripped; int iToken = 0; while(pstrSearchToken) { char* tmp = strchr(pstrSearchToken,':'); if (tmp) { int tabWidth = atoi(tmp+1); if (tabWidth == 0) { LogFile.eSysLog("warning - tab width in \"%s\" is 0, set to min value 1!", Name()); tabWidth = 1; } menuTabs[iToken++] = tabWidth; } else { free(pstrSearch); LogFile.eSysLog("error parsing entry \"%s\", falling back to default entries.", Name()); return false; } *tmp = 0; if (isempty(stripped)) stripped = strdup(pstrSearchToken); else { cString tmp = stripped; stripped = cString::sprintf("%s|%s", *tmp, pstrSearchToken); } pstrSearchToken=strtok_r(NULL, "|", &pptr); } free(pstrSearch); // no limit for the last column if (iToken>0) menuTabs[iToken-1] = 0; if (!isempty(stripped)) { menuTemplate = strdup(stripped); // the status variables are handled in menu_whatson.c itself // to speedup the var-parser we 'hide' them here in renaming them menuTemplate = strreplacei(menuTemplate, "%status%", "$status$"); menuTemplate = strreplacei(menuTemplate, "%t_status%", "$t_status$"); menuTemplate = strreplacei(menuTemplate, "%v_status%", "$v_status$"); menuTemplate = strreplacei(menuTemplate, "%r_status%", "$r_status$"); } return true; } cTemplLine::cTemplLine(void) { name = value = NULL; } cTemplLine::cTemplLine(const char *Name, const char *Value) { name = strdup(Name); value = strdup(Value); } cTemplLine::~cTemplLine() { free(name); free(value); } bool cTemplLine::Parse(char *s) { if (!s) return false; if (s[0] == '#') return true; char *p = strchr(s, '='); if (p) { *p = 0; char *Name = compactspace(s); char *Value = compactspace(p + 1); if (*Name) { name = strdup(Name); value = strdup(Value); return true; } } return false; } cTemplFile::cTemplFile() { Reset(); } void cTemplFile::Reset() { std::set::iterator it; for (it = menuTemplates.begin(); it != menuTemplates.end(); ++it) delete (*it); menuTemplates.clear(); } cMenuTemplate* cTemplFile::GetTemplateByName(const char* Name) { std::set::iterator it; for (it = menuTemplates.begin(); it != menuTemplates.end(); ++it) if (!strcasecmp(Name, (*it)->Name())) return (*it); return NULL; } bool cTemplFile::Load(const char *FileName) { // auto-enable WarEagle-Icons if VDRSymbols font is used if (strstr(Setup.FontOsd, "VDRSymbols") == Setup.FontOsd) EPGSearchConfig.WarEagle = 1; if (cConfig::Load(FileName, true)) { bool result = true; for (cTemplLine *l = First(); l; l = Next(l)) { bool error = false; if (!Parse(l->Name(), l->Value())) error = true; if (error) { result = false; } } return result; } return false; } bool cTemplFile::Parse(const char *Name, const char *Value) { if (Name && Name[0] == '#') return true; if (!strcasecmp(Name, "WarEagleIcons")) { EPGSearchConfig.WarEagle = atoi(Value); return true; } if (!strcasecmp(Name, "MenuWhatsOnNow") || !strcasecmp(Name, "MenuWhatsOnNext") || !strcasecmp(Name, "MenuWhatsOnElse") || !strcasecmp(Name, "MenuSchedule") || !strncasecmp(Name, "MenuSearchResults", strlen("MenuSearchResults")) || !strcasecmp(Name, "MenuFavorites")) { cMenuTemplate* menuTemplate = new cMenuTemplate(Name); if (menuTemplate->PrepareTemplate(Value)) { LogFile.Log(3, "loaded menu template: %s", Name); cMenuTemplate* TemplOld = GetTemplateByName(Name); if (TemplOld) { LogFile.Log(1, "menu template '%s' gets overwritten", Name); menuTemplates.erase(TemplOld); delete TemplOld; } menuTemplates.insert(menuTemplate); return true; } } else { LogFile.eSysLog("ERROR: unknown parameter: %s = %s", Name, Value); return false; } return true; } void cTemplFile::PrepareDefaultTemplates() { char channelnr[20] = ""; { LOCK_CHANNELS_READ; // Channels used in CHNUMWIDTH sprintf(channelnr, "%%chnr%%:%d|", CHNUMWIDTH); } bool text2skin = !(strcmp(Setup.OSDSkin, "soppalusikka") == 0 || strcmp(Setup.OSDSkin, "classic") == 0 || strcmp(Setup.OSDSkin, "sttng") == 0); char menutemplate[MAXTEMPLLEN] = ""; // What's on now cMenuTemplate* WhatsOnNow = GetTemplateByName("MenuWhatsOnNow"); if (!WhatsOnNow) { WhatsOnNow = new cMenuTemplate("MenuWhatsOnNow"); menuTemplates.insert(WhatsOnNow); } if (WhatsOnNow && WhatsOnNow->MenuTemplate() == 0) { sprintf(menutemplate, "%s%%chsh%%:12|%%time%%:6|%s%s$status$:3|%%title%% ~ %%subtitle%%:30", EPGSearchConfig.showChannelNr?channelnr:"", EPGSearchConfig.showProgress==0?"":(EPGSearchConfig.showProgress==1?"%progrT2S%:4|":"%progr%:5|"), text2skin?" ":""); WhatsOnNow->PrepareTemplate(menutemplate); } // What's on next and else sprintf(menutemplate, "%s%%chsh%%:12|%%time%%:7|$status$:4|%%title%% ~ %%subtitle%%:30", EPGSearchConfig.showChannelNr?channelnr:""); cMenuTemplate* WhatsOnNext = GetTemplateByName("MenuWhatsOnNext"); if (!WhatsOnNext) { WhatsOnNext = new cMenuTemplate("MenuWhatsOnNext"); menuTemplates.insert(WhatsOnNext); } if (WhatsOnNext && WhatsOnNext->MenuTemplate() == 0) WhatsOnNext->PrepareTemplate(menutemplate); cMenuTemplate* WhatsOnElse = GetTemplateByName("MenuWhatsOnElse"); if (!WhatsOnElse) { WhatsOnElse = new cMenuTemplate("MenuWhatsOnElse"); menuTemplates.insert(WhatsOnElse); } if (WhatsOnElse && WhatsOnElse->MenuTemplate() == 0) WhatsOnElse->PrepareTemplate(menutemplate); // Schedule cMenuTemplate* Schedule = GetTemplateByName("MenuSchedule"); if (!Schedule) { Schedule = new cMenuTemplate("MenuSchedule"); menuTemplates.insert(Schedule); } if (Schedule && Schedule->MenuTemplate() == 0) { strcpy(menutemplate, "%time_w% %time_d%:7|%time%:6|$status$:4|%title% ~ %subtitle%:30"); Schedule->PrepareTemplate(menutemplate); } // Search results cMenuTemplate* SearchResults = GetTemplateByName("MenuSearchResults"); if (!SearchResults) { SearchResults = new cMenuTemplate("MenuSearchResults"); menuTemplates.insert(SearchResults); } if (SearchResults && SearchResults->MenuTemplate() == 0) { sprintf(menutemplate, "%s%%chsh%%:12|%%datesh%%:6|%%time%%:6|$status$:3|%%title%% ~ %%subtitle%%:30", EPGSearchConfig.showChannelNr?channelnr:""); SearchResults->PrepareTemplate(menutemplate); } // Favorites cMenuTemplate* Favorites = GetTemplateByName("MenuFavorites"); if (!Favorites) { Favorites = new cMenuTemplate("MenuFavorites"); menuTemplates.insert(Favorites); } if (Favorites && Favorites->MenuTemplate() == 0) { sprintf(menutemplate, "%s%%chsh%%:12|%%time%%:6|%%timespan%%:7|$status$:3|%%title%% ~ %%subtitle%%:30", EPGSearchConfig.showChannelNr?channelnr:""); Favorites->PrepareTemplate(menutemplate); } // create an array of all search template names if (SearchTemplates) delete [] SearchTemplates; SearchTemplates = new char*[CountSearchResultsTemplates()]; std::set::iterator it; int Count = 0; for (it = menuTemplates.begin(); it != menuTemplates.end(); ++it) if (!strncasecmp("MenuSearchResults", (*it)->Name(), strlen("MenuSearchResults"))) { char* templateName = strdup((*it)->Name() + strlen("MenuSearchResults")); if (*templateName == 0) templateName = strdup(tr("Standard")); SearchTemplates[Count++] = templateName; } } int cTemplFile::CountSearchResultsTemplates() { int Count = 0; std::set::iterator it; for (it = menuTemplates.begin(); it != menuTemplates.end(); ++it) if (!strncasecmp("MenuSearchResults", (*it)->Name(), strlen("MenuSearchResults"))) Count++; return Count; } cMenuTemplate* cTemplFile::GetSearchTemplateByPos(int iPos) { int Count = 0; std::set::iterator it; for (it = menuTemplates.begin(); it != menuTemplates.end(); ++it) if (!strncasecmp("MenuSearchResults", (*it)->Name(), strlen("MenuSearchResults"))) if(Count++ == iPos) return (*it); return NULL; } vdr-plugin-epgsearch/conflictcheckonly.c0000644000175000017500000000636013145412721020302 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #include #include #include #include "services.h" #include "mainmenushortcut.h" static const char VERSION[] = "0.0.1"; static const char DESCRIPTION[] = trNOOP("Direct access to epgsearch's conflict check menu"); static const char MAINMENUENTRY[] = trNOOP("Timer conflicts"); static const char SETUPTEXT[] = trNOOP("Conflict info in main menu"); cString DateTime(time_t t) { char buffer[32]; if (t == 0) { time(&t); } struct tm tm_r; tm *tm = localtime_r(&t, &tm_r); snprintf(buffer, sizeof(buffer), "%02d.%02d. %02d:%02d", tm->tm_mday, tm->tm_mon + 1, tm->tm_hour, tm->tm_min); return buffer; } class cPluginConflictcheckonly:public cMainMenuShortcut { private: char *_menuText; public: cPluginConflictcheckonly(); ~cPluginConflictcheckonly(); virtual const char *Version() { return VERSION; } virtual const char *Description() { return I18nTranslate(DESCRIPTION, I18nEpgsearch); } virtual bool Initialize(); virtual cOsdObject *MainMenuAction() { return GetEpgSearchMenu("Epgsearch-conflictmenu-v1.0"); } protected: virtual const char *SetupText() { return I18nTranslate(SETUPTEXT, I18nEpgsearch); } virtual const char *MainMenuText(void); }; cPluginConflictcheckonly::cPluginConflictcheckonly():_menuText(NULL) { } cPluginConflictcheckonly::~cPluginConflictcheckonly() { free(_menuText); } const char *cPluginConflictcheckonly::MainMenuText(void) { const char *menuText = I18nTranslate(MAINMENUENTRY, I18nEpgsearch); cPlugin *epgSearchPlugin = cPluginManager::GetPlugin("epgsearch"); if (epgSearchPlugin) { Epgsearch_lastconflictinfo_v1_0 *serviceData = new Epgsearch_lastconflictinfo_v1_0; if (epgSearchPlugin->Service("Epgsearch-lastconflictinfo-v1.0", serviceData)) { if (serviceData->relevantConflicts > 0) { free(_menuText); if (asprintf(&_menuText, "%s (%d, %s: %s)", menuText, serviceData->relevantConflicts, I18nTranslate(trNOOP("next"), I18nEpgsearch), *DateTime(serviceData->nextConflict))) menuText = _menuText; } } delete serviceData; } return menuText; } bool cPluginConflictcheckonly::Initialize(void) { return cMainMenuShortcut::Initialize(); } VDRPLUGINCREATOR(cPluginConflictcheckonly); // Don't touch this! vdr-plugin-epgsearch/conflictcheck.h0000644000175000017500000002417513145412721017411 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #ifndef __EPGSEARCHCONFLCH_H #define __EPGSEARCHCONFLCH_H #include "epgsearchtools.h" #include #include #include #include #define DO_MULTIPLE_RECORDINGS 1 #define DO_REC_AND_PLAY_ON_PRIMARY_DEVICE 1 class cConflictCheckTime; class TimerObjSort; // --- cConflictCheckTimerObj -------------------------------------------------------- class cConflictCheckTimerObj : public cTimerObj { const cEvent* event; public: time_t start; time_t stop; int device; int origIndex; int recDuration; time_t lastRecStart; time_t lastRecStop; cConflictCheckTime* conflCheckTime; std::set* concurrentTimers; bool ignore; cConflictCheckTimerObj(cTimer* Timer, time_t Start, time_t Stop, int Device = -1, int OrigIndex=-1); ~cConflictCheckTimerObj(); int Compare(const cListObject &ListObject) const; const cEvent* Event(); const cEvent* SetEventFromSchedule(); int Matches(const cEvent *Event, int *Overlap) const; const cTimer* OrigTimer(const cTimers* timers) const { return timers->GetById(timer->Id(),timer->Remote()); } cTimer* OrigTimer(cTimers* timers) { return timers->GetById(timer->Id(),timer->Remote()); } }; class TimerObjSort { public: bool operator() (cConflictCheckTimerObj* a, cConflictCheckTimerObj* b) { return (a->Compare(*b) < 0); } }; // --- cConflictCheckTime -------------------------------------------------------- class cConflictCheckTime : public cListObject { public: time_t evaltime; std::set startingTimers; std::set stoppingTimers; std::set failedTimers; std::set concurrentRecs; bool ignore; cConflictCheckTime(time_t EvalTime) : evaltime(EvalTime), ignore(false) {} int Compare(const cListObject &ListObject) const { cConflictCheckTime *p = (cConflictCheckTime *)&ListObject; return evaltime - p->evaltime; } }; // --- cConflictCheckDevice -------------------------------------------------------- // This class tries to emulate the behaviour of a DVB device // NOTE: The case device == NULL is only for debugging purposes class cConflictCheckDevice { public: std::set recTimers; cDevice* device; int devicenr; std::vector bondedDevices; cConflictCheckDevice() { device = NULL; devicenr = 0; } int Priority() const { int prio = -1; for(std::set::iterator it = recTimers.begin(); it != recTimers.end(); ++it) prio = std::max(prio, (*it)->timer->Priority()); return prio; }; int CardIndex(void) const { if (device) return device->CardIndex(); else return devicenr;} bool Receiving() const { return !recTimers.empty(); } bool IsTunedTo (const cChannel* Channel) const { for(std::set::iterator it = recTimers.begin(); it != recTimers.end(); ++it) if ((*it)->timer->Channel()->Source() == Channel->Source() && (*it)->timer->Channel()->Transponder() == Channel->Transponder()) return true; return false; } bool HasDecoder() const { if (device) return device->HasDecoder(); else return (devicenr == 3); } bool HasCi() const { if (device) return device->HasCi(); else return (devicenr == 3); } bool IsPrimaryDevice() const { if (device) return device->IsPrimaryDevice(); else return (devicenr == 3); } bool ProvidesSource(int Source) const { if (device) return device->ProvidesSource(Source); else { // int type = Source & cSource::st_Mask; // if (devicenr == 0) return type == cSource::stCable; // if (devicenr > 0) return type == cSource::stTerr; // return false; return true; } } cCamSlot *CamSlot(void) const { if (device) return device->CamSlot(); else return NULL;} int Ca() const { for(std::set::iterator it = recTimers.begin(); it != recTimers.end(); ++it) return (*it)->timer->Channel()->Ca(); return 0; } bool HasPid(int Pid) const { return true; } bool ProvidesChannel(const cChannel *Channel, int Priority = -1, bool *NeedsDetachReceivers = NULL) const { bool result = false; bool hasPriority = Priority < 0 || Priority > this->Priority(); bool needsDetachReceivers = false; if (ProvidesSource(Channel->Source())) { result = hasPriority; if (Priority >= 0 && Receiving()) { if (IsTunedTo(Channel)) { if ((Channel->Vpid() && !HasPid(Channel->Vpid())) || (Channel->Apid(0) && !HasPid(Channel->Apid(0)))) { #ifdef DO_MULTIPLE_RECORDINGS if (CamSlot() && Channel->Ca() >= CA_ENCRYPTED_MIN) { if (CamSlot()->CanDecrypt(Channel)) result = true; else needsDetachReceivers = true; } else if (!IsPrimaryDevice()) result = true; #ifdef DO_REC_AND_PLAY_ON_PRIMARY_DEVICE else result = Priority >= 0; #endif #endif } else result = !IsPrimaryDevice() || Priority >= 0; } else needsDetachReceivers = true; } } if (result) { if (!BondingOk(Channel)) { // This device is bonded, so we need to check the priorities of the others: for (size_t i=0; iPriority() >= Priority) { LogFile.Log(3, "Attached receiver to bonded device %i has higher priority.", bondedDevices[i]->CardIndex()+1); result = false; break; } } if (result) LogFile.Log(3, "Bonding ok, but detaches receiver on device %i.", CardIndex()); else LogFile.Log(3, "Bonding not okay on device %i.", CardIndex()); needsDetachReceivers = Receiving(); } else { LogFile.Log(3, "Bonding ok on device %i.", CardIndex()); } } if (NeedsDetachReceivers) *NeedsDetachReceivers = needsDetachReceivers; return result; } bool BondingOk(const cChannel *Channel) const { if (bondedDevices.empty()) return true; LogFile.Log(3, "Checking for bonding constraints on device %i", CardIndex()+1); cString BondingParams = GetBondingParams(Channel); for(size_t i=0; i< bondedDevices.size(); i++) { // bonding not okay, if a bonded devices records on another polarization or freq. band if (!bondedDevices[i]->recTimers.empty()) { if (strcmp(BondingParams, GetBondingParams((*bondedDevices[i]->recTimers.begin())->timer->Channel())) != 0) { LogFile.Log(3, "Bonded device %i has receiver attached. Not safe to use device.", bondedDevices[i]->CardIndex()+1); return false; } else { LogFile.Log(3, "Bonded device %i has receiver attached but its safe.", bondedDevices[i]->CardIndex()+1); } } else { LogFile.Log(3, "Bonded device %i has no receivers attached - ok.", bondedDevices[i]->CardIndex()+1); } } return true; } cString GetBondingParams(const cChannel *Channel) const //copied from cDVBTuner { cDvbTransponderParameters dtp(Channel->Parameters()); if (Setup.DiSEqC) { if (const cDiseqc *diseqc = Diseqcs.Get(device->CardIndex() + 1, Channel->Source(), Channel->Frequency(), dtp.Polarization(), NULL)) return diseqc->Commands(); } else { bool ToneOff = Channel->Frequency() < Setup.LnbSLOF; bool VoltOff = dtp.Polarization() == 'V' || dtp.Polarization() == 'R'; return cString::sprintf("%c %c", ToneOff ? 't' : 'T', VoltOff ? 'v' : 'V'); } return ""; } }; // --- cConflictCheck -------------------------------------------------------- class cConflictCheck { cList* timerList; cList* evaltimeList; cList* failedList; std::set pendingTimers; cConflictCheckDevice *devices; int numDevices; time_t maxCheck; std::vector camSlotStatusArray; public: int relevantConflicts; int numConflicts; bool localConflicts; time_t nextRelevantConflictDate; cConflictCheck(); ~cConflictCheck(); void InitDevicesInfo(); void Check(); void BondDevices(const char* bondings); void SetLocal() { localConflicts = true; } bool GetLocal() { return localConflicts; } cList* CreateCurrentTimerList(); cList* CreateEvaluationTimeList(cList*); cList* CreateConflictList(cList*, cList* timerList); void CreateRemoteConflictList(cList* timerList, cList* failedList); int GetDevice(cConflictCheckTimerObj* TimerObj, bool *NeedsDetachReceivers); cList* GetFailed() { return failedList; } cList* GetTimers() { return timerList; } void AddConflict(cConflictCheckTimerObj* TimerObj, cConflictCheckTime* Checktime, std::set& pendingTimers); int ProcessCheckTime(cConflictCheckTime* checkTime); bool TimerInConflict(const cTimer*); void EvaluateConflCheckCmd(); eModuleStatus CamSlotModuleStatus(cCamSlot *CamSlot); }; #endif vdr-plugin-epgsearch/main.c0000644000175000017500000000335113145412721015522 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ // The functions contained in this file are pretty dummy // and are included only as a placeholder. Nevertheless, // they *will* get included in the static library if you // don't remove them :) // // Obviously, you 'll have to write yourself the super-duper // functions to include in the resulting library... // Also, it's not necessary to write every function in this file. // Feel free to add more files in this project. They will be // included in the resulting library. // A function adding two integers and returning the result int SampleAddInt(int i1, int i2) { return i1 + i2; } // A function doing nothing ;) void SampleFunction1() { // insert code here } // A function always returning zero int SampleFunction2() { // insert code here return 0; } vdr-plugin-epgsearch/pending_notifications.h0000644000175000017500000000444513145412721021165 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #ifndef __PENDING_NOTIFICATIONS_H #define __PENDING_NOTIFICATIONS_H #include using std::string; // --- cPendingNotification -------------------------------------------------------- class cPendingNotification : public cListObject { public: int type; tEventID eventID; tChannelID channelID; time_t start; uint timerMod; int searchID; string formatted; static char *buffer; cPendingNotification() : type(-1), start(-1), timerMod(-1), searchID(-1) {} cPendingNotification(int Type, tEventID EventID, tChannelID ChannelID, time_t Start, uint TimerMod = -1, int SearchID = -1, string Formatted = "") : type(Type), eventID(EventID), channelID(ChannelID), start(Start), timerMod(TimerMod), searchID(SearchID), formatted(Formatted) {} ~cPendingNotification(); static bool Read(FILE *f); bool Parse(const char *s); const char *ToText(void) const; bool Save(FILE *f); }; class cPendingNotifications : public cList { public: private: char *fileName; public: cPendingNotifications() { fileName = NULL; } void Clear(void) { free(fileName); fileName = NULL; cList::Clear(); } bool Load(const char *FileName = NULL); bool Save(void); }; extern cPendingNotifications PendingNotifications; #endif vdr-plugin-epgsearch/menu_searchactions.c0000644000175000017500000001473313145412721020456 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #include #include #include "menu_commands.h" #include #include #include #include "menu_searchactions.h" #include "menu_searchresults.h" #include "menu_recsdone.h" #include "menu_timersdone.h" #include "menu_switchtimers.h" #include "menu_blacklists.h" #include "epgsearchtools.h" #include "menu_conflictcheck.h" #include "epgsearchcfg.h" #include "searchtimer_thread.h" #include "menu_searchedit.h" using namespace std; #define ACTION_COUNTER 11 extern int updateForced; // --- cMenuSearchActions --------------------------------------------------------- cMenuSearchActions::cMenuSearchActions(cSearchExt* Search, bool DirectCall) :cOsdMenu(tr("Search actions")) { SetMenuCategory(mcCommand); directCall = DirectCall; SetHasHotkeys(); search = Search; Add(new cOsdItem(hk(tr("Execute search")))); Add(new cOsdItem(hk(tr("Use as search timer on/off")))); Add(new cOsdItem(hk(tr("Trigger search timer update")))); Add(new cOsdItem(hk(tr("Show recordings done")))); Add(new cOsdItem(hk(tr("Show timers created")))); Add(new cOsdItem(hk(tr("Create a copy")))); Add(new cOsdItem(hk(tr("Use as template")))); Add(new cOsdItem(hk(tr("Show switch list")))); Add(new cOsdItem(hk(tr("Show blacklists")))); Add(new cOsdItem(hk(tr("Delete created timers?")))); Add(new cOsdItem(hk(tr("Timer conflict check")))); } cMenuSearchActions::~cMenuSearchActions() { } eOSState cMenuSearchActions::Search(void) { cMenuTemplate* MenuTemplate = NULL; if (!search) return osContinue; if (search->menuTemplate > 0) MenuTemplate = cTemplFile::GetSearchTemplateByPos(search->menuTemplate); if (!MenuTemplate) MenuTemplate = cTemplFile::GetTemplateByName("MenuSearchResults"); return AddSubMenu(new cMenuSearchResultsForSearch(search, MenuTemplate)); } eOSState cMenuSearchActions::OnOffSearchtimer(void) { if (search) { search->useAsSearchTimer = search->useAsSearchTimer?0:1; SearchExts.Save(); if (!search->useAsSearchTimer && Interface->Confirm(tr("Disable associated timers too?"))) search->OnOffTimers(false); if (search->useAsSearchTimer && Interface->Confirm(tr("Activate associated timers too?"))) { search->OnOffTimers(true); if (!EPGSearchConfig.useSearchTimers) // enable search timer thread if necessary { cSearchTimerThread::Init((cPluginEpgsearch*) cPluginManager::GetPlugin("epgsearch"), true); INFO(tr("Search timers activated in setup.")); } } } return osBack; } eOSState cMenuSearchActions::Execute() { int current = Current(); if (current <= ACTION_COUNTER-1) { if (current == 0) return Search(); if (current == 1) return OnOffSearchtimer(); if (current == 2) { if (!EPGSearchConfig.useSearchTimers) // enable search timer thread if necessary { cSearchTimerThread::Init((cPluginEpgsearch*) cPluginManager::GetPlugin("epgsearch"), true); INFO(tr("Search timers activated in setup.")); } if (Interface->Confirm(tr("Run search timer update?"))) updateForced = 3; // with message about completion return osBack; } if (current == 3 && search) return AddSubMenu(new cMenuRecsDone(search)); if (current == 4 && search) return AddSubMenu(new cMenuTimersDone(search)); if (current == 5 && search) { if (!Interface->Confirm(tr("Copy this entry?"))) return osBack; cSearchExt* copy = new cSearchExt; copy->CopyFromTemplate(search); string copyname = string(tr("Copy")) + ": " + search->search; strcpy(copy->search, copyname.c_str()); cMutexLock SearchExtsLock(&SearchExts); copy->ID = SearchExts.GetNewID(); SearchExts.Add(copy); SearchExts.Save(); return AddSubMenu(new cMenuEditSearchExt(copy)); } if (current == 6 && search) { if (!Interface->Confirm(tr("Copy this entry to templates?"))) return osBack; cSearchExt* templateObj = new cSearchExt; templateObj->CopyFromTemplate(search); strcpy(templateObj->search, search->search); cMutexLock SearchTemplatesLock(&SearchTemplates); templateObj->ID = SearchTemplates.GetNewID(); SearchTemplates.Add(templateObj); SearchTemplates.Save(); return osBack; } if (current == 7) return AddSubMenu(new cMenuSwitchTimers()); if (current == 8) return AddSubMenu(new cMenuBlacklists()); if (current == 9) { if (!Interface->Confirm(tr("Delete all timers created from this search?"))) return osBack; search->DeleteAllTimers(); return osBack; } if (current == 10) return AddSubMenu(new cMenuConflictCheck()); } return osContinue; } eOSState cMenuSearchActions::ProcessKey(eKeys Key) { bool hadSubmenu = HasSubMenu(); if (directCall && Key == k1 && !HasSubMenu()) return Search(); eOSState state = cOsdMenu::ProcessKey(Key); // jump back to calling menu, if a command was called directly with key '1' .. '9' if (directCall && hadSubmenu && !HasSubMenu()) return osBack; if (state == osUnknown) { switch (Key) { case kGreen: case kYellow: case kBlue: return osContinue; case kOk: if (!HasSubMenu()) return Execute(); default: break; } } return state; } vdr-plugin-epgsearch/menu_conflictcheck.h0000644000175000017500000000563413145412721020434 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #ifndef __EPGSEARCHMENUCONFL_H #define __EPGSEARCHMENUCONFL_H #include #include "conflictcheck.h" #include "menu_event.h" // --- cMenuConflictCheckItem ------------------------------------------------------ class cMenuConflictCheckItem : public cOsdItem { public: cConflictCheckTime* checktime; cConflictCheckTimerObj* timerObj; cMenuConflictCheckItem(cConflictCheckTime* Ct, cConflictCheckTimerObj* TimerObj = NULL); }; // --- cMenuConflictCheck ------------------------------------------------------ class cMenuConflictCheck : public cOsdMenu { private: cConflictCheck conflictCheck; bool showAll; int lastSel; virtual eOSState ProcessKey(eKeys Key); cConflictCheckTimerObj* CurrentTimerObj(void); void Update(); bool BuildList(); public: cMenuConflictCheck(); }; // --- cMenuConflictCheckDetailsItem ------------------------------------------------------ class cMenuConflictCheckDetailsItem : public cOsdItem { bool hasTimer; public: cConflictCheckTimerObj* timerObj; cMenuConflictCheckDetailsItem(cConflictCheckTimerObj* TimerObj = NULL); bool Update(bool Force = false); }; // --- cMenuConflictCheckDetails ------------------------------------------------------ class cMenuConflictCheckDetails : public cOsdMenu { private: cConflictCheck* conflictCheck; cConflictCheckTimerObj* timerObj; cConflictCheckTime* checktime; cEventObjects eventObjects; virtual eOSState ProcessKey(eKeys Key); cConflictCheckTimerObj* CurrentTimerObj(void); eOSState Commands(eKeys Key); void SetHelpKeys(); eOSState ToggleTimer(cConflictCheckTimerObj* TimerObj); eOSState DeleteTimer(cConflictCheckTimerObj* TimerObj); bool Update(bool Force = false); bool BuildList(); eOSState ShowSummary(); void UpdateCurrent(); public: cMenuConflictCheckDetails(cConflictCheckTimerObj* TimerObj = NULL, cConflictCheck* ConflictCheck = NULL); }; #endif vdr-plugin-epgsearch/menu_search.c0000644000175000017500000001601413145412721017067 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #include #include #include #include #include "menu_search.h" #include "epgsearchtools.h" #include "epgsearchcfg.h" #include "recdone.h" #include "menu_searchedit.h" #include "menu_searchactions.h" #include "timerdone.h" using namespace std; // --- cMenuSearchExtItem ---------------------------------------------------------- class cMenuSearchExtItem : public cOsdItem { private: public: cSearchExt* searchExt; cMenuSearchExtItem(cSearchExt* SearchExt); int Compare(const cListObject &ListObject) const; void Set(void); }; cMenuSearchExtItem::cMenuSearchExtItem(cSearchExt* SearchExt) { searchExt = SearchExt; Set(); } void cMenuSearchExtItem::Set(void) { ostringstream line; if (searchExt->useAsSearchTimer) { if (searchExt->IsActiveAt(time(NULL))) line << ">"; else line << "!"; } line << "\t"; if (searchExt->search && strlen(searchExt->search) > 0) line << setiosflags(ios::left) << string(searchExt->search); else line << setiosflags(ios::left) << "*"; line << "\t"; if (searchExt->useChannel == 1) { if (searchExt->channelMin != searchExt->channelMax) line << setiosflags(ios::left) << searchExt->channelMin->Number() << " - " << searchExt->channelMax->Number(); else line << setiosflags(ios::left) << setw(11) << (searchExt->useChannel?CHANNELNAME(searchExt->channelMin):""); } else if (searchExt->useChannel == 2) line << setiosflags(ios::left) << setw(11) << searchExt->channelGroup; else line << " "; line << "\t"; if (searchExt->useTime) { ostringstream timeline; timeline << setfill('0') << setw(2) << searchExt->startTime / 100 << ":" << setw(2) << searchExt->startTime % 100; timeline << "\t"; timeline << setfill('0') << setw(2) << searchExt->stopTime / 100 << ":" << setw(2) << searchExt->stopTime % 100; line << timeline.str(); } else line << "--:--\t--:--"; SetText(strdup(line.str().c_str()), false); } int cMenuSearchExtItem::Compare(const cListObject &ListObject) const { cMenuSearchExtItem *p = (cMenuSearchExtItem *)&ListObject; return strcasecmp(searchExt->search, p->searchExt->search); } // --- cMenuEPGSearchExt ---------------------------------------------------------- cMenuEPGSearchExt::cMenuEPGSearchExt() :cOsdMenu("", 2, 20, 11, 6, 5) { SetMenuCategory(mcPlugin); cMutexLock SearchExtsLock(&SearchExts); cSearchExt *SearchExt = SearchExts.First(); while (SearchExt) { Add(new cMenuSearchExtItem(SearchExt)); SearchExt = SearchExts.Next(SearchExt); } UpdateTitle(); SetHelp(trVDR("Button$Edit"), trVDR("Button$New"), trVDR("Button$Delete"), tr("Button$Actions")); Sort(); } void cMenuEPGSearchExt::UpdateTitle() { int total=0, active=0; cMutexLock SearchExtsLock(&SearchExts); cSearchExt *SearchExt = SearchExts.First(); while (SearchExt) { if (SearchExt->useAsSearchTimer) active++; SearchExt = SearchExts.Next(SearchExt); total++; } cString buffer = cString::sprintf("%s (%d/%d %s)", tr("Search entries"), active, total, tr("active")); SetTitle(buffer); Display(); } cSearchExt *cMenuEPGSearchExt::CurrentSearchExt(void) { cMenuSearchExtItem *item = (cMenuSearchExtItem *)Get(Current()); if (item && SearchExts.Exists(item->searchExt)) return item->searchExt; return NULL; } eOSState cMenuEPGSearchExt::New(void) { if (HasSubMenu()) return osContinue; return AddSubMenu(new cMenuEditSearchExt(new cSearchExt, true)); } eOSState cMenuEPGSearchExt::Delete(void) { cSearchExt *curSearchExt = CurrentSearchExt(); if (curSearchExt) { if (Interface->Confirm(tr("Edit$Delete search?"))) { int DelID = curSearchExt->ID; if (Interface->Confirm(tr("Delete all timers created from this search?"))) curSearchExt->DeleteAllTimers(); LogFile.Log(1,"search timer %s (%d) deleted", curSearchExt->search, curSearchExt->ID); cMutexLock SearchExtsLock(&SearchExts); SearchExts.Del(curSearchExt); SearchExts.Save(); RecsDone.RemoveSearchID(DelID); TimersDone.RemoveEntriesOfSearch(DelID); cOsdMenu::Del(Current()); Display(); UpdateTitle(); } } return osContinue; } eOSState cMenuEPGSearchExt::Actions(eKeys Key) { if (HasSubMenu() || Count() == 0) return osContinue; cSearchExt* search = CurrentSearchExt(); cMenuSearchActions *menu; eOSState state = AddSubMenu(menu = new cMenuSearchActions(search, true)); if (Key != kNone) state = menu->ProcessKey(Key); return state; } eOSState cMenuEPGSearchExt::ProcessKey(eKeys Key) { int SearchNumber = HasSubMenu() ? Count() : -1; eOSState state = cOsdMenu::ProcessKey(Key); if (state == osUnknown) { switch (Key) { case k0: if (HasSubMenu()) return osContinue; if (CurrentSearchExt()) state = AddSubMenu(new cMenuSearchActions(CurrentSearchExt())); else state = osContinue; break; case k1...k9: return Actions(Key); case kOk: state = Actions(k1); case kBlue: if (HasSubMenu()) return osContinue; state = AddSubMenu(new cMenuSearchActions(CurrentSearchExt())); break; case kRed: if (HasSubMenu()) return osContinue; if (CurrentSearchExt()) state = AddSubMenu(new cMenuEditSearchExt(CurrentSearchExt())); else state = osContinue; break; case kGreen: state = New(); break; case kYellow: state = Delete(); break; default: break; } } if (SearchNumber >= 0 && !HasSubMenu()) { cMutexLock SearchExtsLock(&SearchExts); cSearchExt* search = SearchExts.Get(SearchNumber); if (search) // a newly created search was confirmed with Ok Add(new cMenuSearchExtItem(search)); else search = CurrentSearchExt(); // always update all entries, since channel group names may have changed and affect other searches Sort(); for(int i=0; iSet(); if (item->searchExt == search) SetCurrent(item); } } Display(); UpdateTitle(); } return state; } vdr-plugin-epgsearch/scripts/0000755000175000017500000000000013145412721016117 5ustar tobiastobiasvdr-plugin-epgsearch/scripts/rememberevent.sh0000755000175000017500000000351213145412721021317 0ustar tobiastobias#!/bin/bash # # rememberevent.sh # # source: vdr-plugin epgsearch # # add this lines to your epgsearchcmds.conf: # folgende zeilen in die epgsearchcmds.conf eintragen: # # remember event : /usr/local/bin/rememberevent.sh 0 # remember event (inc. switch): /usr/local/bin/rememberevent.sh 1 # show event list : /usr/local/bin/rememberevent.sh -ls # remove all events? : /usr/local/bin/rememberevent.sh -rm # CONFIG START ATD_SPOOL=/var/spool/atjobs SVDRPSEND=svdrpsend # default settings MINSBEFORE=1 # minutes before event for announcement COLUMNS=17 # columns for the epg entry FORMAT=MET # date format, eg.: UTC/MET # CONFIG END PATH=/usr/local/bin:$PATH case $1 in -ls) grep -s ^'#[0-2][0-9]:[0-5][0-9]#' $ATD_SPOOL/* | sort -t. +1 | cut -d'#' -f3 ;; -rm) find $ATD_SPOOL -exec grep -qs ^'#[0-2][0-9]:[0-5][0-9]#' \{} \; -exec rm -f \{} \; ;; *) switch_time=`date -d "1970-01-01 $FORMAT $3 seconds" +"%a.%d %H:%M"` entry="#${switch_time#* }#$(printf "%-10s%-0s\n" "${6:0:9}" "$switch_time ${2:0:$COLUMNS}")" secs=$(($3-$MINSBEFORE*60)) secs_now=`date +%s` if [ $secs -le $secs_now ]; then echo "$SVDRPSEND MESG '$2 already runs!' >/dev/null" | at now else if [ -z "$(find $ATD_SPOOL -exec grep -qs "^$entry$" \{} \; -exec rm -v \{} \;)" ]; then at $(date -d "1970-01-01 $FORMAT $secs seconds" +"%H:%M %m/%d/%Y") </dev/null sleep $(($MINSBEFORE*60))s if [ $1 -eq 1 ]; then $SVDRPSEND CHAN $5 >/dev/null else $SVDRPSEND MESG '$2 starts!' >/dev/null fi $entry EOT fi fi ;; esac vdr-plugin-epgsearch/scripts/epgsearchcmds-french.conf0000644000175000017500000000345113145412721023044 0ustar tobiastobias# # This is an example of epgsearchcmds.conf with sample entries. # # This file should placed on VDR configuration folder with setup.conf # .../setup.conf # .../plugins/epgsearchcmds.conf # # Syntax is: [?]; # # = descriptor displayed in VDR # [?] = confirmation request, before execute command (optionally) # = command what execute # # When a command is executed the following parameters are passed to it: # # $1: the name of the epg entry # $2: the start time of the epg entry as time_t value (like in the shutdown script) # $3: the end time # $4: the channel of the epg entry # # See also at man-pages vdr(5), it the same syntax as reccmds.conf # ENG remember event? : /usr/local/bin/rememberevent.sh 0 # ENG remember event? (inc. switch) : /usr/local/bin/rememberevent.sh 1 # ENG epg2taste : /usr/local/bin/epg2taste.sh # ENG epg2autotimer : /usr/local/bin/epg2autotimer.sh # # En Francais : Rappel de l'mission? : /usr/lib/vdr/epgsearch/rememberevent.sh 0 Rappel de l'mission? (avec changement de chanes) : /usr/lib/vdr/epgsearch/rememberevent.sh 1 Programme interdit : /usr/lib/vdr/epgsearch/epg2taste.sh Autoprogrammeur : /usr/lib/vdr/epgsearch/epg2autotimer.sh Enregistrement repeter : /usr/lib/vdr/epgsearch/recrep.sh Rappel repeter : /usr/lib/vdr/epgsearch/timerrep.sh # # remember event? : /usr/lib/vdr/epgsearch/rememberevent.sh 0 # remember event? (inc. switch) : /usr/lib/vdr/epgsearch/rememberevent.sh 1 # epg2taste : /usr/lib/vdr/epgsearch/epg2taste.sh # epg2autotimer : /usr/lib/vdr/epgsearch/epg2autotimer.sh vdr-plugin-epgsearch/scripts/recrep.sh0000755000175000017500000000252613145412721017743 0ustar tobiastobias#!/bin/bash #------------------------------------------------------------------------------ # this script allows searching for a repeat of a recording using epgsearch # add the following lines to your reccmds.conf # # Search for repeat : /path_to_this_script/recrep.sh 0 # Search for repeat with subtitle (same episode): /path_to_this_script/recrep.sh 1 # # Author: Christian Wieninger (cwieninger@gmx.de) # Version: 1.1 - 2011-01-16 # # requirements: grep #------------------------------------------------------------------------------ # adjust the following lines to your config # your plugins config dir PLUGINCONFDIR=/var/lib/vdr/plugins/epgsearch # path to svdrpsend SVDRPSEND=svdrpsend # the key used to call epgsearch EPGSEARCHKEY=green # do not edit below this line cat << EOM >/tmp/cmd.sh INFOFILE="$2/info"; TITLE=\$(grep '^T ' \$INFOFILE); #cut leading 'T ' TITLE=\${TITLE#*\$T }; EPISODE=\$(grep '^S ' \$INFOFILE) #cut leading 'S ' EPISODE=\${EPISODE#*\$S }; SEARCHTERM=\$TITLE; if [ "$1" -eq "1" ]; then SEARCHTERM=\$TITLE~\$EPISODE; fi RCFILE=$PLUGINCONFDIR/.epgsearchrc echo Search=\$SEARCHTERM > \$RCFILE #search for this term as phrase echo SearchMode=0 >> \$RCFILE if [ "$1" -eq "0" ]; then echo UseSubtitle=0 >> \$RCFILE; fi echo UseDescr=0 >> \$RCFILE $SVDRPSEND HITK $EPGSEARCHKEY EOM echo ". /tmp/cmd.sh; rm /tmp/cmd.sh" | at now vdr-plugin-epgsearch/scripts/epg2taste.sh0000755000175000017500000000115213145412721020353 0ustar tobiastobias#!/bin/sh # # epg2taste.sh - v.0.1 # # add this line to your epgsearchcmds.conf: # folgende zeile in die epgsearchcmds.conf eintragen: # # epg2taste : /usr/local/bin/epg2taste.sh # CONFIG START TASTE_FILE="/etc/vdr/plugins/taste.conf" SVDRPSEND=svdrpsend # default taste settings REGULAR_EXPRESSION=0 # Regular Expression / Regulrer Ausdruck IGNORE_CASE=0 # Ignore Case / Gro/Kleinschreibung ignorieren # CONFIG END # add taste echo "${REGULAR_EXPRESSION}:${IGNORE_CASE}:${1}" >> "${TASTE_FILE}" echo "Done..." # jump back at now <> $EPGSEARCHDONE_FILE echo "T $Title" >> $EPGSEARCHDONE_FILE [ ! -z "$Subtitle" ] && echo "S $Subtitle" >> $EPGSEARCHDONE_FILE echo "D " >> $EPGSEARCHDONE_FILE echo "r" >> $EPGSEARCHDONE_FILE else printf "SKIP \"%s, %s\"\n\n" "$Title" "$Subtitle" fi } if [ "$1" = "--sid" ]; then shift if [ -z "$1" ]; then printf "\nS-ID as parameter expected\n\n" else DEFAULT_SID=$1 shift printf "\nFound parameter \"--sid\", Default S-ID is now set to $DEFAULT_SID\n\n" fi fi if [ -z "$1" ]; then printf "\nERROR : Parameter 1 should be a Master-Timer done-file\n\n" exit 1 fi [ "$TEST" = "yes" ] && EPGSEARCHDONE_FILE=$EPGSEARCHDONE_FILE.test || cp $EPGSEARCHDONE_FILE $EPGSEARCHDONE_FILE.bak [ "$ASK_SID" = "yes" ] && ShowUsableSIDs printf "Default S-ID: $DEFAULT_SID\n\n" while read i; do AddRecToDone "$i" ; done <$1 if [ "$TEST" = "yes" ]; then printf "\n\nTEST run !!!!\nNow take a look at the File $EPGSEARCHDONE_FILE to see if everything is OK.\n\n" else # Tell epgsearch that done-file was changed echo "$SVDRPSEND PLUG epgsearch UPDD >/dev/null 2>&1" | at now >/dev/null 2>&1 fi vdr-plugin-epgsearch/scripts/timercmds-auxinfo.sh0000755000175000017500000000204113145412721022111 0ustar tobiastobias#!/bin/bash # # Displays the AUX-Info from timers # # Use it as command in timercmds.conf # # Example: # # Display AUX info : /usr/local/bin/timercmds-auxinfo.sh # # 2006-04-24 vejoun @ vdrportal # Version 0.4 # # # Your timers.conf TIMERS="/video/timers.conf" # CHANNELID="$2" START="$3" TITLE="$5" SUBTITLE="$6" DIR="$7" TIME="$(awk 'BEGIN{print strftime("%Y-%m-%d:%H%M",'$START')}')" || exit $? SEARCH="[0-9]*:${CHANNELID}:${TIME}:[0-9]*:[0-9]*:[0-9]*:${DIR//:/|/}:" AUX="$(egrep -m 1 "$SEARCH" "$TIMERS" | cut -d":" -f9-)" if [ -n "$TITLE" ]; then echo -e "TITLE:\n$TITLE\n" else echo -e "TITLE:\nTimer off, no title available\n" fi if [ -n "$SUBTITLE" ]; then echo -e "SUBTITLE:\n$SUBTITLE\n" else if [ -n "$TITLE" ]; then echo -e "SUBTITLE:\nNo subtitle available\n" else echo -e "SUBTITLE:\nTimer off, no subtitle available\n" fi fi if [ -n "$DIR" ]; then echo -e "PATH:\n$DIR\n" fi if [ -z "$AUX" ]; then echo -e "AUX:\nNo AUX data found\n" else echo -e "AUX:\n${AUX//>\\n<}\n" fi #EOF vdr-plugin-epgsearch/scripts/sendEmail.pl0000755000175000017500000017173413145412721020375 0ustar tobiastobias#!/usr/bin/perl -w ############################################################################## ## sendEmail ## Written by: Brandon Zehm ## ## License: ## sendEmail (hereafter referred to as "program") is free software; ## you can redistribute it and/or modify it under the terms of the GNU General ## Public License as published by the Free Software Foundation; either version ## 2 of the License, or (at your option) any later version. ## Note that when redistributing modified versions of this source code, you ## must ensure that this disclaimer and the above coder's names are included ## VERBATIM in the modified code. ## ## Disclaimer: ## This program is provided with no warranty of any kind, either expressed or ## implied. It is the responsibility of the user (you) to fully research and ## comprehend the usage of this program. As with any tool, it can be misused, ## either intentionally (you're a vandal) or unintentionally (you're a moron). ## THE AUTHOR(S) IS(ARE) NOT RESPONSIBLE FOR ANYTHING YOU DO WITH THIS PROGRAM ## or anything that happens because of your use (or misuse) of this program, ## including but not limited to anything you, your lawyers, or anyone else ## can dream up. And now, a relevant quote directly from the GPL: ## ## NO WARRANTY ## ## 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY ## FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN ## OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES ## PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED ## OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF ## MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS ## TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE ## PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, ## REPAIR OR CORRECTION. ## ############################################################################## use strict; use IO::Socket; ######################## ## Global Variables ## ######################## my %conf = ( ## General "programName" => $0, ## The name of this program "version" => '1.52', ## The version of this program "authorName" => 'Brandon Zehm', ## Author's Name "authorEmail" => 'caspian@dotconf.net', ## Author's Email Address "timezone" => '+0000 (GMT)', ## We always use +0000 for the time zone "hostname" => 'localhost', ## Used in printmsg() for all output, and in SMTP EHLO. "debug" => 0, ## Default debug level "error" => '', ## Error messages will often be stored here ## Logging "debug" => 0, "stdout" => 1, "logging" => 0, ## If this is true the printmsg function prints to the log file "logFile" => '', ## If this is specified (form the command line via -l) this file will be used for logging. ## Network "server" => 'localhost', ## Default SMTP server "port" => 25, ## Default port "alarm" => '', ## Default timeout for connects and reads, this gets set from $opt{'timeout'} ## Email "delimiter" => "----MIME delimiter for sendEmail-" ## MIME Delimiter . rand(1000000), ## Add some randomness to the delimiter "Message-ID" => rand(1000000) . "-sendEmail", ## Message-ID for email header "authUsername" => '', ## Username used in SMTP Auth "authPassword" => '', ## Password used in SMTP Auth ); ## This hash stores the options passed on the command line via the -o option. my %opt = ( ## Addressing "reply-to" => '', ## Reply-To field ## Message "message-file" => '', ## File to read message body from "message-header" => '', ## Additional email header line "message-format" => 'normal', ## If "raw" is specified the message is sent unmodified "message-charset" => 'iso-8859-1', ## Message character-set ## Network "timeout" => 60, ## Default timeout for connects and reads, this is copied to $conf{'alarm'} later. ); ## More variables used later in the program my $CRLF = "\015\012"; my $subject = ''; my $message = ''; my $from = ''; my @to = (); my @cc = (); my @bcc = (); my @attachments = (); my @attachments_names = (); ## For printing colors to the console my ${colorRed} = "\033[31;1m"; my ${colorGreen} = "\033[32;1m"; my ${colorCyan} = "\033[36;1m"; my ${colorWhite} = "\033[37;1m"; my ${colorNormal} = "\033[m"; my ${colorBold} = "\033[1m"; my ${colorNoBold} = "\033[0m"; ## Don't use shell escape codes on Windows systems if ($^O =~ /win/i) { ${colorRed} = ""; ${colorGreen} = ""; ${colorCyan} = ""; ${colorWhite} = ""; ${colorNormal} = ""; ${colorBold} = ""; ${colorNoBold} = ""; } ############################# ## ## MAIN PROGRAM ## ############################# ## Initialize initialize(); ## Process Command Line processCommandLine(); $conf{'alarm'} = $opt{'timeout'}; ## Abort program after $conf{'alarm'} seconds to avoid infinite hangs alarm($conf{'alarm'}) if ($^O !~ /win/i); ## alarm() doesn't work in win32 ################################################### ## Read $message from STDIN if -m was not used ## ################################################### if (!($message)) { ## Read message body from a file specified with -o message-file= if ($opt{'message-file'}) { if (! -e $opt{'message-file'}) { printmsg("ERROR => Message body file specified [$opt{'message-file'}] does not exist!", 0); printmsg("HINT => 1) check spelling of your file; 2) fully qualify the path; 3) doubble quote it", 1); quit("", 1); } if (! -r $opt{'message-file'}) { printmsg("ERROR => Message body file specified can not be read due to restricted permissions!", 0); printmsg("HINT => Check permissions on file specified to ensure it can be read", 1); quit("", 1); } if (!open(MFILE, "< " . $opt{'message-file'})) { printmsg("ERROR => Error opening message body file [$opt{'message-file'}]: $!", 0); quit("", 1); } while () { $message .= $_; } close(MFILE); } ## Read message body from STDIN else { alarm($conf{'alarm'}) if ($^O !~ /win/i); ## alarm() doesn't work in win32 if ($conf{'stdout'}) { print "Reading message body from STDIN because the '-m' option was not used.\n"; print "If you are manually typing in a message:\n"; print " - First line must be received within $conf{'alarm'} seconds.\n" if ($^O !~ /win/i); print " - End manual input with a CTRL-D on its own line.\n\n" if ($^O !~ /win/i); print " - End manual input with a CTRL-Z on its own line.\n\n" if ($^O =~ /win/i); } while () { ## Read STDIN into $message $message .= $_; alarm(0) if ($^O !~ /win/i); ## Disable the alarm since at least one line was received } printmsg("Message input complete.", 0); } } ## Replace bare LF's with CRLF's (\012 should always have \015 with it) $message =~ s/(\015)?(\012|$)/\015\012/g; ## Replace bare CR's with CRLF's (\015 should always have \012 with it) $message =~ s/(\015)(\012|$)?/\015\012/g; ## Check message for bare periods and encode them $message =~ s/(^|$CRLF)(\.{1})($CRLF|$)/$1.$2$3/g; ## Get the current date for the email header my ($sec,$min,$hour,$mday,$mon,$year,$day) = gmtime(); $year += 1900; $mon = return_month($mon); $day = return_day($day); my $date = sprintf("%s, %s %s %d %.2d:%.2d:%.2d %s",$day, $mday, $mon, $year, $hour, $min, $sec, $conf{'timezone'}); ################################## ## Connect to the SMTP server ## ################################## printmsg("DEBUG => Connecting to $conf{'server'}:$conf{'port'}", 1); $SIG{'ALRM'} = sub { printmsg("ERROR => Timeout while connecting to $conf{'server'}:$conf{'port'} There was no response after $conf{'alarm'} seconds.", 0); printmsg("HINT => Try specifying a different mail relay with the -s option.", 1); quit("", 1); }; alarm($conf{'alarm'}) if ($^O !~ /win/i); ## alarm() doesn't work in win32; my $SERVER = IO::Socket::INET->new( PeerAddr => $conf{'server'}, PeerPort => $conf{'port'}, Proto => 'tcp', Autoflush => 1, timeout => $conf{'alarm'}, ); alarm(0) if ($^O !~ /win/i); ## alarm() doesn't work in win32; ## Make sure we got connected if ( (!$SERVER) or (!$SERVER->opened()) ) { printmsg("ERROR => Connection attempt to $conf{'server'}:$conf{'port'} failed: $@", 0); printmsg("HINT => Try specifying a different mail relay with the -s option.", 1); quit("", 1); } ######################### ## Do the SMTP Dance ## ######################### ## Read initial greeting to make sure we're talking to a live SMTP server if (SMTPchat()) { quit($conf{'error'}, 1); } ## EHLO if (SMTPchat('EHLO ' . $conf{'hostname'})) { printmsg($conf{'error'}, 0); printmsg("NOTICE => EHLO command failed, attempting HELO instead"); if (SMTPchat('HELO ' . $conf{'hostname'})) { quit($conf{'error'}, 1); } if ( $conf{'authUsername'} and $conf{'authPassword'} ) { printmsg("WARNING => The mail server does not support ESMTP or SMTP AUTH!"); } } else { ## Do SMTP Auth if required if ( $conf{'authUsername'} and $conf{'authPassword'} ) { if (SMTPchat('AUTH LOGIN')) { quit($conf{'error'}, 1); } if (SMTPchat($conf{'authUsername'})) { quit($conf{'error'}, 1); } if (SMTPchat($conf{'authPassword'})) { quit($conf{'error'}, 1); } } } ## MAIL FROM if (SMTPchat('MAIL FROM:<' .(returnAddressParts($from))[1]. '>')) { quit($conf{'error'}, 1); } ## RCPT TO my $oneRcptAccepted = 0; foreach my $rcpt (@to, @cc, @bcc) { my ($name, $address) = returnAddressParts($rcpt); if (SMTPchat('RCPT TO:<' . $address . '>')) { printmsg("WARNING => The recipient <$address> was rejected by the mail server, error follows:", 0); $conf{'error'} =~ s/^ERROR/WARNING/o; printmsg($conf{'error'}, 0); } elsif ($oneRcptAccepted == 0) { $oneRcptAccepted = 1; } } ## If no recipients were accepted we need to exit with an error. if ($oneRcptAccepted == 0) { quit("ERROR => Exiting. No recipients were accepted for delivery by the mail server.", 1); } ## DATA if (SMTPchat('DATA')) { quit($conf{'error'}, 1); } ############################### ## Build and send the body ## ############################### printmsg("INFO => Sending message body",1); ## If the message-format is raw just send the message as-is. if ($opt{'message-format'} =~ /^raw$/i) { print $SERVER $message; } ## If the message-format isn't raw, then build and send the message, else { ## Message-ID: print $SERVER 'Message-ID: <' . $conf{'Message-ID'} . '@' . $conf{'hostname'} . '>' . $CRLF; ## From: "Name" (the pointless test below is just to keep scoping correct) if ($from) { my ($name, $address) = returnAddressParts($from); print $SERVER 'From: "' . $name . '" <' . $address . '>' . $CRLF; } ## Reply-To: if ($opt{'reply-to'}) { my ($name, $address) = returnAddressParts($opt{'reply-to'}); print $SERVER 'Reply-To: "' . $name . '" <' . $address . '>' . $CRLF; } ## To: "Name" if (scalar(@to) > 0) { print $SERVER "To:"; for (my $a = 0; $a < scalar(@to); $a++) { my $msg = ""; my ($name, $address) = returnAddressParts($to[$a]); $msg = " \"$name\" <$address>"; ## If we're not on the last address add a comma to the end of the line. if (($a + 1) != scalar(@to)) { $msg .= ","; } print $SERVER $msg . $CRLF; } } ## We always want a To: line so if the only recipients were bcc'd they don't see who it was sent to else { print $SERVER "To: \"Undisclosed Recipients\" <>$CRLF"; } if (scalar(@cc) > 0) { print $SERVER "Cc:"; for (my $a = 0; $a < scalar(@cc); $a++) { my $msg = ""; my ($name, $address) = returnAddressParts($cc[$a]); $msg = " \"$name\" <$address>"; ## If we're not on the last address add a comma to the end of the line. if (($a + 1) != scalar(@cc)) { $msg .= ","; } print $SERVER $msg . $CRLF; } } print $SERVER 'Subject: ' . $subject . $CRLF; ## Subject print $SERVER 'Date: ' . $date . $CRLF; ## Date print $SERVER 'X-Mailer: sendEmail-'.$conf{'version'}.$CRLF; ## X-Mailer ## Send an additional message header line if specified if ($opt{'message-header'}) { print $SERVER $opt{'message-header'} . $CRLF; } ## Encode all messages with MIME. print $SERVER "MIME-Version: 1.0$CRLF"; print $SERVER "Content-Type: multipart/mixed; boundary=\"$conf{'delimiter'}\"$CRLF"; print $SERVER "$CRLF"; print $SERVER "This is a multi-part message in MIME format. To properly display this message you need a MIME-Version 1.0 compliant Email program.$CRLF"; print $SERVER "$CRLF"; ## Send message body print $SERVER "--$conf{'delimiter'}$CRLF"; ## If the message contains HTML change the Content-Type if ($message =~ /^\s*/i) { printmsg("Message is in HTML format", 1); print $SERVER "Content-Type: text/html;$CRLF"; } ## Otherwise it's a normal text email else { print $SERVER "Content-Type: text/plain;$CRLF"; } print $SERVER " charset=\"" . $opt{'message-charset'} . "\"$CRLF"; print $SERVER "Content-Transfer-Encoding: 7bit$CRLF"; print $SERVER $CRLF; print $SERVER $message; ## Send Attachemnts if ($attachments[0]) { ## Disable the alarm so people on modems can send big attachments alarm(0) if ($^O !~ /win/i); ## alarm() doesn't work in win32 ## Send the attachments foreach my $filename (@attachments) { ## This is check 2, we already checked this above, but just in case... if ( ! -f $filename ) { printmsg("ERROR => The file [$filename] doesn't exist! Email will be sent, but without that attachment.", 0); } elsif ( ! -r $filename ) { printmsg("ERROR => Couldn't open the file [$filename] for reading: $! Email will be sent, but without that attachment.", 0); } else { printmsg("DEBUG => Sending the attachment [$filename]", 1); send_attachment($filename); } } } ## End the mime encoded message print $SERVER "$CRLF--$conf{'delimiter'}--$CRLF"; } ## Tell the server we are done sending the email print $SERVER "$CRLF.$CRLF"; if (SMTPchat()) { quit($conf{'error'}, 1); } #################### # We are done!!! # #################### ## Disconnect from the server if (SMTPchat('QUIT')) { quit($conf{'error'}, 1); } close $SERVER; ####################################### ## Generate exit message/log entry ## ####################################### if ($conf{'debug'} or $conf{'logging'}) { printmsg("Generating a detailed exit message", 3); ## Put the message together my $output = "Email was sent successfully! From: <" . (returnAddressParts($from))[1] . "> "; if (scalar(@to) > 0) { $output .= "To: "; for ($a = 0; $a < scalar(@to); $a++) { $output .= "<" . (returnAddressParts($to[$a]))[1] . "> "; } } if (scalar(@cc) > 0) { $output .= "Cc: "; for ($a = 0; $a < scalar(@cc); $a++) { $output .= "<" . (returnAddressParts($cc[$a]))[1] . "> "; } } if (scalar(@bcc) > 0) { $output .= "Bcc: "; for ($a = 0; $a < scalar(@bcc); $a++) { $output .= "<" . (returnAddressParts($bcc[$a]))[1] . "> "; } } $output .= "Subject: [$subject] " if ($subject); if (scalar(@attachments_names) > 0) { $output .= "Attachment(s): "; foreach(@attachments_names) { $output .= "[$_] "; } } $output .= "Server: [$conf{'server'}:$conf{'port'}]"; ###################### # Exit the program # ###################### ## Print / Log the detailed message quit($output, 0); } else { ## Or the standard message quit("Email was sent successfully!", 0); } ############################################################################################### ## Function: initialize () ## ## Does all the script startup jibberish. ## ############################################################################################### sub initialize { ## Set STDOUT to flush immediatly after each print $| = 1; ## Intercept signals $SIG{'QUIT'} = sub { quit("EXITING: Received SIG$_[0]", 1); }; $SIG{'INT'} = sub { quit("EXITING: Received SIG$_[0]", 1); }; $SIG{'KILL'} = sub { quit("EXITING: Received SIG$_[0]", 1); }; $SIG{'TERM'} = sub { quit("EXITING: Received SIG$_[0]", 1); }; ## ALARM and HUP signals are not supported in Win32 unless ($^O =~ /win/i) { $SIG{'HUP'} = sub { quit("EXITING: Received SIG$_[0]", 1); }; $SIG{'ALRM'} = sub { quit("EXITING: Received SIG$_[0]", 1); }; } ## Fixup $conf{'programName'} $conf{'programName'} =~ s/(.)*[\/,\\]//; $0 = $conf{'programName'} . " " . join(" ", @ARGV); ## Fixup $conf{'hostname'} if ($conf{'hostname'} eq 'localhost') { $conf{'hostname'} = ""; if ($ENV{'HOSTNAME'}) { $conf{'hostname'} = lc($ENV{'HOSTNAME'}); } elsif ($ENV{'COMPUTERNAME'}) { $conf{'hostname'} = lc($ENV{'COMPUTERNAME'}); } else { ## Try the hostname module use Sys::Hostname; $conf{'hostname'} = lc(hostname()); } ## Assign a name of "localhost" if it can't find anything else. if (!$conf{'hostname'}) { $conf{'hostname'} = 'localhost'; } $conf{'hostname'} =~ s/\..*$//; ## Remove domain name if it's present } return(1); } ############################################################################################### ## Function: processCommandLine () ## ## Processes command line storing important data in global vars (usually %conf) ## ############################################################################################### sub processCommandLine { ############################ ## Process command line ## ############################ my @ARGS = @ARGV; ## This is so later we can re-parse the command line args later if we need to my $numargv = @ARGS; help() unless ($numargv); my $counter = 0; for ($counter = 0; $counter < $numargv; $counter++) { if ($ARGS[$counter] =~ /^-h$/i) { ## Help ## help(); } elsif ($ARGS[$counter] eq "") { ## Ignore null arguments ## Do nothing } elsif ($ARGS[$counter] =~ /^--help/) { ## Topical Help ## $counter++; if ($ARGS[$counter] && $ARGS[$counter] !~ /^-/) { helpTopic($ARGS[$counter]); } else { help(); } } elsif ($ARGS[$counter] =~ /^-o$/i) { ## Options specified with -o ## $counter++; ## Loop through each option passed after the -o while ($ARGS[$counter] && $ARGS[$counter] !~ /^-/) { if ($ARGS[$counter] !~ /(\S+)=(\S.*)/) { printmsg("WARNING => Name/Value pair [$ARGS[$counter]] is not properly formatted", 0); printmsg("WARNING => Arguments proceeding -o should be in the form of \"name=value\"", 0); } else { if (exists($opt{$1})) { $opt{$1} = $2; printmsg("DEBUG => Assigned \$opt{} key/value: $1 => $2", 3); } else { printmsg("WARNING => Name/Value pair [$ARGS[$counter]] will be ignored: unknown key [$1]", 0); printmsg("HINT => Try the --help option to find valid command line arguments", 1); } } $counter++; } $counter--; } elsif ($ARGS[$counter] =~ /^-f$/) { ## From ## $counter++; if ($ARGS[$counter] && $ARGS[$counter] !~ /^-/) { $from = $ARGS[$counter]; } else { printmsg("WARNING => The argument after -f was not an email address!", 0); $counter--; } } elsif ($ARGS[$counter] =~ /^-t$/) { ## To ## $counter++; while ($ARGS[$counter] && ($ARGS[$counter] !~ /^-/)) { if ($ARGS[$counter] =~ /[;,]/) { push (@to, split(/[;,]/, $ARGS[$counter])); } else { push (@to,$ARGS[$counter]); } $counter++; } $counter--; } elsif ($ARGS[$counter] =~ /^-cc$/) { ## Cc ## $counter++; while ($ARGS[$counter] && ($ARGS[$counter] !~ /^-/)) { if ($ARGS[$counter] =~ /[;,]/) { push (@cc, split(/[;,]/, $ARGS[$counter])); } else { push (@cc,$ARGS[$counter]); } $counter++; } $counter--; } elsif ($ARGS[$counter] =~ /^-bcc$/) { ## Bcc ## $counter++; while ($ARGS[$counter] && ($ARGS[$counter] !~ /^-/)) { if ($ARGS[$counter] =~ /[;,]/) { push (@bcc, split(/[;,]/, $ARGS[$counter])); } else { push (@bcc,$ARGS[$counter]); } $counter++; } $counter--; } elsif ($ARGS[$counter] =~ /^-m$/) { ## Message ## $counter++; $message = ""; while ($ARGS[$counter] && $ARGS[$counter] !~ /^-/) { if ($message) { $message .= " "; } $message .= $ARGS[$counter]; $counter++; } $counter--; ## Replace '\n' with $CRLF. ## This allows newlines with messages sent on the command line $message =~ s/\\n/$CRLF/g; } elsif ($ARGS[$counter] =~ /^-u$/) { ## Subject ## $counter++; $subject = ""; while ($ARGS[$counter] && $ARGS[$counter] !~ /^-/) { if ($subject) { $subject .= " "; } $subject .= $ARGS[$counter]; $counter++; } $counter--; } elsif ($ARGS[$counter] =~ /^-s$/) { ## Server ## $counter++; if ($ARGS[$counter] && $ARGS[$counter] !~ /^-/) { $conf{'server'} = $ARGS[$counter]; if ($conf{'server'} =~ /:/) { ## Port ## ($conf{'server'},$conf{'port'}) = split(":",$conf{'server'}); } } else { printmsg("WARNING - The argument after -s was not the server!", 0); $counter--; } } elsif ($ARGS[$counter] =~ /^-a$/) { ## Attachments ## $counter++; while ($ARGS[$counter] && ($ARGS[$counter] !~ /^-/)) { push (@attachments,$ARGS[$counter]); $counter++; } $counter--; } elsif ($ARGS[$counter] =~ /^-xu$/) { ## AuthSMTP Username ## $counter++; if ($ARGS[$counter] && $ARGS[$counter] !~ /^-/) { $conf{'authUsername'} = $ARGS[$counter]; my $tmp = substr(pack('u', $conf{'authUsername'}), 1); ## Convert the string to uuencoded text chop($tmp); $tmp =~ tr|` -_|AA-Za-z0-9+/|; ## Translate from uuencode to base64 $conf{'authUsername'} = $tmp; } else { printmsg("WARNING => The argument after -xu was not valid username!", 0); $counter--; } } elsif ($ARGS[$counter] =~ /^-xp$/) { ## AuthSMTP Password ## $counter++; if ($ARGS[$counter] && $ARGS[$counter] !~ /^-/) { $conf{'authPassword'} = $ARGS[$counter]; my $tmp = substr(pack('u', $conf{'authPassword'}), 1); ## Convert the binary to uuencoded text chop($tmp); $tmp =~ tr|` -_|AA-Za-z0-9+/|; ## Translate from uuencode to base64 $conf{'authPassword'} = $tmp; } else { printmsg("WARNING => The argument after -xp was not valid password!", 0); $counter--; } } elsif ($ARGS[$counter] =~ /^-l$/) { ## Logging ## $counter++; $conf{'logging'} = 1; if ($ARGS[$counter] && $ARGS[$counter] !~ /^-/) { $conf{'logFile'} = $ARGS[$counter]; } else { printmsg("WARNING - The argument after -l was not the log file!", 0); $counter--; } } elsif ($ARGS[$counter] =~ s/^-v+//i) { ## Verbosity ## my $tmp = (length($&) - 1); $conf{'debug'} += $tmp; } elsif ($ARGS[$counter] =~ /^-q$/) { ## Quiet ## $conf{'stdout'} = 0; } else { printmsg("Error: \"$ARGS[$counter]\" is not a recognized option!", 0); help(); } } ################################################### ## Verify required variables are set correctly ## ################################################### if (!$conf{'server'}) { $conf{'server'} = 'localhost'; } if (!$conf{'port'}) { $conf{'port'} = 25; } if (!$from) { quit("ERROR => You must specify a 'from' field! Try --help.", 1); } if ( ((scalar(@to)) + (scalar(@cc)) + (scalar(@bcc))) <= 0) { quit("ERROR => You must specify at least one recipient via -t, -cc, or -bcc", 1); } ## Make sure email addresses look OK. foreach my $addr (@to, @cc, @bcc, $from, $opt{'reply-to'}) { if ($addr) { if (!returnAddressParts($addr)) { printmsg("ERROR => Can't use improperly formatted email address: $addr", 0); printmsg("HINT => Try viewing the extended help on addressing with \"--help addressing\"", 1); quit("", 1); } } } ## Make sure all attachments exist. foreach my $file (@attachments) { if ( (! -f $file) or (! -r $file) ) { printmsg("ERROR => The attachment [$file] doesn't exist!", 0); printmsg("HINT => Try specifying the full path to the file or reading extended help with \"--help message\"", 1); quit("", 1); } } if ($conf{'logging'} and (!$conf{'logFile'})) { quit("ERROR => You used -l to enable logging but didn't specify a log file!", 1); } if ( $conf{'authUsername'} ) { if (!$conf{'authPassword'}) { quit ("ERROR => You must supply both a username and a password to use SMTP auth.",1); } } ## Return 0 errors return(0); } ## getline($socketRef) sub getline { my ($socketRef) = @_; local ($/) = "\r\n"; return $$socketRef->getline; } ## Receive a (multiline?) SMTP response from ($socketRef) sub getResponse { my ($socketRef) = @_; my ($tmp, $reply); local ($/) = "\r\n"; return undef unless defined($tmp = getline($socketRef)); return("getResponse() socket is not open") unless ($$socketRef->opened); ## Keep reading lines if it's a multi-line response while ($tmp =~ /^\d{3}-/o) { $reply .= $tmp; return undef unless defined($tmp = getline($socketRef)); } $reply .= $tmp; $reply =~ s/\r?\n$//o; return $reply; } ############################################################################################### ## Function: SMTPchat ( [string $command] ) ## ## Description: Sends $command to the SMTP server (on SERVER) and awaits a successfull ## reply form the server. If the server returns an error, or does not reply ## within $conf{'alarm'} seconds an error is generated. ## NOTE: $command is optional, if no command is specified then nothing will ## be sent to the server, but a valid response is still required from the server. ## ## Input: [$command] A (optional) valid SMTP command (ex. "HELO") ## ## ## Output: Returns zero on success, or non-zero on error. ## Error messages will be stored in $conf{'error'} ## ## ## Example: SMTPchat ("HELO mail.isp.net"); ############################################################################################### sub SMTPchat { my ($command) = @_; printmsg("INFO => Sending: \t$command", 1) if ($command); ## Send our command print $SERVER "$command$CRLF" if ($command); ## Read a response from the server $SIG{'ALRM'} = sub { $conf{'error'} = "alarm"; $SERVER->close(); }; alarm($conf{'alarm'}) if ($^O !~ /win/i); ## alarm() doesn't work in win32; my $result = getResponse(\$SERVER); alarm(0) if ($^O !~ /win/i); ## alarm() doesn't work in win32; ## Generate an alert if we timed out if ($conf{'error'} eq "alarm") { $conf{'error'} = "ERROR => Timeout while reading from $conf{'server'}:$conf{'port'} There was no response after $conf{'alarm'} seconds."; return(1); } ## Make sure the server actually responded if (!$result) { $conf{'error'} = "ERROR => $conf{'server'}:$conf{'port'} returned a zero byte response to our query."; return(2); } ## Validate the response if (evalSMTPresponse($result)) { ## conf{'error'} will already be set here return(2); } ## Print the success messsage printmsg($conf{'error'}, 1); ## Return Success return(0); } ############################################################################################### ## Function: evalSMTPresponse (string $message ) ## ## Description: Searches $message for either an SMTP success or error code, and returns ## 0 on success, and the actual error code on error. ## ## ## Input: $message Data received from a SMTP server (ex. "220 ## ## ## Output: Returns zero on success, or non-zero on error. ## Error messages will be stored in $conf{'error'} ## ## ## Example: SMTPchat ("HELO mail.isp.net"); ############################################################################################### sub evalSMTPresponse { my ($message) = @_; ## Validate input if (!$message) { $conf{'error'} = "ERROR => No message was passed to evalSMTPresponse(). What happened?"; return(1) } printmsg("DEBUG => evalSMTPresponse() - Checking for SMTP success or error status in the message: $message ", 3); ## Look for a SMTP success code if ($message =~ /^([23]\d\d)/) { printmsg("DEBUG => evalSMTPresponse() - Found SMTP success code: $1", 2); $conf{'error'} = "SUCCESS => Received: \t$message"; return(0); } ## Look for a SMTP error code if ($message =~ /^([45]\d\d)/) { printmsg("DEBUG => evalSMTPresponse() - Found SMTP error code: $1", 2); $conf{'error'} = "ERROR => Received: \t$message"; return($1); } ## If no SMTP codes were found return an error of 1 $conf{'error'} = "ERROR => Received a message with no success or error code. The message received was: $message"; return(2); } ######################################################### # SUB: &return_month(0,1,etc) # returns the name of the month that corrosponds # with the number. returns 0 on error. ######################################################### sub return_month { my $x = $_[0]; if ($x == 0) { return 'Jan'; } if ($x == 1) { return 'Feb'; } if ($x == 2) { return 'Mar'; } if ($x == 3) { return 'Apr'; } if ($x == 4) { return 'May'; } if ($x == 5) { return 'Jun'; } if ($x == 6) { return 'Jul'; } if ($x == 7) { return 'Aug'; } if ($x == 8) { return 'Sep'; } if ($x == 9) { return 'Oct'; } if ($x == 10) { return 'Nov'; } if ($x == 11) { return 'Dec'; } return (0); } ######################################################### # SUB: &return_day(0,1,etc) # returns the name of the day that corrosponds # with the number. returns 0 on error. ######################################################### sub return_day { my $x = $_[0]; if ($x == 0) { return 'Sun'; } if ($x == 1) { return 'Mon'; } if ($x == 2) { return 'Tue'; } if ($x == 3) { return 'Wed'; } if ($x == 4) { return 'Thu'; } if ($x == 5) { return 'Fri'; } if ($x == 6) { return 'Sat'; } return (0); } ############################################################################################### ## Function: returnAddressParts(string $address) ## ## Description: Returns a two element array containing the "Name" and "Address" parts of ## an email address. ## ## Example: "Brandon Zehm " ## would return: ("Brandon Zehm", "caspian@dotconf.net"); ## ## "caspian@dotconf.net" ## would return: ("caspian@dotconf.net", "caspian@dotconf.net") ############################################################################################### sub returnAddressParts { my $input = $_[0]; my $name = ""; my $address = ""; ## Make sure to fail if it looks totally invalid if ($input !~ /(\S+\@\S+)/) { $conf{'error'} = "ERROR => The address [$input] doesn't look like a valid email address, ignoring it"; return(undef()); } ## Check 1, should find addresses like: "Brandon Zehm " elsif ($input =~ /^\s*(\S(.*\S)?)\s*<(\S+\@\S+)>/o) { ($name, $address) = ($1, $3); } ## Otherwise if that failed, just get the address: elsif ($input =~ /<(\S+\@\S+)>/o) { $name = $address = $1; } ## Or maybe it was formatted this way: caspian@dotconf.net elsif ($input =~ /(\S+\@\S+)/o) { $name = $address = $1; } ## Something stupid happened, just return an error. unless ($name and $address) { printmsg("ERROR => Couldn't parse the address: $input", 0); printmsg("HINT => If you think this should work, consider reporting this as a bug to $conf{'authorEmail'}", 1); return(undef()); } ## Make sure there aren't invalid characters in the address, and return it. my $ctrl = '\000-\037'; my $nonASCII = '\x80-\xff'; if ($address =~ /[<> ,;:"'\[\]\\$ctrl$nonASCII]/) { printmsg("WARNING => The address [$address] seems to contain invalid characters: continuing anyway", 0); } return($name, $address); } ######################################################### # SUB: send_attachment("/path/filename") # Sends the mime headers and base64 encoded file # to the email server. ######################################################### sub send_attachment { my ($filename) = @_; ## Get filename passed my (@fields, $y, $filename_name, $encoding, ## Local variables @attachlines, $content_type); my $bin = 1; @fields = split(/\/|\\/, $filename); ## Get the actual filename without the path $filename_name = pop(@fields); push @attachments_names, $filename_name; ## FIXME: This is only used later for putting in the log file ########################## ## Autodetect Mime Type ## ########################## @fields = split(/\./, $filename_name); $encoding = $fields[$#fields]; if ($encoding =~ /txt|text|log|conf|^c$|cpp|^h$|inc|m3u/i) { $content_type = 'text/plain'; } elsif ($encoding =~ /html|htm|shtml|shtm|asp|php|cfm/i) { $content_type = 'text/html'; } elsif ($encoding =~ /sh$/i) { $content_type = 'application/x-sh'; } elsif ($encoding =~ /tcl/i) { $content_type = 'application/x-tcl'; } elsif ($encoding =~ /pl$/i) { $content_type = 'application/x-perl'; } elsif ($encoding =~ /js$/i) { $content_type = 'application/x-javascript'; } elsif ($encoding =~ /man/i) { $content_type = 'application/x-troff-man'; } elsif ($encoding =~ /gif/i) { $content_type = 'image/gif'; } elsif ($encoding =~ /jpg|jpeg|jpe|jfif|pjpeg|pjp/i) { $content_type = 'image/jpeg'; } elsif ($encoding =~ /tif|tiff/i) { $content_type = 'image/tiff'; } elsif ($encoding =~ /xpm/i) { $content_type = 'image/x-xpixmap'; } elsif ($encoding =~ /bmp/i) { $content_type = 'image/x-MS-bmp'; } elsif ($encoding =~ /pcd/i) { $content_type = 'image/x-photo-cd'; } elsif ($encoding =~ /png/i) { $content_type = 'image/png'; } elsif ($encoding =~ /aif|aiff/i) { $content_type = 'audio/x-aiff'; } elsif ($encoding =~ /wav/i) { $content_type = 'audio/x-wav'; } elsif ($encoding =~ /mp2|mp3|mpa/i) { $content_type = 'audio/x-mpeg'; } elsif ($encoding =~ /ra$|ram/i) { $content_type = 'audio/x-pn-realaudio'; } elsif ($encoding =~ /mpeg|mpg/i) { $content_type = 'video/mpeg'; } elsif ($encoding =~ /mov|qt$/i) { $content_type = 'video/quicktime'; } elsif ($encoding =~ /avi/i) { $content_type = 'video/x-msvideo'; } elsif ($encoding =~ /zip/i) { $content_type = 'application/x-zip-compressed'; } elsif ($encoding =~ /tar/i) { $content_type = 'application/x-tar'; } elsif ($encoding =~ /jar/i) { $content_type = 'application/java-archive'; } elsif ($encoding =~ /exe|bin/i) { $content_type = 'application/octet-stream'; } elsif ($encoding =~ /ppt|pot|ppa|pps|pwz/i) { $content_type = 'application/vnd.ms-powerpoint'; } elsif ($encoding =~ /mdb|mda|mde/i) { $content_type = 'application/vnd.ms-access'; } elsif ($encoding =~ /xls|xlt|xlm|xld|xla|xlc|xlw|xll/i) { $content_type = 'application/vnd.ms-excel'; } elsif ($encoding =~ /doc|dot/i) { $content_type = 'application/msword'; } elsif ($encoding =~ /rtf/i) { $content_type = 'application/rtf'; } elsif ($encoding =~ /pdf/i) { $content_type = 'application/pdf'; } elsif ($encoding =~ /tex/i) { $content_type = 'application/x-tex'; } elsif ($encoding =~ /latex/i) { $content_type = 'application/x-latex'; } elsif ($encoding =~ /vcf/i) { $content_type = 'application/x-vcard'; } else { $content_type = 'application/octet-stream'; } ############################ ## Process the attachment ## ############################ ##################################### ## Generate and print MIME headers ## ##################################### $y = "$CRLF--$conf{'delimiter'}$CRLF"; $y .= "Content-Type: $content_type;$CRLF"; $y .= " name=\"$filename_name\"$CRLF"; $y .= "Content-Transfer-Encoding: base64$CRLF"; $y .= "Content-Disposition: attachment; filename=\"$filename_name\"$CRLF"; $y .= "$CRLF"; print $SERVER $y; ########################################################### ## Convert the file to base64 and print it to the server ## ########################################################### open (FILETOATTACH, $filename) || do { printmsg("ERROR => Opening the file [$filename] for attachment failed with the error: $!", 0); return(1); }; binmode(FILETOATTACH); ## Hack to make Win32 work my $res = ""; my $tmp = ""; my $base64 = ""; while () { ## Read a line from the (binary) file $res .= $_; ################################### ## Convert binary data to base64 ## ################################### while ($res =~ s/(.{45})//s) { ## Get 45 bytes from the binary string $tmp = substr(pack('u', $&), 1); ## Convert the binary to uuencoded text chop($tmp); $tmp =~ tr|` -_|AA-Za-z0-9+/|; ## Translate from uuencode to base64 $base64 .= $tmp; } ################################ ## Print chunks to the server ## ################################ while ($base64 =~ s/(.{76})//s) { print $SERVER "$1$CRLF"; } } ################################### ## Encode and send the leftovers ## ################################### my $padding = ""; if ( ($res) and (length($res) >= 1) ) { $padding = (3 - length($res) % 3) % 3; ## Set flag if binary data isn't divisible by 3 $res = substr(pack('u', $res), 1); ## Convert the binary to uuencoded text chop($res); $res =~ tr|` -_|AA-Za-z0-9+/|; ## Translate from uuencode to base64 } ############################ ## Fix padding at the end ## ############################ $res = $base64 . $res; ## Get left overs from above $res =~ s/.{$padding}$/'=' x $padding/e if $padding; ## Fix the end padding if flag (from above) is set if ($res) { while ($res =~ s/(.{1,76})//s) { ## Send it to the email server. print $SERVER "$1$CRLF"; } } close (FILETOATTACH) || do { printmsg("ERROR - Closing the filehandle for file [$filename] failed with the error: $!", 0); return(2); }; ## Return 0 errors return(0); } ############################################################################################### ## Function: printmsg (string $message, int $level) ## ## Description: Handles all messages - printing them to the screen only if the messages ## $level is >= the global debug level. If $conf{'logFile'} is defined it ## will also log the message to that file. ## ## Input: $message A message to be printed, logged, etc. ## $level The debug level of the message. If ## not defined 0 will be assumed. 0 is ## considered a normal message, 1 and ## higher is considered a debug message. ## ## Output: Prints to STDOUT ## ## Assumptions: $conf{'hostname'} should be the name of the computer we're running on. ## $conf{'stdout'} should be set to 1 if you want to print to stdout ## $conf{'logFile'} should be a full path to a log file if you want that ## $conf{'syslog'} should be 1 if you want to syslog, the syslog() function ## written by Brandon Zehm should be present. ## $conf{'debug'} should be an integer between 0 and 10. ## ## Example: printmsg("WARNING: We believe in generic error messages... NOT!", 0); ############################################################################################### sub printmsg { ## Assign incoming parameters to variables my ( $message, $level ) = @_; ## Make sure input is sane $level = 0 if (!defined($level)); $message =~ s/\s+$//sgo; $message =~ s/\r?\n/, /sgo; ## Continue only if the debug level of the program is >= message debug level. if ($conf{'debug'} >= $level) { ## Get the date in the format: Dec 3 11:14:04 my ($sec, $min, $hour, $mday, $mon) = localtime(); $mon = ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec')[$mon]; my $date = sprintf("%s %02d %02d:%02d:%02d", $mon, $mday, $hour, $min, $sec); ## Print to STDOUT always if debugging is enabled, or if conf{stdout} is true. if ( ($conf{'debug'} >= 1) or ($conf{'stdout'} == 1) ) { print "$date $conf{'hostname'} $conf{'programName'}\[$$\]: $message\n"; } ## Print to the log file if $conf{'logging'} is true if ($conf{'logFile'}) { if (openLogFile($conf{'logFile'})) { $conf{'logFile'} = ""; printmsg("ERROR => Opening the file [$conf{'logFile'}] for appending returned the error: $!", 1); } print LOGFILE "$date $conf{'hostname'} $conf{'programName'}\[$$\]: $message\n"; } } ## Return 0 errors return(0); } ############################################################################################### ## FUNCTION: ## openLogFile ( $filename ) ## ## ## DESCRIPTION: ## Opens the file $filename and attaches it to the filehandle "LOGFILE". Returns 0 on success ## and non-zero on failure. Error codes are listed below, and the error message gets set in ## global variable $!. ## ## ## Example: ## openFile ("/var/log/sendEmail.log"); ## ############################################################################################### sub openLogFile { ## Get the incoming filename my $filename = $_[0]; ## Make sure our file exists, and if the file doesn't exist then create it if ( ! -f $filename ) { print STDERR "NOTICE: The log file [$filename] does not exist. Creating it now with mode [0600].\n" if ($conf{'stdout'}); open (LOGFILE, ">>$filename"); close LOGFILE; chmod (0600, $filename); } ## Now open the file and attach it to a filehandle open (LOGFILE,">>$filename") or return (1); ## Put the file into non-buffering mode select LOGFILE; $| = 1; select STDOUT; ## Return success return(0); } ############################################################################################### ## Function: quit (string $message, int $errorLevel) ## ## Description: Exits the program, optionally printing $message. It ## returns an exit error level of $errorLevel to the ## system (0 means no errors, and is assumed if empty.) ## ## Example: quit("Exiting program normally", 0); ############################################################################################### sub quit { my %incoming = (); ( $incoming{'message'}, $incoming{'errorLevel'} ) = @_; $incoming{'errorLevel'} = 0 if (!defined($incoming{'errorLevel'})); ## Print exit message if ($incoming{'message'}) { printmsg($incoming{'message'}, 0); } ## Exit exit($incoming{'errorLevel'}); } ############################################################################################### ## Function: help () ## ## Description: For all those newbies ;) ## Prints a help message and exits the program. ## ############################################################################################### sub help { exit(1) if (!$conf{'stdout'}); print <${colorNoBold} Synopsis: $conf{'programName'} -f ADDRESS [options] ${colorRed}Required:${colorNormal} -f ADDRESS from (sender) email address * At least one recipient required via -t, -cc, or -bcc * Message body required via -m, STDIN, or -o message-file=FILE ${colorGreen}Common:${colorNormal} -t ADDRESS [ADDR ...] to email address(es) -u SUBJECT message subject -m MESSAGE message body -s SERVER[:PORT] smtp mail relay, default is $conf{'server'}:$conf{'port'} ${colorGreen}Optional:${colorNormal} -a FILE [FILE ...] file attachment(s) -cc ADDRESS [ADDR ...] cc email address(es) -bcc ADDRESS [ADDR ...] bcc email address(es) ${colorGreen}Paranormal:${colorNormal} -xu USERNAME authentication user (for SMTP authentication) -xp PASSWORD authentication password (for SMTP authentication) -l LOGFILE log to the specified file -v verbosity, use multiple times for greater effect -q be quiet (no stdout output) -o NAME=VALUE see extended help topic "misc" for details ${colorGreen}Help:${colorNormal} --help TOPIC The following extended help topics are available: addressing explain addressing and related options message explain message body input and related options misc explain -xu, -xp, and others networking explain -s, etc output explain logging and other output options EOM exit(1); } ############################################################################################### ## Function: helpTopic ($topic) ## ## Description: For all those newbies ;) ## Prints a help message and exits the program. ## ############################################################################################### sub helpTopic { exit(1) if (!$conf{'stdout'}); my ($topic) = @_; CASE: { ## ADDRESSING ($topic eq 'addressing') && do { print <" Just Address: "john.doe\@gmail.com" The "Full Name" method is useful if you want a name, rather than a plain email address, to be displayed in the recipient's From, To, or Cc fields when they view the message. ${colorGreen}Multiple Recipients${colorNormal} The -t, -cc, and -bcc options each accept multiple addresses. They may be specified by separating them by either a white space, comma, or semi-colon separated list. You may also specify the -t, -cc, and -bcc options multiple times, each occurance will append the new recipients to the respective list. Examples: (I used "-t" in these examples, but it can be "-cc" or "-bcc" as well) * Space separated list: -t jane.doe\@yahoo.com "John Doe " * Semi-colon separated list: -t "jane.doe\@yahoo.com; John Doe " * Comma separated list: -t "jane.doe\@yahoo.com, John Doe " * Multiple -t, -cc, or -bcc options: -t "jane.doe\@yahoo.com" -t "John Doe " EOM last CASE; }; ## MESSAGE ($topic eq 'message') && do { print <" and sendEmail will properly label the mime header so MUAs properly render the message. -o message-file=FILE This option is one of three methods that allow you to specify the message body for your email. To use this option simply specify a text file containing the body of your email message. Examples: -o message-file=/root/message.txt -o message-file="C:\\Program Files\\output.txt" -o message-header=EMAIL HEADER This option allows you to specify an additional single line to insert into the email headers. Do not use this unless you know what you are doing! Example: To scare a Microsoft Outlook user you may want to try this: -o message-header="X-Message-Flag: This message contains illegal content" -o message-format=raw This option instructs sendEmail to assume the message is already a complete email message. SendEmail will not generate any headers and will transmit the message as-is to the remote SMTP server. Due to the nature of this option the following command line options will be ignored when this one is used: -u SUBJECT -o message-header=EMAIL HEADER -o message-charset=CHARSET -a ATTACHMENT -o message-charset=CHARSET This option allows you to specify the character-set for the message body. The default is iso-8859-1. ${colorGreen}The Message Body${colorNormal} The message body may be specified in one of three ways: 1) Via the -m MESSAGE command line option. Example: -m "This is the message body" 2) By putting the message body in a file and using the -o message-file=FILE command line option. Example: -o message-file=/root/message.txt 3) By piping the message body to sendEmail when nither of the above command line options were specified. Example: grep "ERROR" /var/log/messages | sendEmail -t you\@domain.com ... If the message body begins with "" then the message will be treated as an HTML message and the MIME headers will be written so that a HTML capable email client will display the message in it's HTML form. Any of the above methods may be used with the -o message-format=raw option to deliver an already complete email message. EOM last CASE; }; ## MISC ($topic eq 'misc') && do { print < The help topic specified is not valid!", 1); }; exit(1); } vdr-plugin-epgsearch/scripts/undoneepgsearch.sh0000755000175000017500000001531013145412721021630 0ustar tobiastobias#!/bin/sh # $Id: undoneepgsearch.sh,v 1.7 2008/01/24 15:29:10 cjac Exp $ # # Created 2007 by Viking / vdr-portal # # This script does an undone of recrdings done with EPGsearch # It compares Title and Subtitle with the entry in the done file. # If there is no Subtitle, then the Title and Description is compared. # Options : # --TitleOnly Only match title, Subtitle and Description are ignored # This can be dangerous ! With series you remove ALL entries ! # --CheckDone Only tell if recording is done, not undone # --CheckOnly Only tell if recording is done, not undone # # The options can also be combined. # # # Add this to your reccmds.conf : # # Remove from EPGsearch done : /usr/local/bin/undoneepgsearch.sh # Remove from EPGsearch done - TitleOnly : /usr/local/bin/undoneepgsearch.sh --TitleOnly # Is Recording done : /usr/local/bin/undoneepgsearch.sh --CheckDone #------------------------------------------------------------------------------ # default recordingdone settings EPGSEARCHDONE_FILE="/etc/vdr/plugins/epgsearch/epgsearchdone.data" # EPGSEARCHDONE_FILE="/tmp/epgsearchdone.data" # Backup epgsearchdone.data before changing it (only once a day) BACKUP=yes SVDRPSEND=svdrpsend # For some debugging infos, set to yes DEBUG=no ## DEBUG=yes # do not edit below this line #------------------------------------------------------------------------------ [ "$1" = "" ] && printf "\nERROR Parameter 1 is not set !\n" && exit 1 Title="" Subtitle="" TempFile=/tmp/${0##*/}.$$ EPGSEARCHDONE_WORK=$EPGSEARCHDONE_FILE.work Today=$(date +%Y%m%d) Undone=false function CleanExit() { [ -e $TempFile ] && rm -f $TempFile [ -e $EPGSEARCHDONE_WORK ] && rm -f $EPGSEARCHDONE_WORK [ -e $EPGSEARCHDONE_WORK.undone ] && rm -f $EPGSEARCHDONE_WORK.undone exit 1 } # Get "--" options while [ "${1:0:2}" = "--" ]; do eval ${1:2}=yes shift done Rec=$1 [ "$CheckOnly" = "yes" ] && CheckDone=$CheckOnly if [ ! -e "$Rec/info.vdr" ]; then printf "\nNo Info file found in recording\n" exit 0 fi # Find Tite, Subtitle and Description Title=$(grep "^T " $Rec/info.vdr| cut -f2- -d' ') Subtitle=$(grep "^S " $Rec/info.vdr| cut -f2- -d' ') Description=$(grep "^D " $Rec/info.vdr | sed -e 's/\[/\./g' | sed -e 's/\]/\./g' | sed -e 's/\*/\./g') if [ "$TitleOnly" = "yes" ]; then Description="" Subtitle="" fi if [ -z "$Title" -a -z "$Subtitle" ]; then printf "Title and Subtitle not found, doing nothing\n" exit 0 else printf "Title: $Title\n" if [ "$TitleOnly" = "yes" ]; then echo "- Only using title" else [ ! -z "$Subtitle" ] && printf "Subtitle: $Subtitle\n" || printf "Subtitle: No Subtitle, using Description\n" fi # How many times does title match TitleCnt=$(grep -c "^T $Title$" $EPGSEARCHDONE_FILE) printf "\nFound $TitleCnt matching title lines\n" if [ "$CheckDone" = "yes" ]; then printf "\nDone matching all criteria ?\n\n" if [ -z "$Subtitle" ]; then grep -A1 "^T $Title$" $EPGSEARCHDONE_FILE | grep -q "$Description" else grep -A1 "^T $Title$" $EPGSEARCHDONE_FILE | grep -q -B1 "^S $Subtitle$" fi if [ $? -eq 0 ]; then printf "YES, DONE\n" else printf "NO, NOT done\n" fi exit 0 fi if [ $TitleCnt -gt 0 ]; then # Backup done file, but only one backup per day [ ! -e $EPGSEARCHDONE_FILE.$Today -a "$BACKUP" = "yes" ] && cp $EPGSEARCHDONE_FILE $EPGSEARCHDONE_FILE.$Today # Create Workfile cp -f $EPGSEARCHDONE_FILE $EPGSEARCHDONE_WORK else printf "\nNo matching entry found in done-list.\n" exit 0 fi # Try one match after each other let Try=1 let Match=1 while [ $Try -le $TitleCnt ]; do printf "\nDoes $Try. entry match all criteria : " [ $DEBUG = yes ] && printf "\nMatch=$Match\n" [ $Match -eq 1 ] && grep -m$Match -A4 "^T $Title$" $EPGSEARCHDONE_WORK >$TempFile || grep -m$Match -A4 "^T $Title$" $EPGSEARCHDONE_WORK | grep -A5 "^--$" >$TempFile if [ -z "$Subtitle" ]; then grep -q "$Description" $TempFile else grep -q -B1 "^S $Subtitle$" $TempFile fi if [ $? -eq 0 ]; then printf "YES, " let MatchLine=$(grep -m$Match -n "^T $Title$" $EPGSEARCHDONE_WORK |tail -n 1| cut -f1 -d ':') [ $DEBUG = yes ] && printf "\n\nMatching line : $MatchLine\n" if [ $MatchLine -gt 3 ]; then let FirstLine=MatchLine-3 [ $DEBUG = yes ] && printf "First line of Recording : $FirstLine\n" # First line OK ? nice -n 19 head -n $FirstLine $EPGSEARCHDONE_WORK | tail -n 1 | grep -q "^r" if [ $? -ne 0 ]; then printf "\nERROR: something went wrong finding the First line of recording, quitting\n" CleanExit fi let MatchRLine=$(grep -m$Match -n "^r$" $TempFile |head -n 1| cut -f1 -d ':') let LastMatchLine=MatchLine+MatchRLine # Bugfix - if more than one result then results are separated by a "--" line grep -q "^--$" $TempFile && let LastMatchLine-- [ $DEBUG = yes ] && printf "Last Matching line : $LastMatchLine\n" let TailLines=$(wc -l $EPGSEARCHDONE_WORK | cut -f1 -d' ') nice -n 19 head -n $LastMatchLine $EPGSEARCHDONE_WORK | tail -n 1 | grep -q "^R " if [ $? -ne 0 -a $LastMatchLine -lt $TailLines ]; then printf "\nERROR: something went wrong finding the Last line of recording, quitting\n" CleanExit fi let TailLines=TailLines-LastMatchLine+1 [ $DEBUG = yes ] && printf "TailLines = $TailLines\n" # Sanity check if [ $LastMatchLine -gt $FirstLine ]; then nice -n 19 head -n $FirstLine $EPGSEARCHDONE_WORK >$EPGSEARCHDONE_WORK.undone STATUS=$? nice -n 19 tail -n $TailLines $EPGSEARCHDONE_WORK >>$EPGSEARCHDONE_WORK.undone if [ $STATUS -eq 0 -a $? -eq 0 ]; then cp $EPGSEARCHDONE_WORK.undone $EPGSEARCHDONE_WORK Undone=true printf "Undone\n" fi rm -f $EPGSEARCHDONE_WORK.undone fi fi else printf "NO, not undone\n" let Match++ if [ -z "$Subtitle" ]; then printf "\nEPG DESCRIPTION from done (maybe it helps) :\n\n" grep "^D " $TempFile | cut -c3- | tr '|' '\n' fi fi let Try++ done if [ "$Undone" = "true" ]; then let WorkLines=$(wc -l $EPGSEARCHDONE_WORK | cut -f1 -d' ') let EpgsLines=$(wc -l $EPGSEARCHDONE_FILE | cut -f1 -d' ') [ $DEBUG = yes ] && printf "\nOld number of lines $EpgsLines, new $WorkLines\n" if [ $EpgsLines -gt $WorkLines ]; then cp -f $EPGSEARCHDONE_WORK $EPGSEARCHDONE_FILE [ $? -eq 0 ] && printf "\nUndone successfull\n" || printf "\nSomething went wrong with undone\n" # Reload done-file echo "$SVDRPSEND PLUG epgsearch UPDD" | at now 2>/dev/null else printf "\nSomething went wrong with undone\n" fi else [ -z "$Subtitle" ] && printf "\n\nYou could try using the option --TitleOnly\n" fi [ -e $TempFile ] && rm -f $TempFile [ -e $EPGSEARCHDONE_WORK ] && rm -f $EPGSEARCHDONE_WORK fi vdr-plugin-epgsearch/scripts/convert_epgsearchdone_data.pl0000755000175000017500000000402113145412721024014 0ustar tobiastobias#!/usr/bin/perl # # Dieses Script konvertiert die epgsearchdone.data fr # epgsearch >= 0.9.14 # # Die neue epgsearchdone.data funktioniert dann nicht mehr # fr epgsearch < 0.9.14 # # Es werden die epgsearch-Daten aus der Summary in die # @-Zeile verlegt. # # Dies ist nicht zwingend erforderlich. Wenn Du nicht sicher bist, # lass es ;) # # Aufrufen: # # convert_epgsearchdone_data.pl /pfad/zur/epgsearchdone.data/ # # z.B. convert_epgsearchdone_data.pl /etc/vdr/plugins/ # # "svdrpsend plug epgsearch updd" nicht vergesssen. # # Backup erstellen? # # my $backup=1; Auf 0 oder 1 # # Mike Constabel vejoun @ vdrportal # 2006-03-02 # use strict; my $backup=1; die("Kein Parameter, bitte Anleitung im Script lesen.") if ! $ARGV[0]; my $Pfad=$ARGV[0]; my $DateiAlt=$Pfad."/epgsearchdone.data"; my $DateiNeu=$Pfad."/epgsearchdone.data.neu"; my $DateiBak=$Pfad."/epgsearchdone.data.bak"; open(DATEI,"<".$DateiAlt) || die("Datei nicht gefunden: $DateiAlt"); open(NEU,">".$DateiNeu) || die("Datei kann nicht geffnet werden: $DateiAlt"); my $Zeile = ""; my $epgsearch = ""; my $neuformat = 0; my $aux = ""; printf ("Konvertiere %s\n",$DateiAlt); while() { $Zeile = $_; $epgsearch=""; $aux=""; $neuformat = 0; print NEU $Zeile if $Zeile =~ /^[RCTSr].*/; $epgsearch = $1 if $Zeile =~ /^D .*(Kanal.+Suchtimer.+S-ID.+)$/; if ( $Zeile =~ /^(D .+)\|Kanal.+Suchtimer.+S-ID.+$/ ) { print NEU sprintf("%s\n",$1); } elsif ( $Zeile =~ /^(D .+)$/ ) { print NEU sprintf("%s\n",$1); } if ( $Zeile =~ /^(@ .+)$/ ) { $neuformat=1; $aux = $1; } if ( $neuformat == 1 && $aux !~ /epgsearch/ && $epgsearch ne "" ) { $aux .= "".$epgsearch.""; print NEU sprintf("%s\n",$aux); } elsif ( $neuformat == 1 ) { print NEU sprintf("%s\n",$aux); } print NEU sprintf("@ %s\n",$epgsearch) if ( $neuformat == 0 && $epgsearch ne "" ); } close(DATEI); close(NEU); rename $DateiAlt, $DateiBak if ( ! -e $DateiBak && $backup == 1 ); rename $DateiNeu, $DateiAlt; vdr-plugin-epgsearch/scripts/recordingdone.sh0000755000175000017500000001154213145412721021303 0ustar tobiastobias#!/bin/sh # Originally written by : # Viking / vdrportal.de # cjac AT ich-habe-fertig.com # #---------------------------------------------------------------- # Version 1.3 # # Mike Constabel # # HISTORY: # # 2007-03-29: Version 1.3 # # - fixes for use with epgsearch >= 0.9.21 # # 2006-09-01: Version 1.2 # # - fixed setsid calling # # 2006-07-17: Version 1.1 # # - added setsid for calling UPDD # # 2006-??-?? update for vdr >= 1.3.44 and epgsearch >= 0.9.13a # #---------------------------------------------------------------- # # Call with one of these parameters # a. Recording Directory as parameter 1 # b. --recursive "Start_Dir" # c. --recursive # # If called with "--recursive" either "Start_Dir" or "VIDEO_ROOT" # from below is searched for recordings to put to the done-file # #---------------------------------------------------------------- # Should wo only test what is done ? TEST=yes # should we add recordings that have a S-ID in info.vdr ? # That is recordings already recorded with epgsearch-autotimer # and they are probably already in the done file! # yes = add recodrings with S-ID # no = don't add recordings with S-ID ADD_SID_RECORDINGS=no # should the script ask for S-ID for each recording ? # The script shows a list of possible S-ID's at the beginning ASK_SID=no # What S-ID should be used if no other selected DEFAULT_SID=-1 # Use the recording-dir's ctime as recording time? CTIME_FROM_RECORDING=yes # adjust the following line to your path to svdrpsend SVDRPSEND=svdrpsend # Home of EPGsearch EPGSEARCH_HOME="/etc/vdr/plugins" # Video root VIDEO_ROOT="/video" # do not edit below this line #------------------------------------------------------------------------------ EPGSEARCHDONE_FILE="$EPGSEARCH_HOME/epgsearchdone.data" EPGSEARCH_FILE="$EPGSEARCH_HOME/epgsearch.conf" PrevTitle="" function ShowUsableSIDs() { printf "\n" grep -v "^#" $EPGSEARCH_FILE | sort -t':' -k2 | awk -F':' '{ print $1"\t"$2 }' printf "\n" } function AddRecToDone() { Rec=$1 if [ -e "$Rec/info.vdr" ]; then # Get ctime from recordingdir if [ "$CTIME_FROM_RECORDING" = "yes" ]; then CTIME="$(echo "$Rec" | sed 's#......\.rec/##;s#.*/##')" CTIME="$(date +%s -d"${CTIME:0:10} ${CTIME:11:2}:${CTIME:14:2}")" fi # Find S-ID in info.vdr S_IDAlt=`grep -s "^D .*s-id:" $Rec/info.vdr | sed -re 's/^D .*s-id: ([0-9]*).*/\1/'` S_IDNeu=`grep -s "^@ .*.*.*<\/s-id>.*<\/epgsearch>" $Rec/info.vdr | sed -re 's/^@ .*.*([0-9]*)<\/s-id>.*<\/epgsearch>.*/\1/'` [ "$S_IDAlt" != "" ] && S_ID="$S_IDAlt" [ "$S_IDNeu" != "" ] && S_ID="$S_IDNeu" Title=$(grep "^T " $Rec/info.vdr| cut -f2- -d' '|head -1) Subtitle=$(grep "^S " $Rec/info.vdr| cut -f2- -d' '|head -1) if [ "$S_ID" = "" -o "$S_ID" != "" -a "$ADD_SID_RECORDINGS" = "yes" ]; then [ $(grep "^T " $Rec/info.vdr| wc -l) -gt 1 ] && printf "\n\nERROR: DUAL T Line %s\n\n" "$Rec" printf "Adding \"%s, %s\".\n" "$Title" "$Subtitle" if [ "$ASK_SID" = "yes" -a "$S_ID" = "" ]; then if [ "$Title" != "$PrevTitle" ]; then printf "Enter S-ID (s=skip, ENTER=$DEFAULT_SID): " read NEW_SID if [ "$NEW_SID" != "s" ]; then [ -z "$NEW_SID" ] && NEW_SID=$DEFAULT_SID printf "S-ID is set to $NEW_SID for \"$Title\"\n\n" fi else printf "Title matches, using same S-ID as before : $NEW_SID\n\n" fi PrevTitle=$Title else [ "$S_ID" = "" ] && NEW_SID=$DEFAULT_SID || NEW_SID=$S_ID fi if [ "$NEW_SID" != "s" ]; then echo "R $CTIME 0 $NEW_SID" >> $EPGSEARCHDONE_FILE grep -v "^[EVX] " $Rec/info.vdr >> $EPGSEARCHDONE_FILE echo "r" >> $EPGSEARCHDONE_FILE else printf "SKIP \"%s, %s\"\n\n" "$Title" "$Subtitle" fi else printf "SKIP \"%s, %s\" - it has S-ID: $S_ID\n\n" "$Title" "$Subtitle" fi else printf "No Info.vdr found : %s\n" "$Rec" fi } if [ -z "$1" ]; then printf "\nERROR : Parameter 1 should be either \"--recursive\" with start directory or a recording directory.\n" exit 1 fi [ "$TEST" = "yes" ] && EPGSEARCHDONE_FILE=$EPGSEARCHDONE_FILE.test || cp $EPGSEARCHDONE_FILE $EPGSEARCHDONE_FILE.bak if [ "$1" = "--recursive" ]; then shift [ "$ASK_SID" = "yes" ] && ShowUsableSIDs printf "Default S-ID: $DEFAULT_SID\n\n" [ ! -z "$1" ] && START_DIR=$1 || START_DIR=$VIDEO_ROOT for i in $(find $START_DIR/ -type d -name "*.rec" -print); do AddRecToDone $i ; done else AddRecToDone $1 fi if [ "$TEST" = "yes" ]; then printf "\n\nTEST run !!!!\nNow take a look at the File $EPGSEARCHDONE_FILE to see if everything is OK.\n\n" else # Tell epgsearch that done-file was changed if ! echo "$SVDRPSEND PLUG epgsearch UPDD >/dev/null 2>&1" | at now >/dev/null 2>&1; then if ! setsid "$SVDRPSEND" PLUG epgsearch UPDD >/dev/null 2>&1; then echo "ERROR calling $SVDRPSEND PLUG epgsearch UPDD" fi fi fi #EOF vdr-plugin-epgsearch/scripts/epgsearchcmds-fin.conf0000644000175000017500000000161513145412721022353 0ustar tobiastobias# # This is an example of epgsearchcmds.conf with sample entries. # # This file should placed on VDR configuration folder with setup.conf # .../setup.conf # .../plugins/epgsearchcmds.conf # # Syntax is: [?]; # # = descriptor displayed in VDR # [?] = confirmation request, before execute command (optionally) # = command what execute # # When a command is executed the following parameters are passed to it: # # $1: the name of the epg entry # $2: the start time of the epg entry as time_t value (like in the shutdown script) # $3: the end time # $4: the channel of the epg entry # # See also at man-pages vdr(5), it the same syntax as reccmds.conf # Muistutus? : /usr/local/bin/rememberevent.sh 0 Muistutus vaihtaen? : /usr/local/bin/rememberevent.sh 1 epg2taste : /usr/local/bin/epg2taste.sh epg2autotimer : /usr/local/bin/epg2autotimer.sh vdr-plugin-epgsearch/scripts/autotimer2searchtimer.pl0000755000175000017500000001777513145412721023022 0ustar tobiastobias#!/usr/bin/perl # # Convert VDRAdmin-AM autotimer (vdradmin.at) into # epgsearch searchtimer (epgsearch.conf) # # Version: 0.2beta 2006-08-06 # # Author: Mike Constabel (vejoun @ vdrportal) # Andreas Mair (amair @ vdrportal) # # You need: # # - VDRAdmin-AM >= 3.4.6 # - Epgsearch >= 0.9.16 # use Socket; use Getopt::Std; #--------------------------------------------------------------------------- $Usage = qq{ Usage: $0 [options] -i filename -o filename -m 0|1 $0 [options] -i filename -o filename -s -m 0|1 $0 [options] -i filename -s -m 0|1 Action: -i filename input file, vdradmind.at -o filename output file, epgsearch.conf.new (file will be overwritten!) -s send to epgsearch via svdrp (needs running vdr with epgsearch plugin) -m 0|1 which new searchmode for autotimers with active status: yes, once 0 means the whole string must match 1 means every word must match [default] In epgsearch 0 is default, vdradmin only use 1 Options: -r autotimers with regular expressions will be disabled while converting, with this option you can enable the corresponding searchtimers. You should not do this! Check the converted searchtimers and enable them manually! Wrong searchtimers will flood your timers. -d host Host for SVDRP import -p port Port for SVDRP import -h Show this help text }; die $Usage if (!getopts('i:o:srm:d:p:h') || !$opt_i || $opt_h || !($opt_o || $opt_s) || !($opt_m == 0 || $opt_m == 1)); my $AT_FILENAME = $opt_i; my $EPGSEARCH_FILENAME = $opt_o; my $SENDSVDRP = $opt_s ? 1 : 0; my $EnableRegex = $opt_r ? 1 : 0; my $Searchmode = defined $opt_m ? $opt_m : 1; my $Dest = $opt_d ? $opt_d : "localhost"; my $Port = $opt_p ? $opt_p : 6419; my $Timeout = 30; # max. seconds to wait for svdrp response my $conf_str="%i:%s:%i:%s:%s:%i:%s:%i:%i:%i:%i:%i:0:::%i:%i:%s:%i:%s:%s:%s:%s:%s:0:0:0::%i:0:1:1:0:0:0:0:0:1:0:0::1"; # [ID=0], pattern, time?, starttime, stopptime, channel? (0,1), channel, match case (0,1), search mode (0,4), title, subtitle, description, [duration=0], [min=""], [max=""], searchtimer? (0,1), # use week? (0,1), weekday "0", series? (0,1), dir, prio, lft, bstart, bstop, [VPS=0], [action=0], [use ext. epg=0], [ext. epg=""], done? (0,1), [repeats=0], [ctitle=1], [csubtitle=1], [cdescription=0], # [cext. epg=0], [reapeats within days=0], [delete after x days=0], [keep=0], [min before switch=1], [nach x rec pausieren=0], [blacklist=0], [blacklist-id=""], [fuzzy=0] sub AT_Read { my (@at); if (-s $AT_FILENAME) { open(AT_FILE, $AT_FILENAME) || printf("Can't open %s", $AT_FILENAME); while () { chomp; next if ($_ eq ""); my ($active, $pattern, $section, $start, $stop, $episode, $prio, $lft, $channel, $directory, $done, $weekday, $buffers, $bstart, $bstop) = split(/\:/, $_); $pattern =~ s/\|/\:/g; $pattern =~ s/\\:/\|/g; $directory =~ s/\|/\:/g; push( @at, { active => $active, pattern => $pattern, section => $section, start => $start, stop => $stop, buffers => $buffers, bstart => $bstart, bstop => $bstop, episode => $episode, prio => $prio, lft => $lft, channel => $channel, directory => $directory, done => $done, weekdays => $weekday } ); } close(AT_FILE); } return (@at); } sub CONF_Collect { my @at = @_; my @st; my $weekday = $stitle = $ssubtitle = $sdescription = $id = $case = 0; my $mode = $Searchmode; my $pattern; my $directory; for my $at (@at) { if ($at->{pattern} =~ /^\/(.*)\/(i?)$/) { $mode = 4; $case = 1 if ($2 eq "i"); $pattern = $1; } else { $pattern = $at->{pattern}; } $directory = $at->{directory}; $pattern =~ s/\|/\!\^pipe\^\!/g; $pattern =~ s/\:/\|/g; $directory =~ s/\|/\!\^pipe\^\!/g; $directory =~ s/\:/\|/g; $weekday = undef; my $wd_bits = 0; if ($at->{weekdays} =~ /^(\d)(\d)(\d)(\d)(\d)(\d)(\d)$/) { if ($7) { #Sunday $weekday = 0; $wd_bits |= 1; } if ($1) { #Monday $weekday = 1; $wd_bits |= 2; } if ($2) { #Tuesday $weekday = 2; $wd_bits |= 4; } if ($3) { #Wednesday $weekday = 3; $wd_bits |= 8; } if ($4) { #Thursday $weekday = 4; $wd_bits |= 16; } if ($5) { #Friday $weekday = 5; $wd_bits |= 32; } if ($6) { #Saturday $weekday = 6; $wd_bits |= 64; } } if ($wd_bits !~ /^(1|2|4|8|16|32|64)$/) { $weekday = -$wd_bits; } $stitle = $at->{section} & 1 ? 1 : 0; $ssubtitle = $at->{section} & 2 ? 1 : 0; $sdescription = $at->{section} & 4 ? 1 : 0; $id += 1 if ($EPGSEARCH_FILENAME); $data = sprintf $conf_str, $id, $pattern, $at->{start} || $at->{stop} ? 1 : 0, $at->{start} ? sprintf("%04i", $at->{start}) : "", $at->{stop} ? sprintf("%04i", $at->{stop}) : "", $at->{channel} ? 1 : 0, $at->{channel} ? $at->{channel} : "", $case, $mode, $stitle, $ssubtitle, $sdescription, ($at->{active} && ($mode != 4 || $EnableRegex)) ? 1 : 0, $weekday eq -127 || $wd_bits eq 0 ? 0 : 1, $weekday, $at->{episode} ? 1 : 0, $directory, $at->{prio} ? $at->{prio} : "", $at->{lft} ? $at->{lft} : "", $at->{buffers} ? $at->{bstart} : "", $at->{buffers} ? $at->{bstop} : "", $at->{done} ? 1 : 0; #avoid_repeats push @st,$data; } return (@st) } sub Error { print STDERR "@_\n"; close(SOCK); exit 0; } sub SplitLine($) { my ($line)=@_; if ($line =~ /^([0-9]{3})([- ])(.*)$/) { return ($1,$2,$3); } Error("Unidentified Line: $line"); } sub WriteSearchtimerSVDRP { my @str = @_; $SIG{ALRM} = sub { Error("timeout"); }; alarm($Timeout); my $iaddr = inet_aton($Dest) || Error("no host: $Dest"); my $paddr = sockaddr_in($Port, $iaddr); my $proto = getprotobyname('tcp'); socket(SOCK, PF_INET, SOCK_STREAM, $proto) || Error("socket: $!"); connect(SOCK, $paddr) || Error("connect: $!"); select(SOCK); $| = 1; select(STDOUT); while () { chomp; print STDOUT "(1):$_\n"; my ($code,$sep,$data)=SplitLine($_); last if ($code=220 && $sep eq ' '); } foreach my $line (@str) { chomp $line; printf SOCK "PLUG epgsearch NEWS %s\r\n", $line; } while () { chomp; print STDOUT "(2):$_\n"; my ($code,$sep,$data)=SplitLine($_); last if ($code==900 && $sep eq ' '); } print SOCK "quit\r\n"; while () { chomp; print STDOUT "(3):$_\n"; my ($code,$sep,$data)=SplitLine($_); last if ($code==221 && $sep eq ' '); } close(SOCK) || Error("close: $!"); } sub WriteSearchtimerFile { my @str = @_; open(STFILE, ">".$EPGSEARCH_FILENAME) || die("Cannot open file ${EPGSEARCH_FILENAME}!"); print STFILE "#version 2 - DONT TOUCH THIS!\n"; foreach my $line (@str) { chomp $line; printf STFILE "%s\n", $line; } close STFILE } #--------------------------------------------------------------------------- # main my @st; @st = CONF_Collect(AT_Read()); if ( $SENDSVDRP ) { WriteSearchtimerSVDRP(@st); } if ( $EPGSEARCH_FILENAME ) { WriteSearchtimerFile(@st); } vdr-plugin-epgsearch/scripts/epg2autotimer.sh0000755000175000017500000000157513145412721021255 0ustar tobiastobias#!/bin/sh # # epg2autotimer.sh - v.0.1 # # source: epgsearch-plugin # # add this line to your epgsearchcmds.conf: # folgende zeile in die epgsearchcmds.conf eintragen: # # epg2autotimer : /usr/local/bin/epg2autotimer.sh # CONFIG START AUTOTIMER_FILE="$SOURCEDIR/vdradmin/vdradmind.at" SVDRPSEND=svdrpsend # default autotimer settings STATUS=1 # 0 = inactive (by default) / 1 = active SERIE=1 # Serienaufnahme PRIO=0 # Priority / Prioritt LIFE_TIME=0 # Lifetime / Lebensdauer TARGET_DIR= # Folder / Verzeichnis SEARCH_WHERE=1 # Where to search / Wo soll gesucht werden? 1: Title 3: Title+Subtitle 7: All # CONFIG END # add autotimer echo "${STATUS}:${1}:${SEARCH_WHERE}:::${SERIE}:${PRIO}:${LIFE_TIME}:${4}:${TARGET_DIR}" >> "${AUTOTIMER_FILE}" echo "Done..." # jump back at now <=0.9.3). # it requires the timercmd patch from Gerhard Steiner, that extends the timers # menu of VDR with commands like in recordings menu # # add the following lines to your timercmds.conf # # Search for repeat : /path_of_this_script/timerrep.sh 0 # Search for repeat (with subtitle): /path_of_this_script/timerrep.sh 1 # # Author: Christian Wieninger (cwieninger@gmx.de) #------------------------------------------------------------------------------ # adjust the following lines to your config # your plugins config dir PLUGINCONFDIR=/etc/vdr/plugins/epgsearch # path to svdrpsend SVDRPSEND=svdrpsend # if you are using special subfolders for some recordings, please add them here FOLDERS="Comedy,Wissen,Serien,Magazine" # the key used to call epgsearch EPGSEARCHKEY=green # do not edit below this line #------------------------------------------------------------------------------ cat << EOM >/tmp/cmd.sh SEARCHTERM="$6"~"$7"; #event info not yet present? then extract it from the file name if test "\$SEARCHTERM" == "~"; then SEARCHTERM='$8' #cut leading special folders i=0; FOLDERS=$FOLDERS; while [ "\$LASTWORD" != "\$FOLDERS" ]; do LASTWORD=\${FOLDERS%%,*}; SEARCHTERM=\${SEARCHTERM#*\$LASTWORD~}; i=\$i+1; FOLDERS=\${FOLDERS#*,}; done #cut trailing dummy subtitle created by epgsearch SEARCHTERM=\${SEARCHTERM%~???_??.??.????-??:??} if [ "$1" -eq "0" ]; then SEARCHTERM=\${SEARCHTERM%~*}; fi fi RCFILE=$PLUGINCONFDIR/.epgsearchrc; echo Search=\$SEARCHTERM > \$RCFILE; echo SearchMode=0 >> \$RCFILE; echo UseDescr=0 >> \$RCFILE; $SVDRPSEND HITK $EPGSEARCHKEY; EOM echo ". /tmp/cmd.sh; rm /tmp/cmd.sh" | at now vdr-plugin-epgsearch/scripts/convert_info_vdr.pl0000755000175000017500000000343213145412721022027 0ustar tobiastobias#!/usr/bin/perl # # Dieses Script konvertiert die info.vdrs in das Format, das # vdr >= 1.3.44 und epgsearch >= 0.9.14 verwenden. # # Aufrufen: # # find "/video" -path "*.rec" -exec convert_info_vdr.pl "{}" \; # # Bitte die beiden Variablen unter Einstellungen anpassen! # # Mike Constabel vejoun @ vdrportal # 2006-03-01 # use strict; ## my $backup=1; # Backup erstellen? 1=Ja (info.bak), 0=Nein my $keepdata=1; # Die epgsearch-Daten in summary behalten? 1=Ja, 0=Nein ## die("Kein Parameter, bitte Anleitung im Script lesen.") if ! $ARGV[0]; my $Pfad=$ARGV[0]; my $DateiAlt=$Pfad."/info.vdr"; my $DateiNeu=$Pfad."/info.neu"; my $DateiBak=$Pfad."/info.bak"; open(DATEI,"<".$DateiAlt) || die("Datei nicht gefunden: $DateiAlt"); open(NEU,">".$DateiNeu) || die("Datei kann nicht geffnet werden: $DateiAlt"); my $Zeile = ""; my $epgsearch = ""; my $neuformat = 0; my $aux = ""; printf ("Konvertiere %s\n",$DateiAlt); while() { $Zeile = $_; print NEU $Zeile if $Zeile =~ /^[CETSX] .+/; $epgsearch = $1 if $Zeile =~ /^D .*(Kanal.+Suchtimer.+S-ID.+)$/; if ( $Zeile =~ /^(D .+)\|Kanal.+Suchtimer.+S-ID.+$/ && ! $keepdata ) { print NEU sprintf("%s\n",$1); } elsif ( $Zeile =~ /^(D .+)$/ ) { print NEU sprintf("%s\n",$1); } if ( $Zeile =~ /^(@ .+)$/ ) { $neuformat=1; $aux = $1; } } if ( $neuformat == 1 && $aux !~ /epgsearch/ && $epgsearch ne "" ) { $aux .= "".$epgsearch.""; print NEU sprintf("%s\n",$aux); } elsif ( $neuformat == 1 ) { print NEU sprintf("%s\n",$aux); } print NEU sprintf("@ %s\n",$epgsearch) if ( $neuformat == 0 && $epgsearch ne "" ); close(DATEI); close(NEU); rename $DateiAlt, $DateiBak if ( ! -e $DateiBak && $backup == 1 ); rename $DateiNeu, $DateiAlt; vdr-plugin-epgsearch/scripts/epgsearchcmds.conf0000644000175000017500000000166513145412721021606 0ustar tobiastobias# # This is an example of epgsearchcmds.conf with sample entries. # # This file should placed on VDR configuration folder with setup.conf # .../setup.conf # .../plugins/epgsearchcmds.conf # # Syntax is: [?]; # # = descriptor displayed in VDR # [?] = confirmation request, before execute command (optionally) # = command what execute # # When a command is executed the following parameters are passed to it: # # $1: the name of the epg entry # $2: the start time of the epg entry as time_t value (like in the shutdown script) # $3: the end time # $4: the channel of the epg entry # # See also at man-pages vdr(5), it the same syntax as reccmds.conf # remember event? : /usr/local/bin/rememberevent.sh 0 remember event? (inc. switch) : /usr/local/bin/rememberevent.sh 1 epg2taste : /usr/local/bin/epg2taste.sh epg2autotimer : /usr/local/bin/epg2autotimer.sh vdr-plugin-epgsearch/scripts/epg2master-timer.sh0000755000175000017500000000210713145412721021645 0ustar tobiastobias#!/bin/sh # # epg2master-timer.sh # # source: epgsearch-plugin, taken from vdr-wiki.de # author: Christian Jacobsen / Viking (vdrportal) # # add this line to your epgsearchcmds.conf: # folgende zeile in die epgsearchcmds.conf eintragen: # # epg2master-timer : /path_to_this_script/epg2master-timer.sh # epg2master-timer (no subtitle) : /path_to_this_script/epg2master-timer.sh -nosub # CONFIG START MASTERTIMER_FILE=/etc/master-timer/torecord # CONFIG END if touch $MASTERTIMER_FILE >/dev/null 2>&1 ; then USESUB=yes if [ "$1" = -nosub ] ; then USESUB=no fi # add timer printf "\nAdding Master-Timer :\n" printf "\n[$1]\nTitle = $1\n" | tee -a $MASTERTIMER_FILE if [ "$6" != "" -a $USESUB = yes ] ; then printf "Subtitle = $6\n" | tee -a $MASTERTIMER_FILE fi # with "^" and "$" so that the exact channel name is used. printf "Channel = ^$5\$\n" | tee -a $MASTERTIMER_FILE printf "\n\nLast 10 lines of torecord : \n\n" tail -10 $MASTERTIMER_FILE else echo "Error, cannot open file ($MASTERTIMER_FILE)..." fi vdr-plugin-epgsearch/menu_switchtimers.h0000644000175000017500000000337313145412721020360 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #ifndef __MENU_SWITCHTIMER_H #define __MENU_SWITCHTIMER_H #include #include #include "switchtimer.h" // --- cMenuSwitchTimerItem ---------------------------------------------------------- class cMenuSwitchTimerItem : public cOsdItem { public: cSwitchTimer* switchTimer; const cEvent* event; cMenuSwitchTimerItem(cSwitchTimer* SwitchTimer, const cEvent* event); void Set(); int Compare(const cListObject &ListObject) const; }; class cMenuSwitchTimers : public cOsdMenu { private: eOSState Delete(void); eOSState DeleteAll(void); protected: void Set(); virtual eOSState ProcessKey(eKeys Key); eOSState Summary(void); cSwitchTimer* CurrentSwitchTimer(void); public: cMenuSwitchTimers(); }; #endif vdr-plugin-epgsearch/patches/0000755000175000017500000000000013145412721016057 5ustar tobiastobiasvdr-plugin-epgsearch/patches/README.patches0000644000175000017500000000070113145412721020363 0ustar tobiastobias---------------------- Description of patches ---------------------- - MainMenuHooks-v1_0_1.diff.gz: patches vdr to allow plugins to replace main menu items like 'Schedule', 'Recordings',... Use this one, if epgsearch shall replace the schedules menu. This patch is also used by other plugins like the extrec-plugin. - vdr.epgsearch-exttimeredit-2.3.6.diff this patch against VDR integrates epgsearch's timer edit menu to VDR's timer menu. vdr-plugin-epgsearch/patches/vdr.epgsearch-exttimeredit-2.3.6.diff0000644000175000017500000000644313145412721024624 0ustar tobiastobias--- a/menu.c.orig 2017-06-04 19:18:37.423036244 +0200 +++ b/menu.c 2017-06-09 21:33:53.775782116 +0200 @@ -1155,6 +1155,7 @@ class cMenuTimerItem : public cOsdItem { private: const cTimer *timer; + void DoSet(void); public: cMenuTimerItem(const cTimer *Timer); virtual int Compare(const cListObject &ListObject) const; @@ -1166,7 +1167,7 @@ cMenuTimerItem::cMenuTimerItem(const cTimer *Timer) { timer = Timer; - Set(); + DoSet(); } int cMenuTimerItem::Compare(const cListObject &ListObject) const @@ -1176,6 +1177,20 @@ void cMenuTimerItem::Set(void) { + // check for deleted timer + LOCK_TIMERS_READ; + if (!Timers->Contains(timer)) + { + if (const cTimer *t = Timers->GetById(timer->Id(), timer->Remote())) + timer = t; + else + return; // no matching timer found + } + DoSet(); +} + +void cMenuTimerItem::DoSet(void) +{ cString day, name(""); if (timer->WeekDays()) day = timer->PrintDay(0, timer->WeekDays(), false); @@ -1223,8 +1238,7 @@ cStateKey timersStateKey; int helpKeys; void Set(void); - eOSState Edit(void); - eOSState New(void); + eOSState Edit(bool New = false); eOSState Delete(void); eOSState OnOff(void); eOSState Info(void); @@ -1316,21 +1330,34 @@ return osContinue; } -eOSState cMenuTimers::Edit(void) +eOSState cMenuTimers::Edit(bool New) { - if (HasSubMenu() || Count() == 0) + if (HasSubMenu() || Count() == 0 && !New) return osContinue; - return AddSubMenu(new cMenuEditTimer(GetTimer())); -} - -eOSState cMenuTimers::New(void) -{ - if (HasSubMenu()) - return osContinue; - cTimer *Timer = new cTimer; + cTimer *Timer; + if (New) + { + Timer = new cTimer; if (Setup.SVDRPPeering && *Setup.SVDRPDefaultHost) Timer->SetRemote(Setup.SVDRPDefaultHost); - return AddSubMenu(new cMenuEditTimer(Timer, true)); + } + // Data structure for service "Epgsearch-exttimeredit-v1.0" + struct Epgsearch_exttimeredit_v1_0 + { + // in + cTimer* timer; // pointer to the timer to edit + bool bNew; // flag that indicates, if this is a new timer or an existing one + const cEvent* event; // pointer to the event corresponding to this timer (may be NULL) + // out + cOsdMenu* pTimerMenu; // pointer to the menu of results + } exttimeredit; + exttimeredit.timer = New ? Timer : GetTimer(); + exttimeredit.bNew = New; + exttimeredit.event = exttimeredit.timer->Event(); + if (cPluginManager::CallFirstService("Epgsearch-exttimeredit-v1.0", &exttimeredit)) + return AddSubMenu(exttimeredit.pTimerMenu); + + return AddSubMenu(new cMenuEditTimer(exttimeredit.timer, New)); } eOSState cMenuTimers::Delete(void) @@ -1386,7 +1413,7 @@ switch (Key) { case kOk: return Edit(); case kRed: state = OnOff(); break; // must go through SetHelpKeys()! - case kGreen: return New(); + case kGreen: return Edit(true); case kYellow: state = Delete(); break; case kInfo: case kBlue: return Info(); @@ -1400,6 +1427,14 @@ Add(new cMenuTimerItem(Timer), true); Display(); } + if (!HasSubMenu()) { + LOCK_TIMERS_READ; + if (Timers->Count()}Ňs63bO*^Cc]^vQɌ6$ iY".aA `cE/ Cz{zvoX D T΅IawFKF?VA2Mdөc s﵁hDsebx-%j~D KszlGE-Τ Z mn?C /bfKDZ"c[kQJa$ZpPMXVuGʇ>u'"清3z ]VX%鲣ͬP i ܅5Lچ{= vt7:4d֛Ka"X;4YgNN<RT>l<f2JSp4u!t5B:yX=gՕ <*Gp)Ѭ8r˵}zߣn7Z_q{ BŹ:,[y;E1С$+yd#f,,y=&Faf(8|ϛhr~},RRcS "a9 [*HEZWŮP &| 25z*!]I6`fck[ENNנ?* (ּ-UUOu%>5b* YnCmFއjz`%~RSTƹʔsZ9^6\58\s򯷫&_Zitd0za6{>HMhMN@.0b}Ԧ'!d"&1+ͺy;qfuvτ5ZRDX=Rdq;:5\ǐD9EV6X[́Hΰ7b7XG ([U/:X ͡H[(V/d΂װb*s4b1l4cov^aN|obfRIe^KHԢFiHRiDkTN]GQP|,amy!\`A WE 2(Ca)ESr(Jy,暨*ϙu}qAS&vJKd 6ŀn<{ c|ǝ^#=֒?Tmg#^/V/>xWnjЃ]wDjY9B\ U%W6Ac4 ل+B#0S 㮟p!r~?w޾zn/fΆhQ咩9W$ls@akCѢÖLG\c#HJ_)^`z66[!#jRԭN^wZݷh)fN}[-:"S؃itt+xnoog-~=5ݶEO ~umo:I>U\;ꆫޓVHG~>tH^]FgOk\ t]7w'[JE5T(: *pw Q Y0 ܥwa. .Sl ԓo]dN!&}S*%I"WwrbK.6s"%g_kFy5rp0Jql*{Bɴ23|GXo#>,s[A`; -%>`UvB](<]+iq'.Jw]o:Suqk/tP1z95C\u ~ch4,=fBW\w{iʃk/>|6KUa'~sVH ~G3UK.d0 +A|l8&t蚇rZ*~k]h1B|&'hyYޏ.ߏCO쌿~u5:ƽ Rvdr-plugin-epgsearch/menu_myedittimer.c0000644000175000017500000003612113145412721020157 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #include #include "menu_myedittimer.h" #include "epgsearchcfg.h" #include "epgsearchcats.h" #include "timer_thread.h" #include "menu_dirselect.h" #include "menu_searchedit.h" #include "epgsearchtools.h" #include "recstatus.h" #include "uservars.h" #include "menu_deftimercheckmethod.h" #include "timerstatus.h" #include const char *cMenuMyEditTimer::CheckModes[3]; cMenuMyEditTimer::cMenuMyEditTimer(cTimer *Timer, bool New, const cEvent* Event, const cChannel* forcechannel) :cOsdMenu(trVDR("Edit timer"), 14) { SetMenuCategory(mcTimerEdit); CheckModes[0] = tr("no check"); CheckModes[UPD_CHDUR] = tr("by channel and time"); CheckModes[UPD_EVENTID] = tr("by event ID"); strcpy(file, ""); strcpy(directory, ""); strcpy(remote, ""); UserDefDaysOfWeek = 0; checkmode = 0; if (Timer) { timer = Timer; newtimer = *timer; event = Event; flags = Timer->Flags(); day = Timer->Day(); weekdays = Timer->WeekDays(); start = Timer->Start(); stop = Timer->Stop(); priority = Timer->Priority(); lifetime = Timer->Lifetime(); strcpy(file, Timer->File()); channel = Timer->Channel()->Number(); #ifdef USE_PINPLUGIN fskProtection = Timer->FskProtection(); #endif if (Timer->Remote()) strcpy(remote, Timer->Remote()); if (forcechannel) channel = forcechannel->Number(); SplitFile(); addIfConfirmed = New; Set(); SetHelp(addIfConfirmed?NULL:trVDR("Button$Delete"), NULL, NULL, NULL); } } void cMenuMyEditTimer::SplitFile() { char* tmp = strrchr(file, '~'); if (tmp) // split file in real file and directory { if (event && !isempty(event->ShortText())) { cString eventFile = cString::sprintf("%s~%s", event->Title(), event->ShortText()); char* tmp2 = strstr(file, eventFile); if (tmp2) // file contains title and subtitle { if (tmp2 > file) { *(tmp2-1) = 0; strcpy(directory, file); strcpy(file, tmp2); } else *directory = 0; } else { *tmp = 0; strcpy(directory, file); strcpy(file, tmp+1); } } else { *tmp = 0; strcpy(directory, file); strcpy(file, tmp+1); } } else *directory = 0; } void cMenuMyEditTimer::Set() { int current = Current(); Clear(); cSearchExt* search = TriggeredFromSearchTimer(timer); Add(new cMenuEditStrItem( trVDR("File"), file, MaxFileName, trVDR(FileNameChars))); Add(new cMenuEditStrItem( tr("Directory"), directory, MaxFileName, tr(AllowedChars))); Add(new cMenuEditBitItem( trVDR("Active"), &flags, tfActive)); #ifdef USE_PINPLUGIN if (cOsd::pinValid || !fskProtection) Add(new cMenuEditChanItem(tr("Channel"), &channel)); else { LOCK_CHANNELS_READ; cString buf = cString::sprintf("%s\t%s", tr("Channel"), Channels->GetByNumber(channel)->Name()); Add(new cOsdItem(buf)); } #else Add(new cMenuEditChanItem(trVDR("Channel"), &channel)); #endif Add(new cMenuEditDateItem(trVDR("Day"), &day, &weekdays)); if (!IsSingleEvent()) Add(new cMenuEditDateItem(trVDR("First day"), &day)); Add(new cMenuEditTimeItem(trVDR("Start"), &start)); Add(new cMenuEditTimeItem(trVDR("Stop"), &stop)); Add(new cMenuEditBitItem( trVDR("VPS"), &flags, tfVps)); Add(new cMenuEditIntItem( trVDR("Priority"), &priority, 0, MAXPRIORITY)); Add(new cMenuEditIntItem( trVDR("Lifetime"), &lifetime, 0, MAXLIFETIME)); #ifdef USE_PINPLUGIN if (cOsd::pinValid || !fskProtection) Add(new cMenuEditBoolItem(tr("Childlock"),&fskProtection)); else { cString buf = cString::sprintf("%s\t%s", tr("Childlock"), fskProtection ? trVDR("yes") : trVDR("no")); Add(new cOsdItem(buf)); } #endif if (GetSVDRPServerNames(&svdrpServerNames)) { svdrpServerNames.Sort(true); svdrpServerNames.Insert(strdup("")); Add(new cMenuEditStrlItem(tr("Record on"), remote, sizeof(remote), &svdrpServerNames)); } if (search) { cMenuEditStrItem* searchtimerItem = new cMenuEditStrItem( tr("Search timer"), search->search, MaxFileName, tr(AllowedChars)); searchtimerItem->SetSelectable(false); Add(searchtimerItem); } else if (IsSingleEvent() && event) { { LOCK_CHANNELS_READ; checkmode = DefTimerCheckModes.GetMode(Channels->GetByNumber(channel)); } char* checkmodeAux = GetAuxValue(timer, "update"); if (checkmodeAux) { checkmode = atoi(checkmodeAux); free(checkmodeAux); } Add(new cMenuEditStraItem(tr("Timer check"), &checkmode, 3, CheckModes)); } int deviceNr = gl_recStatusMonitor->TimerRecDevice(timer); if (deviceNr > 0) { cOsdItem* pInfoItem = new cOsdItem(""); pInfoItem->SetSelectable(false); Add(pInfoItem); cString info = cString::sprintf("%s: %d/%d", tr("recording with device"), deviceNr, cDevice::NumDevices()); pInfoItem = new cOsdItem(info); pInfoItem->SetSelectable(false); Add(pInfoItem); } if (current > -1) { SetCurrent(Get(current)); RefreshCurrent(); } Display(); } cMenuMyEditTimer::~cMenuMyEditTimer() { if (timer && addIfConfirmed) delete timer; // apparently it wasn't confirmed } void cMenuMyEditTimer::HandleSubtitle() { const char* ItemText = Get(Current())->Text(); if (strstr(ItemText, trVDR("File")) != ItemText) return; if (InEditMode(ItemText, trVDR("File"), file)) return; if (!event || (event && !event->ShortText())) return; char* tmp = strchr(file, '~'); if (tmp) { *tmp = 0; SetHelp(addIfConfirmed?NULL:trVDR("Button$Delete"), NULL, trVDR("Button$Reset"), tr("Button$With subtitle")); } else { strcat(file, "~"); strncat(file, event->ShortText(), MaxFileName - strlen(file) - 1); SetHelp(addIfConfirmed?NULL:trVDR("Button$Delete"), NULL, trVDR("Button$Reset"), tr("Button$Without subtitle")); } RefreshCurrent(); Display(); } bool cMenuMyEditTimer::IsSingleEvent(void) const { return !weekdays; } eOSState cMenuMyEditTimer::DeleteTimer() { // Check if this timer is active: LOCK_TIMERS_WRITE; Timers->SetExplicitModify(); if (timer && !addIfConfirmed) { if (Interface->Confirm(trVDR("Delete timer?"))) { if (timer->Recording()) { if (Interface->Confirm(trVDR("Timer still recording - really delete?"))) { if (!timer->Remote()) { timer->Skip(); cRecordControls::Process(Timers, time(NULL)); } } else timer = NULL; } if (timer) { if (!HandleRemoteTimerModifications(NULL, timer)) { LogFile.Log(2,"HandleRemoteTimerModifications failed"); return osContinue; } LogFile.iSysLog("deleting timer %s", *timer->ToDescr()); Timers->Del(timer); gl_timerStatusMonitor->SetConflictCheckAdvised(); Timers->SetModified(); return osBack; } } } return osContinue; } eOSState cMenuMyEditTimer::ProcessKey(eKeys Key) { bool bWasSingleEvent = IsSingleEvent(); eOSState state = cOsdMenu::ProcessKey(Key); if (bWasSingleEvent != IsSingleEvent()) { Set(); Display(); } int iOnDirectoryItem = 0; int iOnFileItem = 0; int iOnDayItem = 0; const char* ItemText = Get(Current())->Text(); if (!HasSubMenu() && ItemText && strlen(ItemText)>0) { if (strstr(ItemText, trVDR("Day")) == ItemText) { if (!IsSingleEvent()) { SetHelp(trVDR("Button$Edit")); iOnDayItem = 1; } else SetHelp(addIfConfirmed?NULL:trVDR("Button$Delete"), NULL, NULL, NULL); } else if (strstr(ItemText, tr("Directory")) == ItemText) { if (!InEditMode(ItemText, tr("Directory"), directory)) SetHelp(addIfConfirmed?NULL:trVDR("Button$Delete"), NULL, trVDR("Button$Reset"), tr("Button$Select")); iOnDirectoryItem = 1; } else if (strstr(ItemText, trVDR("File")) == ItemText) { if (!InEditMode(ItemText, trVDR("File"), file)) { if (event && event->ShortText()) { if (strchr(file, '~')) SetHelp(addIfConfirmed?NULL:trVDR("Button$Delete"), NULL, trVDR("Button$Reset"), tr("Button$Without subtitle")); else SetHelp(addIfConfirmed?NULL:trVDR("Button$Delete"), NULL, trVDR("Button$Reset"), tr("Button$With subtitle")); } else SetHelp(addIfConfirmed?NULL:trVDR("Button$Delete"), NULL, trVDR("Button$Reset"), NULL); } iOnFileItem = 1; } else SetHelp(addIfConfirmed?NULL:trVDR("Button$Delete"), NULL, NULL, NULL); } if ((Key == kYellow) && ((iOnDirectoryItem && !InEditMode(ItemText, tr("Directory"), directory)) || (iOnFileItem && !InEditMode(ItemText, trVDR("File"), file)))) { if (iOnDirectoryItem) strcpy(directory, ""); if (iOnFileItem && event) strn0cpy(file, event->Title(),sizeof(file)); RefreshCurrent(); Display(); } if (state == osUnknown) { switch (Key) { case kOk: { string fullaux = ""; string aux = ""; if (timer && timer->Aux()) fullaux = timer->Aux(); if (event && IsSingleEvent()) { time_t startTime = 0, stopTime = 0;; int begin = cTimer::TimeToInt(start); // seconds from midnight int length = cTimer::TimeToInt(stop) - begin; if (length < 0) length += SECSINDAY; startTime = cTimer::SetTime(day, begin); stopTime = startTime + length; // calculate margins int bstart = event->StartTime() - startTime; int bstop = stopTime - event->EndTime(); char* epgsearchaux = GetAuxValue(timer, "epgsearch"); if (epgsearchaux) { aux = epgsearchaux; free(epgsearchaux); } LOCK_CHANNELS_READ; const cChannel *ch = Channels->GetByNumber(channel); if (!ch) { ERROR(tr("*** Invalid Channel ***")); break; } aux = UpdateAuxValue(aux, "channel", NumToString(ch->Number()) + " - " + CHANNELNAME(ch)); aux = UpdateAuxValue(aux, "update", checkmode); aux = UpdateAuxValue(aux, "eventid", event->EventID()); aux = UpdateAuxValue(aux, "bstart", bstart); aux = UpdateAuxValue(aux, "bstop", bstop); if (addIfConfirmed) // do not update start and stop time in aux if this is an existing timer, we need this to detect manual editing { aux = UpdateAuxValue(aux, "start", startTime); aux = UpdateAuxValue(aux, "stop", stopTime); } fullaux = UpdateAuxValue(fullaux, "epgsearch", aux); } #ifdef USE_PINPLUGIN aux = ""; aux = UpdateAuxValue(aux, "protected", fskProtection ? "yes" : "no"); fullaux = UpdateAuxValue(fullaux, "pin-plugin", aux); #endif char* tmpFile = strdup(file); strreplace(tmpFile, ':', '|'); char* tmpDir = strdup(directory); strreplace(tmpDir, ':', '|'); if (timer) { LOCK_TIMERS_WRITE; if (!addIfConfirmed && !Timers->Contains(timer)) { if (cTimer *t = Timers->GetById(timer->Id(), timer->Remote())) timer = t; else { ERROR(tr("Timer has been deleted")); break; } } LOCK_CHANNELS_READ; const cChannel *ch = Channels->GetByNumber(channel); if (!ch) { ERROR(tr("*** Invalid Channel ***")); break; } if (strlen(tmpFile) == 0) { free(tmpFile); tmpFile = strdup(CHANNELNAME(ch)); } cString cmdbuf; cmdbuf = cString::sprintf("%d:%d:%s:%04d:%04d:%d:%d:%s%s%s:%s", flags, channel, PRINTDAY(day, weekdays, true), start, stop, priority, lifetime, strlen(tmpDir)>0?tmpDir:"", (strlen(tmpDir)>0 && strlen(tmpFile)>0)?"~":"", tmpFile, fullaux.c_str()); newtimer.Parse(cmdbuf); free(tmpFile); free(tmpDir); newtimer.SetRemote(*remote ? remote : NULL); if (addIfConfirmed) { *timer = newtimer; Timers->Add(timer); if (!HandleRemoteTimerModifications(timer)) { Timers->Del(timer); ERROR(tr("Epgsearch: RemoteTimerModifications failed")); return osContinue; } } else { if (!HandleRemoteTimerModifications(&newtimer, timer)) { return osContinue; } if (timer->Local() && timer->Recording() && newtimer.Remote()) cRecordControls::Stop(timer); *timer = newtimer; } LOCK_SCHEDULES_READ; timer->SetEventFromSchedule(Schedules); timer->Matches(); gl_timerStatusMonitor->SetConflictCheckAdvised(); addIfConfirmed = false; } else { free(tmpFile); free(tmpDir); } } return osBack; case kRed: if (HasSubMenu()) return osContinue; else if (iOnDayItem) return AddSubMenu(new cMenuEditDaysOfWeek(&weekdays,1,false)); else return DeleteTimer(); break; case kGreen: case kYellow: return osContinue; case kBlue: if (HasSubMenu()) return osContinue; if (iOnDirectoryItem && !InEditMode(ItemText, tr("Directory"), directory)) state = AddSubMenu(new cMenuDirSelect(directory)); if (iOnFileItem) { HandleSubtitle(); return osContinue; } break; default: break; } } if (Key != kNone && !HasSubMenu()) { if (iOnDirectoryItem && !InEditMode(ItemText, tr("Directory"), directory)) ReplaceDirVars(); } return state; } void cMenuMyEditTimer::ReplaceDirVars() { if (!strchr(directory,'%') || !event) return; cVarExpr varExpr(directory); strcpy(directory, varExpr.Evaluate(event).c_str()); if (strchr(directory, '%') != NULL) // only set directory to new value if all categories could have been replaced *directory = 0; if (varExpr.DependsOnVar("%title%", event) || varExpr.DependsOnVar("%subtitle%", event)) { strcpy(file, directory); *directory = 0; SplitFile(); } RefreshCurrent(); // update title too if (Current() > 0) Get(Current()-1)->Set(); Display(); return; } vdr-plugin-epgsearch/menu_announcelist.c0000644000175000017500000001414213145412721020324 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #include #include "menu_announcelist.h" #include "epgsearchcfg.h" #include "noannounce.h" bool cMenuAnnounceList::showsDetails; // --- cMenuAnnounceList ------------------------------------------------------- cMenuAnnounceList::cMenuAnnounceList(cSearchResults& SearchResults) :cMenuSearchResultsForList(SearchResults, tr("%d new broadcast"), false) { showsDetails = false; } void cMenuAnnounceList::SetHelpKeys(bool Force) { cMenuSearchResultsItem *item = (cMenuSearchResultsItem *)Get(Current()); int NewHelpKeys = 0; if (item) { if (item->Selectable() && item->timerMatch == tmFull) NewHelpKeys = 2; else NewHelpKeys = 1; } bool hasTimer = (NewHelpKeys == 2); if (NewHelpKeys != helpKeys || Force) { if (toggleKeys==0) SetHelp((EPGSearchConfig.redkeymode==0?(hasTimer?trVDR("Button$Timer"):trVDR("Button$Record")):tr("Button$Commands")), m_bSort? tr("Button$by channel"):tr("Button$by time"), modeYellow==showTitleEpisode?tr("Button$Episode"):tr("Button$Title"), trVDR("Button$Edit")); else SetHelp((EPGSearchConfig.redkeymode==1?(hasTimer?trVDR("Button$Timer"):trVDR("Button$Record")):tr("Button$Commands")), m_bSort? tr("Button$by channel"):tr("Button$by time"), modeYellow==showTitleEpisode?tr("Button$Episode"):tr("Button$Title"), trVDR("Button$Edit")); helpKeys = NewHelpKeys; } } eOSState cMenuAnnounceList::ProcessKey(eKeys Key) { eOSState state = cMenuSearchResultsForList::ProcessKey(Key); if (state == osUnknown) { switch (Key) { case kBlue: { cMenuSearchResultsItem *item = (cMenuSearchResultsItem *)Get(Current()); if (item) { if (!HasSubMenu()) return AddSubMenu(new cMenuAnnounceDetails(item->event, item->search)); else if (!showsDetails) return Switch(); else return osContinue; } } break; default: break; } } return state; } // --- cMenuAnnounceDetails ------------------------------------------------------- cMenuAnnounceDetails::cMenuAnnounceDetails(const cEvent* Event, const cSearchExt* Search) :cOsdMenu("", 25), event(Event) { SetMenuCategory(mcEvent); cMenuAnnounceList::showsDetails = true; if (event && !isempty(event->Title())) { cString szTitle = cString::sprintf("%s: %s", tr("announce details"), event->Title()); SetTitle(szTitle); } search = Search; announceAgain = 1; announceWithNextUpdate = 1; announceAgainDay = 0; cNoAnnounce* noAnnounce = NoAnnounces.InList(event); if (noAnnounce) { if (noAnnounce->nextAnnounce > 0) { announceAgainDay = noAnnounce->nextAnnounce; announceWithNextUpdate = 0; } else announceAgain = 0; } Set(); } cMenuAnnounceDetails::~cMenuAnnounceDetails() { cMenuAnnounceList::showsDetails = false; } void cMenuAnnounceDetails::Set() { int current = Current(); Clear(); Add(new cMenuEditBoolItem(tr("announce again"), &announceAgain, trVDR("no"), trVDR("yes"))); if (announceAgain) { Add(new cMenuEditBoolItem(IndentMenuItem(tr("with next update")), &announceWithNextUpdate, trVDR("no"), trVDR("yes"))); if (!announceWithNextUpdate) Add(new cMenuEditDateItem(IndentMenuItem(IndentMenuItem(tr("again from"))), &announceAgainDay, NULL)); } else announceAgainDay = 0; if (search) { cOsdItem* pInfoItem = new cOsdItem(""); pInfoItem->SetSelectable(false); Add(pInfoItem); cString info = cString::sprintf("%s: %s", tr("Search timer"), search->search); pInfoItem = new cOsdItem(info); pInfoItem->SetSelectable(false); Add(pInfoItem); } SetCurrent(Get(current)); Display(); } eOSState cMenuAnnounceDetails::ProcessKey(eKeys Key) { int iTemp_announceAgain = announceAgain; int iTemp_announceWithNextUpdate = announceWithNextUpdate; eOSState state = cOsdMenu::ProcessKey(Key); if (iTemp_announceAgain != announceAgain || iTemp_announceWithNextUpdate != announceWithNextUpdate) { Set(); Display(); } if (state == osUnknown) { switch (Key) { case kRed: case kGreen: case kBlue: case kYellow: case kFastRew: case kFastFwd: case kRecord: case k0...k9: return osContinue; case kOk: { cNoAnnounce* noAnnounce = NoAnnounces.InList(event); if (!announceAgain || !announceWithNextUpdate) { if (!noAnnounce) { noAnnounce = new cNoAnnounce(event, announceAgainDay); NoAnnounces.Add(noAnnounce); } else NoAnnounces.UpdateNextAnnounce(event, announceAgainDay); NoAnnounces.ClearOutdated(); } if (announceAgain && announceWithNextUpdate && noAnnounce) NoAnnounces.Del(noAnnounce); NoAnnounces.Save(); } return osBack; default: break; } } return state; } vdr-plugin-epgsearch/conflictcheck.c0000644000175000017500000007710613145412721017406 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #include #include #include "conflictcheck.h" #include "epgsearchcfg.h" /*#include */ #include "conflictcheck_thread.h" #include "recstatus.h" #include "timerstatus.h" #include "uservars.h" #include #define FULLMATCH 1000 #define EPGLIMITBEFORE (1 * 3600) // Time in seconds before a timer's start time and #define EPGLIMITAFTER (1 * 3600) // after its stop time within which EPG events will be taken into consideration. // --- cConflictCheckTimerObj -------------------------------------------------------- cConflictCheckTimerObj::cConflictCheckTimerObj(cTimer* Timer, time_t Start, time_t Stop, int Device, int OrigIndex) : cTimerObj(Timer), start(Start), stop(Stop), device(Device), origIndex(OrigIndex), conflCheckTime(NULL), concurrentTimers(NULL), ignore(false) { event = Timer->Event(); recDuration = 0; lastRecStart = 0; lastRecStop = 0; } cConflictCheckTimerObj::~cConflictCheckTimerObj() { // conflict checks works on a copy of a timer, so delete it again DELETENULL(timer); } int cConflictCheckTimerObj::Compare(const cListObject &ListObject) const { cConflictCheckTimerObj *p = (cConflictCheckTimerObj *)&ListObject; long diff = start - p->start; if (diff == 0) diff = p->timer->Priority() - timer->Priority(); if (diff == 0) diff = origIndex - p->origIndex; return diff; } const cEvent* cConflictCheckTimerObj::Event() { if(timer->Event()) return timer->Event(); else if (!event) event = SetEventFromSchedule(); return event; } const cEvent* cConflictCheckTimerObj::SetEventFromSchedule() { LOCK_SCHEDULES_READ; if (!Schedules) return NULL; const cSchedule *Schedule = Schedules->GetSchedule(timer->Channel()); if (Schedule && Schedule->Events()->First()) { const cEvent *Event = NULL; if (timer->HasFlags(tfVps) && Schedule->Events()->First()->Vps()) { // VPS timers only match if their start time exactly matches the event's VPS time: for (const cEvent *e = Schedule->Events()->First(); e; e = Schedule->Events()->Next(e)) { if (e->StartTime() && e->RunningStatus() != SI::RunningStatusNotRunning) { // skip outdated events int overlap = 0; Matches(e, &overlap); if (overlap > FULLMATCH) { Event = e; break; // take the first matching event } } } } else { // Normal timers match the event they have the most overlap with: int Overlap = 0; // Set up the time frame within which to check events: timer->Matches(0, true); time_t TimeFrameBegin = start - EPGLIMITBEFORE; time_t TimeFrameEnd = stop + EPGLIMITAFTER; for (const cEvent *e = Schedule->Events()->First(); e; e = Schedule->Events()->Next(e)) { if (e->EndTime() < TimeFrameBegin) continue; // skip events way before the timer starts if (e->StartTime() > TimeFrameEnd) break; // the rest is way after the timer ends int overlap = 0; Matches(e, &overlap); if (overlap && overlap >= Overlap) { if (Event && overlap == Overlap && e->Duration() <= Event->Duration()) continue; // if overlap is the same, we take the longer event Overlap = overlap; Event = e; } } } return Event; } return NULL; } int cConflictCheckTimerObj::Matches(const cEvent *Event, int *Overlap) const { // Overlap is the percentage of the Event's duration that is covered by // this timer (based on FULLMATCH for finer granularity than just 100). // To make sure a VPS timer can be distinguished from a plain 100% overlap, // it gets an additional 100 added, and a VPS event that is actually running // gets 200 added to the FULLMATCH. if (timer->Channel()->GetChannelID() == Event->ChannelID()) { bool UseVps = timer->HasFlags(tfVps) && Event->Vps(); timer->Matches(UseVps ? Event->Vps() : Event->StartTime(), true); int overlap = 0; if (UseVps) overlap = (start == Event->Vps()) ? FULLMATCH + (Event->IsRunning() ? 200 : 100) : 0; if (!overlap) { if (start <= Event->StartTime() && Event->EndTime() <= stop) overlap = FULLMATCH; else if (stop <= Event->StartTime() || Event->EndTime() <= start) overlap = 0; else overlap = (std::min(stop, Event->EndTime()) - std::max(start, Event->StartTime())) * FULLMATCH / std::max(Event->Duration(), 1); } if (Overlap) *Overlap = overlap; if (UseVps) return overlap > FULLMATCH ? tmFull : tmNone; return overlap >= FULLMATCH ? tmFull : overlap > 0 ? tmPartial : tmNone; } return tmNone; } // --- cConflictCheck ------------------------------------------------------- cConflictCheck::cConflictCheck() { evaltimeList = NULL; timerList = NULL; failedList = NULL; relevantConflicts = 0; numConflicts = 0; devices = NULL; localConflicts = !(EPGSearchConfig.RemoteConflictCheck && Setup.SVDRPPeering); InitDevicesInfo(); } cConflictCheck::~cConflictCheck() { if (evaltimeList) { evaltimeList->Clear(); DELETENULL(evaltimeList); } if (timerList) { timerList->Clear(); DELETENULL(timerList); } if (devices) delete [] devices; } void cConflictCheck::InitDevicesInfo() { if (devices) delete [] devices; devices = new cConflictCheckDevice[MAXDEVICES]; #ifdef DEBUG_CONFL numDevices = 4; for(int i=0; i 0 && array[i] == array[j] && i != j) { LogFile.Log(3, "Bond devices %i and %i.", i+1, j+1); devices[i].bondedDevices.push_back(&(devices[j])); } } } } LogFile.Log(3, "Bond Devices done."); } void cConflictCheck::Check() { if (evaltimeList) DELETENULL(evaltimeList); if (timerList) DELETENULL(timerList); LogFile.Log(3, "check only local conflicts = %s",GetLocal()?"yes":"no"); timerList = CreateCurrentTimerList(); if (timerList) evaltimeList = CreateEvaluationTimeList(timerList); if (evaltimeList) failedList = CreateConflictList(evaltimeList, timerList); if ((!localConflicts) && timerList) CreateRemoteConflictList(timerList,failedList); if (failedList) for(cConflictCheckTime* checkTime = failedList->First(); checkTime; checkTime = failedList->Next(checkTime)) { LogFile.Log(2,"result of conflict check for %s:", DAYDATETIME(checkTime->evaltime)); std::set::iterator it; for (it = checkTime->failedTimers.begin(); it != checkTime->failedTimers.end(); ++it) { if (!localConflicts) LogFile.Log(2,"timer '%s' (%s, channel %s) %s%s failed", (*it)->timer->File(), DAYDATETIME((*it)->timer->StartTime()), CHANNELNAME((*it)->timer->Channel()), (*it)->timer->Remote()?"@":"",(*it)->timer->Remote()?(*it)->timer->Remote():""); else LogFile.Log(2,"timer '%s' (%s, channel %s) failed", (*it)->timer->File(), DAYDATETIME((*it)->timer->StartTime()), CHANNELNAME((*it)->timer->Channel())); } } if (numConflicts > 0 && gl_timerStatusMonitor) gl_timerStatusMonitor->SetConflictCheckAdvised(); } cList* cConflictCheck::CreateCurrentTimerList() { LogFile.Log(3,"current timer list creation started"); cList* CurrentTimerList = NULL; // collect single event timers time_t tMax = 0; LOCK_TIMERS_READ; const cTimer* ti = NULL; for (ti = Timers->First(); ti; ti = Timers->Next(ti)) { tMax = std::max(tMax, ti->StartTime()); if (localConflicts && ti->Remote()) continue; if (!ti->IsSingleEvent()) continue; // already recording? int deviceNr = -1; if (ti->Local()) // we check devices only for local timers deviceNr = gl_recStatusMonitor->TimerRecDevice(ti)-1; // create a copy of this timer cTimer* clone = new cTimer(*ti); clone->SetEvent(ti->Event()); cConflictCheckTimerObj* timerObj = new cConflictCheckTimerObj(clone, ti->StartTime(), ti->StopTime(), deviceNr, ti->Id()); if (deviceNr >= 0) { devices[deviceNr].recTimers.insert(timerObj); timerObj->lastRecStart = ti->StartTime(); } LogFile.Log(3,"add timer '%s' (%s, channel %s) for conflict check", ti->File(), DAYDATETIME(ti->StartTime()), CHANNELNAME(ti->Channel())); if (deviceNr >= 0) LogFile.Log(3,"timer already recording since %s on device %d", DAYDATETIME(ti->StartTime()), deviceNr+1); if (!CurrentTimerList) CurrentTimerList = new cList; CurrentTimerList->Add(timerObj); } // collect repeating timers from now until the date of the timer with tMax time_t maxCheck = time(NULL) + std::min(14,EPGSearchConfig.checkMaxDays) * SECSINDAY; tMax = std::max(tMax, maxCheck); for (ti = Timers->First(); ti; ti = Timers->Next(ti)) { if (ti->IsSingleEvent()) continue; if (localConflicts && ti->Remote()) continue; //JF??? time_t day = time(NULL); while(day < tMax) { if (ti->DayMatches(day)) { time_t Start = cTimer::SetTime(day, cTimer::TimeToInt(ti->Start())); int deviceNr = -1; if (Start < time(NULL)) { #ifndef DEBUG_CONFL if (ti->Local() && ti->Recording()) deviceNr = gl_recStatusMonitor->TimerRecDevice(ti)-1; #else if (Start + ti->StopTime() - ti->StartTime() > time(NULL)) deviceNr = 0; #endif if (deviceNr == -1) // currently not recording, skip it { day += SECSINDAY; continue; } } else if (Start < ti->StartTime()) { day += SECSINDAY; continue; } // create a copy of this timer cTimer* clone = new cTimer(*ti); clone->SetEvent(ti->Event()); cConflictCheckTimerObj* timerObj = new cConflictCheckTimerObj(clone, Start, Start + ti->StopTime() - ti->StartTime(), deviceNr, ti->Id()); LogFile.Log(3,"add timer '%s' (%s, channel %s) for conflict check", ti->File(), DAYDATETIME(Start), CHANNELNAME(ti->Channel())); if (deviceNr >= 0) { LogFile.Log(3,"timer already recording since %s on device %d", DAYDATETIME(Start), deviceNr+1); devices[deviceNr].recTimers.insert(timerObj); timerObj->lastRecStart = Start; } if (!CurrentTimerList) CurrentTimerList = new cList; CurrentTimerList->Add(timerObj); } day += SECSINDAY; } } if (CurrentTimerList) CurrentTimerList->Sort(); LogFile.Log(3,"current timer list created"); return CurrentTimerList; } // create a list of all times that have to be checked cList* cConflictCheck::CreateEvaluationTimeList(cList* TimerList) { LogFile.Log(3,"create check time list"); cList* EvalTimeList = NULL; for(cConflictCheckTimerObj* TimerObj= TimerList->First(); TimerObj; TimerObj = TimerList->Next(TimerObj)) { if (!TimerObj->timer->HasFlags(tfActive)) continue; if (TimerObj->timer->Remote()) continue; // here we check local timers only if (!EvalTimeList) EvalTimeList = new cList; cConflictCheckTime* checkTime = NULL; // add all timer start times for(cConflictCheckTime* checkTimeTest = EvalTimeList->First(); checkTimeTest; checkTimeTest = EvalTimeList->Next(checkTimeTest)) { if (checkTimeTest->evaltime == TimerObj->start) { checkTime = checkTimeTest; break; } } if (!checkTime) { checkTime = new cConflictCheckTime(TimerObj->start); EvalTimeList->Add(checkTime); } checkTime->startingTimers.insert(TimerObj); // add all timer stop times checkTime = NULL; for(cConflictCheckTime* checkTimeTest = EvalTimeList->First(); checkTimeTest; checkTimeTest = EvalTimeList->Next(checkTimeTest)) { if (checkTimeTest->evaltime == TimerObj->stop) { checkTime = checkTimeTest; break; } } if (!checkTime) { checkTime = new cConflictCheckTime(TimerObj->stop); EvalTimeList->Add(checkTime); } checkTime->stoppingTimers.insert(TimerObj); } if (EvalTimeList) EvalTimeList->Sort(); LogFile.Log(3,"create check time list - done"); return EvalTimeList; } // this return a list of all conflicts cList* cConflictCheck::CreateConflictList(cList* EvalTimeList, cList* TimerList) { LogFile.Log(3,"create conflict list"); relevantConflicts = 0; numConflicts = 0; maxCheck = time(NULL) + std::min(14, EPGSearchConfig.checkMaxDays) * SECSINDAY; // check each time for(cConflictCheckTime* checkTime = EvalTimeList->First(); checkTime; checkTime = EvalTimeList->Next(checkTime)) { int Conflicts = ProcessCheckTime(checkTime); if (Conflicts > 0) // if there were conflicts do a retry as VDR would do a few seconds after the conflict { LogFile.Log(3,"retry check time %s", DAYDATETIME(checkTime->evaltime)); int OldConflicts = Conflicts; while(true) { Conflicts = ProcessCheckTime(checkTime); if (Conflicts == OldConflicts) break; // no change after retry? OldConflicts = Conflicts; }; } } nextRelevantConflictDate = 0; for(cConflictCheckTime* checkTime = EvalTimeList->First(); checkTime;) // clear the list { cConflictCheckTime* checkTimeNext = EvalTimeList->Next(checkTime); if (checkTime->failedTimers.empty()) EvalTimeList->Del(checkTime); else { bool allTimersIgnored = true; std::set::iterator it; for (it = checkTime->failedTimers.begin(); it != checkTime->failedTimers.end(); ++it) { numConflicts++; if (!(*it)->ignore) { if (!nextRelevantConflictDate) nextRelevantConflictDate = checkTime->evaltime; else nextRelevantConflictDate = std::min(nextRelevantConflictDate, checkTime->evaltime); relevantConflicts++; allTimersIgnored = false; break; } } if (allTimersIgnored) checkTime->ignore = true; } checkTime = checkTimeNext; } // store for external access cConflictCheckThread::m_cacheNextConflict = nextRelevantConflictDate; cConflictCheckThread::m_cacheRelevantConflicts = relevantConflicts; cConflictCheckThread::m_cacheTotalConflicts = numConflicts; LogFile.Log(3,"create conflict list - done"); return EvalTimeList; } void cConflictCheck::CreateRemoteConflictList(cList* TimerList, cList* failedList) { LogFile.Log(3,"add remote conflicts to list"); bool foundRemote = false; cStringList RemoteHosts; // check if we have any Remote timers RemoteHosts.Clear(); for(cConflictCheckTimerObj* TimerObj= TimerList->First(); TimerObj; TimerObj = TimerList->Next(TimerObj)) { if (!TimerObj->timer->HasFlags(tfActive)) continue; if (TimerObj->timer->Remote()) { if (RemoteHosts.Find(TimerObj->timer->Remote()) < 0) { foundRemote = true; RemoteHosts.Append(strdup(TimerObj->timer->Remote())); } } } if (!foundRemote) { LogFile.Log(3,"no remote timers to add"); return; } RemoteHosts.Sort(); cStringList Response; // for all RemoteHosts for (int i=0; i< RemoteHosts.Size(); i++) { Response.Clear(); if (ExecSVDRPCommand(RemoteHosts[i], "PLUG epgsearch LSCC REL", &Response)) { for (int j = 0; j < Response.Size(); j++) { const char *s = Response[j]; int Code = SVDRPCode(s); if (Code == 901) { LogFile.Log(3,"conflictcheck %s no remote conflicts found",RemoteHosts[i]); continue; } else if (Code != 900) { LogFile.Log(2,"Invalid remote response %d %s", Code, SVDRPValue(s)); break; } else if (const char* line = SVDRPValue(s)) { LogFile.Log(2,"remote conflictcheck line %s",line); int Id,recPart; char rest[256]; time_t evaltime; sscanf(line,"%ld:%d|%s",&evaltime,&Id,rest); cConflictCheckTime* checkTime = new cConflictCheckTime(evaltime); if (!failedList) failedList = new cList; LogFile.Log(2,"added remote checkTime %s to failedList",DAYDATETIME(evaltime)); failedList->Add(checkTime); numConflicts++; // find TimerObj with id Id in timerList cConflictCheckTimerObj* failedTimer = NULL; bool foundfT = false; for(failedTimer = TimerList->First(); failedTimer; failedTimer = TimerList->Next(failedTimer)) { if (failedTimer->timer->Id() == Id) { foundfT = true; break; } } if (!foundfT) { LogFile.Log(2,"remote failed Timer disappeared"); continue; } LogFile.Log(2,"create remote failedTimer with Id %d",Id); failedTimer->conflCheckTime = checkTime; failedTimer->origIndex = Id; sscanf(rest,"%d|%s",&recPart,rest); failedTimer->recDuration=((failedTimer->stop-failedTimer->start)* recPart / 100); cConflictCheckTimerObj* concurrentTimer = NULL; while (strlen(rest) > 0) { int n = sscanf(rest,"%d#%s",&Id,rest); if (n < 2) { if (sscanf(rest,"%d",&Id) <= 0) { LogFile.Log(2,"error scanning rest of line %s",rest); break; } *rest = 0; // TODO : possible ?? } // find TimerObj itcc for with Id in timerList bool foundcT = false; for(concurrentTimer = TimerList->First(); concurrentTimer; concurrentTimer = TimerList->Next(concurrentTimer)) { if (concurrentTimer->timer->Id() == Id) { foundcT = true; break; } } if (!foundcT) { LogFile.Log(2,"remote concurrent Timer disappeared"); continue; } if (!failedTimer->concurrentTimers) failedTimer->concurrentTimers = new std::set; LogFile.Log(2,"insert remote Id %d into concurrentTimers",concurrentTimer->timer->Id()); failedTimer->concurrentTimers->insert(concurrentTimer); } // while concurrent Timers LogFile.Log(2,"insert Id %d into checkTime->failedTimers",failedTimer->timer->Id()); checkTime->failedTimers.insert(failedTimer); relevantConflicts++; } else LogFile.Log(2,"got Code %d, but no Value from %s",Code,RemoteHosts[i]); } // received response } else { LogFile.Log(2,"ExecSVDRPCommand failed for %s",RemoteHosts[i]); } } // for all RemoteHosts cConflictCheckThread::m_cacheTotalConflicts = numConflicts; cConflictCheckThread::m_cacheRelevantConflicts = relevantConflicts; LogFile.Log(3,"add remote conflicts done"); } // checks for conflicts at one special time int cConflictCheck::ProcessCheckTime(cConflictCheckTime* checkTime) { if (!checkTime) return 0; LogFile.Log(3,"check time %s", DAYDATETIME(checkTime->evaltime)); LogFile.Log(3,"detach stopping timers"); int Conflicts = 0; // detach all stopping timers from their devices std::set::iterator it; for (it = checkTime->stoppingTimers.begin(); it != checkTime->stoppingTimers.end(); ++it) if ((*it) && (*it)->device >= 0) { LogFile.Log(3,"detach device %d from timer '%s' (%s, channel %s) at %s", ((*it)->device)+1, (*it)->timer->File(), DAYDATETIME((*it)->start), CHANNELNAME((*it)->timer->Channel()), DAYDATETIME(checkTime->evaltime)); devices[(*it)->device].recTimers.erase(*it); (*it)->lastRecStop = checkTime->evaltime; if ((*it)->lastRecStart > 0 && (*it)->lastRecStart < (*it)->lastRecStop) { (*it)->recDuration += (*it)->lastRecStop - (*it)->lastRecStart; (*it)->lastRecStart = 0; if (((*it)->stop - (*it)->start - (*it)->recDuration) < EPGSearchConfig.checkMinDuration * 60) (*it)->ignore = true; } } LogFile.Log(3,"add pending timers"); // if we have pending timers add them to the current start list for (it = pendingTimers.begin(); it != pendingTimers.end(); ++it) { if ((*it) && (*it)->stop > checkTime->evaltime) checkTime->startingTimers.insert(*it); pendingTimers.erase(*it); } LogFile.Log(3,"attach starting timers"); // handle starting timers for (it = checkTime->startingTimers.begin(); it != checkTime->startingTimers.end(); ++it) { bool NeedsDetachReceivers = false; if (!(*it) || (*it)->device >= 0) continue; // already has a device int device = GetDevice(*it, &NeedsDetachReceivers); if (device >= 0) // device will be attached? { if (NeedsDetachReceivers) // but needs to detach all others? { // disable running timers std::set::iterator it2 = devices[device].recTimers.begin(); for(; it2 != devices[device].recTimers.end(); ++it2) { LogFile.Log(3,"stopping timer '%s' (%s, channel %s) at %s on device %d because of higher priority", (*it2)->timer->File(), DAYDATETIME((*it2)->start), CHANNELNAME((*it2)->timer->Channel()), DAYDATETIME(checkTime->evaltime), device+1); AddConflict((*it2), checkTime, pendingTimers); devices[device].recTimers.erase(*it2); Conflicts++; } } devices[device].recTimers.insert(*it); (*it)->device = device; (*it)->lastRecStart = checkTime->evaltime; LogFile.Log(3,"recording timer '%s' (%s, channel %s) at %s on device %d", (*it)->timer->File(), DAYDATETIME((*it)->start), CHANNELNAME((*it)->timer->Channel()), DAYDATETIME(checkTime->evaltime), device+1); } else { AddConflict((*it), checkTime, pendingTimers); Conflicts++; } } LogFile.Log(3,"check time %s - done", DAYDATETIME(checkTime->evaltime)); return Conflicts; } eModuleStatus cConflictCheck::CamSlotModuleStatus(cCamSlot *CamSlot) { if (!CamSlot) return msNone; if ((int)camSlotStatusArray.size() != CamSlots.Count()) for (cCamSlot *CamSlot = CamSlots.First(); CamSlot; CamSlot = CamSlots.Next(CamSlot)) camSlotStatusArray.push_back(CamSlot->ModuleStatus()); if (CamSlot->Index() < (int)camSlotStatusArray.size()) return camSlotStatusArray[CamSlot->Index()]; else return msNone; } int cConflictCheck::GetDevice(cConflictCheckTimerObj* TimerObj, bool* NeedsDetachReceivers) { int Priority = TimerObj->timer->Priority(); const cChannel* Channel = TimerObj->timer->Channel(); // Collect the current priorities of all CAM slots that can decrypt the channel: int selDevice = -1; int NumCamSlots = CamSlots.Count(); int SlotPriority[NumCamSlots]; int NumUsableSlots = 0; if (Channel->Ca() >= CA_ENCRYPTED_MIN) { for (cCamSlot *CamSlot = CamSlots.First(); CamSlot; CamSlot = CamSlots.Next(CamSlot)) { SlotPriority[CamSlot->Index()] = MAXPRIORITY + 1; // assumes it can't be used if (CamSlotModuleStatus(CamSlot) == msReady) { if (CamSlot->ProvidesCa(Channel->Caids())) { if (!ChannelCamRelations.CamChecked(Channel->GetChannelID(), CamSlot->SlotNumber())) { SlotPriority[CamSlot->Index()] = CamSlot->Priority(); NumUsableSlots++; } } } } #ifdef CFLC int NumUsableSlots = 1; #endif if (!NumUsableSlots) return selDevice; // no CAM is able to decrypt this channel } if (NeedsDetachReceivers) *NeedsDetachReceivers = false; uint32_t Impact = 0xFFFFFFFF; // we're looking for a device with the least impact for (int j = 0; j < NumCamSlots || !NumUsableSlots; j++) { if (NumUsableSlots && SlotPriority[j] > MAXPRIORITY) continue; // there is no CAM available in this slot for (int i = 0; i < numDevices; i++) { if (Channel->Ca() && Channel->Ca() <= CA_DVB_MAX && Channel->Ca() != devices[i].CardIndex() + 1) continue; // a specific card was requested, but not this one if (NumUsableSlots && !CamSlots.Get(j)->Assign(devices[i].device, true)) continue; // CAM slot can't be used with this device bool ndr; if (devices[i].ProvidesChannel(Channel, Priority, &ndr)) { // this device is basically able to do the job if (NumUsableSlots && devices[i].CamSlot() && devices[i].CamSlot() != CamSlots.Get(j)) ndr = true; // using a different CAM slot requires detaching receivers // Put together an integer number that reflects the "impact" using // this device would have on the overall system. Each condition is represented // by one bit in the number (or several bits, if the condition is actually // a numeric value). The sequence in which the conditions are listed corresponds // to their individual severity, where the one listed first will make the most // difference, because it results in the most significant bit of the result. uint32_t imp = 0; // prefer the primary device for live viewing if we don't need to detach existing receivers imp <<= 1; ; // use receiving devices if we don't need to detach existing receivers imp <<= 1; imp |= !devices[i].Receiving() || ndr; // avoid devices that are receiving imp <<= 1; imp |= devices[i].Receiving(); // use the device with the lowest priority (+MAXPRIORITY to assure that values -99..99 can be used) imp <<= 8; imp |= std::min(std::max(devices[i].Priority() + MAXPRIORITY, 0), 0xFF); // use the CAM slot with the lowest priority (+MAXPRIORITY to assure that values -99..99 can be used) imp <<= 8; imp |= std::min(std::max((NumUsableSlots ? SlotPriority[j] : 0) + MAXPRIORITY, 0), 0xFF); // avoid devices if we need to detach existing receivers imp <<= 1; imp |= ndr; // avoid the primary device imp <<= 1; imp |= devices[i].IsPrimaryDevice(); // avoid cards with Common Interface for FTA channels imp <<= 1; imp |= NumUsableSlots ? 0 : devices[i].HasCi(); // avoid full featured cards imp <<= 1; imp |= devices[i].HasDecoder(); // prefer CAMs that are known to decrypt this channel imp <<= 1; imp |= NumUsableSlots ? !ChannelCamRelations.CamDecrypt(Channel->GetChannelID(), j + 1) : 0; if (imp < Impact) { // This device has less impact than any previous one, so we take it. Impact = imp; selDevice = i; if (NeedsDetachReceivers) *NeedsDetachReceivers = ndr; } } } if (!NumUsableSlots) break; // no CAM necessary, so just one loop over the devices } return selDevice; } void cConflictCheck::AddConflict(cConflictCheckTimerObj* TimerObj, cConflictCheckTime* CheckTime, std::set& pendingTimers) { for(cConflictCheckTimerObj* concTimer= timerList->First(); concTimer; concTimer = timerList->Next(concTimer)) { if (concTimer->start >= TimerObj->stop) continue; if (concTimer->stop <= TimerObj->start) continue; if (!TimerObj->concurrentTimers) TimerObj->concurrentTimers = new std::set; TimerObj->concurrentTimers->insert(concTimer); } TimerObj->ignore = (TimerObj->timer->Priority() < EPGSearchConfig.checkMinPriority) || TimerObj->start > maxCheck; CheckTime->concurrentRecs.insert(TimerObj); pendingTimers.insert(TimerObj); TimerObj->lastRecStop = CheckTime->evaltime; if (TimerObj->lastRecStart > 0 && TimerObj->lastRecStart < TimerObj->lastRecStop) { TimerObj->recDuration += TimerObj->lastRecStop - TimerObj->lastRecStart; TimerObj->lastRecStart = 0; if ((TimerObj->stop - TimerObj->start - TimerObj->recDuration) < EPGSearchConfig.checkMinDuration * 60) TimerObj->ignore = true; } TimerObj->device = -1; if (!TimerObj->conflCheckTime) TimerObj->conflCheckTime = CheckTime; else return; CheckTime->failedTimers.insert(TimerObj); LogFile.Log(3,"conflict found for timer '%s' (%s, channel %s)", TimerObj->timer->File(), DAYDATETIME(TimerObj->start), CHANNELNAME(TimerObj->timer->Channel())); } bool cConflictCheck::TimerInConflict(const cTimer* timer) { if (!failedList) return false; for(cConflictCheckTime* checkTime = failedList->First(); checkTime; checkTime = failedList->Next(checkTime)) { std::set::iterator it; for (it = checkTime->failedTimers.begin(); it != checkTime->failedTimers.end(); ++it) { if (!(*it)->ignore) { std::set::iterator it2; if ((*it)->concurrentTimers) { LOCK_TIMERS_READ; for (it2 = (*it)->concurrentTimers->begin(); it2 != (*it)->concurrentTimers->end(); ++it2) { if ((*it2)->OrigTimer(Timers) == timer) return true; } } } } } return false; } void cConflictCheck::EvaluateConflCheckCmd() { if (strlen(EPGSearchConfig.conflCheckCmd) > 0) { LogFile.Log(2,"evaluating conflict check command '%s'", EPGSearchConfig.conflCheckCmd); for(cConflictCheckTime* ct = failedList->First(); ct; ct = failedList->Next(ct)) { if (ct->ignore) continue; std::set::iterator it; for (it = ct->failedTimers.begin(); it != ct->failedTimers.end(); ++it) if ((*it) && !(*it)->ignore) { string result = EPGSearchConfig.conflCheckCmd; LOCK_TIMERS_READ; if (!(*it)->OrigTimer(Timers)) { LogFile.Log(3,"timer has disappeared meanwhile"); continue; } else LogFile.Log(3,"evaluating conflict check command for timer '%s' (%s, channel %s)", (*it)->timer->File(), DAYDATETIME((*it)->start), CHANNELNAME((*it)->timer->Channel())); if ((*it)->Event()) { cVarExpr varExprEvent(result); result = varExprEvent.Evaluate((*it)->Event()); } cVarExpr varExprTimer(result); result = varExprTimer.Evaluate((*it)->timer); cVarExpr varExpr(result); varExpr.Evaluate(); } } } } vdr-plugin-epgsearch/po/0000755000175000017500000000000013145412721015046 5ustar tobiastobiasvdr-plugin-epgsearch/po/ca_ES.po0000644000175000017500000005735213145412721016374 0ustar tobiastobias# VDR plugin language source file. # Copyright (C) 2007 Klaus Schmidinger # This file is distributed under the same license as the VDR package. # Marc Rovira Vall , 2003 # Ramon Roca , 2003 # Jordi Vilà , 2003 # msgid "" msgstr "" "Project-Id-Version: VDR 1.5.7\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-06-15 11:15+0200\n" "PO-Revision-Date: 2007-08-14 20:21+0200\n" "Last-Translator: Jordi Vilà \n" "Language-Team: Catalan \n" "Language: ca\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "Channel groups" msgstr "" msgid "Button$Select" msgstr "" msgid "Channel group used by:" msgstr "" msgid "Edit$Delete group?" msgstr "" msgid "Edit channel group" msgstr "" msgid "Group name" msgstr "" msgid "Button$Invert selection" msgstr "" msgid "Button$All yes" msgstr "" msgid "Button$All no" msgstr "" msgid "Group name is empty!" msgstr "" msgid "Group name already exists!" msgstr "" msgid "Direct access to epgsearch's conflict check menu" msgstr "" msgid "Timer conflicts" msgstr "" msgid "Conflict info in main menu" msgstr "" msgid "next" msgstr "" #, c-format msgid "timer conflict at %s! Show it?" msgstr "" #, c-format msgid "%d timer conflicts! First at %s. Show them?" msgstr "" msgid "search the EPG for repeats and more" msgstr "" msgid "Program guide" msgstr "" msgid "search timer update running" msgstr "" msgid "Direct access to epgsearch's search menu" msgstr "" msgid "Search" msgstr "" msgid "EpgSearch-Search in main menu" msgstr "" msgid "Button$Help" msgstr "" msgid "Standard" msgstr "" #, fuzzy msgid "Button$Commands" msgstr "Gravar" msgid "Button$Search" msgstr "" msgid "never" msgstr "" msgid "always" msgstr "" msgid "smart" msgstr "" msgid "before user-def. times" msgstr "" msgid "after user-def. times" msgstr "" msgid "before 'next'" msgstr "" msgid "General" msgstr "" msgid "EPG menus" msgstr "" msgid "User-defined EPG times" msgstr "" msgid "Timer programming" msgstr "" msgid "Search and search timers" msgstr "" msgid "Timer conflict checking" msgstr "" msgid "Email notification" msgstr "" msgid "Hide main menu entry" msgstr "" msgid "Help$Hides the main menu entry and may be useful if this plugin is used to replace the original 'Schedule' entry." msgstr "" msgid "Main menu entry" msgstr "" msgid "Help$The name of the main menu entry which defaults to 'Programm guide'." msgstr "" msgid "Replace original schedule" msgstr "" msgid "Help$When VDR is patched to allow this plugin to replace the original 'Schedule' entry, you can de/activate this replacement here." msgstr "" msgid "Start menu" msgstr "" msgid "Help$Choose between 'Overview - Now' and 'Schedule' as start menu when this plugin is called." msgstr "" msgid "Ok key" msgstr "" msgid "" "Help$Choose here the behaviour of key 'Ok'. You can use it to display the summary or to switch to the corresponding channel.\n" "Note: the functionality of key 'blue' (Switch/Info/Search) depends on this setting." msgstr "" msgid "Red key" msgstr "" msgid "" "Help$Choose which standard function ('Record' or 'Commands') you like to have on the red key.\n" "(Can be toggled with key '0')" msgstr "" msgid "Blue key" msgstr "" msgid "" "Help$Choose which standard function ('Switch'/'Info' or 'Search') you like to have on the blue key.\n" "(Can be toggled with key '0')" msgstr "" msgid "Show progress in 'Now'" msgstr "" msgid "Help$Shows a progressbar in 'Overview - Now' that informs about the remaining time of the current event." msgstr "" msgid "Show channel numbers" msgstr "" msgid "" "Help$Display channel numbers in 'Overview - Now'.\n" "\n" "(To completely define your own menu look please inspect the MANUAL)" msgstr "" msgid "Show channel separators" msgstr "" msgid "Help$Display VDR channel groups as separators between your channels in 'Overview - Now'." msgstr "" msgid "Show day separators" msgstr "" msgid "Help$Display a separator line at day break in 'Schedule'." msgstr "" msgid "Show radio channels" msgstr "" msgid "Help$Show also radio channels." msgstr "" msgid "Limit channels from 1 to" msgstr "" msgid "Help$If you have a large channel set you can speed up things when you limit the displayed channels with this setting. Use '0' to disable the limit." msgstr "" msgid "'One press' timer creation" msgstr "" msgid "Help$When a timer is created with 'Record' you can choose between an immediate creation of the timer or the display of the timer edit menu." msgstr "" msgid "Show channels without EPG" msgstr "" msgid "Help$Choose 'yes' here if you want to display channels without EPG in 'Overview - Now'. 'Ok' on these entries switches the channel." msgstr "" msgid "Time interval for FRew/FFwd [min]" msgstr "" msgid "" "Help$Choose here the time interval which should be used for jumping through the EPG by pressing FRew/FFwd.\n" "\n" "(If you don't have those keys, you can toggle to this functionality pressing '0' and get '<<' and '>>' on the keys green and yellow)" msgstr "" msgid "Toggle Green/Yellow" msgstr "" msgid "Help$Specify if green and yellow shall also be switched when pressing '0'." msgstr "" msgid "Show favorites menu" msgstr "" msgid "" "Help$A favorites menu can display a list of your favorite broadcasts. Enable this if you want an additional menu besides 'Now' and 'Next'\n" "Any search can be used as a favorite. You only have to set the option 'Use in favorites menu' when editing a search." msgstr "" msgid "for the next ... hours" msgstr "" msgid "Help$This value controls the timespan used to display your favorites." msgstr "" msgid "Use user-defined time" msgstr "" msgid "Help$Besides 'Now' and 'Next' you can specify up to 4 other times in the EPG which can be used by repeatedly pressing the green key, e.g. 'prime time', 'late night',..." msgstr "" msgid "Description" msgstr "" msgid "Help$This is the description for your user-defined time as it will appear as label on the green button." msgstr "" msgid "Time" msgstr "" msgid "Help$Specify the user-defined time here in 'HH:MM'." msgstr "" msgid "Use VDR's timer edit menu" msgstr "" msgid "" "Help$This plugin has its own timer edit menu extending the original one with some extra functionality like\n" "- an additional directory entry\n" "- user-defined days of week for repeating timers\n" "- adding an episode name\n" "- support for EPG variables (see MANUAL)" msgstr "" msgid "Default recording dir" msgstr "" msgid "Help$When creating a timer you can specify here a default recording directory." msgstr "" msgid "Add episode to manual timers" msgstr "" msgid "" "Help$If you create a timer for a series, you can automatically add the episode name.\n" "\n" "- never: no addition\n" "- always: always add episode name if present\n" "- smart: add only if event lasts less than 80 mins." msgstr "" msgid "Default timer check method" msgstr "" msgid "" "Help$Manual timers can be checked for EPG changes. Here you can setup the default check method for each channel. Choose between\n" "\n" "- no checking\n" "- by event ID: checks by an event ID supplied by the channel provider.\n" "- by channel and time: check by the duration match." msgstr "" msgid "Button$Setup" msgstr "Configuració" msgid "Use search timers" msgstr "" msgid "Help$'Search timers' can be used to automatically create timers for events that match your search criterions." msgstr "" msgid " Update interval [min]" msgstr "" msgid "Help$Specify here the time intervall to be used when searching for events in the background." msgstr "" msgid " SVDRP port" msgstr "" msgid "Help$Programming of new timers or timer changes is done with SVDRP. The default value should be correct, so change it only if you know what you are doing." msgstr "" msgid "Help$Specify here the default priority of timers created with this plugin. This value can also be adjusted for each search itself." msgstr "" msgid "Help$Specify here the default lifetime of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "" msgid "Help$Specify here the default start recording margin of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "" msgid "Help$Specify here the default stop recording margin of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "" msgid "No announcements when replaying" msgstr "" msgid "Help$Set this to 'yes' if you don't like to get any announcements of broadcasts if you currently replay anything." msgstr "" msgid "Recreate timers after deletion" msgstr "" msgid "Help$Set this to 'yes' if you want timers to be recreated with the next search timer update after deleting them." msgstr "" msgid "Check if EPG exists for ... [h]" msgstr "" msgid "Help$Specify how many hours of future EPG there should be and get warned else after a search timer update." msgstr "" msgid "Warn by OSD" msgstr "" msgid "Help$Set this to 'yes' if you want get warnings from the EPG check via OSD." msgstr "" msgid "Warn by mail" msgstr "" msgid "Help$Set this to 'yes' if you want get warnings from the EPG check by mail." msgstr "" msgid "Channel group to check" msgstr "" msgid "Help$Specify the channel group to check." msgstr "" msgid "Ignore PayTV channels" msgstr "" msgid "Help$Set this to 'yes' if don't want to see events on PayTV channels when searching for repeats." msgstr "" msgid "Search templates" msgstr "" msgid "Help$Here you can setup templates for your searches." msgstr "" msgid "Blacklists" msgstr "" msgid "Help$Here you can setup blacklists which can be used within a search to exclude events you don't like." msgstr "" msgid "Help$Here you can setup channel groups which can be used within a search. These are different to VDR channel groups and represent a set of arbitrary channels, e.g. 'FreeTV'." msgstr "" msgid "Ignore below priority" msgstr "" msgid "Help$If a timer with priority below the given value will fail it will not be classified as important. Only important conflicts will produce an OSD message about the conflict after an automatic conflict check." msgstr "" msgid "Ignore conflict duration less ... min." msgstr "" msgid "Help$If a conflicts duration is less then the given number of minutes it will not be classified as important. Only important conflicts will produce an OSD message about the conflict after an automatic conflict check." msgstr "" msgid "Only check within next ... days" msgstr "" msgid "Help$This value reduces the conflict check to the given range of days. All other conflicts are classified as 'not yet important'." msgstr "" msgid "Check also remote conflicts" msgstr "" msgid "Help$Set this to 'yes' if the conflict check should be done for timers set on remote hosts. This needs SVDRPPeering to be set in vdr and Plugin epgsearch running on the remote host." msgstr "" msgid "--- Automatic checking ---" msgstr "" msgid "After each timer programming" msgstr "" msgid "Help$Set this to 'yes' if the conflict check should be performed after each manual timer programming. In the case of a conflict you get immediately a message that informs you about it. The message is only displayed if this timer is involved in any conflict." msgstr "" msgid "When a recording starts" msgstr "" msgid "Help$Set this to 'yes' if the conflict check should be performed when a recording starts. In the case of a conflict you get immediately a message that informs you about it. The message is only displayed if the conflict is within the next 2 hours." msgstr "" msgid "After each search timer update" msgstr "" msgid "Help$Set this to 'yes' if the conflict check should be performed after each search timer update." msgstr "" msgid "every ... minutes" msgstr "" msgid "" "Help$Specify here the time intervall to be used for an automatic conflict check in the background.\n" "('0' disables an automatic check)" msgstr "" msgid "if conflicts within next ... minutes" msgstr "" msgid "Help$If the next conflict will appear in the given number of minutes you can specify here a shorter check intervall to get more OSD notifications about it." msgstr "" msgid "Avoid notification when replaying" msgstr "" msgid "Help$Set this to 'yes' if the don't want to get OSD messages about conflicts if you currently replay something. Nevertheless messages will be displayed if the first upcoming conflict is within the next 2 hours." msgstr "" msgid "Search timer notification" msgstr "" msgid "Help$Set this to 'yes' if you want to get an email notification about the search timers that where programmed automatically in the background." msgstr "" msgid "Time between mails [h]" msgstr "" msgid "" "Help$Specifiy how much time in [h] you would\n" "like to have atleast between two mails.\n" "With '0' you get a new mail after each\n" "search timer update with new results." msgstr "" msgid "Timer conflict notification" msgstr "" msgid "Help$Set this to 'yes' if you want to get an email notification about the timer conflicts." msgstr "" msgid "Send to" msgstr "" msgid "Help$Specify the email address where notifications should be sent to." msgstr "" msgid "Mail method" msgstr "" msgid "" "Help$Specify here the method to use when sending mails.\n" "You can choose between\n" " - 'sendmail': requires a properly configured email system\n" " - 'SendEmail.pl': simple script for mail delivery" msgstr "" msgid "--- Email account ---" msgstr "" msgid "Email address" msgstr "" msgid "Help$Specify the email address where notifications should be sent from." msgstr "" msgid "SMTP server" msgstr "" msgid "Help$Specify the SMTP server that should deliver the notifications. If it's using a port different from the default(25) append the port with \":port\"." msgstr "" msgid "Use SMTP authentication" msgstr "" msgid "Help$Set this to 'yes' if your account needs authentication to send mails." msgstr "" msgid "Auth user" msgstr "" msgid "Help$Specify the auth user, if this account needs authentication for SMTP." msgstr "" msgid "Auth password" msgstr "" msgid "Help$Specify the auth password, if this account needs authentication for SMTP." msgstr "" msgid "Mail account check failed!" msgstr "" msgid "Button$Test" msgstr "" msgid "$ abcdefghijklmnopqrstuvwxyz0123456789-.,#~\\^$[]|()*+?{}/:%@&_" msgstr "" msgid "Start/Stop time has changed" msgstr "" msgid "Title/episode has changed" msgstr "" msgid "No new timers were added." msgstr "" msgid "No timers were modified." msgstr "" msgid "No timers were deleted." msgstr "" msgid "No new events to announce." msgstr "" msgid "This version of EPGSearch does not support this service!" msgstr "" msgid "EPGSearch does not exist!" msgstr "" #, c-format msgid "%d new broadcast" msgstr "" msgid "Button$by channel" msgstr "" msgid "Button$by time" msgstr "" msgid "Button$Episode" msgstr "" msgid "Button$Title" msgstr "" msgid "announce details" msgstr "" msgid "announce again" msgstr "" msgid "with next update" msgstr "" msgid "again from" msgstr "" msgid "Search timer" msgstr "" msgid "Edit blacklist" msgstr "" msgid "phrase" msgstr "" msgid "all words" msgstr "" msgid "at least one word" msgstr "" msgid "match exactly" msgstr "" msgid "regular expression" msgstr "" msgid "fuzzy" msgstr "" msgid "user-defined" msgstr "" msgid "interval" msgstr "" msgid "channel group" msgstr "" msgid "only FTA" msgstr "" msgid "Search term" msgstr "" msgid "Search mode" msgstr "" msgid "Tolerance" msgstr "" msgid "Match case" msgstr "" msgid "Use title" msgstr "" msgid "Use subtitle" msgstr "" msgid "Use description" msgstr "" msgid "Use extended EPG info" msgstr "" msgid "Ignore missing categories" msgstr "" msgid "Use channel" msgstr "" msgid " from channel" msgstr "" msgid " to channel" msgstr "" msgid "Channel group" msgstr "" msgid "Use time" msgstr "" msgid " Start after" msgstr "" msgid " Start before" msgstr "" msgid "Use duration" msgstr "" msgid " Min. duration" msgstr "" msgid " Max. duration" msgstr "" msgid "Use day of week" msgstr "" msgid "Day of week" msgstr "" msgid "Use global" msgstr "" msgid "Button$Templates" msgstr "" msgid "*** Invalid Channel ***" msgstr "" msgid "Please check channel criteria!" msgstr "" msgid "Edit$Delete blacklist?" msgstr "" msgid "Repeats" msgstr "" msgid "Create search" msgstr "" msgid "Search in recordings" msgstr "" msgid "Mark as 'already recorded'?" msgstr "" msgid "Add/Remove to/from switch list?" msgstr "" msgid "Create blacklist" msgstr "" msgid "EPG Commands" msgstr "" msgid "Epgsearch: RemoteTimerModifications failed" msgstr "" msgid "Already running!" msgstr "" msgid "Add to switch list?" msgstr "" msgid "Delete from switch list?" msgstr "" msgid "Button$Details" msgstr "" msgid "Button$Filter" msgstr "" msgid "Button$Show all" msgstr "" msgid "conflicts" msgstr "" msgid "no conflicts!" msgstr "" msgid "no important conflicts!" msgstr "" msgid "C" msgstr "C" msgid "Button$Repeats" msgstr "" msgid "no check" msgstr "" msgid "by channel and time" msgstr "" msgid "by event ID" msgstr "" msgid "Select directory" msgstr "" msgid "Button$Level" msgstr "" msgid "Event" msgstr "" msgid "Favorites" msgstr "" msgid "Search results" msgstr "" msgid "Timer conflict! Show?" msgstr "" msgid "Directory" msgstr "" msgid "Channel" msgstr "" msgid "Childlock" msgstr "" msgid "Record on" msgstr "" msgid "Timer check" msgstr "" msgid "recording with device" msgstr "" msgid "Button$With subtitle" msgstr "" msgid "Button$Without subtitle" msgstr "" msgid "Timer has been deleted" msgstr "" msgid "Button$Extended" msgstr "" msgid "Button$Simple" msgstr "" msgid "Use blacklists" msgstr "" msgid "Edit$Search text too short - use anyway?" msgstr "" #, fuzzy msgid "Button$Orphaned" msgstr "Gravar" msgid "Button$by name" msgstr "" msgid "Button$by date" msgstr "" msgid "Button$Delete all" msgstr "" msgid "Recordings" msgstr "" msgid "Edit$Delete entry?" msgstr "" msgid "Edit$Delete all entries?" msgstr "" msgid "Summary" msgstr "" msgid "Auxiliary info" msgstr "" msgid "Button$Aux info" msgstr "" msgid "Search actions" msgstr "" msgid "Execute search" msgstr "" msgid "Use as search timer on/off" msgstr "" msgid "Trigger search timer update" msgstr "" msgid "Show recordings done" msgstr "" msgid "Show timers created" msgstr "" msgid "Create a copy" msgstr "" msgid "Use as template" msgstr "" msgid "Show switch list" msgstr "" msgid "Show blacklists" msgstr "" msgid "Delete created timers?" msgstr "" msgid "Timer conflict check" msgstr "" msgid "Disable associated timers too?" msgstr "" msgid "Activate associated timers too?" msgstr "" msgid "Search timers activated in setup." msgstr "" msgid "Run search timer update?" msgstr "" msgid "Copy this entry?" msgstr "" msgid "Copy" msgstr "" msgid "Copy this entry to templates?" msgstr "" msgid "Delete all timers created from this search?" msgstr "" msgid "Button$Actions" msgstr "" msgid "Search entries" msgstr "" msgid "active" msgstr "" msgid "Edit$Delete search?" msgstr "" msgid "Edit search" msgstr "" msgid "Record" msgstr "Gravar" msgid "Announce by OSD" msgstr "" msgid "Switch only" msgstr "" msgid "Announce and switch" msgstr "" msgid "Announce by mail" msgstr "" msgid "Inactive record" msgstr "" msgid "only globals" msgstr "" msgid "Selection" msgstr "" msgid "all" msgstr "" msgid "count recordings" msgstr "" msgid "count days" msgstr "" msgid "if present" msgstr "" msgid "same day" msgstr "" msgid "same week" msgstr "" msgid "same month" msgstr "" msgid "Template name" msgstr "" msgid "Help$Specify the name of the template." msgstr "" msgid "Help$Specify here the term to search for." msgstr "" msgid "" "Help$The following search modes exist:\n" "\n" "- phrase: searches for sub terms\n" "- all words: all single words must appear\n" "- at least one word: at least one single word must appear\n" "- match exactly: must match exactly\n" "- regular expression: match a regular expression\n" "- fuzzy searching: searches approximately" msgstr "" msgid "Help$This sets the tolerance of fuzzy searching. The value represents the allowed errors." msgstr "" msgid "Help$Set this to 'Yes' if your search should match the case." msgstr "" msgid "Help$Set this to 'Yes' if you like to search in the title of an event." msgstr "" msgid "Help$Set this to 'Yes' if you like to search in the episode of an event." msgstr "" msgid "Help$Set this to 'Yes' if you like to search in the summary of an event." msgstr "" msgid "Use content descriptor" msgstr "" msgid "Help$Set this to 'Yes' if you want to search the contents by a descriptor." msgstr "" msgid "Help$The summary of an event, can contain additional information like 'Genre', 'Category', 'Year',... called 'EPG categories' within EPGSearch. External EPG providers often deliver this information. This allows refining a search and other nice things, like searching for the 'tip of the day'. To use it set this to 'Yes'." msgstr "" msgid "Help$The file epgsearchcats.conf specifies the search mode for this entry. One can search by text or by value. You can also edit a list of predefined values in this file that can be selected here." msgstr "" msgid "Help$If a selected category is not part of the summary of an event this normally excludes this event from the search results. To avoid this, set this option to 'Yes', but please handle this with care to avoid a huge amount of results." msgstr "" msgid "Use in favorites menu" msgstr "" msgid "Result menu layout" msgstr "" msgid "Use as search timer" msgstr "" msgid "Action" msgstr "" msgid "Switch ... minutes before start" msgstr "" msgid "Unmute sound" msgstr "" msgid "Ask ... minutes before start" msgstr "" msgid " Series recording" msgstr "" msgid "Delete recordings after ... days" msgstr "" msgid "Keep ... recordings" msgstr "" msgid "Pause when ... recordings exist" msgstr "" msgid "Avoid repeats" msgstr "" msgid "Allowed repeats" msgstr "" msgid "Only repeats within ... days" msgstr "" msgid "Compare title" msgstr "" msgid "Compare subtitle" msgstr "" msgid "Compare summary" msgstr "" msgid "Min. match in %" msgstr "" msgid "Compare date" msgstr "" msgid "Compare categories" msgstr "" msgid "VPS" msgstr "" msgid "Auto delete" msgstr "" msgid "after ... recordings" msgstr "" msgid "after ... days after first rec." msgstr "" msgid "Edit user-defined days of week" msgstr "" msgid "Compare" msgstr "" msgid "Select blacklists" msgstr "" msgid "Values for EPG category" msgstr "" msgid "Button$Apply" msgstr "" msgid "less" msgstr "" msgid "less or equal" msgstr "" msgid "greater" msgstr "" msgid "greater or equal" msgstr "" msgid "equal" msgstr "" msgid "not equal" msgstr "" msgid "Activation of search timer" msgstr "" msgid "First day" msgstr "" msgid "Last day" msgstr "" msgid "Button$all channels" msgstr "" msgid "Button$only FTA" msgstr "" msgid "Button$Timer preview" msgstr "" msgid "Blacklist results" msgstr "" msgid "found recordings" msgstr "" msgid "Error while accessing recording!" msgstr "" msgid "Button$Default" msgstr "" msgid "Edit$Delete template?" msgstr "" msgid "Overwrite existing entries?" msgstr "" msgid "Edit entry" msgstr "" msgid "Switch" msgstr "" msgid "Announce only" msgstr "" msgid "Announce ... minutes before start" msgstr "" msgid "action at" msgstr "" msgid "Switch list" msgstr "" msgid "Edit template" msgstr "" msgid "Timers" msgstr "" msgid ">>> no info! <<<" msgstr "" msgid "Overview" msgstr "" msgid "Button$Favorites" msgstr "" msgid "Quick search for broadcasts" msgstr "" msgid "Quick search" msgstr "" msgid "Show in main menu" msgstr "" #, c-format msgid "%d new broadcast(s) found! Show them?" msgstr "" msgid "Search timer update done!" msgstr "" #, c-format msgid "small EPG content on:%s" msgstr "" msgid "VDR EPG check warning" msgstr "" #, c-format msgid "Switch to (%d) '%s'?" msgstr "" msgid "Programming timer failed!" msgstr "" vdr-plugin-epgsearch/po/es_ES.po0000644000175000017500000012103013145412721016401 0ustar tobiastobias# VDR plugin language source file. # Copyright (C) 2007 Klaus Schmidinger # This file is distributed under the same license as the VDR package. # Users from todopvr.com: agusmir, bittor, dragondefuego, GenaroL, lopezm and nachofr # msgid "" msgstr "" "Project-Id-Version: VDR 1.5.7\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-06-15 11:15+0200\n" "PO-Revision-Date: 2007-11-18 20:09+0200\n" "Last-Translator: bittor from open7x0.org \n" "Language-Team: Spanish \n" "Language: es\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "Channel groups" msgstr "Grupos de canales" msgid "Button$Select" msgstr "Seleccionar" msgid "Channel group used by:" msgstr "Grupo de canales usado por:" msgid "Edit$Delete group?" msgstr "¿Borrar grupo?" msgid "Edit channel group" msgstr "Editar grupo de canales" msgid "Group name" msgstr "Nombre del grupo" msgid "Button$Invert selection" msgstr "Invertir selección" msgid "Button$All yes" msgstr "Todo sí" msgid "Button$All no" msgstr "Todo no" msgid "Group name is empty!" msgstr "¡Nombre del grupo vacío!" msgid "Group name already exists!" msgstr "¡Ya existe el nombre del grupo!" msgid "Direct access to epgsearch's conflict check menu" msgstr "Acceso directo al menú de conflictos EPGSearch" msgid "Timer conflicts" msgstr "Conflictos de programación" msgid "Conflict info in main menu" msgstr "Mostrar conflictos en menú principal" msgid "next" msgstr "siguiente" #, c-format msgid "timer conflict at %s! Show it?" msgstr "¿Mostrar conflicto de programación a las %s?" #, c-format msgid "%d timer conflicts! First at %s. Show them?" msgstr "¡%d conflictos de programación! El 1º a las %s. ¿Mostrarlos?" msgid "search the EPG for repeats and more" msgstr "Buscar repeticiones en la EPG" msgid "Program guide" msgstr "Guía de programación" msgid "search timer update running" msgstr "Actualizando programación por búsqueda" msgid "Direct access to epgsearch's search menu" msgstr "Acceso directo al menú de búsquedas en EPG" msgid "Search" msgstr "Búsquedas en EPG" msgid "EpgSearch-Search in main menu" msgstr "Búsquedas en EPG en menú principal" msgid "Button$Help" msgstr "Ayuda" msgid "Standard" msgstr "Estándar" msgid "Button$Commands" msgstr "Órdenes" msgid "Button$Search" msgstr "Buscar" msgid "never" msgstr "nunca" msgid "always" msgstr "siempre" msgid "smart" msgstr "inteligente" msgid "before user-def. times" msgstr "antes hora-def." msgid "after user-def. times" msgstr "después hora-def." msgid "before 'next'" msgstr "antes de 'Después'" msgid "General" msgstr "General" msgid "EPG menus" msgstr "Menús EPG" msgid "User-defined EPG times" msgstr "Horario EPG definido por el usuario" msgid "Timer programming" msgstr "Programación" msgid "Search and search timers" msgstr "Búsqueda y programaciones por búsqueda" msgid "Timer conflict checking" msgstr "Comprobando conflictos de programación" msgid "Email notification" msgstr "Notificación por correo" msgid "Hide main menu entry" msgstr "Ocultar entrada del menú principal" msgid "Help$Hides the main menu entry and may be useful if this plugin is used to replace the original 'Schedule' entry." msgstr "Oculta la entrada del menú principal y puede ser útil si este plugin sustituye a la entrada 'Guía de programación' original." msgid "Main menu entry" msgstr "Entrada en el menú principal" msgid "Help$The name of the main menu entry which defaults to 'Programm guide'." msgstr "El nombre de la entrada para el menú principal, que por defecto es 'Guía de programación'." msgid "Replace original schedule" msgstr "Sustituir guía de prog. original" msgid "Help$When VDR is patched to allow this plugin to replace the original 'Schedule' entry, you can de/activate this replacement here." msgstr "Aquí puede des/activar que éste plugin sustituya la entrada original 'Guía de programación', pero sólo funciona cuando el VDR está parcheado para permitirlo." msgid "Start menu" msgstr "Menú de inicio" msgid "Help$Choose between 'Overview - Now' and 'Schedule' as start menu when this plugin is called." msgstr "Elija entre 'Ahora' y 'Guía de programación' como menú inicial cuando se llama a este plugin." msgid "Ok key" msgstr "Botón OK" msgid "" "Help$Choose here the behaviour of key 'Ok'. You can use it to display the summary or to switch to the corresponding channel.\n" "Note: the functionality of key 'blue' (Switch/Info/Search) depends on this setting." msgstr "" "Elija el comportamiento del botón 'OK'. Puede usarse para mostrar el resumen o cambiar al canal correspondiente.\n" "Nota: la funcionalidad del botón 'azul' (Cambiar/Info/Buscar) depende de ésta configuración." msgid "Red key" msgstr "Botón rojo" msgid "" "Help$Choose which standard function ('Record' or 'Commands') you like to have on the red key.\n" "(Can be toggled with key '0')" msgstr "" "Elija la función estándar ('Grabar' u 'Órdenes') que desee tener en el botón rojo.\n" "(Puede alternarse con el botón '0')" msgid "Blue key" msgstr "Botón azul" msgid "" "Help$Choose which standard function ('Switch'/'Info' or 'Search') you like to have on the blue key.\n" "(Can be toggled with key '0')" msgstr "" "Elija la función estándar ('Cambiar'/'Info' o 'Buscar') que desee tener en el botón azul.\n" "(Puede alternarse con el botón '0')" msgid "Show progress in 'Now'" msgstr "Mostrar progreso en 'Ahora'" msgid "Help$Shows a progressbar in 'Overview - Now' that informs about the remaining time of the current event." msgstr "Muestra una barra de progreso en la pantalla 'Ahora' que informa sobre el tiempo restante de la emisión actual." msgid "Show channel numbers" msgstr "Mostrar el número de los canales" msgid "" "Help$Display channel numbers in 'Overview - Now'.\n" "\n" "(To completely define your own menu look please inspect the MANUAL)" msgstr "" "Muestra el número de los canales en la pantalla 'Ahora'.\n" "\n" "(Para definir el menú totalmente a su gusto, por favor lea el MANUAL)" msgid "Show channel separators" msgstr "Mostrar separadores de canales" msgid "Help$Display VDR channel groups as separators between your channels in 'Overview - Now'." msgstr "Muestra los grupos de canales VDR como separadores entre sus canales en la pantalla 'Ahora'." msgid "Show day separators" msgstr "Mostrar separadores de día" msgid "Help$Display a separator line at day break in 'Schedule'." msgstr "Muestra una línea de separación al cambiar de día en la 'Guía de programación'." msgid "Show radio channels" msgstr "Mostrar los canales de radio" msgid "Help$Show also radio channels." msgstr "Mostrar también los canales de radio" msgid "Limit channels from 1 to" msgstr "Limitar canales de 1 a" msgid "Help$If you have a large channel set you can speed up things when you limit the displayed channels with this setting. Use '0' to disable the limit." msgstr "Si tiene un gran número de canales, puede acelerar los menús limitando los canales mostrados con éste parámetro. Use '0' para desactivar el límite." msgid "'One press' timer creation" msgstr "Crear programación inmediata" msgid "Help$When a timer is created with 'Record' you can choose between an immediate creation of the timer or the display of the timer edit menu." msgstr "Cuando crea una programación con 'Grabar', puede elegir entre crearla inmediatamente o mostrar el menú para editarla." msgid "Show channels without EPG" msgstr "Mostrar canales sin EPG" msgid "Help$Choose 'yes' here if you want to display channels without EPG in 'Overview - Now'. 'Ok' on these entries switches the channel." msgstr "Elija 'sí' cuando desee mostrar los canales sin EPG en la pantalla 'Ahora'. Pulse 'OK' sobre estas entradas para cambiar a ese canal." msgid "Time interval for FRew/FFwd [min]" msgstr "Minutos para Rebobinar/Avanzar" msgid "" "Help$Choose here the time interval which should be used for jumping through the EPG by pressing FRew/FFwd.\n" "\n" "(If you don't have those keys, you can toggle to this functionality pressing '0' and get '<<' and '>>' on the keys green and yellow)" msgstr "" "Elija el intervalo de tiempo que se usará para saltar a través de la EPG pulsando '<<' y '>>'.\n" "\n" "(Si no tiene estos botones en su mando a distancia, puede acceder a esta funcionalidad pulsando el botón '0' y tendrá las funciones '<<' y '>>' en los botones verde y amarillo)" msgid "Toggle Green/Yellow" msgstr "Alternar Verde/Amarillo" msgid "Help$Specify if green and yellow shall also be switched when pressing '0'." msgstr "Especifique si los botones verde y amarillo también cambian al pulsar '0'." msgid "Show favorites menu" msgstr "Mostrar el menú favoritos" msgid "" "Help$A favorites menu can display a list of your favorite broadcasts. Enable this if you want an additional menu besides 'Now' and 'Next'\n" "Any search can be used as a favorite. You only have to set the option 'Use in favorites menu' when editing a search." msgstr "" "Un menú de favoritos puede mostrar una lista de sus emisiones favoritas. Actívelo si desea un menú adicional a los existentes 'Ahora' y 'Después'.\n" "Algunas búsquedas pueden ser usadas como favoritos si activa la opción 'Usar en el menú favoritos' cuando edita una búsqueda." msgid "for the next ... hours" msgstr "para las próximas ... horas" msgid "Help$This value controls the timespan used to display your favorites." msgstr "Éste valor controla el intervalo usado para mostrar sus favoritos." msgid "Use user-defined time" msgstr "Usar horario definido por usuario" msgid "Help$Besides 'Now' and 'Next' you can specify up to 4 other times in the EPG which can be used by repeatedly pressing the green key, e.g. 'prime time', 'late night',..." msgstr "Además de 'Ahora' y 'Después' puede definir hasta 4 horarios distintos en la EPG, que pueden usarse pulsando varias veces el botón verde, p.e. 'hora de mayor audiencia', 'medianoche', ..." msgid "Description" msgstr "Descripción" msgid "Help$This is the description for your user-defined time as it will appear as label on the green button." msgstr "Ésta es la descripción de su horario definido que se mostrará como etiqueta del botón verde." msgid "Time" msgstr "Horario" msgid "Help$Specify the user-defined time here in 'HH:MM'." msgstr "Especifique el horario definido en 'HH:MM'." msgid "Use VDR's timer edit menu" msgstr "Usar menú editar programación VDR" msgid "" "Help$This plugin has its own timer edit menu extending the original one with some extra functionality like\n" "- an additional directory entry\n" "- user-defined days of week for repeating timers\n" "- adding an episode name\n" "- support for EPG variables (see MANUAL)" msgstr "" "Este plugin posee un editor de programaciones que amplía el original con ciertas funcionalidades adicionales como:\n" "- una entrada adicional de directorio\n" "- definir días de la semana para repetir programaciones\n" "- añadir el nombre del episodio\n" "- soporte para variables EPG (ver el MANUAL)" msgid "Default recording dir" msgstr "Dir. de grabación por defecto" msgid "Help$When creating a timer you can specify here a default recording directory." msgstr "Cuando crea una programación, aquí puede especificar un directorio por defecto para la grabación." msgid "Add episode to manual timers" msgstr "Añadir episodio a prog. manual" msgid "" "Help$If you create a timer for a series, you can automatically add the episode name.\n" "\n" "- never: no addition\n" "- always: always add episode name if present\n" "- smart: add only if event lasts less than 80 mins." msgstr "" "Cuando crea una programación en serie, puede añadir automáticamente el nombre del episodio.\n" "\n" "- nunca: no añadir\n" "- siempre: si existe, añadir siempre el nombre del episodio\n" "- inteligente: añadir solamente si la emisión dura menos de 80 minutos." msgid "Default timer check method" msgstr "Método de comprobación por defecto" msgid "" "Help$Manual timers can be checked for EPG changes. Here you can setup the default check method for each channel. Choose between\n" "\n" "- no checking\n" "- by event ID: checks by an event ID supplied by the channel provider.\n" "- by channel and time: check by the duration match." msgstr "" "Las programaciones manuales pueden comprobar cambios en la EPG. Aquí puede establecer el método de comprobación por defecto para cada canal. Elija entre\n" "\n" "- sin comprobación.\n" "- por ID de emisión: comprueba un ID de emisión suministrado por el emisor del canal.\n" "- por canal y hora: comprueba que coincida la duración." msgid "Button$Setup" msgstr "Configuración" msgid "Use search timers" msgstr "Usar programaciones por búsqueda" msgid "Help$'Search timers' can be used to automatically create timers for events that match your search criterions." msgstr "'Programaciones por búsqueda' se usa para crear automáticamente programaciones de emisiones que coincidan con los criterios de búsqueda." msgid " Update interval [min]" msgstr " Intervalo de actualización [min]" msgid "Help$Specify here the time intervall to be used when searching for events in the background." msgstr "Especifique el intervalo de tiempo con el que se buscarán nuevas emisiones." msgid " SVDRP port" msgstr " Puerto SVDRP" msgid "Help$Programming of new timers or timer changes is done with SVDRP. The default value should be correct, so change it only if you know what you are doing." msgstr "Las nuevas programaciones o cambios de programación se realizan con SVDRP. El valor por defecto debe ser correcto, sólo modifíquelo si sabe lo que está haciendo." msgid "Help$Specify here the default priority of timers created with this plugin. This value can also be adjusted for each search itself." msgstr "Especifique la prioridad por defecto de las programaciones creadas con este plugin. Éste valor también lo puede establecer para cada búsqueda." msgid "Help$Specify here the default lifetime of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "Especifique el tiempo de duración por defecto de las programaciones/grabaciones creadas con este plugin. Éste valor también lo puede establecer para cada búsqueda." msgid "Help$Specify here the default start recording margin of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "Especifique el margen de tiempo por defecto para el inicio de las programaciones/grabaciones creadas con este plugin. Éste valor también lo puede establecer para cada búsqueda." msgid "Help$Specify here the default stop recording margin of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "Especifique el margen de tiempo por defecto para el final de las programaciones/grabaciones creadas con este plugin. Éste valor también lo puede establecer para cada búsqueda." msgid "No announcements when replaying" msgstr "Sin avisos mientras se reproduce" msgid "Help$Set this to 'yes' if you don't like to get any announcements of broadcasts if you currently replay anything." msgstr "Establecer a 'sí' cuando no desee recibir ningún aviso de emisiones durante una reproducción." msgid "Recreate timers after deletion" msgstr "Recrear programaciones tras borrar" msgid "Help$Set this to 'yes' if you want timers to be recreated with the next search timer update after deleting them." msgstr "Establecer a 'sí' cuando desee que las programaciones se creen de nuevo con la siguiente actualización de programación por búsqueda después de borrarlas." msgid "Check if EPG exists for ... [h]" msgstr "" #, fuzzy msgid "Help$Specify how many hours of future EPG there should be and get warned else after a search timer update." msgstr "Establecer a 'sí' cuando desee comprobar conflictos después de actualizar cada programación por búsqueda." #, fuzzy msgid "Warn by OSD" msgstr "Sólo avisar" #, fuzzy msgid "Help$Set this to 'yes' if you want get warnings from the EPG check via OSD." msgstr "Establecer a 'sí' cuando desee recibir una notificación por correo sobre los conflictos de programación." #, fuzzy msgid "Warn by mail" msgstr "Sólo avisar" #, fuzzy msgid "Help$Set this to 'yes' if you want get warnings from the EPG check by mail." msgstr "Establecer a 'sí' cuando su cuenta necesite autenticación para enviar correos." #, fuzzy msgid "Channel group to check" msgstr "Grupo de canales" #, fuzzy msgid "Help$Specify the channel group to check." msgstr "Especifique el nombre de la plantilla." msgid "Ignore PayTV channels" msgstr "Ignorar los canales de pago" msgid "Help$Set this to 'yes' if don't want to see events on PayTV channels when searching for repeats." msgstr "Establecer a 'sí' cuando no desee buscar en los canales de pago." msgid "Search templates" msgstr "Plantillas de búsqueda" msgid "Help$Here you can setup templates for your searches." msgstr "Aquí puede configurar las plantillas de búsqueda." msgid "Blacklists" msgstr "Listas negras" msgid "Help$Here you can setup blacklists which can be used within a search to exclude events you don't like." msgstr "Aquí puede configurar las listas negras, que pueden ser usadas para excluir emisiones no deseadas." msgid "Help$Here you can setup channel groups which can be used within a search. These are different to VDR channel groups and represent a set of arbitrary channels, e.g. 'FreeTV'." msgstr "Aquí puede configurar los grupos de canales que pueden ser usados en una búsqueda. Éstos son diferentes a los grupos de canales del VDR y representan un conjunto de canales arbitrario, p.e.: 'Cine'." msgid "Ignore below priority" msgstr "Ignorar la prioridad inferior" msgid "Help$If a timer with priority below the given value will fail it will not be classified as important. Only important conflicts will produce an OSD message about the conflict after an automatic conflict check." msgstr "Si falla una programación con una prioridad por debajo del valor dado, no será clasificada como importante. Después de una comprobación de conflictos, sólo los conflictos importantes mostrarán un mensaje OSD sobre el conflicto." msgid "Ignore conflict duration less ... min." msgstr "Ignorar conflicto inferior a ... min." msgid "Help$If a conflicts duration is less then the given number of minutes it will not be classified as important. Only important conflicts will produce an OSD message about the conflict after an automatic conflict check." msgstr "Si la duración de un conflicto es menor que el número de minutos dado, no será clasificada como importante. Sólo los conflictos importantes mostrarán un mensaje OSD sobre el conflicto después de una comprobación de conflictos automática." msgid "Only check within next ... days" msgstr "Sólo comprobar los próximos ... días" msgid "Help$This value reduces the conflict check to the given range of days. All other conflicts are classified as 'not yet important'." msgstr "Este valor reduce la comprobación de conflictos al rango de días dados. El resto de conflictos son clasificados como 'no importantes'." msgid "Check also remote conflicts" msgstr "" msgid "Help$Set this to 'yes' if the conflict check should be done for timers set on remote hosts. This needs SVDRPPeering to be set in vdr and Plugin epgsearch running on the remote host." msgstr "" msgid "--- Automatic checking ---" msgstr "--- Comprobación automática ---" msgid "After each timer programming" msgstr "Después de cada programación" msgid "Help$Set this to 'yes' if the conflict check should be performed after each manual timer programming. In the case of a conflict you get immediately a message that informs you about it. The message is only displayed if this timer is involved in any conflict." msgstr "Establecer a 'sí' cuando desee ejecutar la comprobación de conflictos después de cada programación manual. En caso de existir un conflicto se mostrará inmediatamente un mensaje que informe de ello. Éste mensaje sólo se mostrará si la programación está implicada en un conflicto." msgid "When a recording starts" msgstr "Cuando empieza una grabación" msgid "Help$Set this to 'yes' if the conflict check should be performed when a recording starts. In the case of a conflict you get immediately a message that informs you about it. The message is only displayed if the conflict is within the next 2 hours." msgstr "Establecer a 'sí' cuando desee comprobar conflictos al iniciar una grabación. En caso de existir un conflicto se mostrará inmediatamente un mensaje que informe de ello. Éste mensaje sólo se mostrará si el conflicto se produce en las próximas 2 horas." msgid "After each search timer update" msgstr "Después de actualizar programación" msgid "Help$Set this to 'yes' if the conflict check should be performed after each search timer update." msgstr "Establecer a 'sí' cuando desee comprobar conflictos después de actualizar cada programación por búsqueda." msgid "every ... minutes" msgstr "cada ... minutos" msgid "" "Help$Specify here the time intervall to be used for an automatic conflict check in the background.\n" "('0' disables an automatic check)" msgstr "" "Especifique el intervalo de tiempo a usar para la comprobación de conflictos automática en segundo plano.\n" "('0' deshabilita la comprobación automática)" msgid "if conflicts within next ... minutes" msgstr "si hay conflictos en próximos ... min." msgid "Help$If the next conflict will appear in the given number of minutes you can specify here a shorter check intervall to get more OSD notifications about it." msgstr "Si el próximo conflicto aparece en el número de minutos indicado, puede especificar un intervalo de comprobación menor para obtener más notificaciones OSD sobre él." msgid "Avoid notification when replaying" msgstr "Evitar notificación al reproducir" msgid "Help$Set this to 'yes' if the don't want to get OSD messages about conflicts if you currently replay something. Nevertheless messages will be displayed if the first upcoming conflict is within the next 2 hours." msgstr "Establecer a 'sí' cuando no desee mostrar mensajes OSD de conflictos mientras está reproduciendo algo. Sin embargo, se mostrarán mensajes si el primer conflicto se produce en las 2 horas siguientes." msgid "Search timer notification" msgstr "Notificar prog. por búsqueda" msgid "Help$Set this to 'yes' if you want to get an email notification about the search timers that where programmed automatically in the background." msgstr "Establecer a 'sí' cuando desee tener una notificación por correo de las programaciones por búsqueda que fueron creadas automáticamente." msgid "Time between mails [h]" msgstr "" msgid "" "Help$Specifiy how much time in [h] you would\n" "like to have atleast between two mails.\n" "With '0' you get a new mail after each\n" "search timer update with new results." msgstr "" msgid "Timer conflict notification" msgstr "Notificar conflicto en programación" msgid "Help$Set this to 'yes' if you want to get an email notification about the timer conflicts." msgstr "Establecer a 'sí' cuando desee recibir una notificación por correo sobre los conflictos de programación." msgid "Send to" msgstr "Enviar a" msgid "Help$Specify the email address where notifications should be sent to." msgstr "Especifique la dirección de correo donde deben enviarse las notificaciones." msgid "Mail method" msgstr "Método de correo" msgid "" "Help$Specify here the method to use when sending mails.\n" "You can choose between\n" " - 'sendmail': requires a properly configured email system\n" " - 'SendEmail.pl': simple script for mail delivery" msgstr "" "Especifique el método a usar para enviar correos.\n" "Puede elegir entre\n" " - 'sendmail': necesita un sistema de correo correctamente configurado\n" " - 'SendEmail.pl': script simple para la entrega de correo" msgid "--- Email account ---" msgstr "--- Cuenta de correo ---" msgid "Email address" msgstr "Dirección de correo" msgid "Help$Specify the email address where notifications should be sent from." msgstr "Especifique la dirección de correo desde donde se enviarán las notificaciones." msgid "SMTP server" msgstr "Servidor SMTP" msgid "Help$Specify the SMTP server that should deliver the notifications. If it's using a port different from the default(25) append the port with \":port\"." msgstr "Especifique el servidor SMTP que debe entregar las notificaciones. Si está usando un puerto distinto al normal(25) añada el puerto con \":puerto\"." msgid "Use SMTP authentication" msgstr "Usar autenticación SMTP" msgid "Help$Set this to 'yes' if your account needs authentication to send mails." msgstr "Establecer a 'sí' cuando su cuenta necesite autenticación para enviar correos." msgid "Auth user" msgstr "Usuario" msgid "Help$Specify the auth user, if this account needs authentication for SMTP." msgstr "Si esta cuenta necesita autenticación SMTP, especifique el usuario." msgid "Auth password" msgstr "Contraseña" msgid "Help$Specify the auth password, if this account needs authentication for SMTP." msgstr "Si esta cuenta necesita autenticación SMTP, especifique la contraseña." msgid "Mail account check failed!" msgstr "¡Falló la prueba de cuenta de correo!" msgid "Button$Test" msgstr "Probar" msgid "$ abcdefghijklmnopqrstuvwxyz0123456789-.,#~\\^$[]|()*+?{}/:%@&_" msgstr " aábcçdeéfghiíjklmnñoópqrstuúüvwxyz0123456789-_.,#~\\^$[]|()*+?{}/:%@&_" msgid "Start/Stop time has changed" msgstr "Ha cambiado el tiempo inicial/final" msgid "Title/episode has changed" msgstr "Ha cambiado el título/episodio" msgid "No new timers were added." msgstr "No se añadieron nuevas programaciones." msgid "No timers were modified." msgstr "No se modificaron programaciones." msgid "No timers were deleted." msgstr "No se borraron programaciones." msgid "No new events to announce." msgstr "" msgid "This version of EPGSearch does not support this service!" msgstr "¡Esta versión de EPGSearch no soporta este servicio!" msgid "EPGSearch does not exist!" msgstr "¡No existe EPGSearch!" #, c-format msgid "%d new broadcast" msgstr "%d nuevas emisiones" msgid "Button$by channel" msgstr "por canal" msgid "Button$by time" msgstr "por horario" msgid "Button$Episode" msgstr "Episodio" msgid "Button$Title" msgstr "Título" msgid "announce details" msgstr "detalles del aviso" msgid "announce again" msgstr "avisar otra vez" msgid "with next update" msgstr "con la próxima actualización" msgid "again from" msgstr "otra vez desde" msgid "Search timer" msgstr "Programación por búsqueda" msgid "Edit blacklist" msgstr "Editar la lista negra" msgid "phrase" msgstr "frase" msgid "all words" msgstr "palabra completa" msgid "at least one word" msgstr "mínimo 1 palabra" msgid "match exactly" msgstr "exacta" msgid "regular expression" msgstr "expresión regular" msgid "fuzzy" msgstr "imprecisa" msgid "user-defined" msgstr "definido por usuario" msgid "interval" msgstr "intervalo" msgid "channel group" msgstr "grupo de canales" msgid "only FTA" msgstr "sólo en abierto" msgid "Search term" msgstr "Buscar palabra" msgid "Search mode" msgstr "Modo de búsqueda" msgid "Tolerance" msgstr "Tolerancia" msgid "Match case" msgstr "Mayúscula/minúscula" msgid "Use title" msgstr "Usar título" msgid "Use subtitle" msgstr "Usar subtítulo" msgid "Use description" msgstr "Usar descripción" msgid "Use extended EPG info" msgstr "Usar info ampliada de la EPG" msgid "Ignore missing categories" msgstr "Ignorar categorías perdidas" msgid "Use channel" msgstr "Usar canal" msgid " from channel" msgstr " desde el canal" msgid " to channel" msgstr " hasta el canal" msgid "Channel group" msgstr "Grupo de canales" msgid "Use time" msgstr "Usar horario" msgid " Start after" msgstr " Comenzar después" msgid " Start before" msgstr " Comenzar antes" msgid "Use duration" msgstr "Usar duración" msgid " Min. duration" msgstr " Duración mín." msgid " Max. duration" msgstr " Duración máx." msgid "Use day of week" msgstr "Usar día de la semana" msgid "Day of week" msgstr "Día de la semana" msgid "Use global" msgstr "" msgid "Button$Templates" msgstr "Plantillas" msgid "*** Invalid Channel ***" msgstr "*** Canal no válido ***" msgid "Please check channel criteria!" msgstr "¡Compruebe requisitos del canal!" msgid "Edit$Delete blacklist?" msgstr "¿Borrar la lista negra?" msgid "Repeats" msgstr "Repeticiones" msgid "Create search" msgstr "Crear una búsqueda" msgid "Search in recordings" msgstr "Buscar en las grabaciones" msgid "Mark as 'already recorded'?" msgstr "¿Marcar como 'ya grabado'?" msgid "Add/Remove to/from switch list?" msgstr "¿Añadir/Borrar a/de la lista de cambio?" msgid "Create blacklist" msgstr "Crear lista negra" msgid "EPG Commands" msgstr "Órdenes EPG" msgid "Epgsearch: RemoteTimerModifications failed" msgstr "" msgid "Already running!" msgstr "¡Ya se está ejecutando!" msgid "Add to switch list?" msgstr "¿Añadir a la lista de cambio?" msgid "Delete from switch list?" msgstr "¿Borrar de la lista de cambio?" msgid "Button$Details" msgstr "Detalles" msgid "Button$Filter" msgstr "Filtro" msgid "Button$Show all" msgstr "Mostrar todo" msgid "conflicts" msgstr "conflictos" msgid "no conflicts!" msgstr "¡no hay conflictos!" msgid "no important conflicts!" msgstr "¡no hay conflictos importantes!" msgid "C" msgstr "C" msgid "Button$Repeats" msgstr "Repeticiones" msgid "no check" msgstr "sin comprobación" msgid "by channel and time" msgstr "por canal y hora" msgid "by event ID" msgstr "por ID de emisión" msgid "Select directory" msgstr "Seleccionar directorio" msgid "Button$Level" msgstr "Nivel" msgid "Event" msgstr "Emisión" msgid "Favorites" msgstr "Favoritos" msgid "Search results" msgstr "Resultados de la búsqueda" msgid "Timer conflict! Show?" msgstr "¿Mostrar conflicto de programación?" msgid "Directory" msgstr "Directorio" msgid "Channel" msgstr "Canal" msgid "Childlock" msgstr "Bloqueo niños" msgid "Record on" msgstr "" msgid "Timer check" msgstr "Comprobación" msgid "recording with device" msgstr "grabación con dispositivo" msgid "Button$With subtitle" msgstr "Con subtítulo" msgid "Button$Without subtitle" msgstr "Sin subtítulo" msgid "Timer has been deleted" msgstr "" msgid "Button$Extended" msgstr "Ampliado" msgid "Button$Simple" msgstr "Simple" msgid "Use blacklists" msgstr "Usar listas negras" msgid "Edit$Search text too short - use anyway?" msgstr "El texto a buscar es muy corto - ¿usar de todas formas?" #, fuzzy msgid "Button$Orphaned" msgstr "por canal" msgid "Button$by name" msgstr "por nombre" msgid "Button$by date" msgstr "por fecha" msgid "Button$Delete all" msgstr "Borrar todo" msgid "Recordings" msgstr "Grabaciones" msgid "Edit$Delete entry?" msgstr "¿Borrar entrada?" msgid "Edit$Delete all entries?" msgstr "¿Borrar todas las entradas?" msgid "Summary" msgstr "Resumen" msgid "Auxiliary info" msgstr "Más información" msgid "Button$Aux info" msgstr "Más info" msgid "Search actions" msgstr "Acciones de búsqueda" msgid "Execute search" msgstr "Realizar búsqueda" msgid "Use as search timer on/off" msgstr "Usar como prog. por búsqueda sí/no" msgid "Trigger search timer update" msgstr "Actualizar prog. por búsqueda" msgid "Show recordings done" msgstr "Mostrar grabaciones realizadas" msgid "Show timers created" msgstr "Mostrar programaciones creadas" msgid "Create a copy" msgstr "Crear una copia" msgid "Use as template" msgstr "Usar como plantilla" msgid "Show switch list" msgstr "Mostrar lista de cambio" msgid "Show blacklists" msgstr "Mostrar listas negras" msgid "Delete created timers?" msgstr "¿Borrar las programaciones creadas?" msgid "Timer conflict check" msgstr "Comprobar conflictos de programación" msgid "Disable associated timers too?" msgstr "¿Desactivar las programaciones asociadas?" msgid "Activate associated timers too?" msgstr "¿Activar las programaciones asociadas?" msgid "Search timers activated in setup." msgstr "Progs. por búsqueda activas en la configuración." msgid "Run search timer update?" msgstr "¿Actualizar programación por búsqueda?" msgid "Copy this entry?" msgstr "¿Copiar esta entrada?" msgid "Copy" msgstr "Copiar" msgid "Copy this entry to templates?" msgstr "¿Copiar esta entrada a plantillas?" msgid "Delete all timers created from this search?" msgstr "¿Borrar las programaciones creadas por esta búsqueda?" msgid "Button$Actions" msgstr "Acciones" msgid "Search entries" msgstr "Entradas de búsqueda" msgid "active" msgstr "activa" msgid "Edit$Delete search?" msgstr "¿Borrar la búsqueda?" msgid "Edit search" msgstr "Editar búsqueda" msgid "Record" msgstr "Grabar" #, fuzzy msgid "Announce by OSD" msgstr "Sólo avisar" msgid "Switch only" msgstr "Cambiar de canal" msgid "Announce and switch" msgstr "Avisar y cambiar" #, fuzzy msgid "Announce by mail" msgstr "Sólo avisar" msgid "Inactive record" msgstr "" msgid "only globals" msgstr "" msgid "Selection" msgstr "selección" msgid "all" msgstr "todo" msgid "count recordings" msgstr "incluir grabaciones" msgid "count days" msgstr "incluir días" msgid "if present" msgstr "si existe" #, fuzzy msgid "same day" msgstr "Último día" #, fuzzy msgid "same week" msgstr "Día de la semana" msgid "same month" msgstr "" msgid "Template name" msgstr "Nombre de la plantilla" msgid "Help$Specify the name of the template." msgstr "Especifique el nombre de la plantilla." msgid "Help$Specify here the term to search for." msgstr "Especifique la palabra a buscar." msgid "" "Help$The following search modes exist:\n" "\n" "- phrase: searches for sub terms\n" "- all words: all single words must appear\n" "- at least one word: at least one single word must appear\n" "- match exactly: must match exactly\n" "- regular expression: match a regular expression\n" "- fuzzy searching: searches approximately" msgstr "" "Existen los siguientes modos de búsqueda:\n" "\n" "- frase: búsquedas por subpalabras\n" "- palabra completa: deben aparecer todas las palabras\n" "- mínimo 1 palabra: debe aparecer al menos una palabra\n" "- exacta: debe coincidir exactamente\n" "- expresión regular: coincidir con una expresión regular\n" "- imprecisa: búsquedas por aproximación" msgid "Help$This sets the tolerance of fuzzy searching. The value represents the allowed errors." msgstr "Establece la tolerancia de la búsqueda imprecisa. El valor representa los errores permitidos." msgid "Help$Set this to 'Yes' if your search should match the case." msgstr "Establecer a 'Sí' cuando la búsqueda deba coincidir con el valor dado." msgid "Help$Set this to 'Yes' if you like to search in the title of an event." msgstr "Establecer a 'Sí' cuando desee buscar en el título de una emisión." msgid "Help$Set this to 'Yes' if you like to search in the episode of an event." msgstr "Establecer a 'Sí' cuando desee buscar en el episodio de una emisión." msgid "Help$Set this to 'Yes' if you like to search in the summary of an event." msgstr "Establecer a 'Sí' cuando desee buscar en el resumen de una emisión." #, fuzzy msgid "Use content descriptor" msgstr "Usar descripción" #, fuzzy msgid "Help$Set this to 'Yes' if you want to search the contents by a descriptor." msgstr "Establecer a 'Sí' cuando desee buscar en el título de una emisión." msgid "Help$The summary of an event, can contain additional information like 'Genre', 'Category', 'Year',... called 'EPG categories' within EPGSearch. External EPG providers often deliver this information. This allows refining a search and other nice things, like searching for the 'tip of the day'. To use it set this to 'Yes'." msgstr "El resumen de una emisión puede contener información adicional como 'Género', 'Categoría', 'Año', ... llamada 'categorías EPG' en el EPGSearch. A menudo los proveedores EPG externos ofrecen esta información. Esto permite refinar una búsqueda y otras funcionalidades atractivas, como buscar por el 'consejo del día'. Para usarlo, establecer a 'Sí'." msgid "Help$The file epgsearchcats.conf specifies the search mode for this entry. One can search by text or by value. You can also edit a list of predefined values in this file that can be selected here." msgstr "El archivo epgsearchcats.conf especifica el modo de búsqueda de esta entrada. Se puede buscar por texto o por valor. También puede editar una lista de valores predefinidos en este archivo que puede seleccionar aquí." msgid "Help$If a selected category is not part of the summary of an event this normally excludes this event from the search results. To avoid this, set this option to 'Yes', but please handle this with care to avoid a huge amount of results." msgstr "Si una categoría seleccionada no es parte del resumen de una emisión, normalmente ésta no incluye ese evento en los resultados de la búsqueda. Para evitarlo establezca esta opción a 'Sí', pero maneje esto con cuidado para evitar una gran cantidad de resultados." msgid "Use in favorites menu" msgstr "Usar en el menú favoritos" msgid "Result menu layout" msgstr "Presentación de resultados" msgid "Use as search timer" msgstr "Usar como prog. por búsqueda" msgid "Action" msgstr "Acción" msgid "Switch ... minutes before start" msgstr "Cambiar ... minutos antes del inicio" msgid "Unmute sound" msgstr "Sonido quitar silencio" msgid "Ask ... minutes before start" msgstr "Preguntar ... minutos antes del inicio" msgid " Series recording" msgstr " Grabación en serie" msgid "Delete recordings after ... days" msgstr "Borrar grabación a los ... días" msgid "Keep ... recordings" msgstr "Mantener ... grabaciones" msgid "Pause when ... recordings exist" msgstr "Pausar al tener ... grabaciones" msgid "Avoid repeats" msgstr "Evitar repeticiones" msgid "Allowed repeats" msgstr "Permitir repeticiones" msgid "Only repeats within ... days" msgstr "Sólo repetidos dentro de ... días" msgid "Compare title" msgstr "Comparar título" msgid "Compare subtitle" msgstr "Comparar subtítulo" msgid "Compare summary" msgstr "Comparar resumen" #, fuzzy msgid "Min. match in %" msgstr " Duración mín." #, fuzzy msgid "Compare date" msgstr "Comparar título" msgid "Compare categories" msgstr "Comparar categorías" msgid "VPS" msgstr "VPS" msgid "Auto delete" msgstr "Auto borrar" msgid "after ... recordings" msgstr "después ... grabaciones" msgid "after ... days after first rec." msgstr "después ... días de la 1ª grab." msgid "Edit user-defined days of week" msgstr "Editar días de la semana definidos por el usuario" msgid "Compare" msgstr "Comparar" msgid "Select blacklists" msgstr "Seleccionar las listas negras" msgid "Values for EPG category" msgstr "Valores para categorías EPG" msgid "Button$Apply" msgstr "Aplicar" msgid "less" msgstr "menor" msgid "less or equal" msgstr "menor o igual" msgid "greater" msgstr "mayor" msgid "greater or equal" msgstr "mayor o igual" msgid "equal" msgstr "igual" msgid "not equal" msgstr "distinto" msgid "Activation of search timer" msgstr "Activar prog. por búsqueda" msgid "First day" msgstr "Primer día" msgid "Last day" msgstr "Último día" msgid "Button$all channels" msgstr "todos los canales" msgid "Button$only FTA" msgstr "sólo en abierto" msgid "Button$Timer preview" msgstr "Previsualizar programación" msgid "Blacklist results" msgstr "Resultados de la lista negra" msgid "found recordings" msgstr "grabaciones encontradas" msgid "Error while accessing recording!" msgstr "¡Error al acceder a grabación!" msgid "Button$Default" msgstr "Por defecto" msgid "Edit$Delete template?" msgstr "¿Borrar plantilla?" msgid "Overwrite existing entries?" msgstr "¿Sobrescribir las entradas existentes?" msgid "Edit entry" msgstr "Editar entrada" msgid "Switch" msgstr "Cambiar" msgid "Announce only" msgstr "Sólo avisar" msgid "Announce ... minutes before start" msgstr "Avisar ... minutos antes del inicio" msgid "action at" msgstr "ejecutar a las" msgid "Switch list" msgstr "Lista de cambio" msgid "Edit template" msgstr "Editar plantilla" msgid "Timers" msgstr "Programaciones" msgid ">>> no info! <<<" msgstr " «sin información» " msgid "Overview" msgstr "Resumen" msgid "Button$Favorites" msgstr "Favoritos" msgid "Quick search for broadcasts" msgstr "Búsqueda rápida de emisiones" msgid "Quick search" msgstr "Búsqueda rápida" msgid "Show in main menu" msgstr "Mostrar en menú principal" #, c-format msgid "%d new broadcast(s) found! Show them?" msgstr "¡%d nuevas emisiones encontradas! ¿Mostrarlas?" msgid "Search timer update done!" msgstr "¡Programación por búsqueda actualizada!" #, c-format msgid "small EPG content on:%s" msgstr "" msgid "VDR EPG check warning" msgstr "" #, c-format msgid "Switch to (%d) '%s'?" msgstr "¿Cambiar a (%d) '%s'?" msgid "Programming timer failed!" msgstr "¡La programación ha fallado!" #~ msgid "in %02ldd" #~ msgstr "en %02ldd" #~ msgid "in %02ldh" #~ msgstr "en %02ldh" #~ msgid "in %02ldm" #~ msgstr "en %02ldm" #, fuzzy #~ msgid "Compare expression" #~ msgstr "expresión regular" vdr-plugin-epgsearch/po/hr_HR.po0000644000175000017500000005730613145412721016423 0ustar tobiastobias# VDR plugin language source file. # Copyright (C) 2007 Klaus Schmidinger # This file is distributed under the same license as the VDR package. # Drazen Dupor , 2004 # Dino Ravnic , 2004 # msgid "" msgstr "" "Project-Id-Version: VDR 1.5.7\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-06-15 11:15+0200\n" "PO-Revision-Date: 2007-08-14 20:21+0200\n" "Last-Translator: Drazen Dupor \n" "Language-Team: Croatian \n" "Language: hr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "Channel groups" msgstr "" msgid "Button$Select" msgstr "" msgid "Channel group used by:" msgstr "" msgid "Edit$Delete group?" msgstr "" msgid "Edit channel group" msgstr "" msgid "Group name" msgstr "" msgid "Button$Invert selection" msgstr "" msgid "Button$All yes" msgstr "" msgid "Button$All no" msgstr "" msgid "Group name is empty!" msgstr "" msgid "Group name already exists!" msgstr "" msgid "Direct access to epgsearch's conflict check menu" msgstr "" msgid "Timer conflicts" msgstr "" msgid "Conflict info in main menu" msgstr "" msgid "next" msgstr "" #, c-format msgid "timer conflict at %s! Show it?" msgstr "" #, c-format msgid "%d timer conflicts! First at %s. Show them?" msgstr "" msgid "search the EPG for repeats and more" msgstr "" msgid "Program guide" msgstr "" msgid "search timer update running" msgstr "" msgid "Direct access to epgsearch's search menu" msgstr "" msgid "Search" msgstr "" msgid "EpgSearch-Search in main menu" msgstr "" msgid "Button$Help" msgstr "" msgid "Standard" msgstr "" #, fuzzy msgid "Button$Commands" msgstr "Snimi" msgid "Button$Search" msgstr "" msgid "never" msgstr "" msgid "always" msgstr "" msgid "smart" msgstr "" msgid "before user-def. times" msgstr "" msgid "after user-def. times" msgstr "" msgid "before 'next'" msgstr "" msgid "General" msgstr "" msgid "EPG menus" msgstr "" msgid "User-defined EPG times" msgstr "" msgid "Timer programming" msgstr "" msgid "Search and search timers" msgstr "" msgid "Timer conflict checking" msgstr "" msgid "Email notification" msgstr "" msgid "Hide main menu entry" msgstr "" msgid "Help$Hides the main menu entry and may be useful if this plugin is used to replace the original 'Schedule' entry." msgstr "" msgid "Main menu entry" msgstr "" msgid "Help$The name of the main menu entry which defaults to 'Programm guide'." msgstr "" msgid "Replace original schedule" msgstr "" msgid "Help$When VDR is patched to allow this plugin to replace the original 'Schedule' entry, you can de/activate this replacement here." msgstr "" msgid "Start menu" msgstr "" msgid "Help$Choose between 'Overview - Now' and 'Schedule' as start menu when this plugin is called." msgstr "" msgid "Ok key" msgstr "" msgid "" "Help$Choose here the behaviour of key 'Ok'. You can use it to display the summary or to switch to the corresponding channel.\n" "Note: the functionality of key 'blue' (Switch/Info/Search) depends on this setting." msgstr "" msgid "Red key" msgstr "" msgid "" "Help$Choose which standard function ('Record' or 'Commands') you like to have on the red key.\n" "(Can be toggled with key '0')" msgstr "" msgid "Blue key" msgstr "" msgid "" "Help$Choose which standard function ('Switch'/'Info' or 'Search') you like to have on the blue key.\n" "(Can be toggled with key '0')" msgstr "" msgid "Show progress in 'Now'" msgstr "" msgid "Help$Shows a progressbar in 'Overview - Now' that informs about the remaining time of the current event." msgstr "" msgid "Show channel numbers" msgstr "" msgid "" "Help$Display channel numbers in 'Overview - Now'.\n" "\n" "(To completely define your own menu look please inspect the MANUAL)" msgstr "" msgid "Show channel separators" msgstr "" msgid "Help$Display VDR channel groups as separators between your channels in 'Overview - Now'." msgstr "" msgid "Show day separators" msgstr "" msgid "Help$Display a separator line at day break in 'Schedule'." msgstr "" msgid "Show radio channels" msgstr "" msgid "Help$Show also radio channels." msgstr "" msgid "Limit channels from 1 to" msgstr "" msgid "Help$If you have a large channel set you can speed up things when you limit the displayed channels with this setting. Use '0' to disable the limit." msgstr "" msgid "'One press' timer creation" msgstr "" msgid "Help$When a timer is created with 'Record' you can choose between an immediate creation of the timer or the display of the timer edit menu." msgstr "" msgid "Show channels without EPG" msgstr "" msgid "Help$Choose 'yes' here if you want to display channels without EPG in 'Overview - Now'. 'Ok' on these entries switches the channel." msgstr "" msgid "Time interval for FRew/FFwd [min]" msgstr "" msgid "" "Help$Choose here the time interval which should be used for jumping through the EPG by pressing FRew/FFwd.\n" "\n" "(If you don't have those keys, you can toggle to this functionality pressing '0' and get '<<' and '>>' on the keys green and yellow)" msgstr "" msgid "Toggle Green/Yellow" msgstr "" msgid "Help$Specify if green and yellow shall also be switched when pressing '0'." msgstr "" msgid "Show favorites menu" msgstr "" msgid "" "Help$A favorites menu can display a list of your favorite broadcasts. Enable this if you want an additional menu besides 'Now' and 'Next'\n" "Any search can be used as a favorite. You only have to set the option 'Use in favorites menu' when editing a search." msgstr "" msgid "for the next ... hours" msgstr "" msgid "Help$This value controls the timespan used to display your favorites." msgstr "" msgid "Use user-defined time" msgstr "" msgid "Help$Besides 'Now' and 'Next' you can specify up to 4 other times in the EPG which can be used by repeatedly pressing the green key, e.g. 'prime time', 'late night',..." msgstr "" msgid "Description" msgstr "" msgid "Help$This is the description for your user-defined time as it will appear as label on the green button." msgstr "" msgid "Time" msgstr "" msgid "Help$Specify the user-defined time here in 'HH:MM'." msgstr "" msgid "Use VDR's timer edit menu" msgstr "" msgid "" "Help$This plugin has its own timer edit menu extending the original one with some extra functionality like\n" "- an additional directory entry\n" "- user-defined days of week for repeating timers\n" "- adding an episode name\n" "- support for EPG variables (see MANUAL)" msgstr "" msgid "Default recording dir" msgstr "" msgid "Help$When creating a timer you can specify here a default recording directory." msgstr "" msgid "Add episode to manual timers" msgstr "" msgid "" "Help$If you create a timer for a series, you can automatically add the episode name.\n" "\n" "- never: no addition\n" "- always: always add episode name if present\n" "- smart: add only if event lasts less than 80 mins." msgstr "" msgid "Default timer check method" msgstr "" msgid "" "Help$Manual timers can be checked for EPG changes. Here you can setup the default check method for each channel. Choose between\n" "\n" "- no checking\n" "- by event ID: checks by an event ID supplied by the channel provider.\n" "- by channel and time: check by the duration match." msgstr "" msgid "Button$Setup" msgstr "Konfiguracija" msgid "Use search timers" msgstr "" msgid "Help$'Search timers' can be used to automatically create timers for events that match your search criterions." msgstr "" msgid " Update interval [min]" msgstr "" msgid "Help$Specify here the time intervall to be used when searching for events in the background." msgstr "" msgid " SVDRP port" msgstr "" msgid "Help$Programming of new timers or timer changes is done with SVDRP. The default value should be correct, so change it only if you know what you are doing." msgstr "" msgid "Help$Specify here the default priority of timers created with this plugin. This value can also be adjusted for each search itself." msgstr "" msgid "Help$Specify here the default lifetime of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "" msgid "Help$Specify here the default start recording margin of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "" msgid "Help$Specify here the default stop recording margin of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "" msgid "No announcements when replaying" msgstr "" msgid "Help$Set this to 'yes' if you don't like to get any announcements of broadcasts if you currently replay anything." msgstr "" msgid "Recreate timers after deletion" msgstr "" msgid "Help$Set this to 'yes' if you want timers to be recreated with the next search timer update after deleting them." msgstr "" msgid "Check if EPG exists for ... [h]" msgstr "" msgid "Help$Specify how many hours of future EPG there should be and get warned else after a search timer update." msgstr "" msgid "Warn by OSD" msgstr "" msgid "Help$Set this to 'yes' if you want get warnings from the EPG check via OSD." msgstr "" msgid "Warn by mail" msgstr "" msgid "Help$Set this to 'yes' if you want get warnings from the EPG check by mail." msgstr "" msgid "Channel group to check" msgstr "" msgid "Help$Specify the channel group to check." msgstr "" msgid "Ignore PayTV channels" msgstr "" msgid "Help$Set this to 'yes' if don't want to see events on PayTV channels when searching for repeats." msgstr "" msgid "Search templates" msgstr "" msgid "Help$Here you can setup templates for your searches." msgstr "" msgid "Blacklists" msgstr "" msgid "Help$Here you can setup blacklists which can be used within a search to exclude events you don't like." msgstr "" msgid "Help$Here you can setup channel groups which can be used within a search. These are different to VDR channel groups and represent a set of arbitrary channels, e.g. 'FreeTV'." msgstr "" msgid "Ignore below priority" msgstr "" msgid "Help$If a timer with priority below the given value will fail it will not be classified as important. Only important conflicts will produce an OSD message about the conflict after an automatic conflict check." msgstr "" msgid "Ignore conflict duration less ... min." msgstr "" msgid "Help$If a conflicts duration is less then the given number of minutes it will not be classified as important. Only important conflicts will produce an OSD message about the conflict after an automatic conflict check." msgstr "" msgid "Only check within next ... days" msgstr "" msgid "Help$This value reduces the conflict check to the given range of days. All other conflicts are classified as 'not yet important'." msgstr "" msgid "Check also remote conflicts" msgstr "" msgid "Help$Set this to 'yes' if the conflict check should be done for timers set on remote hosts. This needs SVDRPPeering to be set in vdr and Plugin epgsearch running on the remote host." msgstr "" msgid "--- Automatic checking ---" msgstr "" msgid "After each timer programming" msgstr "" msgid "Help$Set this to 'yes' if the conflict check should be performed after each manual timer programming. In the case of a conflict you get immediately a message that informs you about it. The message is only displayed if this timer is involved in any conflict." msgstr "" msgid "When a recording starts" msgstr "" msgid "Help$Set this to 'yes' if the conflict check should be performed when a recording starts. In the case of a conflict you get immediately a message that informs you about it. The message is only displayed if the conflict is within the next 2 hours." msgstr "" msgid "After each search timer update" msgstr "" msgid "Help$Set this to 'yes' if the conflict check should be performed after each search timer update." msgstr "" msgid "every ... minutes" msgstr "" msgid "" "Help$Specify here the time intervall to be used for an automatic conflict check in the background.\n" "('0' disables an automatic check)" msgstr "" msgid "if conflicts within next ... minutes" msgstr "" msgid "Help$If the next conflict will appear in the given number of minutes you can specify here a shorter check intervall to get more OSD notifications about it." msgstr "" msgid "Avoid notification when replaying" msgstr "" msgid "Help$Set this to 'yes' if the don't want to get OSD messages about conflicts if you currently replay something. Nevertheless messages will be displayed if the first upcoming conflict is within the next 2 hours." msgstr "" msgid "Search timer notification" msgstr "" msgid "Help$Set this to 'yes' if you want to get an email notification about the search timers that where programmed automatically in the background." msgstr "" msgid "Time between mails [h]" msgstr "" msgid "" "Help$Specifiy how much time in [h] you would\n" "like to have atleast between two mails.\n" "With '0' you get a new mail after each\n" "search timer update with new results." msgstr "" msgid "Timer conflict notification" msgstr "" msgid "Help$Set this to 'yes' if you want to get an email notification about the timer conflicts." msgstr "" msgid "Send to" msgstr "" msgid "Help$Specify the email address where notifications should be sent to." msgstr "" msgid "Mail method" msgstr "" msgid "" "Help$Specify here the method to use when sending mails.\n" "You can choose between\n" " - 'sendmail': requires a properly configured email system\n" " - 'SendEmail.pl': simple script for mail delivery" msgstr "" msgid "--- Email account ---" msgstr "" msgid "Email address" msgstr "" msgid "Help$Specify the email address where notifications should be sent from." msgstr "" msgid "SMTP server" msgstr "" msgid "Help$Specify the SMTP server that should deliver the notifications. If it's using a port different from the default(25) append the port with \":port\"." msgstr "" msgid "Use SMTP authentication" msgstr "" msgid "Help$Set this to 'yes' if your account needs authentication to send mails." msgstr "" msgid "Auth user" msgstr "" msgid "Help$Specify the auth user, if this account needs authentication for SMTP." msgstr "" msgid "Auth password" msgstr "" msgid "Help$Specify the auth password, if this account needs authentication for SMTP." msgstr "" msgid "Mail account check failed!" msgstr "" msgid "Button$Test" msgstr "" msgid "$ abcdefghijklmnopqrstuvwxyz0123456789-.,#~\\^$[]|()*+?{}/:%@&_" msgstr "" msgid "Start/Stop time has changed" msgstr "" msgid "Title/episode has changed" msgstr "" msgid "No new timers were added." msgstr "" msgid "No timers were modified." msgstr "" msgid "No timers were deleted." msgstr "" msgid "No new events to announce." msgstr "" msgid "This version of EPGSearch does not support this service!" msgstr "" msgid "EPGSearch does not exist!" msgstr "" #, c-format msgid "%d new broadcast" msgstr "" msgid "Button$by channel" msgstr "" msgid "Button$by time" msgstr "" msgid "Button$Episode" msgstr "" msgid "Button$Title" msgstr "" msgid "announce details" msgstr "" msgid "announce again" msgstr "" msgid "with next update" msgstr "" msgid "again from" msgstr "" msgid "Search timer" msgstr "" msgid "Edit blacklist" msgstr "" msgid "phrase" msgstr "" msgid "all words" msgstr "" msgid "at least one word" msgstr "" msgid "match exactly" msgstr "" msgid "regular expression" msgstr "" msgid "fuzzy" msgstr "" msgid "user-defined" msgstr "" msgid "interval" msgstr "" msgid "channel group" msgstr "" msgid "only FTA" msgstr "" msgid "Search term" msgstr "" msgid "Search mode" msgstr "" msgid "Tolerance" msgstr "" msgid "Match case" msgstr "" msgid "Use title" msgstr "" msgid "Use subtitle" msgstr "" msgid "Use description" msgstr "" msgid "Use extended EPG info" msgstr "" msgid "Ignore missing categories" msgstr "" msgid "Use channel" msgstr "" msgid " from channel" msgstr "" msgid " to channel" msgstr "" msgid "Channel group" msgstr "" msgid "Use time" msgstr "" msgid " Start after" msgstr "" msgid " Start before" msgstr "" msgid "Use duration" msgstr "" msgid " Min. duration" msgstr "" msgid " Max. duration" msgstr "" msgid "Use day of week" msgstr "" msgid "Day of week" msgstr "" msgid "Use global" msgstr "" msgid "Button$Templates" msgstr "" msgid "*** Invalid Channel ***" msgstr "" msgid "Please check channel criteria!" msgstr "" msgid "Edit$Delete blacklist?" msgstr "" msgid "Repeats" msgstr "" msgid "Create search" msgstr "" msgid "Search in recordings" msgstr "" msgid "Mark as 'already recorded'?" msgstr "" msgid "Add/Remove to/from switch list?" msgstr "" msgid "Create blacklist" msgstr "" msgid "EPG Commands" msgstr "" msgid "Epgsearch: RemoteTimerModifications failed" msgstr "" msgid "Already running!" msgstr "" msgid "Add to switch list?" msgstr "" msgid "Delete from switch list?" msgstr "" msgid "Button$Details" msgstr "" msgid "Button$Filter" msgstr "" msgid "Button$Show all" msgstr "" msgid "conflicts" msgstr "" msgid "no conflicts!" msgstr "" msgid "no important conflicts!" msgstr "" msgid "C" msgstr "C" msgid "Button$Repeats" msgstr "" msgid "no check" msgstr "" msgid "by channel and time" msgstr "" msgid "by event ID" msgstr "" msgid "Select directory" msgstr "" msgid "Button$Level" msgstr "" msgid "Event" msgstr "" msgid "Favorites" msgstr "" msgid "Search results" msgstr "" msgid "Timer conflict! Show?" msgstr "" msgid "Directory" msgstr "" msgid "Channel" msgstr "" msgid "Childlock" msgstr "" msgid "Record on" msgstr "" msgid "Timer check" msgstr "" msgid "recording with device" msgstr "" msgid "Button$With subtitle" msgstr "" msgid "Button$Without subtitle" msgstr "" msgid "Timer has been deleted" msgstr "" msgid "Button$Extended" msgstr "" msgid "Button$Simple" msgstr "" msgid "Use blacklists" msgstr "" msgid "Edit$Search text too short - use anyway?" msgstr "" #, fuzzy msgid "Button$Orphaned" msgstr "Snimi" msgid "Button$by name" msgstr "" msgid "Button$by date" msgstr "" msgid "Button$Delete all" msgstr "" msgid "Recordings" msgstr "" msgid "Edit$Delete entry?" msgstr "" msgid "Edit$Delete all entries?" msgstr "" msgid "Summary" msgstr "" msgid "Auxiliary info" msgstr "" msgid "Button$Aux info" msgstr "" msgid "Search actions" msgstr "" msgid "Execute search" msgstr "" msgid "Use as search timer on/off" msgstr "" msgid "Trigger search timer update" msgstr "" msgid "Show recordings done" msgstr "" msgid "Show timers created" msgstr "" msgid "Create a copy" msgstr "" msgid "Use as template" msgstr "" msgid "Show switch list" msgstr "" msgid "Show blacklists" msgstr "" msgid "Delete created timers?" msgstr "" msgid "Timer conflict check" msgstr "" msgid "Disable associated timers too?" msgstr "" msgid "Activate associated timers too?" msgstr "" msgid "Search timers activated in setup." msgstr "" msgid "Run search timer update?" msgstr "" msgid "Copy this entry?" msgstr "" msgid "Copy" msgstr "" msgid "Copy this entry to templates?" msgstr "" msgid "Delete all timers created from this search?" msgstr "" msgid "Button$Actions" msgstr "" msgid "Search entries" msgstr "" msgid "active" msgstr "" msgid "Edit$Delete search?" msgstr "" msgid "Edit search" msgstr "" msgid "Record" msgstr "Snimi" msgid "Announce by OSD" msgstr "" msgid "Switch only" msgstr "" msgid "Announce and switch" msgstr "" msgid "Announce by mail" msgstr "" msgid "Inactive record" msgstr "" msgid "only globals" msgstr "" msgid "Selection" msgstr "" msgid "all" msgstr "" msgid "count recordings" msgstr "" msgid "count days" msgstr "" msgid "if present" msgstr "" msgid "same day" msgstr "" msgid "same week" msgstr "" msgid "same month" msgstr "" msgid "Template name" msgstr "" msgid "Help$Specify the name of the template." msgstr "" msgid "Help$Specify here the term to search for." msgstr "" msgid "" "Help$The following search modes exist:\n" "\n" "- phrase: searches for sub terms\n" "- all words: all single words must appear\n" "- at least one word: at least one single word must appear\n" "- match exactly: must match exactly\n" "- regular expression: match a regular expression\n" "- fuzzy searching: searches approximately" msgstr "" msgid "Help$This sets the tolerance of fuzzy searching. The value represents the allowed errors." msgstr "" msgid "Help$Set this to 'Yes' if your search should match the case." msgstr "" msgid "Help$Set this to 'Yes' if you like to search in the title of an event." msgstr "" msgid "Help$Set this to 'Yes' if you like to search in the episode of an event." msgstr "" msgid "Help$Set this to 'Yes' if you like to search in the summary of an event." msgstr "" msgid "Use content descriptor" msgstr "" msgid "Help$Set this to 'Yes' if you want to search the contents by a descriptor." msgstr "" msgid "Help$The summary of an event, can contain additional information like 'Genre', 'Category', 'Year',... called 'EPG categories' within EPGSearch. External EPG providers often deliver this information. This allows refining a search and other nice things, like searching for the 'tip of the day'. To use it set this to 'Yes'." msgstr "" msgid "Help$The file epgsearchcats.conf specifies the search mode for this entry. One can search by text or by value. You can also edit a list of predefined values in this file that can be selected here." msgstr "" msgid "Help$If a selected category is not part of the summary of an event this normally excludes this event from the search results. To avoid this, set this option to 'Yes', but please handle this with care to avoid a huge amount of results." msgstr "" msgid "Use in favorites menu" msgstr "" msgid "Result menu layout" msgstr "" msgid "Use as search timer" msgstr "" msgid "Action" msgstr "" msgid "Switch ... minutes before start" msgstr "" msgid "Unmute sound" msgstr "" msgid "Ask ... minutes before start" msgstr "" msgid " Series recording" msgstr "" msgid "Delete recordings after ... days" msgstr "" msgid "Keep ... recordings" msgstr "" msgid "Pause when ... recordings exist" msgstr "" msgid "Avoid repeats" msgstr "" msgid "Allowed repeats" msgstr "" msgid "Only repeats within ... days" msgstr "" msgid "Compare title" msgstr "" msgid "Compare subtitle" msgstr "" msgid "Compare summary" msgstr "" msgid "Min. match in %" msgstr "" msgid "Compare date" msgstr "" msgid "Compare categories" msgstr "" msgid "VPS" msgstr "" msgid "Auto delete" msgstr "" msgid "after ... recordings" msgstr "" msgid "after ... days after first rec." msgstr "" msgid "Edit user-defined days of week" msgstr "" msgid "Compare" msgstr "" msgid "Select blacklists" msgstr "" msgid "Values for EPG category" msgstr "" msgid "Button$Apply" msgstr "" msgid "less" msgstr "" msgid "less or equal" msgstr "" msgid "greater" msgstr "" msgid "greater or equal" msgstr "" msgid "equal" msgstr "" msgid "not equal" msgstr "" msgid "Activation of search timer" msgstr "" msgid "First day" msgstr "" msgid "Last day" msgstr "" msgid "Button$all channels" msgstr "" msgid "Button$only FTA" msgstr "" msgid "Button$Timer preview" msgstr "" msgid "Blacklist results" msgstr "" msgid "found recordings" msgstr "" msgid "Error while accessing recording!" msgstr "" msgid "Button$Default" msgstr "" msgid "Edit$Delete template?" msgstr "" msgid "Overwrite existing entries?" msgstr "" msgid "Edit entry" msgstr "" msgid "Switch" msgstr "" msgid "Announce only" msgstr "" msgid "Announce ... minutes before start" msgstr "" msgid "action at" msgstr "" msgid "Switch list" msgstr "" msgid "Edit template" msgstr "" msgid "Timers" msgstr "" msgid ">>> no info! <<<" msgstr "" msgid "Overview" msgstr "" msgid "Button$Favorites" msgstr "" msgid "Quick search for broadcasts" msgstr "" msgid "Quick search" msgstr "" msgid "Show in main menu" msgstr "" #, c-format msgid "%d new broadcast(s) found! Show them?" msgstr "" msgid "Search timer update done!" msgstr "" #, c-format msgid "small EPG content on:%s" msgstr "" msgid "VDR EPG check warning" msgstr "" #, c-format msgid "Switch to (%d) '%s'?" msgstr "" msgid "Programming timer failed!" msgstr "" vdr-plugin-epgsearch/po/pl_PL.po0000644000175000017500000005717513145412721016433 0ustar tobiastobias# VDR plugin language source file. # Copyright (C) 2007 Klaus Schmidinger # This file is distributed under the same license as the VDR package. # Michael Rakowski , 2002 # msgid "" msgstr "" "Project-Id-Version: VDR 1.5.7\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-06-15 11:15+0200\n" "PO-Revision-Date: 2007-08-14 20:21+0200\n" "Last-Translator: Michael Rakowski \n" "Language-Team: Polish \n" "Language: pl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "Channel groups" msgstr "" msgid "Button$Select" msgstr "" msgid "Channel group used by:" msgstr "" msgid "Edit$Delete group?" msgstr "" msgid "Edit channel group" msgstr "" msgid "Group name" msgstr "" msgid "Button$Invert selection" msgstr "" msgid "Button$All yes" msgstr "" msgid "Button$All no" msgstr "" msgid "Group name is empty!" msgstr "" msgid "Group name already exists!" msgstr "" msgid "Direct access to epgsearch's conflict check menu" msgstr "" msgid "Timer conflicts" msgstr "" msgid "Conflict info in main menu" msgstr "" msgid "next" msgstr "" #, c-format msgid "timer conflict at %s! Show it?" msgstr "" #, c-format msgid "%d timer conflicts! First at %s. Show them?" msgstr "" msgid "search the EPG for repeats and more" msgstr "" msgid "Program guide" msgstr "" #, fuzzy msgid "search timer update running" msgstr "/oui" msgid "Direct access to epgsearch's search menu" msgstr "" msgid "Search" msgstr "" msgid "EpgSearch-Search in main menu" msgstr "" msgid "Button$Help" msgstr "" msgid "Standard" msgstr "" msgid "Button$Commands" msgstr "" msgid "Button$Search" msgstr "" msgid "never" msgstr "" msgid "always" msgstr "" msgid "smart" msgstr "" msgid "before user-def. times" msgstr "" msgid "after user-def. times" msgstr "" msgid "before 'next'" msgstr "" msgid "General" msgstr "" msgid "EPG menus" msgstr "" msgid "User-defined EPG times" msgstr "" msgid "Timer programming" msgstr "" msgid "Search and search timers" msgstr "" msgid "Timer conflict checking" msgstr "" msgid "Email notification" msgstr "" msgid "Hide main menu entry" msgstr "" msgid "Help$Hides the main menu entry and may be useful if this plugin is used to replace the original 'Schedule' entry." msgstr "" msgid "Main menu entry" msgstr "" msgid "Help$The name of the main menu entry which defaults to 'Programm guide'." msgstr "" msgid "Replace original schedule" msgstr "" msgid "Help$When VDR is patched to allow this plugin to replace the original 'Schedule' entry, you can de/activate this replacement here." msgstr "" msgid "Start menu" msgstr "" msgid "Help$Choose between 'Overview - Now' and 'Schedule' as start menu when this plugin is called." msgstr "" msgid "Ok key" msgstr "" msgid "" "Help$Choose here the behaviour of key 'Ok'. You can use it to display the summary or to switch to the corresponding channel.\n" "Note: the functionality of key 'blue' (Switch/Info/Search) depends on this setting." msgstr "" msgid "Red key" msgstr "" msgid "" "Help$Choose which standard function ('Record' or 'Commands') you like to have on the red key.\n" "(Can be toggled with key '0')" msgstr "" msgid "Blue key" msgstr "" msgid "" "Help$Choose which standard function ('Switch'/'Info' or 'Search') you like to have on the blue key.\n" "(Can be toggled with key '0')" msgstr "" msgid "Show progress in 'Now'" msgstr "" msgid "Help$Shows a progressbar in 'Overview - Now' that informs about the remaining time of the current event." msgstr "" msgid "Show channel numbers" msgstr "" msgid "" "Help$Display channel numbers in 'Overview - Now'.\n" "\n" "(To completely define your own menu look please inspect the MANUAL)" msgstr "" msgid "Show channel separators" msgstr "" msgid "Help$Display VDR channel groups as separators between your channels in 'Overview - Now'." msgstr "" msgid "Show day separators" msgstr "" msgid "Help$Display a separator line at day break in 'Schedule'." msgstr "" msgid "Show radio channels" msgstr "" msgid "Help$Show also radio channels." msgstr "" msgid "Limit channels from 1 to" msgstr "" msgid "Help$If you have a large channel set you can speed up things when you limit the displayed channels with this setting. Use '0' to disable the limit." msgstr "" msgid "'One press' timer creation" msgstr "" msgid "Help$When a timer is created with 'Record' you can choose between an immediate creation of the timer or the display of the timer edit menu." msgstr "" msgid "Show channels without EPG" msgstr "" msgid "Help$Choose 'yes' here if you want to display channels without EPG in 'Overview - Now'. 'Ok' on these entries switches the channel." msgstr "" msgid "Time interval for FRew/FFwd [min]" msgstr "" msgid "" "Help$Choose here the time interval which should be used for jumping through the EPG by pressing FRew/FFwd.\n" "\n" "(If you don't have those keys, you can toggle to this functionality pressing '0' and get '<<' and '>>' on the keys green and yellow)" msgstr "" msgid "Toggle Green/Yellow" msgstr "" msgid "Help$Specify if green and yellow shall also be switched when pressing '0'." msgstr "" msgid "Show favorites menu" msgstr "" msgid "" "Help$A favorites menu can display a list of your favorite broadcasts. Enable this if you want an additional menu besides 'Now' and 'Next'\n" "Any search can be used as a favorite. You only have to set the option 'Use in favorites menu' when editing a search." msgstr "" msgid "for the next ... hours" msgstr "" msgid "Help$This value controls the timespan used to display your favorites." msgstr "" msgid "Use user-defined time" msgstr "" msgid "Help$Besides 'Now' and 'Next' you can specify up to 4 other times in the EPG which can be used by repeatedly pressing the green key, e.g. 'prime time', 'late night',..." msgstr "" msgid "Description" msgstr "" msgid "Help$This is the description for your user-defined time as it will appear as label on the green button." msgstr "" msgid "Time" msgstr "" msgid "Help$Specify the user-defined time here in 'HH:MM'." msgstr "" msgid "Use VDR's timer edit menu" msgstr "" msgid "" "Help$This plugin has its own timer edit menu extending the original one with some extra functionality like\n" "- an additional directory entry\n" "- user-defined days of week for repeating timers\n" "- adding an episode name\n" "- support for EPG variables (see MANUAL)" msgstr "" msgid "Default recording dir" msgstr "" msgid "Help$When creating a timer you can specify here a default recording directory." msgstr "" msgid "Add episode to manual timers" msgstr "" msgid "" "Help$If you create a timer for a series, you can automatically add the episode name.\n" "\n" "- never: no addition\n" "- always: always add episode name if present\n" "- smart: add only if event lasts less than 80 mins." msgstr "" msgid "Default timer check method" msgstr "" msgid "" "Help$Manual timers can be checked for EPG changes. Here you can setup the default check method for each channel. Choose between\n" "\n" "- no checking\n" "- by event ID: checks by an event ID supplied by the channel provider.\n" "- by channel and time: check by the duration match." msgstr "" msgid "Button$Setup" msgstr "Nastawy" msgid "Use search timers" msgstr "" msgid "Help$'Search timers' can be used to automatically create timers for events that match your search criterions." msgstr "" msgid " Update interval [min]" msgstr "" msgid "Help$Specify here the time intervall to be used when searching for events in the background." msgstr "" msgid " SVDRP port" msgstr "" msgid "Help$Programming of new timers or timer changes is done with SVDRP. The default value should be correct, so change it only if you know what you are doing." msgstr "" msgid "Help$Specify here the default priority of timers created with this plugin. This value can also be adjusted for each search itself." msgstr "" msgid "Help$Specify here the default lifetime of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "" msgid "Help$Specify here the default start recording margin of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "" msgid "Help$Specify here the default stop recording margin of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "" msgid "No announcements when replaying" msgstr "" msgid "Help$Set this to 'yes' if you don't like to get any announcements of broadcasts if you currently replay anything." msgstr "" msgid "Recreate timers after deletion" msgstr "" msgid "Help$Set this to 'yes' if you want timers to be recreated with the next search timer update after deleting them." msgstr "" msgid "Check if EPG exists for ... [h]" msgstr "" msgid "Help$Specify how many hours of future EPG there should be and get warned else after a search timer update." msgstr "" msgid "Warn by OSD" msgstr "" msgid "Help$Set this to 'yes' if you want get warnings from the EPG check via OSD." msgstr "" msgid "Warn by mail" msgstr "" msgid "Help$Set this to 'yes' if you want get warnings from the EPG check by mail." msgstr "" msgid "Channel group to check" msgstr "" msgid "Help$Specify the channel group to check." msgstr "" msgid "Ignore PayTV channels" msgstr "" msgid "Help$Set this to 'yes' if don't want to see events on PayTV channels when searching for repeats." msgstr "" msgid "Search templates" msgstr "" msgid "Help$Here you can setup templates for your searches." msgstr "" msgid "Blacklists" msgstr "" msgid "Help$Here you can setup blacklists which can be used within a search to exclude events you don't like." msgstr "" msgid "Help$Here you can setup channel groups which can be used within a search. These are different to VDR channel groups and represent a set of arbitrary channels, e.g. 'FreeTV'." msgstr "" msgid "Ignore below priority" msgstr "" msgid "Help$If a timer with priority below the given value will fail it will not be classified as important. Only important conflicts will produce an OSD message about the conflict after an automatic conflict check." msgstr "" msgid "Ignore conflict duration less ... min." msgstr "" msgid "Help$If a conflicts duration is less then the given number of minutes it will not be classified as important. Only important conflicts will produce an OSD message about the conflict after an automatic conflict check." msgstr "" msgid "Only check within next ... days" msgstr "" msgid "Help$This value reduces the conflict check to the given range of days. All other conflicts are classified as 'not yet important'." msgstr "" msgid "Check also remote conflicts" msgstr "" msgid "Help$Set this to 'yes' if the conflict check should be done for timers set on remote hosts. This needs SVDRPPeering to be set in vdr and Plugin epgsearch running on the remote host." msgstr "" msgid "--- Automatic checking ---" msgstr "" msgid "After each timer programming" msgstr "" msgid "Help$Set this to 'yes' if the conflict check should be performed after each manual timer programming. In the case of a conflict you get immediately a message that informs you about it. The message is only displayed if this timer is involved in any conflict." msgstr "" msgid "When a recording starts" msgstr "" msgid "Help$Set this to 'yes' if the conflict check should be performed when a recording starts. In the case of a conflict you get immediately a message that informs you about it. The message is only displayed if the conflict is within the next 2 hours." msgstr "" msgid "After each search timer update" msgstr "" msgid "Help$Set this to 'yes' if the conflict check should be performed after each search timer update." msgstr "" msgid "every ... minutes" msgstr "" msgid "" "Help$Specify here the time intervall to be used for an automatic conflict check in the background.\n" "('0' disables an automatic check)" msgstr "" msgid "if conflicts within next ... minutes" msgstr "" msgid "Help$If the next conflict will appear in the given number of minutes you can specify here a shorter check intervall to get more OSD notifications about it." msgstr "" msgid "Avoid notification when replaying" msgstr "" msgid "Help$Set this to 'yes' if the don't want to get OSD messages about conflicts if you currently replay something. Nevertheless messages will be displayed if the first upcoming conflict is within the next 2 hours." msgstr "" msgid "Search timer notification" msgstr "/oui" msgid "Help$Set this to 'yes' if you want to get an email notification about the search timers that where programmed automatically in the background." msgstr "" msgid "Time between mails [h]" msgstr "" msgid "" "Help$Specifiy how much time in [h] you would\n" "like to have atleast between two mails.\n" "With '0' you get a new mail after each\n" "search timer update with new results." msgstr "" msgid "Timer conflict notification" msgstr "" msgid "Help$Set this to 'yes' if you want to get an email notification about the timer conflicts." msgstr "" msgid "Send to" msgstr "" msgid "Help$Specify the email address where notifications should be sent to." msgstr "" msgid "Mail method" msgstr "" msgid "" "Help$Specify here the method to use when sending mails.\n" "You can choose between\n" " - 'sendmail': requires a properly configured email system\n" " - 'SendEmail.pl': simple script for mail delivery" msgstr "" msgid "--- Email account ---" msgstr "" msgid "Email address" msgstr "" msgid "Help$Specify the email address where notifications should be sent from." msgstr "" msgid "SMTP server" msgstr "" msgid "Help$Specify the SMTP server that should deliver the notifications. If it's using a port different from the default(25) append the port with \":port\"." msgstr "" msgid "Use SMTP authentication" msgstr "" msgid "Help$Set this to 'yes' if your account needs authentication to send mails." msgstr "" msgid "Auth user" msgstr "" msgid "Help$Specify the auth user, if this account needs authentication for SMTP." msgstr "" msgid "Auth password" msgstr "" msgid "Help$Specify the auth password, if this account needs authentication for SMTP." msgstr "" msgid "Mail account check failed!" msgstr "" msgid "Button$Test" msgstr "" msgid "$ abcdefghijklmnopqrstuvwxyz0123456789-.,#~\\^$[]|()*+?{}/:%@&_" msgstr "" msgid "Start/Stop time has changed" msgstr "" msgid "Title/episode has changed" msgstr "" msgid "No new timers were added." msgstr "" msgid "No timers were modified." msgstr "" msgid "No timers were deleted." msgstr "" msgid "No new events to announce." msgstr "" msgid "This version of EPGSearch does not support this service!" msgstr "" msgid "EPGSearch does not exist!" msgstr "" #, c-format msgid "%d new broadcast" msgstr "" msgid "Button$by channel" msgstr "" msgid "Button$by time" msgstr "" msgid "Button$Episode" msgstr "" msgid "Button$Title" msgstr "" msgid "announce details" msgstr "" msgid "announce again" msgstr "" msgid "with next update" msgstr "" msgid "again from" msgstr "" msgid "Search timer" msgstr "" msgid "Edit blacklist" msgstr "" msgid "phrase" msgstr "" msgid "all words" msgstr "" msgid "at least one word" msgstr "" msgid "match exactly" msgstr "" msgid "regular expression" msgstr "" msgid "fuzzy" msgstr "" msgid "user-defined" msgstr "" msgid "interval" msgstr "" msgid "channel group" msgstr "" msgid "only FTA" msgstr "" msgid "Search term" msgstr "" msgid "Search mode" msgstr "" msgid "Tolerance" msgstr "" msgid "Match case" msgstr "" msgid "Use title" msgstr "" msgid "Use subtitle" msgstr "" msgid "Use description" msgstr "" msgid "Use extended EPG info" msgstr "" msgid "Ignore missing categories" msgstr "" msgid "Use channel" msgstr "" msgid " from channel" msgstr "" msgid " to channel" msgstr "" msgid "Channel group" msgstr "" msgid "Use time" msgstr "" msgid " Start after" msgstr "" msgid " Start before" msgstr "" msgid "Use duration" msgstr "" msgid " Min. duration" msgstr "" msgid " Max. duration" msgstr "" msgid "Use day of week" msgstr "" msgid "Day of week" msgstr "" msgid "Use global" msgstr "" msgid "Button$Templates" msgstr "" msgid "*** Invalid Channel ***" msgstr "" msgid "Please check channel criteria!" msgstr "" msgid "Edit$Delete blacklist?" msgstr "" msgid "Repeats" msgstr "" msgid "Create search" msgstr "" msgid "Search in recordings" msgstr "" msgid "Mark as 'already recorded'?" msgstr "" msgid "Add/Remove to/from switch list?" msgstr "" msgid "Create blacklist" msgstr "" msgid "EPG Commands" msgstr "" msgid "Epgsearch: RemoteTimerModifications failed" msgstr "" msgid "Already running!" msgstr "" msgid "Add to switch list?" msgstr "" msgid "Delete from switch list?" msgstr "" msgid "Button$Details" msgstr "" msgid "Button$Filter" msgstr "" msgid "Button$Show all" msgstr "" msgid "conflicts" msgstr "" msgid "no conflicts!" msgstr "" msgid "no important conflicts!" msgstr "" msgid "C" msgstr "C" msgid "Button$Repeats" msgstr "" msgid "no check" msgstr "" msgid "by channel and time" msgstr "" msgid "by event ID" msgstr "" msgid "Select directory" msgstr "" msgid "Button$Level" msgstr "" msgid "Event" msgstr "" msgid "Favorites" msgstr "" msgid "Search results" msgstr "" msgid "Timer conflict! Show?" msgstr "" msgid "Directory" msgstr "" msgid "Channel" msgstr "" msgid "Childlock" msgstr "" msgid "Record on" msgstr "" msgid "Timer check" msgstr "" msgid "recording with device" msgstr "" msgid "Button$With subtitle" msgstr "" msgid "Button$Without subtitle" msgstr "" msgid "Timer has been deleted" msgstr "" msgid "Button$Extended" msgstr "" msgid "Button$Simple" msgstr "" msgid "Use blacklists" msgstr "" msgid "Edit$Search text too short - use anyway?" msgstr "" msgid "Button$Orphaned" msgstr "" msgid "Button$by name" msgstr "" msgid "Button$by date" msgstr "" msgid "Button$Delete all" msgstr "" msgid "Recordings" msgstr "" msgid "Edit$Delete entry?" msgstr "" msgid "Edit$Delete all entries?" msgstr "" msgid "Summary" msgstr "" msgid "Auxiliary info" msgstr "" msgid "Button$Aux info" msgstr "" msgid "Search actions" msgstr "" msgid "Execute search" msgstr "" msgid "Use as search timer on/off" msgstr "" msgid "Trigger search timer update" msgstr "" msgid "Show recordings done" msgstr "" msgid "Show timers created" msgstr "" msgid "Create a copy" msgstr "" msgid "Use as template" msgstr "" msgid "Show switch list" msgstr "" msgid "Show blacklists" msgstr "" msgid "Delete created timers?" msgstr "" msgid "Timer conflict check" msgstr "" msgid "Disable associated timers too?" msgstr "" msgid "Activate associated timers too?" msgstr "" msgid "Search timers activated in setup." msgstr "" msgid "Run search timer update?" msgstr "" msgid "Copy this entry?" msgstr "" msgid "Copy" msgstr "" msgid "Copy this entry to templates?" msgstr "" msgid "Delete all timers created from this search?" msgstr "" msgid "Button$Actions" msgstr "" msgid "Search entries" msgstr "" msgid "active" msgstr "" msgid "Edit$Delete search?" msgstr "" msgid "Edit search" msgstr "" msgid "Record" msgstr "Nagraj" msgid "Announce by OSD" msgstr "" msgid "Switch only" msgstr "" msgid "Announce and switch" msgstr "" msgid "Announce by mail" msgstr "" msgid "Inactive record" msgstr "" msgid "only globals" msgstr "" msgid "Selection" msgstr "" msgid "all" msgstr "" msgid "count recordings" msgstr "" msgid "count days" msgstr "" msgid "if present" msgstr "" msgid "same day" msgstr "" msgid "same week" msgstr "" msgid "same month" msgstr "" msgid "Template name" msgstr "" msgid "Help$Specify the name of the template." msgstr "" msgid "Help$Specify here the term to search for." msgstr "" msgid "" "Help$The following search modes exist:\n" "\n" "- phrase: searches for sub terms\n" "- all words: all single words must appear\n" "- at least one word: at least one single word must appear\n" "- match exactly: must match exactly\n" "- regular expression: match a regular expression\n" "- fuzzy searching: searches approximately" msgstr "" msgid "Help$This sets the tolerance of fuzzy searching. The value represents the allowed errors." msgstr "" msgid "Help$Set this to 'Yes' if your search should match the case." msgstr "" msgid "Help$Set this to 'Yes' if you like to search in the title of an event." msgstr "" msgid "Help$Set this to 'Yes' if you like to search in the episode of an event." msgstr "" msgid "Help$Set this to 'Yes' if you like to search in the summary of an event." msgstr "" msgid "Use content descriptor" msgstr "" msgid "Help$Set this to 'Yes' if you want to search the contents by a descriptor." msgstr "" msgid "Help$The summary of an event, can contain additional information like 'Genre', 'Category', 'Year',... called 'EPG categories' within EPGSearch. External EPG providers often deliver this information. This allows refining a search and other nice things, like searching for the 'tip of the day'. To use it set this to 'Yes'." msgstr "" msgid "Help$The file epgsearchcats.conf specifies the search mode for this entry. One can search by text or by value. You can also edit a list of predefined values in this file that can be selected here." msgstr "" msgid "Help$If a selected category is not part of the summary of an event this normally excludes this event from the search results. To avoid this, set this option to 'Yes', but please handle this with care to avoid a huge amount of results." msgstr "" msgid "Use in favorites menu" msgstr "" msgid "Result menu layout" msgstr "" msgid "Use as search timer" msgstr "" msgid "Action" msgstr "" msgid "Switch ... minutes before start" msgstr "" msgid "Unmute sound" msgstr "" msgid "Ask ... minutes before start" msgstr "" msgid " Series recording" msgstr "" msgid "Delete recordings after ... days" msgstr "" msgid "Keep ... recordings" msgstr "" msgid "Pause when ... recordings exist" msgstr "" msgid "Avoid repeats" msgstr "" msgid "Allowed repeats" msgstr "" msgid "Only repeats within ... days" msgstr "" msgid "Compare title" msgstr "" msgid "Compare subtitle" msgstr "" msgid "Compare summary" msgstr "" msgid "Min. match in %" msgstr "" msgid "Compare date" msgstr "" msgid "Compare categories" msgstr "" msgid "VPS" msgstr "" msgid "Auto delete" msgstr "" msgid "after ... recordings" msgstr "" msgid "after ... days after first rec." msgstr "" msgid "Edit user-defined days of week" msgstr "" msgid "Compare" msgstr "" msgid "Select blacklists" msgstr "" msgid "Values for EPG category" msgstr "" msgid "Button$Apply" msgstr "" msgid "less" msgstr "" msgid "less or equal" msgstr "" msgid "greater" msgstr "" msgid "greater or equal" msgstr "" msgid "equal" msgstr "" msgid "not equal" msgstr "" msgid "Activation of search timer" msgstr "" msgid "First day" msgstr "" msgid "Last day" msgstr "" msgid "Button$all channels" msgstr "" msgid "Button$only FTA" msgstr "" msgid "Button$Timer preview" msgstr "" msgid "Blacklist results" msgstr "" msgid "found recordings" msgstr "" msgid "Error while accessing recording!" msgstr "" msgid "Button$Default" msgstr "" msgid "Edit$Delete template?" msgstr "" msgid "Overwrite existing entries?" msgstr "" msgid "Edit entry" msgstr "" msgid "Switch" msgstr "" msgid "Announce only" msgstr "" msgid "Announce ... minutes before start" msgstr "" msgid "action at" msgstr "" msgid "Switch list" msgstr "" msgid "Edit template" msgstr "" msgid "Timers" msgstr "" msgid ">>> no info! <<<" msgstr "" msgid "Overview" msgstr "" msgid "Button$Favorites" msgstr "" msgid "Quick search for broadcasts" msgstr "" msgid "Quick search" msgstr "" msgid "Show in main menu" msgstr "" #, c-format msgid "%d new broadcast(s) found! Show them?" msgstr "" msgid "Search timer update done!" msgstr "" #, c-format msgid "small EPG content on:%s" msgstr "" msgid "VDR EPG check warning" msgstr "" #, c-format msgid "Switch to (%d) '%s'?" msgstr "" msgid "Programming timer failed!" msgstr "" vdr-plugin-epgsearch/po/el_GR.po0000644000175000017500000005730013145412721016403 0ustar tobiastobias# VDR plugin language source file. # Copyright (C) 2007 Klaus Schmidinger # This file is distributed under the same license as the VDR package. # Dimitrios Dimitrakos , 2002 # msgid "" msgstr "" "Project-Id-Version: VDR 1.5.7\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-06-15 11:15+0200\n" "PO-Revision-Date: 2007-08-14 20:21+0200\n" "Last-Translator: Dimitrios Dimitrakos \n" "Language-Team: Greek \n" "Language: el\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "Channel groups" msgstr "" msgid "Button$Select" msgstr "" msgid "Channel group used by:" msgstr "" msgid "Edit$Delete group?" msgstr "" msgid "Edit channel group" msgstr "" msgid "Group name" msgstr "" msgid "Button$Invert selection" msgstr "" msgid "Button$All yes" msgstr "" msgid "Button$All no" msgstr "" msgid "Group name is empty!" msgstr "" msgid "Group name already exists!" msgstr "" msgid "Direct access to epgsearch's conflict check menu" msgstr "" msgid "Timer conflicts" msgstr "" msgid "Conflict info in main menu" msgstr "" msgid "next" msgstr "" #, c-format msgid "timer conflict at %s! Show it?" msgstr "" #, c-format msgid "%d timer conflicts! First at %s. Show them?" msgstr "" msgid "search the EPG for repeats and more" msgstr "" msgid "Program guide" msgstr "" msgid "search timer update running" msgstr "" msgid "Direct access to epgsearch's search menu" msgstr "" msgid "Search" msgstr "" msgid "EpgSearch-Search in main menu" msgstr "" msgid "Button$Help" msgstr "" msgid "Standard" msgstr "" #, fuzzy msgid "Button$Commands" msgstr "Εγγραφή" msgid "Button$Search" msgstr "" msgid "never" msgstr "" msgid "always" msgstr "" msgid "smart" msgstr "" msgid "before user-def. times" msgstr "" msgid "after user-def. times" msgstr "" msgid "before 'next'" msgstr "" msgid "General" msgstr "" msgid "EPG menus" msgstr "" msgid "User-defined EPG times" msgstr "" msgid "Timer programming" msgstr "" msgid "Search and search timers" msgstr "" msgid "Timer conflict checking" msgstr "" msgid "Email notification" msgstr "" msgid "Hide main menu entry" msgstr "" msgid "Help$Hides the main menu entry and may be useful if this plugin is used to replace the original 'Schedule' entry." msgstr "" msgid "Main menu entry" msgstr "" msgid "Help$The name of the main menu entry which defaults to 'Programm guide'." msgstr "" msgid "Replace original schedule" msgstr "" msgid "Help$When VDR is patched to allow this plugin to replace the original 'Schedule' entry, you can de/activate this replacement here." msgstr "" msgid "Start menu" msgstr "" msgid "Help$Choose between 'Overview - Now' and 'Schedule' as start menu when this plugin is called." msgstr "" msgid "Ok key" msgstr "" msgid "" "Help$Choose here the behaviour of key 'Ok'. You can use it to display the summary or to switch to the corresponding channel.\n" "Note: the functionality of key 'blue' (Switch/Info/Search) depends on this setting." msgstr "" msgid "Red key" msgstr "" msgid "" "Help$Choose which standard function ('Record' or 'Commands') you like to have on the red key.\n" "(Can be toggled with key '0')" msgstr "" msgid "Blue key" msgstr "" msgid "" "Help$Choose which standard function ('Switch'/'Info' or 'Search') you like to have on the blue key.\n" "(Can be toggled with key '0')" msgstr "" msgid "Show progress in 'Now'" msgstr "" msgid "Help$Shows a progressbar in 'Overview - Now' that informs about the remaining time of the current event." msgstr "" msgid "Show channel numbers" msgstr "" msgid "" "Help$Display channel numbers in 'Overview - Now'.\n" "\n" "(To completely define your own menu look please inspect the MANUAL)" msgstr "" msgid "Show channel separators" msgstr "" msgid "Help$Display VDR channel groups as separators between your channels in 'Overview - Now'." msgstr "" msgid "Show day separators" msgstr "" msgid "Help$Display a separator line at day break in 'Schedule'." msgstr "" msgid "Show radio channels" msgstr "" msgid "Help$Show also radio channels." msgstr "" msgid "Limit channels from 1 to" msgstr "" msgid "Help$If you have a large channel set you can speed up things when you limit the displayed channels with this setting. Use '0' to disable the limit." msgstr "" msgid "'One press' timer creation" msgstr "" msgid "Help$When a timer is created with 'Record' you can choose between an immediate creation of the timer or the display of the timer edit menu." msgstr "" msgid "Show channels without EPG" msgstr "" msgid "Help$Choose 'yes' here if you want to display channels without EPG in 'Overview - Now'. 'Ok' on these entries switches the channel." msgstr "" msgid "Time interval for FRew/FFwd [min]" msgstr "" msgid "" "Help$Choose here the time interval which should be used for jumping through the EPG by pressing FRew/FFwd.\n" "\n" "(If you don't have those keys, you can toggle to this functionality pressing '0' and get '<<' and '>>' on the keys green and yellow)" msgstr "" msgid "Toggle Green/Yellow" msgstr "" msgid "Help$Specify if green and yellow shall also be switched when pressing '0'." msgstr "" msgid "Show favorites menu" msgstr "" msgid "" "Help$A favorites menu can display a list of your favorite broadcasts. Enable this if you want an additional menu besides 'Now' and 'Next'\n" "Any search can be used as a favorite. You only have to set the option 'Use in favorites menu' when editing a search." msgstr "" msgid "for the next ... hours" msgstr "" msgid "Help$This value controls the timespan used to display your favorites." msgstr "" msgid "Use user-defined time" msgstr "" msgid "Help$Besides 'Now' and 'Next' you can specify up to 4 other times in the EPG which can be used by repeatedly pressing the green key, e.g. 'prime time', 'late night',..." msgstr "" msgid "Description" msgstr "" msgid "Help$This is the description for your user-defined time as it will appear as label on the green button." msgstr "" msgid "Time" msgstr "" msgid "Help$Specify the user-defined time here in 'HH:MM'." msgstr "" msgid "Use VDR's timer edit menu" msgstr "" msgid "" "Help$This plugin has its own timer edit menu extending the original one with some extra functionality like\n" "- an additional directory entry\n" "- user-defined days of week for repeating timers\n" "- adding an episode name\n" "- support for EPG variables (see MANUAL)" msgstr "" msgid "Default recording dir" msgstr "" msgid "Help$When creating a timer you can specify here a default recording directory." msgstr "" msgid "Add episode to manual timers" msgstr "" msgid "" "Help$If you create a timer for a series, you can automatically add the episode name.\n" "\n" "- never: no addition\n" "- always: always add episode name if present\n" "- smart: add only if event lasts less than 80 mins." msgstr "" msgid "Default timer check method" msgstr "" msgid "" "Help$Manual timers can be checked for EPG changes. Here you can setup the default check method for each channel. Choose between\n" "\n" "- no checking\n" "- by event ID: checks by an event ID supplied by the channel provider.\n" "- by channel and time: check by the duration match." msgstr "" msgid "Button$Setup" msgstr "Ρυθμισεις" msgid "Use search timers" msgstr "" msgid "Help$'Search timers' can be used to automatically create timers for events that match your search criterions." msgstr "" msgid " Update interval [min]" msgstr "" msgid "Help$Specify here the time intervall to be used when searching for events in the background." msgstr "" msgid " SVDRP port" msgstr "" msgid "Help$Programming of new timers or timer changes is done with SVDRP. The default value should be correct, so change it only if you know what you are doing." msgstr "" msgid "Help$Specify here the default priority of timers created with this plugin. This value can also be adjusted for each search itself." msgstr "" msgid "Help$Specify here the default lifetime of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "" msgid "Help$Specify here the default start recording margin of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "" msgid "Help$Specify here the default stop recording margin of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "" msgid "No announcements when replaying" msgstr "" msgid "Help$Set this to 'yes' if you don't like to get any announcements of broadcasts if you currently replay anything." msgstr "" msgid "Recreate timers after deletion" msgstr "" msgid "Help$Set this to 'yes' if you want timers to be recreated with the next search timer update after deleting them." msgstr "" msgid "Check if EPG exists for ... [h]" msgstr "" msgid "Help$Specify how many hours of future EPG there should be and get warned else after a search timer update." msgstr "" msgid "Warn by OSD" msgstr "" msgid "Help$Set this to 'yes' if you want get warnings from the EPG check via OSD." msgstr "" msgid "Warn by mail" msgstr "" msgid "Help$Set this to 'yes' if you want get warnings from the EPG check by mail." msgstr "" msgid "Channel group to check" msgstr "" msgid "Help$Specify the channel group to check." msgstr "" msgid "Ignore PayTV channels" msgstr "" msgid "Help$Set this to 'yes' if don't want to see events on PayTV channels when searching for repeats." msgstr "" msgid "Search templates" msgstr "" msgid "Help$Here you can setup templates for your searches." msgstr "" msgid "Blacklists" msgstr "" msgid "Help$Here you can setup blacklists which can be used within a search to exclude events you don't like." msgstr "" msgid "Help$Here you can setup channel groups which can be used within a search. These are different to VDR channel groups and represent a set of arbitrary channels, e.g. 'FreeTV'." msgstr "" msgid "Ignore below priority" msgstr "" msgid "Help$If a timer with priority below the given value will fail it will not be classified as important. Only important conflicts will produce an OSD message about the conflict after an automatic conflict check." msgstr "" msgid "Ignore conflict duration less ... min." msgstr "" msgid "Help$If a conflicts duration is less then the given number of minutes it will not be classified as important. Only important conflicts will produce an OSD message about the conflict after an automatic conflict check." msgstr "" msgid "Only check within next ... days" msgstr "" msgid "Help$This value reduces the conflict check to the given range of days. All other conflicts are classified as 'not yet important'." msgstr "" msgid "Check also remote conflicts" msgstr "" msgid "Help$Set this to 'yes' if the conflict check should be done for timers set on remote hosts. This needs SVDRPPeering to be set in vdr and Plugin epgsearch running on the remote host." msgstr "" msgid "--- Automatic checking ---" msgstr "" msgid "After each timer programming" msgstr "" msgid "Help$Set this to 'yes' if the conflict check should be performed after each manual timer programming. In the case of a conflict you get immediately a message that informs you about it. The message is only displayed if this timer is involved in any conflict." msgstr "" msgid "When a recording starts" msgstr "" msgid "Help$Set this to 'yes' if the conflict check should be performed when a recording starts. In the case of a conflict you get immediately a message that informs you about it. The message is only displayed if the conflict is within the next 2 hours." msgstr "" msgid "After each search timer update" msgstr "" msgid "Help$Set this to 'yes' if the conflict check should be performed after each search timer update." msgstr "" msgid "every ... minutes" msgstr "" msgid "" "Help$Specify here the time intervall to be used for an automatic conflict check in the background.\n" "('0' disables an automatic check)" msgstr "" msgid "if conflicts within next ... minutes" msgstr "" msgid "Help$If the next conflict will appear in the given number of minutes you can specify here a shorter check intervall to get more OSD notifications about it." msgstr "" msgid "Avoid notification when replaying" msgstr "" msgid "Help$Set this to 'yes' if the don't want to get OSD messages about conflicts if you currently replay something. Nevertheless messages will be displayed if the first upcoming conflict is within the next 2 hours." msgstr "" msgid "Search timer notification" msgstr "" msgid "Help$Set this to 'yes' if you want to get an email notification about the search timers that where programmed automatically in the background." msgstr "" msgid "Time between mails [h]" msgstr "" msgid "" "Help$Specifiy how much time in [h] you would\n" "like to have atleast between two mails.\n" "With '0' you get a new mail after each\n" "search timer update with new results." msgstr "" msgid "Timer conflict notification" msgstr "" msgid "Help$Set this to 'yes' if you want to get an email notification about the timer conflicts." msgstr "" msgid "Send to" msgstr "" msgid "Help$Specify the email address where notifications should be sent to." msgstr "" msgid "Mail method" msgstr "" msgid "" "Help$Specify here the method to use when sending mails.\n" "You can choose between\n" " - 'sendmail': requires a properly configured email system\n" " - 'SendEmail.pl': simple script for mail delivery" msgstr "" msgid "--- Email account ---" msgstr "" msgid "Email address" msgstr "" msgid "Help$Specify the email address where notifications should be sent from." msgstr "" msgid "SMTP server" msgstr "" msgid "Help$Specify the SMTP server that should deliver the notifications. If it's using a port different from the default(25) append the port with \":port\"." msgstr "" msgid "Use SMTP authentication" msgstr "" msgid "Help$Set this to 'yes' if your account needs authentication to send mails." msgstr "" msgid "Auth user" msgstr "" msgid "Help$Specify the auth user, if this account needs authentication for SMTP." msgstr "" msgid "Auth password" msgstr "" msgid "Help$Specify the auth password, if this account needs authentication for SMTP." msgstr "" msgid "Mail account check failed!" msgstr "" msgid "Button$Test" msgstr "" msgid "$ abcdefghijklmnopqrstuvwxyz0123456789-.,#~\\^$[]|()*+?{}/:%@&_" msgstr "" msgid "Start/Stop time has changed" msgstr "" msgid "Title/episode has changed" msgstr "" msgid "No new timers were added." msgstr "" msgid "No timers were modified." msgstr "" msgid "No timers were deleted." msgstr "" msgid "No new events to announce." msgstr "" msgid "This version of EPGSearch does not support this service!" msgstr "" msgid "EPGSearch does not exist!" msgstr "" #, c-format msgid "%d new broadcast" msgstr "" msgid "Button$by channel" msgstr "" msgid "Button$by time" msgstr "" msgid "Button$Episode" msgstr "" msgid "Button$Title" msgstr "" msgid "announce details" msgstr "" msgid "announce again" msgstr "" msgid "with next update" msgstr "" msgid "again from" msgstr "" msgid "Search timer" msgstr "" msgid "Edit blacklist" msgstr "" msgid "phrase" msgstr "" msgid "all words" msgstr "" msgid "at least one word" msgstr "" msgid "match exactly" msgstr "" msgid "regular expression" msgstr "" msgid "fuzzy" msgstr "" msgid "user-defined" msgstr "" msgid "interval" msgstr "" msgid "channel group" msgstr "" msgid "only FTA" msgstr "" msgid "Search term" msgstr "" msgid "Search mode" msgstr "" msgid "Tolerance" msgstr "" msgid "Match case" msgstr "" msgid "Use title" msgstr "" msgid "Use subtitle" msgstr "" msgid "Use description" msgstr "" msgid "Use extended EPG info" msgstr "" msgid "Ignore missing categories" msgstr "" msgid "Use channel" msgstr "" msgid " from channel" msgstr "" msgid " to channel" msgstr "" msgid "Channel group" msgstr "" msgid "Use time" msgstr "" msgid " Start after" msgstr "" msgid " Start before" msgstr "" msgid "Use duration" msgstr "" msgid " Min. duration" msgstr "" msgid " Max. duration" msgstr "" msgid "Use day of week" msgstr "" msgid "Day of week" msgstr "" msgid "Use global" msgstr "" msgid "Button$Templates" msgstr "" msgid "*** Invalid Channel ***" msgstr "" msgid "Please check channel criteria!" msgstr "" msgid "Edit$Delete blacklist?" msgstr "" msgid "Repeats" msgstr "" msgid "Create search" msgstr "" msgid "Search in recordings" msgstr "" msgid "Mark as 'already recorded'?" msgstr "" msgid "Add/Remove to/from switch list?" msgstr "" msgid "Create blacklist" msgstr "" msgid "EPG Commands" msgstr "" msgid "Epgsearch: RemoteTimerModifications failed" msgstr "" msgid "Already running!" msgstr "" msgid "Add to switch list?" msgstr "" msgid "Delete from switch list?" msgstr "" msgid "Button$Details" msgstr "" msgid "Button$Filter" msgstr "" msgid "Button$Show all" msgstr "" msgid "conflicts" msgstr "" msgid "no conflicts!" msgstr "" msgid "no important conflicts!" msgstr "" msgid "C" msgstr "C" msgid "Button$Repeats" msgstr "" msgid "no check" msgstr "" msgid "by channel and time" msgstr "" msgid "by event ID" msgstr "" msgid "Select directory" msgstr "" msgid "Button$Level" msgstr "" msgid "Event" msgstr "" msgid "Favorites" msgstr "" msgid "Search results" msgstr "" msgid "Timer conflict! Show?" msgstr "" msgid "Directory" msgstr "" msgid "Channel" msgstr "" msgid "Childlock" msgstr "" msgid "Record on" msgstr "" msgid "Timer check" msgstr "" msgid "recording with device" msgstr "" msgid "Button$With subtitle" msgstr "" msgid "Button$Without subtitle" msgstr "" msgid "Timer has been deleted" msgstr "" msgid "Button$Extended" msgstr "" msgid "Button$Simple" msgstr "" msgid "Use blacklists" msgstr "" msgid "Edit$Search text too short - use anyway?" msgstr "" #, fuzzy msgid "Button$Orphaned" msgstr "Εγγραφή" msgid "Button$by name" msgstr "" msgid "Button$by date" msgstr "" msgid "Button$Delete all" msgstr "" msgid "Recordings" msgstr "" msgid "Edit$Delete entry?" msgstr "" msgid "Edit$Delete all entries?" msgstr "" msgid "Summary" msgstr "" msgid "Auxiliary info" msgstr "" msgid "Button$Aux info" msgstr "" msgid "Search actions" msgstr "" msgid "Execute search" msgstr "" msgid "Use as search timer on/off" msgstr "" msgid "Trigger search timer update" msgstr "" msgid "Show recordings done" msgstr "" msgid "Show timers created" msgstr "" msgid "Create a copy" msgstr "" msgid "Use as template" msgstr "" msgid "Show switch list" msgstr "" msgid "Show blacklists" msgstr "" msgid "Delete created timers?" msgstr "" msgid "Timer conflict check" msgstr "" msgid "Disable associated timers too?" msgstr "" msgid "Activate associated timers too?" msgstr "" msgid "Search timers activated in setup." msgstr "" msgid "Run search timer update?" msgstr "" msgid "Copy this entry?" msgstr "" msgid "Copy" msgstr "" msgid "Copy this entry to templates?" msgstr "" msgid "Delete all timers created from this search?" msgstr "" msgid "Button$Actions" msgstr "" msgid "Search entries" msgstr "" msgid "active" msgstr "" msgid "Edit$Delete search?" msgstr "" msgid "Edit search" msgstr "" msgid "Record" msgstr "Εγγραφή" msgid "Announce by OSD" msgstr "" msgid "Switch only" msgstr "" msgid "Announce and switch" msgstr "" msgid "Announce by mail" msgstr "" msgid "Inactive record" msgstr "" msgid "only globals" msgstr "" msgid "Selection" msgstr "" msgid "all" msgstr "" msgid "count recordings" msgstr "" msgid "count days" msgstr "" msgid "if present" msgstr "" msgid "same day" msgstr "" msgid "same week" msgstr "" msgid "same month" msgstr "" msgid "Template name" msgstr "" msgid "Help$Specify the name of the template." msgstr "" msgid "Help$Specify here the term to search for." msgstr "" msgid "" "Help$The following search modes exist:\n" "\n" "- phrase: searches for sub terms\n" "- all words: all single words must appear\n" "- at least one word: at least one single word must appear\n" "- match exactly: must match exactly\n" "- regular expression: match a regular expression\n" "- fuzzy searching: searches approximately" msgstr "" msgid "Help$This sets the tolerance of fuzzy searching. The value represents the allowed errors." msgstr "" msgid "Help$Set this to 'Yes' if your search should match the case." msgstr "" msgid "Help$Set this to 'Yes' if you like to search in the title of an event." msgstr "" msgid "Help$Set this to 'Yes' if you like to search in the episode of an event." msgstr "" msgid "Help$Set this to 'Yes' if you like to search in the summary of an event." msgstr "" msgid "Use content descriptor" msgstr "" msgid "Help$Set this to 'Yes' if you want to search the contents by a descriptor." msgstr "" msgid "Help$The summary of an event, can contain additional information like 'Genre', 'Category', 'Year',... called 'EPG categories' within EPGSearch. External EPG providers often deliver this information. This allows refining a search and other nice things, like searching for the 'tip of the day'. To use it set this to 'Yes'." msgstr "" msgid "Help$The file epgsearchcats.conf specifies the search mode for this entry. One can search by text or by value. You can also edit a list of predefined values in this file that can be selected here." msgstr "" msgid "Help$If a selected category is not part of the summary of an event this normally excludes this event from the search results. To avoid this, set this option to 'Yes', but please handle this with care to avoid a huge amount of results." msgstr "" msgid "Use in favorites menu" msgstr "" msgid "Result menu layout" msgstr "" msgid "Use as search timer" msgstr "" msgid "Action" msgstr "" msgid "Switch ... minutes before start" msgstr "" msgid "Unmute sound" msgstr "" msgid "Ask ... minutes before start" msgstr "" msgid " Series recording" msgstr "" msgid "Delete recordings after ... days" msgstr "" msgid "Keep ... recordings" msgstr "" msgid "Pause when ... recordings exist" msgstr "" msgid "Avoid repeats" msgstr "" msgid "Allowed repeats" msgstr "" msgid "Only repeats within ... days" msgstr "" msgid "Compare title" msgstr "" msgid "Compare subtitle" msgstr "" msgid "Compare summary" msgstr "" msgid "Min. match in %" msgstr "" msgid "Compare date" msgstr "" msgid "Compare categories" msgstr "" msgid "VPS" msgstr "" msgid "Auto delete" msgstr "" msgid "after ... recordings" msgstr "" msgid "after ... days after first rec." msgstr "" msgid "Edit user-defined days of week" msgstr "" msgid "Compare" msgstr "" msgid "Select blacklists" msgstr "" msgid "Values for EPG category" msgstr "" msgid "Button$Apply" msgstr "" msgid "less" msgstr "" msgid "less or equal" msgstr "" msgid "greater" msgstr "" msgid "greater or equal" msgstr "" msgid "equal" msgstr "" msgid "not equal" msgstr "" msgid "Activation of search timer" msgstr "" msgid "First day" msgstr "" msgid "Last day" msgstr "" msgid "Button$all channels" msgstr "" msgid "Button$only FTA" msgstr "" msgid "Button$Timer preview" msgstr "" msgid "Blacklist results" msgstr "" msgid "found recordings" msgstr "" msgid "Error while accessing recording!" msgstr "" msgid "Button$Default" msgstr "" msgid "Edit$Delete template?" msgstr "" msgid "Overwrite existing entries?" msgstr "" msgid "Edit entry" msgstr "" msgid "Switch" msgstr "" msgid "Announce only" msgstr "" msgid "Announce ... minutes before start" msgstr "" msgid "action at" msgstr "" msgid "Switch list" msgstr "" msgid "Edit template" msgstr "" msgid "Timers" msgstr "" msgid ">>> no info! <<<" msgstr "" msgid "Overview" msgstr "" msgid "Button$Favorites" msgstr "" msgid "Quick search for broadcasts" msgstr "" msgid "Quick search" msgstr "" msgid "Show in main menu" msgstr "" #, c-format msgid "%d new broadcast(s) found! Show them?" msgstr "" msgid "Search timer update done!" msgstr "" #, c-format msgid "small EPG content on:%s" msgstr "" msgid "VDR EPG check warning" msgstr "" #, c-format msgid "Switch to (%d) '%s'?" msgstr "" msgid "Programming timer failed!" msgstr "" vdr-plugin-epgsearch/po/sk_SK.po0000644000175000017500000011736313145412721016433 0ustar tobiastobias# VDR plugin language source file. # Copyright (C) 2007 Klaus Schmidinger # This file is distributed under the same license as the VDR package. # Vladimír Bárta , 2006 # msgid "" msgstr "" "Project-Id-Version: epgsearch\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-06-15 11:15+0200\n" "PO-Revision-Date: 2009-11-02 09:40+0100\n" "Last-Translator: Milan Hrala \n" "Language-Team: Slovak \n" "Language: sk\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "Channel groups" msgstr "Skupiny kanálov" msgid "Button$Select" msgstr "Vybrať" msgid "Channel group used by:" msgstr "Použitá skupina kanálov:" msgid "Edit$Delete group?" msgstr "Vymazať skupinu" msgid "Edit channel group" msgstr "Upraviť skupinu kanálu" msgid "Group name" msgstr "Názov skupiny" msgid "Button$Invert selection" msgstr "Prevrátiť výber" msgid "Button$All yes" msgstr "Áno všetko" msgid "Button$All no" msgstr "Všetko nie" msgid "Group name is empty!" msgstr "Meno skupiny je prázdne!" msgid "Group name already exists!" msgstr "Meno skupiny existuje!" msgid "Direct access to epgsearch's conflict check menu" msgstr "Priamy prístup EPGsearch k menu konfliktov" msgid "Timer conflicts" msgstr "Konflikty plánovača" msgid "Conflict info in main menu" msgstr "Informácie o konfliktoch v hlav menu" msgid "next" msgstr "ďalší" #, c-format msgid "timer conflict at %s! Show it?" msgstr "Konflikt plánu o %s! Zobraziť?" #, c-format msgid "%d timer conflicts! First at %s. Show them?" msgstr "%d konflikty plánovania! Prvý o %s. Ukázať" msgid "search the EPG for repeats and more" msgstr "Prehľadať televízny program, či nebude repríza" msgid "Program guide" msgstr "Programový sprievodca" #, fuzzy msgid "search timer update running" msgstr "Aktualizácia vyhľadávania plánov skončená!" msgid "Direct access to epgsearch's search menu" msgstr "Priamy prístup k epgsearch cez vyhľadávacie menu" msgid "Search" msgstr "Hĺadať" msgid "EpgSearch-Search in main menu" msgstr "EpgSearch-Vyhľadávanie v hlavnom menu" msgid "Button$Help" msgstr "Pomoc" msgid "Standard" msgstr "bežne" msgid "Button$Commands" msgstr "Príkazy" msgid "Button$Search" msgstr "Hľadať" msgid "never" msgstr "nikdy" msgid "always" msgstr "vždy" msgid "smart" msgstr "chytrý" msgid "before user-def. times" msgstr "pred užívateľ-def. plánu" msgid "after user-def. times" msgstr "po užívateľ-def. plánu" msgid "before 'next'" msgstr "pred 'ďalším'" msgid "General" msgstr "Hlavné" msgid "EPG menus" msgstr "EPG menu" msgid "User-defined EPG times" msgstr "Užívateľom-určený EPG plán" msgid "Timer programming" msgstr "Plán programovania" msgid "Search and search timers" msgstr "Hľadať a prehľadať plány" msgid "Timer conflict checking" msgstr "Kontrola konfliktov plánu" msgid "Email notification" msgstr "Oznámenie na Email" msgid "Hide main menu entry" msgstr "Skryť v hlavnom menu" msgid "Help$Hides the main menu entry and may be useful if this plugin is used to replace the original 'Schedule' entry." msgstr "Skryje v hlavnom menu položku. Môže to byť užitočné, ak tento modul má nahradiť pôvodný 'Program' ." msgid "Main menu entry" msgstr "Hlavné menu" msgid "Help$The name of the main menu entry which defaults to 'Programm guide'." msgstr "meno položky v hlavnom menu , ktorá je nastavená na 'Programový sprievodca'." msgid "Replace original schedule" msgstr "Nahradiť pôvodný harmonogram" msgid "Help$When VDR is patched to allow this plugin to replace the original 'Schedule' entry, you can de/activate this replacement here." msgstr "Keď je VDR opravený, môžete aktivovať výmenu televízneho programu tu, aby tento modul nahradil pôvodný televízny program." msgid "Start menu" msgstr "Štart menu" msgid "Help$Choose between 'Overview - Now' and 'Schedule' as start menu when this plugin is called." msgstr "Keď sa spustí tento modul, tak si vyberte medzi 'Prehľad - teraz' a 'Televíznym programom' v Štart menu." msgid "Ok key" msgstr "Ok klávesa" msgid "" "Help$Choose here the behaviour of key 'Ok'. You can use it to display the summary or to switch to the corresponding channel.\n" "Note: the functionality of key 'blue' (Switch/Info/Search) depends on this setting." msgstr "" "Tu si vyberte správanie klávesy 'Ok'. Môžete ju použiť na zobrazenie súhrnu alebo prepnúť na zodpovedajúci kanál.\n" "Poznámka: funkcia 'modrej' klávesy (Prepnúť / Informácie / Hľadať) závisí na nastavení." msgid "Red key" msgstr "Červená klávesa" msgid "" "Help$Choose which standard function ('Record' or 'Commands') you like to have on the red key.\n" "(Can be toggled with key '0')" msgstr "" "Vyberte si, ktoré štandardné funkcie ( 'Nahrávky' alebo 'príkazy'), chcete mať pod červeným tlačítkom.\n" "(Možno zapínať s klávesou '0')" msgid "Blue key" msgstr "Modrá klávesa" msgid "" "Help$Choose which standard function ('Switch'/'Info' or 'Search') you like to have on the blue key.\n" "(Can be toggled with key '0')" msgstr "" "Vyberte si, ktoré štandardné funkcie ( 'Nahrávky' alebo 'príkazy'), chcete mať pod modrým tlačítkom.\n" "(Možno zapínať s klávesou '0')" msgid "Show progress in 'Now'" msgstr "Zobraziť proces v 'Now'" msgid "Help$Shows a progressbar in 'Overview - Now' that informs about the remaining time of the current event." msgstr "Ukazuje priebeh v 'Prehľad - teraz', ktorý informuje o zostávajúcom čase aktuálnej udalosti." msgid "Show channel numbers" msgstr "Zobraziť číslo kanálu" msgid "" "Help$Display channel numbers in 'Overview - Now'.\n" "\n" "(To completely define your own menu look please inspect the MANUAL)" msgstr "" "Zobrazenie čísla kanálov v 'Prehľad - Teraz'. \n" "\n" "(Ak chcete kompletne definovať vlastné menu ,prosím skontrolujte MANUÁL)" msgid "Show channel separators" msgstr "Oddeliť zobrazené kanály" msgid "Help$Display VDR channel groups as separators between your channels in 'Overview - Now'." msgstr "Zobraziť skupiny VDR kanálov s oddeľovačmi v 'Prehľad - Teraz'." msgid "Show day separators" msgstr "Zobraziť oddeľovače dní" msgid "Help$Display a separator line at day break in 'Schedule'." msgstr "Zobraziť deliace čiary cez dennú prestávku v 'Plánovači." msgid "Show radio channels" msgstr "Zobraziť rádio kanály" msgid "Help$Show also radio channels." msgstr "Zobraziť tiež rozhlasové kanály" msgid "Limit channels from 1 to" msgstr "Limit kanálov od 1 do" msgid "Help$If you have a large channel set you can speed up things when you limit the displayed channels with this setting. Use '0' to disable the limit." msgstr "Ak máte veľa nastavených kanálov, môžete urýchliť vec tak, že obmedzíte zobrazené kanály s týmto nastavením. Použite '0 'pre vypnutie limitu." msgid "'One press' timer creation" msgstr "Raz stlačiť vytvorenie plánu" msgid "Help$When a timer is created with 'Record' you can choose between an immediate creation of the timer or the display of the timer edit menu." msgstr "Keď je časovač vytvorený s 'Nahrať', tak si môžete vybrať medzi okamžitým vytvorením časovača alebo zobrazenie menu s úpravami časovača." msgid "Show channels without EPG" msgstr "Zobraziť kanály bez EPG" msgid "Help$Choose 'yes' here if you want to display channels without EPG in 'Overview - Now'. 'Ok' on these entries switches the channel." msgstr "Vyberte 'áno', ak chcete zobraziť kanály bez EPG v 'Prehľad - Teraz'. 'Ok' na tejto položieke prepína kanál." msgid "Time interval for FRew/FFwd [min]" msgstr "Časový úsek pre FRew/FFwd [min]" msgid "" "Help$Choose here the time interval which should be used for jumping through the EPG by pressing FRew/FFwd.\n" "\n" "(If you don't have those keys, you can toggle to this functionality pressing '0' and get '<<' and '>>' on the keys green and yellow)" msgstr "" "Tu si vyberte časový interval, ktorý by mal byť použitý pre skákanie cez EPG stlačením FRew / FFwd.\n" "\n" "(Ak nemáte tie klávesy, môžete prepínať na túto funkciu stlačením '0' a '<<' alebo '>>' ' klávesy zelenej a žltej)search" msgid "Toggle Green/Yellow" msgstr "Prepínač zelenej/žltej" msgid "Help$Specify if green and yellow shall also be switched when pressing '0'." msgstr "Uveďte, či zelenou a žltou, sa má tiež prepínať pri stlačení '0 '." msgid "Show favorites menu" msgstr "Zobraziť obľúbené menu" msgid "" "Help$A favorites menu can display a list of your favorite broadcasts. Enable this if you want an additional menu besides 'Now' and 'Next'\n" "Any search can be used as a favorite. You only have to set the option 'Use in favorites menu' when editing a search." msgstr "" "Obľúbené položky menu je možné zobraziť zoznam obľúbených staníc. Povoliť, ak chcete ďalšie ponuky vedľa 'teraz' a 'Nasleduje' \n" "Akékoľvek vyhľadávania možno použiť ako obľúbené. Musíte len nastaviť voľbu 'Použiť do obľúbených položiek menu' pri úpravách vyhľadávania." msgid "for the next ... hours" msgstr "Za ďalšie ... hodiny" msgid "Help$This value controls the timespan used to display your favorites." msgstr "Táto hodnota určuje časové rozpätie pre zobrazenie obľúbených." msgid "Use user-defined time" msgstr "Použiť užívateľom definované plánovanie" msgid "Help$Besides 'Now' and 'Next' you can specify up to 4 other times in the EPG which can be used by repeatedly pressing the green key, e.g. 'prime time', 'late night',..." msgstr "Okrem 'teraz' a 'Nasleduje' môžete zadať až 4 iné časy v EPG, ktoré môžu byť použité po opakovanom stlačení zeleného tlačitka, napr 'hlavnom vysielacom čase', 'neskoro v noci',..." msgid "Description" msgstr "Popis" msgid "Help$This is the description for your user-defined time as it will appear as label on the green button." msgstr "To to je znázornené pre užívateľom-stanovenej lehote(času), ako bude vyzerať označenie na zelenom tlačítku." msgid "Time" msgstr "Čas" msgid "Help$Specify the user-defined time here in 'HH:MM'." msgstr "Presne napíšte čas vo formáte 'HH:MM'." msgid "Use VDR's timer edit menu" msgstr "Použiť menu úpravy VDR časovača" msgid "" "Help$This plugin has its own timer edit menu extending the original one with some extra functionality like\n" "- an additional directory entry\n" "- user-defined days of week for repeating timers\n" "- adding an episode name\n" "- support for EPG variables (see MANUAL)" msgstr "" "Tento modul je rozšírením pôvodného menu s úpravami vysielacieho času a pridáva niektoré nové funkcie, ako je \n" "- Pridávanie položkou v adresári \n" "- Určenie dňa v týždni, ak sa opakujú vysielacie časy \n" "- Pridanie mena epizódy \n" "- Podporu pre menlivé EPG (pozri manuál)" msgid "Default recording dir" msgstr "Predvolený adresár záznamov" msgid "Help$When creating a timer you can specify here a default recording directory." msgstr "Tu môžete zadať predvolený adresár záznamov ,ktorý sa použije ak vytvárate nový plán nahrávania," msgid "Add episode to manual timers" msgstr "Pridať epizódy do ručného časovača" msgid "" "Help$If you create a timer for a series, you can automatically add the episode name.\n" "\n" "- never: no addition\n" "- always: always add episode name if present\n" "- smart: add only if event lasts less than 80 mins." msgstr "" "Ak vytvoríte plán nahrávania pre sériu, môžete automaticky pridať názov epizódy. \n" "\n" "- Nikdy: nie okrem \n" "- Vždy: vždy pridať meno epizódy ak je prítomné \n" "- Inteligentne :pridať iba ak udalosť trvá menej ako 80 minút." msgid "Default timer check method" msgstr "Predvolený postup kontroly plánov" msgid "" "Help$Manual timers can be checked for EPG changes. Here you can setup the default check method for each channel. Choose between\n" "\n" "- no checking\n" "- by event ID: checks by an event ID supplied by the channel provider.\n" "- by channel and time: check by the duration match." msgstr "" "Manuálne plány môžu byť kontrolované na zmeny EPG. Tu si môžete nastaviť predvolený spôsob kontroly pre každý kanál. Vyberte si medzi \n" "\n" "- nekontrolovať \n" " - Podľa ID udalosti: kontroly ID udalosti poskytované poskytovateľom kanála. \n" "- Podľa kanálu a času: kontrola dĺžky vysielaného programu." msgid "Button$Setup" msgstr "Nastavenie" msgid "Use search timers" msgstr "Použiť vyhľadávanie časovačov" msgid "Help$'Search timers' can be used to automatically create timers for events that match your search criterions." msgstr "Vyhľadávanie vysielacieho času 'možno použiť na automatické vytváranie plánov nahrávania, ktoré zodpovedajú vášmu hľadanému kritériu." msgid " Update interval [min]" msgstr " obnovovací interval [min]" msgid "Help$Specify here the time intervall to be used when searching for events in the background." msgstr "Zvolte ako často sa majú na pozadí hľadať udalosti." msgid " SVDRP port" msgstr " SVDRP port" msgid "Help$Programming of new timers or timer changes is done with SVDRP. The default value should be correct, so change it only if you know what you are doing." msgstr "Programovanie nových plánov alebo úpravy plánov sa vykonávajú so SVDRP. Predvolená hodnota by mala byť v poriadku, takže ho zmente len vtedy, ak viete, čo robíte." msgid "Help$Specify here the default priority of timers created with this plugin. This value can also be adjusted for each search itself." msgstr "Uveďte predvolenú prioritu plánov nahrávania vytvorených s týmto modulom. Túto hodnotu možno upraviť aj pre každé samostatné hľadanie." msgid "Help$Specify here the default lifetime of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "Uveďte predvolenú životnosť plánov / nahrávky vytvorených s týmto modulom. Túto hodnotu možno upraviť aj pre každé samostatné hľadanie." msgid "Help$Specify here the default start recording margin of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "Uveďte predvolený nadbytok úvodného záznamu plánu / nahrávky vytvoreným s týmto modulom. Túto hodnotu možno upraviť aj pre každé samostatné hľadanie." msgid "Help$Specify here the default stop recording margin of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "Uveďte predvolený nadbytok pri ukončení nahrávania plánu / nahrávky vytvoreným s týmto modulom. Túto hodnotu možno upraviť aj pre každé samostatné hľadanie." msgid "No announcements when replaying" msgstr "Neoznamovať pri prehrávaní" msgid "Help$Set this to 'yes' if you don't like to get any announcements of broadcasts if you currently replay anything." msgstr "Ak niečo prehrávate a nepáči sa vám oznamovanie o vysielaní, tak nastavte 'áno'" msgid "Recreate timers after deletion" msgstr "Znova vytvoriť plán po vymazaní" msgid "Help$Set this to 'yes' if you want timers to be recreated with the next search timer update after deleting them." msgstr "Ak zmažete plán nahrávania a nechcete aby bol znova vytvorený po automatickom obnovení vyhľadávača plánov, tak nastavte 'áno'" msgid "Check if EPG exists for ... [h]" msgstr "" #, fuzzy msgid "Help$Specify how many hours of future EPG there should be and get warned else after a search timer update." msgstr "Ak kontrola konfliktov by mala byť vykonávaná pri každom obnovení vyhľadávača plánov, tak nastavte 'áno'" #, fuzzy msgid "Warn by OSD" msgstr "Iba oznámiť" #, fuzzy msgid "Help$Set this to 'yes' if you want get warnings from the EPG check via OSD." msgstr "Nastavte áno ak potrebujete oznamovať konflikty plánu na mail" #, fuzzy msgid "Warn by mail" msgstr "Iba oznámiť" #, fuzzy msgid "Help$Set this to 'yes' if you want get warnings from the EPG check by mail." msgstr "Nastavte Áno, ak váš účet potrebuje overenie na poslanie mailov" #, fuzzy msgid "Channel group to check" msgstr "Skupina kanálov" #, fuzzy msgid "Help$Specify the channel group to check." msgstr "Uveďte meno šablony" msgid "Ignore PayTV channels" msgstr "Nevšímať si PayTV kanály" msgid "Help$Set this to 'yes' if don't want to see events on PayTV channels when searching for repeats." msgstr "Ak nepotrebujete zobraziť udalosti na kanáloch PayTV pri opakovanom vyhľadávaní, nastavte 'áno'" msgid "Search templates" msgstr "Vyhľadávanie šablóny" msgid "Help$Here you can setup templates for your searches." msgstr "Tu si môžete nastaviť šablóny pre vyhľadávanie." msgid "Blacklists" msgstr "Čierny zoznam" msgid "Help$Here you can setup blacklists which can be used within a search to exclude events you don't like." msgstr "Tu sa nastavuje čierny zoznam, ktorý môže byť použitý v rámci hľadania a tak vylúčiť udalosti, ktoré sa vám nepáčia." msgid "Help$Here you can setup channel groups which can be used within a search. These are different to VDR channel groups and represent a set of arbitrary channels, e.g. 'FreeTV'." msgstr "Tu si môžete nastaviť skupinu kanálov, ktoré majú byť použité v rámci hľadania. Tie sú odlišné od kanálov VDR skupín a predstavujú súbor ľubovoľných kanálov, napr 'volne šíriteľné '." msgid "Ignore below priority" msgstr "nevšímať si prioritu" msgid "Help$If a timer with priority below the given value will fail it will not be classified as important. Only important conflicts will produce an OSD message about the conflict after an automatic conflict check." msgstr "Ak je plán nahrávania s prioritou pod danú hodnotu dôjde k zlyhaniu, pretože nebude klasifikovaný ako dôležitý. Iba dôležité konflikty vyvolávajú OSD správy." msgid "Ignore conflict duration less ... min." msgstr "Nevšímať si konflikty menšie ako ... min" msgid "Help$If a conflicts duration is less then the given number of minutes it will not be classified as important. Only important conflicts will produce an OSD message about the conflict after an automatic conflict check." msgstr "Ak doba konfliktu pretrváva menej ako daný počet minút, nebude konflikt brať ako dôležitý. Iba dôležité konflikty sa automaticky zobrazia ako OSD správa." msgid "Only check within next ... days" msgstr "Skontrolovať iba do budúcich ... dní" msgid "Help$This value reduces the conflict check to the given range of days. All other conflicts are classified as 'not yet important'." msgstr "Táto hodnota znižuje konflikty podľa daného rozsahu dní. Všetky ostatné konflikty sú klasifikované ako 'ešte dôležité'." msgid "Check also remote conflicts" msgstr "" msgid "Help$Set this to 'yes' if the conflict check should be done for timers set on remote hosts. This needs SVDRPPeering to be set in vdr and Plugin epgsearch running on the remote host." msgstr "" msgid "--- Automatic checking ---" msgstr "--- Automatická kontrola ---" msgid "After each timer programming" msgstr "Po každom programovaní časovača" msgid "Help$Set this to 'yes' if the conflict check should be performed after each manual timer programming. In the case of a conflict you get immediately a message that informs you about it. The message is only displayed if this timer is involved in any conflict." msgstr "Ak pri ručnom programovaní plánu nastane konflikt, tak vám vypíše okamžitú správu o konflikte. Správa sa zobrazí v prípade ak plán je zapojený do akéhokoľvek konfliktu. Ak danú funkciu chcete použiť zvolte 'áno'" msgid "When a recording starts" msgstr "Pri nahrávaní sa spustí" msgid "Help$Set this to 'yes' if the conflict check should be performed when a recording starts. In the case of a conflict you get immediately a message that informs you about it. The message is only displayed if the conflict is within the next 2 hours." msgstr "Nastavte 'áno' ak by mala byť kontrola konfliktov vykonaná pri spustiní nahrávania. V prípade konfliktu vám pošle okamžite správu. Správa sa zobrazí v prípade konfliktu iba počas 2 hodín." msgid "After each search timer update" msgstr "Po každom hľadaní plánu zmenené" msgid "Help$Set this to 'yes' if the conflict check should be performed after each search timer update." msgstr "Ak kontrola konfliktov by mala byť vykonávaná pri každom obnovení vyhľadávača plánov, tak nastavte 'áno'" msgid "every ... minutes" msgstr "každých ... minút" msgid "" "Help$Specify here the time intervall to be used for an automatic conflict check in the background.\n" "('0' disables an automatic check)" msgstr "" "Zvolte ako často majú byť použité automatické kontroly konfliktov na pozadí. \n" "('0 'Zakáže automatické kontroly)" msgid "if conflicts within next ... minutes" msgstr "ak je v rozpore s ďalšou ... minútou" msgid "Help$If the next conflict will appear in the given number of minutes you can specify here a shorter check intervall to get more OSD notifications about it." msgstr "Ak sa objaví ďalší konflikt v danom počte minút, môžete zvoliť kratší interval kontroly a tak získať viac OSD oznámení. " msgid "Avoid notification when replaying" msgstr "Vyhnúť sa oznámeniam pri prehrávaní" msgid "Help$Set this to 'yes' if the don't want to get OSD messages about conflicts if you currently replay something. Nevertheless messages will be displayed if the first upcoming conflict is within the next 2 hours." msgstr "Nastavte 'áno', ak nechcete dostávať OSD správu o konfliktoch, v prípade,že niečo prehrávate. Avšak, správy sa zobrazia v prípade prvého nadchádzajúceho konfliktu v nasledujúcich 2 hodinách." msgid "Search timer notification" msgstr "Hlásenie vyhľadávania časovača" msgid "Help$Set this to 'yes' if you want to get an email notification about the search timers that where programmed automatically in the background." msgstr "Nastavte áno ak potrebujete oznamovať automaticky vyhľadané plány na mail" msgid "Time between mails [h]" msgstr "" msgid "" "Help$Specifiy how much time in [h] you would\n" "like to have atleast between two mails.\n" "With '0' you get a new mail after each\n" "search timer update with new results." msgstr "" msgid "Timer conflict notification" msgstr "Oznámiť konflikt plánov" msgid "Help$Set this to 'yes' if you want to get an email notification about the timer conflicts." msgstr "Nastavte áno ak potrebujete oznamovať konflikty plánu na mail" msgid "Send to" msgstr "Poslať no" msgid "Help$Specify the email address where notifications should be sent to." msgstr "Rozpíšte email adresu, na ktorú by sa mali posielať oznámenia." msgid "Mail method" msgstr "Mailová metóda" msgid "" "Help$Specify here the method to use when sending mails.\n" "You can choose between\n" " - 'sendmail': requires a properly configured email system\n" " - 'SendEmail.pl': simple script for mail delivery" msgstr "" "Zvolte použitý spôsob posielania mailov.\n" "Vyberte medzi\n" " - 'sendmail': vyžaduje, aby bol správne nakonfigurovaný systém e-mailu - 'SendEmail.pl': jednoduchý skript pre doručovanie pošty" msgid "--- Email account ---" msgstr "--- Email účet ---" msgid "Email address" msgstr "Email adresa" msgid "Help$Specify the email address where notifications should be sent from." msgstr "Zadajte mailovú adresu na ktorá sa budú posielať upozornenia." msgid "SMTP server" msgstr "SMTP server" msgid "Help$Specify the SMTP server that should deliver the notifications. If it's using a port different from the default(25) append the port with \":port\"." msgstr "Zadajte SMTP server, ktorý by mal posielať oznámenia. Ak sa port líši od predvoleného (25), tak pripíšte port s \": port \"." msgid "Use SMTP authentication" msgstr "Použiť SMTP overenie" msgid "Help$Set this to 'yes' if your account needs authentication to send mails." msgstr "Nastavte Áno, ak váš účet potrebuje overenie na poslanie mailov" msgid "Auth user" msgstr "Dôveryhodný užívateľ" msgid "Help$Specify the auth user, if this account needs authentication for SMTP." msgstr "Zvolte overovacie meno, ak účet potrebuje overenie pre SMTP" msgid "Auth password" msgstr "Dôveryhodné heslo" msgid "Help$Specify the auth password, if this account needs authentication for SMTP." msgstr "Zvolte overovacie heslo, ak je nutné overenie pre SMTP." msgid "Mail account check failed!" msgstr "Chyba kontroly mailového účtu!" msgid "Button$Test" msgstr "Testovať" msgid "$ abcdefghijklmnopqrstuvwxyz0123456789-.,#~\\^$[]|()*+?{}/:%@&_" msgstr " aáäbcčdďeéfghiíjklĺľmnňoóôpqrŕsštťuúvwxyýzž0123456789-.,#~\\^$[]|()*+?{}/:%@&_" msgid "Start/Stop time has changed" msgstr "Spustiť/Zastaviť dobu zmien" msgid "Title/episode has changed" msgstr "Názov / epizóda sa zmenila" msgid "No new timers were added." msgstr "Žiadne nové plány neboli pridané." msgid "No timers were modified." msgstr "Žiadne plány neboli upravované." msgid "No timers were deleted." msgstr "Žiadne plány neboli vymazané." msgid "No new events to announce." msgstr "" msgid "This version of EPGSearch does not support this service!" msgstr "Táto verzia epgsearch nepodporuje túto službu!" msgid "EPGSearch does not exist!" msgstr "Epgsearch neexistuje!" #, c-format msgid "%d new broadcast" msgstr "%d nové vysielanie" msgid "Button$by channel" msgstr "podľa kanálu" msgid "Button$by time" msgstr "podľa času" msgid "Button$Episode" msgstr "Epizóda" msgid "Button$Title" msgstr "Názov" msgid "announce details" msgstr "oznámiť podrobnosti" msgid "announce again" msgstr "oznámiť znova" msgid "with next update" msgstr "s ďalšou aktualizáciou" msgid "again from" msgstr "znova od" msgid "Search timer" msgstr "Hľadať časy" msgid "Edit blacklist" msgstr "Upraviť čiernu listinu" msgid "phrase" msgstr "slovné spojenie" msgid "all words" msgstr "všetky slová" msgid "at least one word" msgstr "aspoň jedno slovo" msgid "match exactly" msgstr "prispôsobiť presne" msgid "regular expression" msgstr "bežný výraz" msgid "fuzzy" msgstr "nejasný" msgid "user-defined" msgstr "určené užívateľom" msgid "interval" msgstr "časové rozpätie" msgid "channel group" msgstr "skupin kanálov" msgid "only FTA" msgstr "iba voľne šíritelné" msgid "Search term" msgstr "Hľadať termín" msgid "Search mode" msgstr "Spôsob vyhľadávania" msgid "Tolerance" msgstr "odchylka " msgid "Match case" msgstr "Argumenty zhody" msgid "Use title" msgstr "Použiť názov" msgid "Use subtitle" msgstr "Použiť titulky" msgid "Use description" msgstr "Použiť popis" msgid "Use extended EPG info" msgstr "Použiť rozšírené EPG informácie" msgid "Ignore missing categories" msgstr "Ignorovať chýbajúce kategórie" msgid "Use channel" msgstr "Použi kanál" msgid " from channel" msgstr " od kanálu" msgid " to channel" msgstr " po kanál" msgid "Channel group" msgstr "Skupina kanálov" msgid "Use time" msgstr " Použi čas" msgid " Start after" msgstr " od kedy" msgid " Start before" msgstr " Po kedy" msgid "Use duration" msgstr " Poži trvanie" msgid " Min. duration" msgstr " Min. doba" msgid " Max. duration" msgstr " Max doba" msgid "Use day of week" msgstr " Použi deň v týždni" msgid "Day of week" msgstr " Deň v týždni" msgid "Use global" msgstr "" msgid "Button$Templates" msgstr "Šablony" msgid "*** Invalid Channel ***" msgstr "*** Neplatný kanál ***" msgid "Please check channel criteria!" msgstr "Prosím, skontrolujte kritéria kanálu!" msgid "Edit$Delete blacklist?" msgstr "Vymazať čierny zoznam?" msgid "Repeats" msgstr "Repríza" msgid "Create search" msgstr "Vytvoriť vyhľadávanie" msgid "Search in recordings" msgstr "Hľadať v nahrávkach" msgid "Mark as 'already recorded'?" msgstr "Vymazať určené nahrá " msgid "Add/Remove to/from switch list?" msgstr "Pridať/Vymazať do/zo zoznamu?" msgid "Create blacklist" msgstr "Vytvoriť čiernu listinu" msgid "EPG Commands" msgstr "EPG príkazy" msgid "Epgsearch: RemoteTimerModifications failed" msgstr "" msgid "Already running!" msgstr "Práve spustené!" msgid "Add to switch list?" msgstr "Pridať do zoznamu?" msgid "Delete from switch list?" msgstr "Vymazať zo zoznamu?" msgid "Button$Details" msgstr "Podrobnosti" msgid "Button$Filter" msgstr "filter" msgid "Button$Show all" msgstr "Zobraziť všetko" msgid "conflicts" msgstr "konflikty" msgid "no conflicts!" msgstr "Bez konfliktu!" msgid "no important conflicts!" msgstr "žiadne dôležité konflikty!" msgid "C" msgstr "C" msgid "Button$Repeats" msgstr "Reprízy" msgid "no check" msgstr "neskontrolované" msgid "by channel and time" msgstr "podľa kanálu a času" msgid "by event ID" msgstr "podľa ID" msgid "Select directory" msgstr "Vybrať adresár" msgid "Button$Level" msgstr "Úroveň" msgid "Event" msgstr "Udalosti" msgid "Favorites" msgstr "Obľúbené" msgid "Search results" msgstr "Výsledok hľadania" msgid "Timer conflict! Show?" msgstr "Konflikt plánu! Zobraziť?" msgid "Directory" msgstr "Adresár" msgid "Channel" msgstr "Kanál" msgid "Childlock" msgstr "Detský zámok" msgid "Record on" msgstr "" msgid "Timer check" msgstr "Kontrola plánu" msgid "recording with device" msgstr "nahrávanie so zariadením" msgid "Button$With subtitle" msgstr "S titulkami" msgid "Button$Without subtitle" msgstr "Bez titulkov" msgid "Timer has been deleted" msgstr "" msgid "Button$Extended" msgstr "Rozšírené" msgid "Button$Simple" msgstr "Jednoduché" msgid "Use blacklists" msgstr "Použiť čiernu listinu" msgid "Edit$Search text too short - use anyway?" msgstr "Hľadaný text je krátky - použiť aj tak?" #, fuzzy msgid "Button$Orphaned" msgstr "podľa kanálu" msgid "Button$by name" msgstr "podľa mena" msgid "Button$by date" msgstr "podľa dátumu" msgid "Button$Delete all" msgstr "Vymazať všetko" msgid "Recordings" msgstr "Nahrávky" msgid "Edit$Delete entry?" msgstr "Vymazať údaje?" msgid "Edit$Delete all entries?" msgstr "Vymazať všetky údaje?" msgid "Summary" msgstr "Celkovo" msgid "Auxiliary info" msgstr "Doplňujúce informácie" msgid "Button$Aux info" msgstr "Pomocné informácie" msgid "Search actions" msgstr "Hľadať akcie" msgid "Execute search" msgstr "Spustiť vyhladávanie" msgid "Use as search timer on/off" msgstr "Použiť ako vyhľadávač plánu zapnuté/vypnuté" msgid "Trigger search timer update" msgstr "Spustená aktualizácia vyhľadávania plánu" msgid "Show recordings done" msgstr "Zobraziť spravené nahrávky" msgid "Show timers created" msgstr "Zobraziť vytvorené plány" msgid "Create a copy" msgstr "Vytvoriť a kopírovať" msgid "Use as template" msgstr "Použiť ako šablonu" msgid "Show switch list" msgstr "Zobraziť zoznam" msgid "Show blacklists" msgstr "Zobraziť čiernu listinu" msgid "Delete created timers?" msgstr "Vymazať vytvorené plány?" msgid "Timer conflict check" msgstr "Kontrola konfliktu plánov" msgid "Disable associated timers too?" msgstr "Zakázať súvisiace plány?" msgid "Activate associated timers too?" msgstr "Povoliť aj súvisiace plány?" msgid "Search timers activated in setup." msgstr "Vyhľadávač plánov aktivovaný v nastavení." msgid "Run search timer update?" msgstr "Spustiť aktualizáciu vyhladávania plánov?" msgid "Copy this entry?" msgstr "Kopírovať tieto údaje?" msgid "Copy" msgstr "Kopírovať" msgid "Copy this entry to templates?" msgstr "Kopírovať tieto údaje z šablon?" msgid "Delete all timers created from this search?" msgstr "Vymazať všetky plány vytvorené cez vyhľadávač?" msgid "Button$Actions" msgstr "Akcia" msgid "Search entries" msgstr "Vyhľadať údaje" msgid "active" msgstr "aktívne" msgid "Edit$Delete search?" msgstr "Vymazať vyhľadané?" msgid "Edit search" msgstr "Upraviť vyhladávanie" msgid "Record" msgstr "Nahrať" #, fuzzy msgid "Announce by OSD" msgstr "Iba oznámiť" msgid "Switch only" msgstr "Prepnúť iba" #, fuzzy msgid "Announce and switch" msgstr "Iba oznámiť" #, fuzzy msgid "Announce by mail" msgstr "Iba oznámiť" msgid "Inactive record" msgstr "" msgid "only globals" msgstr "" msgid "Selection" msgstr "Vybrané" msgid "all" msgstr "všetko" msgid "count recordings" msgstr "Počet nahrávok" msgid "count days" msgstr "Počet dní" msgid "if present" msgstr "" #, fuzzy msgid "same day" msgstr "Posledný deň" #, fuzzy msgid "same week" msgstr " Deň v týždni" msgid "same month" msgstr "" msgid "Template name" msgstr "Meno šablony" msgid "Help$Specify the name of the template." msgstr "Uveďte meno šablony" msgid "Help$Specify here the term to search for." msgstr "Sem zadajte termín pre vyhĺadávanie" msgid "" "Help$The following search modes exist:\n" "\n" "- phrase: searches for sub terms\n" "- all words: all single words must appear\n" "- at least one word: at least one single word must appear\n" "- match exactly: must match exactly\n" "- regular expression: match a regular expression\n" "- fuzzy searching: searches approximately" msgstr "" "Podľa spôsobu vyhĺadávania je: \n" "\n" "- Veta: vyhľadávanie čiastkového termínu \n" "- Všetky slová: všetky jednotlivé slová musia byť \n" "- Aspoň jedno slovo: aspoň jedno jediné slovo, musí byť \n" "- Presne sa zhodujú: musia presne zodpovedať \n" "- Zvyčajný výraz: presný výraz \n" "- Nepresné vyhľadávanie: vyhľadávanie približne" msgid "Help$This sets the tolerance of fuzzy searching. The value represents the allowed errors." msgstr "Toto nastaví toleranciu nepresnosti vyhľadávania. Hodnota predstavuje povolené chyby." msgid "Help$Set this to 'Yes' if your search should match the case." msgstr "Nastavte 'Áno', ak vaše vyhľadávanie by malo zodpovedať prípadu." msgid "Help$Set this to 'Yes' if you like to search in the title of an event." msgstr "Nastavte 'Áno', ak chcete hľadať v názvoch ." msgid "Help$Set this to 'Yes' if you like to search in the episode of an event." msgstr "Nastavte 'Áno', ak chcete hľadať v epizóde ." msgid "Help$Set this to 'Yes' if you like to search in the summary of an event." msgstr "Nastavte 'Áno', ak chcete hľadať vo všetkých údajoch." #, fuzzy msgid "Use content descriptor" msgstr "Použiť popis" #, fuzzy msgid "Help$Set this to 'Yes' if you want to search the contents by a descriptor." msgstr "Nastavte 'Áno', ak chcete hľadať v názvoch ." msgid "Help$The summary of an event, can contain additional information like 'Genre', 'Category', 'Year',... called 'EPG categories' within EPGSearch. External EPG providers often deliver this information. This allows refining a search and other nice things, like searching for the 'tip of the day'. To use it set this to 'Yes'." msgstr "Súhrn udalostí, môže obsahovať ďalšie informácie, ako 'Žáner', 'Kategória', 'Rok',... tzv 'EPG kategórie' v epgsearch. Vonkajšie EPG služby často takéto informácie poskytujú. To umožňuje kvalitnejšie vyhľadávanie a iné veci, ako je hľadanie 'typ dňa' alebo 'kino na' . Pre použitie nastavte na 'Áno'." msgid "Help$The file epgsearchcats.conf specifies the search mode for this entry. One can search by text or by value. You can also edit a list of predefined values in this file that can be selected here." msgstr "Súbor epgsearchcats.conf špecifikuje režim hľadania pre túto položku. Môže vyhľadávať podľa textu alebo hodnoty. Môžete tiež upravovať zoznam preddefinovaných hodnôt, v tomto súbore, ktorý možno vybrať tu." msgid "Help$If a selected category is not part of the summary of an event this normally excludes this event from the search results. To avoid this, set this option to 'Yes', but please handle this with care to avoid a huge amount of results." msgstr "Ak vybraná kategória nie je súčasťou súhrnu údajov, tak je zvyčajne vylúčená z výsledkov vyhľadávania. Ak chcete tomu predísť, nastavte túto voľbu na 'Áno', ale s mierou prosím , aby sa zabránilo veľkému množstvu výsledkov." msgid "Use in favorites menu" msgstr "Použiť v obľúbenom menu" msgid "Result menu layout" msgstr "Usporiadať výsledné menu" msgid "Use as search timer" msgstr "Použiť ako vyhľadávač plánu" msgid "Action" msgstr "Akcia" msgid "Switch ... minutes before start" msgstr "Prepnúť ... minút pred štartom" msgid "Unmute sound" msgstr "Pustiť zvuk" #, fuzzy msgid "Ask ... minutes before start" msgstr "Prepnúť ... minút pred štartom" msgid " Series recording" msgstr " Sériové nahrávky" msgid "Delete recordings after ... days" msgstr "Vymazať nahrávky po ... dňoch" msgid "Keep ... recordings" msgstr "Uchovať ... nahrávok" msgid "Pause when ... recordings exist" msgstr "Zastaviť ak ... nahrávka existuje" msgid "Avoid repeats" msgstr "Vyhýbať sa reprízam" msgid "Allowed repeats" msgstr "povoliť reprízy" msgid "Only repeats within ... days" msgstr "Iba reprízy behom ... dní" msgid "Compare title" msgstr "porovnať tituly" msgid "Compare subtitle" msgstr "porovnať titulky" msgid "Compare summary" msgstr "porovnať celkovo" #, fuzzy msgid "Min. match in %" msgstr " Min. doba" #, fuzzy msgid "Compare date" msgstr "porovnať tituly" msgid "Compare categories" msgstr "porovnať kategórie" msgid "VPS" msgstr "VPS" msgid "Auto delete" msgstr "automaticky vymazať" msgid "after ... recordings" msgstr "po ... nahrávkach" msgid "after ... days after first rec." msgstr "po ... dňoch od prvého nahratia." msgid "Edit user-defined days of week" msgstr "Upraviť užívateľom určený deň v týždni" msgid "Compare" msgstr "porovnať" msgid "Select blacklists" msgstr "Vybrať čiernu listinu" msgid "Values for EPG category" msgstr "Hodnota pre EPG kategóriu" msgid "Button$Apply" msgstr "Použiť" msgid "less" msgstr "menej" msgid "less or equal" msgstr "menej alebo rovnako" msgid "greater" msgstr "viacej" msgid "greater or equal" msgstr "Väčší alebo rovný" msgid "equal" msgstr "rovnaký" msgid "not equal" msgstr "nerovná sa" msgid "Activation of search timer" msgstr "Aktivácia vyhľadávania plánu" msgid "First day" msgstr "Prvý deň" msgid "Last day" msgstr "Posledný deň" msgid "Button$all channels" msgstr "všetky kanály" msgid "Button$only FTA" msgstr "iba voľne šíriteľné" msgid "Button$Timer preview" msgstr "Náhľad plánu" msgid "Blacklist results" msgstr "výsledky čierneho zoznamu" msgid "found recordings" msgstr "nájdené nahrávky" msgid "Error while accessing recording!" msgstr "Chyba prístupu k záznamom!" msgid "Button$Default" msgstr "Predvolené" msgid "Edit$Delete template?" msgstr "Vymazať šablónu?" msgid "Overwrite existing entries?" msgstr "Prepísať existujúce údaje?" msgid "Edit entry" msgstr "Upraviť údaje" #, fuzzy msgid "Switch" msgstr "Prepnúť iba" msgid "Announce only" msgstr "Iba oznámiť" #, fuzzy msgid "Announce ... minutes before start" msgstr "Prepnúť ... minút pred štartom" msgid "action at" msgstr "za akciou" msgid "Switch list" msgstr "Prepnúť zoznam" msgid "Edit template" msgstr "Upraviť šablóny" msgid "Timers" msgstr "Plány" msgid ">>> no info! <<<" msgstr ">>> žiadne informácie! <<<" msgid "Overview" msgstr "Prehľad" msgid "Button$Favorites" msgstr "Obľúbené" msgid "Quick search for broadcasts" msgstr "Rýchle vyhľadávanie vo vysielaní" msgid "Quick search" msgstr "Rýchle hľadanie" msgid "Show in main menu" msgstr "Zobraziť v hlavnom menu" #, c-format msgid "%d new broadcast(s) found! Show them?" msgstr "%d nové vysielanie(a) nájdené! Zobraziť ich?" msgid "Search timer update done!" msgstr "Aktualizácia vyhľadávania plánov skončená!" #, c-format msgid "small EPG content on:%s" msgstr "" msgid "VDR EPG check warning" msgstr "" #, c-format msgid "Switch to (%d) '%s'?" msgstr "" msgid "Programming timer failed!" msgstr "Chyba programovania plánovača" #~ msgid "in %02ldd" #~ msgstr "v %02ldd" #~ msgid "in %02ldh" #~ msgstr "v %02ldh" #~ msgid "in %02ldm" #~ msgstr "v %02ldm" #, fuzzy #~ msgid "Compare expression" #~ msgstr "bežný výraz" #~ msgid "File" #~ msgstr "Súbor" #~ msgid "Day" #~ msgstr "Deň" vdr-plugin-epgsearch/po/it_IT.po0000644000175000017500000012027713145412721016427 0ustar tobiastobias# VDR plugin language source file. # Copyright (C) 2007 Klaus Schmidinger # This file is distributed under the same license as the VDR package. # Alberto Carraro , 2001 # Antonio Ospite , 2003 # Sean Carlos , 2005 # msgid "" msgstr "" "Project-Id-Version: VDR 1.5.7\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-06-15 11:15+0200\n" "PO-Revision-Date: 2011-07-17 17:46+0100\n" "Last-Translator: Diego Pierotto \n" "Language-Team: Italian \n" "Language: it\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Language: Italian\n" "X-Poedit-Country: ITALY\n" "X-Poedit-SourceCharset: utf-8\n" msgid "Channel groups" msgstr "Gruppi canali" msgid "Button$Select" msgstr "Seleziona" msgid "Channel group used by:" msgstr "Gruppo canali utilizzato da:" msgid "Edit$Delete group?" msgstr "Eliminare il gruppo?" msgid "Edit channel group" msgstr "Modifica gruppo canali" msgid "Group name" msgstr "Nome gruppo" msgid "Button$Invert selection" msgstr "Inverti sel." msgid "Button$All yes" msgstr "Tutti sì" msgid "Button$All no" msgstr "Tutti no" msgid "Group name is empty!" msgstr "Il nome gruppo è vuoto!" msgid "Group name already exists!" msgstr "Nome gruppo già esistente!" msgid "Direct access to epgsearch's conflict check menu" msgstr "Accesso diretto al menu di verifica conflitti di epgsearch" msgid "Timer conflicts" msgstr "Conflitti timer" msgid "Conflict info in main menu" msgstr "Informazioni conflitto nel menu principale" msgid "next" msgstr "prossimo" #, c-format msgid "timer conflict at %s! Show it?" msgstr "Conflitto timer alle %s! Mostrare?" #, c-format msgid "%d timer conflicts! First at %s. Show them?" msgstr "%d conflitto timer! Primo alle %s. Mostrarli?" msgid "search the EPG for repeats and more" msgstr "Cerca nella guida EPG: per parole, repliche e altro" msgid "Program guide" msgstr "Guida programmi" msgid "search timer update running" msgstr "aggiornamento timer ricerca in esecuzione" msgid "Direct access to epgsearch's search menu" msgstr "Accesso diretto al menu di ricerca di epgsearch" msgid "Search" msgstr "Cerca" msgid "EpgSearch-Search in main menu" msgstr "Ricerca EpgSearch nel menu principale" msgid "Button$Help" msgstr "Aiuto" msgid "Standard" msgstr "Standard" msgid "Button$Commands" msgstr "Comandi" msgid "Button$Search" msgstr "Cerca" msgid "never" msgstr "mai" msgid "always" msgstr "sempre" msgid "smart" msgstr "intelligente" msgid "before user-def. times" msgstr "prima orari def. da utente" msgid "after user-def. times" msgstr "dopo orari def. da utente" msgid "before 'next'" msgstr "prima 'prossimi'" msgid "General" msgstr "Generale" msgid "EPG menus" msgstr "Menu EPG" msgid "User-defined EPG times" msgstr "Date EPG definite dall'utente" msgid "Timer programming" msgstr "Programmazione" msgid "Search and search timers" msgstr "Ricerca e timer ricerca" msgid "Timer conflict checking" msgstr "Verifica conflitti timer" msgid "Email notification" msgstr "Notifica email" msgid "Hide main menu entry" msgstr "Nascondi voce menu principale" msgid "Help$Hides the main menu entry and may be useful if this plugin is used to replace the original 'Schedule' entry." msgstr "Nascondere la voce nel menu può essere utile se questo plugin è usato per sostituire la voce originale 'Programmi'" msgid "Main menu entry" msgstr "Voce nel menu principale" msgid "Help$The name of the main menu entry which defaults to 'Programm guide'." msgstr "Nome della voce menu che corrisponde a 'Guida programmazione'" msgid "Replace original schedule" msgstr "Sostituisci Programmi originale" msgid "Help$When VDR is patched to allow this plugin to replace the original 'Schedule' entry, you can de/activate this replacement here." msgstr "Quando VDR è patchato per permettere a questo plugin di sostituire la voce originale 'Programmi', puoi dis/attivare qui la sostituzione." msgid "Start menu" msgstr "Menu avvio" msgid "Help$Choose between 'Overview - Now' and 'Schedule' as start menu when this plugin is called." msgstr "Scegli tra 'Sommario - Adesso' e 'Programmi' come menu iniziale quando questo plugin è chiamato." msgid "Ok key" msgstr "Tasto Ok" msgid "" "Help$Choose here the behaviour of key 'Ok'. You can use it to display the summary or to switch to the corresponding channel.\n" "Note: the functionality of key 'blue' (Switch/Info/Search) depends on this setting." msgstr "" "Scegli il comportamento del tasto 'Ok'. Puoi usarlo per vedere il sommario o cambiare il canale corrispondente.\n" "Nota: la funzionalità del tasto 'blu' (Cambia/Info/Cerca) dipende da questa impostazione." msgid "Red key" msgstr "Tasto rosso" msgid "" "Help$Choose which standard function ('Record' or 'Commands') you like to have on the red key.\n" "(Can be toggled with key '0')" msgstr "" "Scegli quale funzione standard ('Registrazione' o 'Comandi') vuoi avere nel tasto rosso.\n" "(Può essere impostata con il tasto '0')" msgid "Blue key" msgstr "Tasto blu" msgid "" "Help$Choose which standard function ('Switch'/'Info' or 'Search') you like to have on the blue key.\n" "(Can be toggled with key '0')" msgstr "" "Scegli quale funzione standard ('Cambia'/'Info' o 'Cerca') vuoi avere nel tasto blu.\n" "(Può essere impostata con il tasto '0')" msgid "Show progress in 'Now'" msgstr "Visualizza progresso in 'Adesso'" msgid "Help$Shows a progressbar in 'Overview - Now' that informs about the remaining time of the current event." msgstr "Mostra una barra d'avanzamento in 'Sommario - Adesso' che informa sul tempo rimanente dell'evento attuale." msgid "Show channel numbers" msgstr "Visualizza i numeri dei canali" msgid "" "Help$Display channel numbers in 'Overview - Now'.\n" "\n" "(To completely define your own menu look please inspect the MANUAL)" msgstr "" "Visualizza i numeri dei canali in 'Sommario - Adesso'\n" "\n" "(Per definire completamente il tuo proprio look del menu leggi il file MANUAL)" msgid "Show channel separators" msgstr "Mostra separatori canali" msgid "Help$Display VDR channel groups as separators between your channels in 'Overview - Now'." msgstr "Visualizza i gruppi canali come separatori tra i tuoi canali in 'Sommario - Adesso'." msgid "Show day separators" msgstr "Mostra separatori giorni" msgid "Help$Display a separator line at day break in 'Schedule'." msgstr "Visualizza una linea di separazione al cambio del giorno in 'Programmi'." msgid "Show radio channels" msgstr "Mostra canali radio" msgid "Help$Show also radio channels." msgstr "Mostra anche i canali radio." msgid "Limit channels from 1 to" msgstr "Limita canali da 1 a" msgid "Help$If you have a large channel set you can speed up things when you limit the displayed channels with this setting. Use '0' to disable the limit." msgstr "Se hai un gran numero di canali puoi velocizzarli limitando i canali visualizzati con questa impostazione. Utilizza '0' per disabilitare il limite." msgid "'One press' timer creation" msgstr "Crea timer ad 'una pressione'" msgid "Help$When a timer is created with 'Record' you can choose between an immediate creation of the timer or the display of the timer edit menu." msgstr "Quando un timer è creato con 'Registra' puoi selezionare tra una creazione immediata del timer o la visualizzazione del menu modifica timer." msgid "Show channels without EPG" msgstr "Mostra canali senza EPG" msgid "Help$Choose 'yes' here if you want to display channels without EPG in 'Overview - Now'. 'Ok' on these entries switches the channel." msgstr "Scegli 'sì' se vuoi vedere i canali senza EPG in 'Sommario - Adesso'. 'Ok' in questi valori cambia il canale." msgid "Time interval for FRew/FFwd [min]" msgstr "Intervallo tempo FRew/FFwd [min]" msgid "" "Help$Choose here the time interval which should be used for jumping through the EPG by pressing FRew/FFwd.\n" "\n" "(If you don't have those keys, you can toggle to this functionality pressing '0' and get '<<' and '>>' on the keys green and yellow)" msgstr "" "Scegli l'intervallo di tempo che dovrebbe essere usato per spostarsi attraverso l'EPG premendo FRew/FFwd.\n" "\n" "(Se non hai questi tasti, puoi impostare questa funzione premendo '0' ed avere '<<' e '>>' sui tasti verde e giallo)" msgid "Toggle Green/Yellow" msgstr "Alterna i tasti Verde/Giallo" msgid "Help$Specify if green and yellow shall also be switched when pressing '0'." msgstr "Specifica se i tasti verde e giallo si scambieranno anche premendo '0'." msgid "Show favorites menu" msgstr "Mostra il menu preferiti" msgid "" "Help$A favorites menu can display a list of your favorite broadcasts. Enable this if you want an additional menu besides 'Now' and 'Next'\n" "Any search can be used as a favorite. You only have to set the option 'Use in favorites menu' when editing a search." msgstr "" "Un menu preferiti può mostrare un elenco delle tue trasmissioni preferite. Abilitalo se vuoi un menu supplementare in 'Adesso' e 'Prossimi'\n" "Qualsiasi ricerca può essere usata come preferita. Devi solo impostare l'opzione 'Utilizza nel menu preferiti' quando modifichi una ricerca." msgid "for the next ... hours" msgstr "per le prossime ... ore" msgid "Help$This value controls the timespan used to display your favorites." msgstr "Questo valore controlla il tipo di ora usata per visualizzare i tuoi preferiti." msgid "Use user-defined time" msgstr "Utilizza ora utente" msgid "Help$Besides 'Now' and 'Next' you can specify up to 4 other times in the EPG which can be used by repeatedly pressing the green key, e.g. 'prime time', 'late night',..." msgstr "All'interno di 'Adesso' e 'Prossimi' puoi specificare fino ad altre 4 ore nell'EPG che può essere usato ripetutamente premendo il tasto verde, esempio 'prima serata', 'tarda sera',..." msgid "Description" msgstr "Descrizione" msgid "Help$This is the description for your user-defined time as it will appear as label on the green button." msgstr "Questa è la descrizione dell'ora definita dall'utente che apparirà come etichetta nel pulsante verde." msgid "Time" msgstr "Orario" msgid "Help$Specify the user-defined time here in 'HH:MM'." msgstr "Specifica l'ora definita qui dall'utente in 'HH:MM'." msgid "Use VDR's timer edit menu" msgstr "Utilizza menu modifica timer VDR" msgid "" "Help$This plugin has its own timer edit menu extending the original one with some extra functionality like\n" "- an additional directory entry\n" "- user-defined days of week for repeating timers\n" "- adding an episode name\n" "- support for EPG variables (see MANUAL)" msgstr "" "Questo plugin ha il suo menu modifica timer che estende quello originale con alcune funzionalità extra come:\n" "- un voce directory supplementare\n" "- giorni della settimana definiti dall'utente per i timer ripetuti\n" "- aggiunta nome episodio\n" "- supporto per variabili EPG (vedi MANUAL)" msgid "Default recording dir" msgstr "Dir. predefinita registrazione" msgid "Help$When creating a timer you can specify here a default recording directory." msgstr "Quando si crea un timer puoi specificare una directory di registrazione." msgid "Add episode to manual timers" msgstr "Aggiungi episodi ai timer manuali" msgid "" "Help$If you create a timer for a series, you can automatically add the episode name.\n" "\n" "- never: no addition\n" "- always: always add episode name if present\n" "- smart: add only if event lasts less than 80 mins." msgstr "" "Se crei un timer per le serie, puoi automaticamente aggiungere il nome episodio.\n" "\n" "- mai: nessuna aggiunta\n" "- sempre: aggiunge sempre un nome episodio se presente\n" "- veloce: lo aggiunge solo se l'evento termina in meno di 80 minuti" msgid "Default timer check method" msgstr "Metodo verifica timer predefinito" msgid "" "Help$Manual timers can be checked for EPG changes. Here you can setup the default check method for each channel. Choose between\n" "\n" "- no checking\n" "- by event ID: checks by an event ID supplied by the channel provider.\n" "- by channel and time: check by the duration match." msgstr "" "I timer manuali possono essere verificati con le modifiche EPG. Qui puoi impostare il metodo di verifica predefinito per ciascun canale. Scegli tra:\n" "\n" "- nessuna verifica\n" "- ID evento: verifica da un ID evento fornito dall'emittente del canale.\n" "- canale e ora: verifica la corrispondenza della durata." msgid "Button$Setup" msgstr "Opzioni" msgid "Use search timers" msgstr "Utilizza timer di ricerca" msgid "Help$'Search timers' can be used to automatically create timers for events that match your search criterions." msgstr "'Cerca timer' può essere usato per creare automaticamente timer per eventi che corrispondano a criteri di ricerca." msgid " Update interval [min]" msgstr " Intervallo aggiorn. [min]" msgid "Help$Specify here the time intervall to be used when searching for events in the background." msgstr "Specifica l'intervallo di tempo da usare durante la ricerca di eventi in sottofondo." msgid " SVDRP port" msgstr " Porta SVDRP" msgid "Help$Programming of new timers or timer changes is done with SVDRP. The default value should be correct, so change it only if you know what you are doing." msgstr "La programmazione di nuovi timer o la modifica dei timer viene fatta con SVDRP. Il valore predefinito dovrebbe essere corretto, quindi cambialo solo se sai cosa stai facendo." msgid "Help$Specify here the default priority of timers created with this plugin. This value can also be adjusted for each search itself." msgstr "Specifica qui la priorità predefinita dei timer creati con questo plugin. Questo valore può anche essere adattato per ciascuna ricerca." msgid "Help$Specify here the default lifetime of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "Specifica qui la durata predefinita dei timer/registrazioni creati con questo plugin. Questo valore può anche essere adattato per ciascuna ricerca." msgid "Help$Specify here the default start recording margin of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "Specifica qui il margine predefinito di inizio della registrazione dei timer/registrazioni creati con questo plugin. Questo valore può anche essere adattato per ciascuna ricerca." msgid "Help$Specify here the default stop recording margin of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "Specifica qui il margine predefinito di fine registrazione dei timer/registrazioni creati con questo plugin. Questo valore può anche essere adattato per ciascuna ricerca." msgid "No announcements when replaying" msgstr "Nessun annuncio durante riproduzione" msgid "Help$Set this to 'yes' if you don't like to get any announcements of broadcasts if you currently replay anything." msgstr "Imposta 'sì' se non ti piace avere degli annunci dalle emittenti se stai attualmente riproducendo qualcosa." msgid "Recreate timers after deletion" msgstr "Ricrea timer dopo eliminazione" msgid "Help$Set this to 'yes' if you want timers to be recreated with the next search timer update after deleting them." msgstr "Imposta 'sì' se vuoi ricreare i timer con la successiva ricerca di aggiornamento timer dopo la loro eliminazione." msgid "Check if EPG exists for ... [h]" msgstr "Verifica se l'EPG esiste per ... [h]" msgid "Help$Specify how many hours of future EPG there should be and get warned else after a search timer update." msgstr "Specifica quante ore degli EPG futuri dovrebbero essere notificati anche dopo un aggiornamento del timer di ricerca." msgid "Warn by OSD" msgstr "Notifica tramite OSD" msgid "Help$Set this to 'yes' if you want get warnings from the EPG check via OSD." msgstr "Imposta 'sì' se vuoi avere una notifica OSD sulle verifiche EPG." msgid "Warn by mail" msgstr "Notifica tramite mail" msgid "Help$Set this to 'yes' if you want get warnings from the EPG check by mail." msgstr "Imposta 'sì' se vuoi avere una notifica email sulle verifiche EPG." msgid "Channel group to check" msgstr "Gruppo canali da verificare" msgid "Help$Specify the channel group to check." msgstr "Specifica il gruppo canali da verificare." msgid "Ignore PayTV channels" msgstr "Ignora i canali a pagamento" msgid "Help$Set this to 'yes' if don't want to see events on PayTV channels when searching for repeats." msgstr "Imposta 'sì' se non vuoi vedere gli eventi dei canali a pagamento durante la ricerca delle repliche." msgid "Search templates" msgstr "Cerca modelli" msgid "Help$Here you can setup templates for your searches." msgstr "Qui puoi impostare i modelli per le ricerche." msgid "Blacklists" msgstr "Lista esclusioni" msgid "Help$Here you can setup blacklists which can be used within a search to exclude events you don't like." msgstr "Qui puoi impostare le liste di esclusione che possono essere usate all'interno delle ricerche per escludere eventi che non ti piacciono." msgid "Help$Here you can setup channel groups which can be used within a search. These are different to VDR channel groups and represent a set of arbitrary channels, e.g. 'FreeTV'." msgstr "Qui puoi impostare i gruppi di canali che possono essere usati all'interno di una ricerca. Questi sono diversi dai gruppi canali di VDR e rappresentano un insieme arbitrario di canali, ad esempio 'Gratuiti'." msgid "Ignore below priority" msgstr "Ignora priorità bassa" msgid "Help$If a timer with priority below the given value will fail it will not be classified as important. Only important conflicts will produce an OSD message about the conflict after an automatic conflict check." msgstr "Se un timer con priorità più bassa di un dato valore fallirà esso non sarà classificato come importante. Solo i conflitti importanti genereranno un messaggio OSD sul conflitto dopo una verifica automatica del conflitto." msgid "Ignore conflict duration less ... min." msgstr "Ignora durata conflitto minore ... min." msgid "Help$If a conflicts duration is less then the given number of minutes it will not be classified as important. Only important conflicts will produce an OSD message about the conflict after an automatic conflict check." msgstr "Se la durata di un conflitto è inferiore al numero di minuti dati non sarà classificato come importante. Solo i conflitti importanti genereranno un messaggio OSD sul conflitto dopo la verifica automatica di ciascun conflitto." msgid "Only check within next ... days" msgstr "Verifica solo entro i prossimi ... giorni" msgid "Help$This value reduces the conflict check to the given range of days. All other conflicts are classified as 'not yet important'." msgstr "Questo valore riduce la verifica del conflitto ad un dato range di giorni. Tutti gli altri conflitti sono classificati come 'non ancora importanti'." msgid "Check also remote conflicts" msgstr "" msgid "Help$Set this to 'yes' if the conflict check should be done for timers set on remote hosts. This needs SVDRPPeering to be set in vdr and Plugin epgsearch running on the remote host." msgstr "" msgid "--- Automatic checking ---" msgstr "--- Verifica automatica ---" msgid "After each timer programming" msgstr "Dopo program. di ciascun timer" msgid "Help$Set this to 'yes' if the conflict check should be performed after each manual timer programming. In the case of a conflict you get immediately a message that informs you about it. The message is only displayed if this timer is involved in any conflict." msgstr "Imposta 'sì' se il controllo di conflitto dovrebbe essere eseguito dopo la programmazione di ciascun timer manuale. Nel caso di un conflitto avrai immediatamente un messaggio che ti informa di questo. Il messaggio viene visualizzato solo se questo timer è coinvolto in qualche conflitto." msgid "When a recording starts" msgstr "Quando inizia una reg." msgid "Help$Set this to 'yes' if the conflict check should be performed when a recording starts. In the case of a conflict you get immediately a message that informs you about it. The message is only displayed if the conflict is within the next 2 hours." msgstr "Imposta 'sì' se il controllo di conflitto dovrebbe essere eseguito dopo l'inizio di una registrazione. Nel caso di un conflitto avrai immediatamente un messaggio che ti informa di questo. Il messaggio viene visualizzato solo se questo conflitto avviene nelle prossime 2 ore." msgid "After each search timer update" msgstr "Dopo ogni aggiorn. timer ricerca" msgid "Help$Set this to 'yes' if the conflict check should be performed after each search timer update." msgstr "Imposta 'sì' se la verifica del conflitto dovrebbe essere eseguita dopo ciascun aggiornamento del timer di ricerca." msgid "every ... minutes" msgstr "ogni ... minuti" msgid "" "Help$Specify here the time intervall to be used for an automatic conflict check in the background.\n" "('0' disables an automatic check)" msgstr "" "Specifica qui l'intervallo da usare per la verifica automatica di un conflitto in sottofondo.\n" "('0' disabilita la verifica automatica)" msgid "if conflicts within next ... minutes" msgstr "in conflitto entro i prossimi ... minuti" msgid "Help$If the next conflict will appear in the given number of minutes you can specify here a shorter check intervall to get more OSD notifications about it." msgstr "Se il prossimo conflitto comparirà nel numero dato di minuti puoi specificare qui un intervallo di verifica più breve per avere più notifiche OSD su di esso." msgid "Avoid notification when replaying" msgstr "Evita notifiche durante riprod." msgid "Help$Set this to 'yes' if the don't want to get OSD messages about conflicts if you currently replay something. Nevertheless messages will be displayed if the first upcoming conflict is within the next 2 hours." msgstr "Imposta 'sì' se non vuoi avere messaggi OSD sui conflitti se stai riproducendo qualcosa. Tuttavia i messaggi saranno visualizzati se il primo conflitto avviene entro le prossime 2 ore." msgid "Search timer notification" msgstr "Notifica timer di ricerca" msgid "Help$Set this to 'yes' if you want to get an email notification about the search timers that where programmed automatically in the background." msgstr "Imposta 'sì' se vuoi avere una email di notifica sui timer di ricerca che sono stati programmati automaticamente dal sistema." msgid "Time between mails [h]" msgstr "Tempo tra le email [h]" msgid "" "Help$Specifiy how much time in [h] you would\n" "like to have atleast between two mails.\n" "With '0' you get a new mail after each\n" "search timer update with new results." msgstr "" "Specifica quanto tempo in [h]\n" "vuoi almeno avere tra due email.\n" "Con '0' hai una nuova email dopo ogni\n" "aggiornamento del timer di ricerca\n" "con nuovi risultati." msgid "Timer conflict notification" msgstr "Notifica timer in conflitto" msgid "Help$Set this to 'yes' if you want to get an email notification about the timer conflicts." msgstr "Imposta 'sì' se vuoi avere una notifica email sui timer in conflitto." msgid "Send to" msgstr "Invia a" msgid "Help$Specify the email address where notifications should be sent to." msgstr "Specifica l'indirizzo di posta al quale le notifiche dovrebbero essere spedite." msgid "Mail method" msgstr "Metodo email" msgid "" "Help$Specify here the method to use when sending mails.\n" "You can choose between\n" " - 'sendmail': requires a properly configured email system\n" " - 'SendEmail.pl': simple script for mail delivery" msgstr "" "Specifica qui il metodo da usare per l'invio delle email.\n" "Puoi scegliere tra:\n" "- 'sendmail': richiede un proprio sistema email configurato\n" "- 'SendEmail.pl': semplice script per la consegna delle email" msgid "--- Email account ---" msgstr "--- Account email ---" msgid "Email address" msgstr "Indirizzo di posta" msgid "Help$Specify the email address where notifications should be sent from." msgstr "Specifica l'indirizzo di posta dal quale le notifiche dovrebbero essere spedite." msgid "SMTP server" msgstr "Server SMTP" msgid "Help$Specify the SMTP server that should deliver the notifications. If it's using a port different from the default(25) append the port with \":port\"." msgstr "Specifica il server SMTP che dovrebbe consegnare le notifiche. Se utilizza una porta diversa da quella di default (25) aggiungi la porta con \":porta\"." msgid "Use SMTP authentication" msgstr "Utilizza autenticazione SMTP" msgid "Help$Set this to 'yes' if your account needs authentication to send mails." msgstr "Imposta 'sì' se il tuo account ha bisogno di autenticazione per inviare email." msgid "Auth user" msgstr "Autenticazione utente" msgid "Help$Specify the auth user, if this account needs authentication for SMTP." msgstr "Specifica l'utente di autenticazione, se questo account ne ha bisogno per SMTP." msgid "Auth password" msgstr "Password autenticazione" msgid "Help$Specify the auth password, if this account needs authentication for SMTP." msgstr "Specifica la password di autenticazione, se quanto account ne ha bisogno per SMTP." msgid "Mail account check failed!" msgstr "Verifica account email fallita!" msgid "Button$Test" msgstr "Prova" msgid "$ abcdefghijklmnopqrstuvwxyz0123456789-.,#~\\^$[]|()*+?{}/:%@&_" msgstr " aáàbcdeéèfghiíìjklmnoóòpqrstuúùvwxyz0123456789-.,#~\\^$[]|()*+?{}/:%@&°_" msgid "Start/Stop time has changed" msgstr "L'orario di Inizio/Fine è cambiato" msgid "Title/episode has changed" msgstr "Il Titolo/episodio è cambiato" msgid "No new timers were added." msgstr "Nessun nuovo timer aggiunto." msgid "No timers were modified." msgstr "Nessun timer modificato." msgid "No timers were deleted." msgstr "Nessun timer eliminato." msgid "No new events to announce." msgstr "Nessun nuovo evento da annunciare." msgid "This version of EPGSearch does not support this service!" msgstr "Questa versione di EPGSearch non supporta questo servizio!" msgid "EPGSearch does not exist!" msgstr "EPGSearch non esiste!" #, c-format msgid "%d new broadcast" msgstr "%d nuova emittente" msgid "Button$by channel" msgstr "Per canale" msgid "Button$by time" msgstr "Per orario" msgid "Button$Episode" msgstr "Episodio" msgid "Button$Title" msgstr "Titolo" msgid "announce details" msgstr "dettagli annuncio" msgid "announce again" msgstr "annuncia ancora" msgid "with next update" msgstr "con nuovo aggiornamento" msgid "again from" msgstr "ancora da" msgid "Search timer" msgstr "Cerca timer" msgid "Edit blacklist" msgstr "Modifica lista esclusioni" msgid "phrase" msgstr "frase" msgid "all words" msgstr "tutte le parole" msgid "at least one word" msgstr "almeno una parola" msgid "match exactly" msgstr "corrispondenza esatta" msgid "regular expression" msgstr "espressione regolare" msgid "fuzzy" msgstr "imprecisa" msgid "user-defined" msgstr "definito dall'utente" msgid "interval" msgstr "intervallo" msgid "channel group" msgstr "gruppo canali" msgid "only FTA" msgstr "solo gratuiti" msgid "Search term" msgstr "Termine ricerca" msgid "Search mode" msgstr "Modalità di ricerca" msgid "Tolerance" msgstr "Tolleranza" msgid "Match case" msgstr "Maiuscolo/Minuscolo" msgid "Use title" msgstr "Utilizza titolo" msgid "Use subtitle" msgstr "Utilizza sottotitolo" msgid "Use description" msgstr "Utilizza descrizione" msgid "Use extended EPG info" msgstr "Utilizza informazioni EPG estesa" msgid "Ignore missing categories" msgstr "Ignora categorie mancanti" msgid "Use channel" msgstr "Utilizza canale" msgid " from channel" msgstr " da canale" msgid " to channel" msgstr " a canale" msgid "Channel group" msgstr "Gruppo canali" msgid "Use time" msgstr "Utilizza orario" msgid " Start after" msgstr " Inizia dopo" msgid " Start before" msgstr " Inizia prima" msgid "Use duration" msgstr "Utilizza durata" msgid " Min. duration" msgstr " Durata Minima" msgid " Max. duration" msgstr " Durata Massima" msgid "Use day of week" msgstr "Utilizza giorno settimana" msgid "Day of week" msgstr "Giorno settimana" msgid "Use global" msgstr "Utilizza globale" msgid "Button$Templates" msgstr "Modelli" msgid "*** Invalid Channel ***" msgstr "*** Canale NON valido ***" msgid "Please check channel criteria!" msgstr "Controlla i criteri del canale!" msgid "Edit$Delete blacklist?" msgstr "Eliminare lista esclusioni?" msgid "Repeats" msgstr "Repliche" msgid "Create search" msgstr "Crea ricerca" msgid "Search in recordings" msgstr "Cerca nelle registrazioni" msgid "Mark as 'already recorded'?" msgstr "Segnare come 'già registrato'?" msgid "Add/Remove to/from switch list?" msgstr "Aggiungere/Rimuovere a/dalla lista modifiche?" msgid "Create blacklist" msgstr "Crea lista esclusioni" msgid "EPG Commands" msgstr "Comandi EPG" msgid "Epgsearch: RemoteTimerModifications failed" msgstr "" msgid "Already running!" msgstr "In esecuzione!" msgid "Add to switch list?" msgstr "Aggiungere alla lista modifiche?" msgid "Delete from switch list?" msgstr "Eliminare dalla lista modifiche?" msgid "Button$Details" msgstr "Dettagli" msgid "Button$Filter" msgstr "Filtro" msgid "Button$Show all" msgstr "Mostra tutti" msgid "conflicts" msgstr "conflitti" msgid "no conflicts!" msgstr "nessun conflitto!" msgid "no important conflicts!" msgstr "nessun conflitto importante!" msgid "C" msgstr "C" msgid "Button$Repeats" msgstr "Repliche" msgid "no check" msgstr "nessuna verifica" msgid "by channel and time" msgstr "per canale e ora" msgid "by event ID" msgstr "per ID evento" msgid "Select directory" msgstr "Seleziona directory" msgid "Button$Level" msgstr "Livello" msgid "Event" msgstr "Evento" msgid "Favorites" msgstr "Preferiti" msgid "Search results" msgstr "Risultati della ricerca" msgid "Timer conflict! Show?" msgstr "Conflitto timer! Mostrare?" msgid "Directory" msgstr "Directory" msgid "Channel" msgstr "Canale" msgid "Childlock" msgstr "Filtro famiglia" msgid "Record on" msgstr "" msgid "Timer check" msgstr "Verifica timer" msgid "recording with device" msgstr "registra con scheda" msgid "Button$With subtitle" msgstr "Con sottotitoli" msgid "Button$Without subtitle" msgstr "Senza sottotitoli" msgid "Timer has been deleted" msgstr "Il timer è stata eliminato!" msgid "Button$Extended" msgstr "Esteso" msgid "Button$Simple" msgstr "Semplice" msgid "Use blacklists" msgstr "Utilizza lista esclusioni" msgid "Edit$Search text too short - use anyway?" msgstr "Il testo da cercare è troppo corto - continuare?" #, fuzzy msgid "Button$Orphaned" msgstr "Per canale" msgid "Button$by name" msgstr "Per nome" msgid "Button$by date" msgstr "Per data" msgid "Button$Delete all" msgstr "Elimina tutti" msgid "Recordings" msgstr "Registrazioni" msgid "Edit$Delete entry?" msgstr "Eliminare voce?" msgid "Edit$Delete all entries?" msgstr "Eliminare tutte le voci?" msgid "Summary" msgstr "Sommario" msgid "Auxiliary info" msgstr "Informazioni ausiliarie" msgid "Button$Aux info" msgstr "Info ausiliarie" msgid "Search actions" msgstr "Azioni ricerca" msgid "Execute search" msgstr "Esegui ricerca" msgid "Use as search timer on/off" msgstr "Utilizza come timer ricerca attivo/disattivo" msgid "Trigger search timer update" msgstr "Attiva aggiornamento timer ricerca" msgid "Show recordings done" msgstr "Mostra registrazioni completate" msgid "Show timers created" msgstr "Mostra timer creati" msgid "Create a copy" msgstr "Crea una copia" msgid "Use as template" msgstr "Utilizza come modello" msgid "Show switch list" msgstr "Mostra lista modifiche" msgid "Show blacklists" msgstr "Mostra lista esclusioni" msgid "Delete created timers?" msgstr "Eliminare timer creati?" msgid "Timer conflict check" msgstr "Verifica conflitti timer" msgid "Disable associated timers too?" msgstr "Disabilitare anche i timer associati?" msgid "Activate associated timers too?" msgstr "Attivare anche i timer associati?" msgid "Search timers activated in setup." msgstr "Timer di ricerca attivati nelle opzioni." msgid "Run search timer update?" msgstr "Eseguire aggiornamento ricerca timer?" msgid "Copy this entry?" msgstr "Copiare questo valore?" msgid "Copy" msgstr "Copia" msgid "Copy this entry to templates?" msgstr "Copiare questo valore nei modelli?" msgid "Delete all timers created from this search?" msgstr "Eliminare tutti i timer creati da questa ricerca?" msgid "Button$Actions" msgstr "Azioni" msgid "Search entries" msgstr "Valori ricerca" msgid "active" msgstr "attivo" msgid "Edit$Delete search?" msgstr "Eliminare criteri?" msgid "Edit search" msgstr "Modifica ricerca" msgid "Record" msgstr "Registra" msgid "Announce by OSD" msgstr "Annuncia tramite OSD" msgid "Switch only" msgstr "Cambia soltanto" msgid "Announce and switch" msgstr "Annuncia e cambia" msgid "Announce by mail" msgstr "Annuncia tramite email" msgid "Inactive record" msgstr "" msgid "only globals" msgstr "solo globali" msgid "Selection" msgstr "Selezione" msgid "all" msgstr "tutti" msgid "count recordings" msgstr "conteggia registrazioni" msgid "count days" msgstr "conteggia giorni" msgid "if present" msgstr "se presente" msgid "same day" msgstr "stesso giorno" msgid "same week" msgstr "stessa settimana" msgid "same month" msgstr "stesso mese" msgid "Template name" msgstr "Nome modello" msgid "Help$Specify the name of the template." msgstr "Specifica il nome del modello." msgid "Help$Specify here the term to search for." msgstr "Specifica qui il termine da cercare." msgid "" "Help$The following search modes exist:\n" "\n" "- phrase: searches for sub terms\n" "- all words: all single words must appear\n" "- at least one word: at least one single word must appear\n" "- match exactly: must match exactly\n" "- regular expression: match a regular expression\n" "- fuzzy searching: searches approximately" msgstr "" "Esistono i seguenti metodi di ricerca:\n" "\n" "- frase: ricerca per sotto termini\n" "- tutte le parole: tutte le singole parole presenti\n" "- almeno una parola: almeno una parola presente\n" "- esatta corrispondenza: deve corrispondere esattamente\n" "- espressione regolare: corrisponde a una espressione regolare\n" "- ricerca imprecisa: ricerca approssimativamente" msgid "Help$This sets the tolerance of fuzzy searching. The value represents the allowed errors." msgstr "Questo imposta la tolleranza della ricerca imprecisa. Il valore rappresenta gli errori ammessi." msgid "Help$Set this to 'Yes' if your search should match the case." msgstr "Imposta 'Sì' nel caso la ricerca dovesse corrispondere." msgid "Help$Set this to 'Yes' if you like to search in the title of an event." msgstr "Imposta 'Sì' se vuoi cercare il titolo di un evento." msgid "Help$Set this to 'Yes' if you like to search in the episode of an event." msgstr "Imposta 'Sì' se vuoi cercare l'episodio di un evento." msgid "Help$Set this to 'Yes' if you like to search in the summary of an event." msgstr "Imposta 'Sì' se vuoi cercare il sommario di un evento." msgid "Use content descriptor" msgstr "Utilizza contenuto descrizione" msgid "Help$Set this to 'Yes' if you want to search the contents by a descriptor." msgstr "Imposta 'Sì' se vuoi cercare i contenuti per descrizione." msgid "Help$The summary of an event, can contain additional information like 'Genre', 'Category', 'Year',... called 'EPG categories' within EPGSearch. External EPG providers often deliver this information. This allows refining a search and other nice things, like searching for the 'tip of the day'. To use it set this to 'Yes'." msgstr "Il sommario di un evento, può contenere informazione addizionale come 'Genere', 'Categoria', 'Anno',... chiamata 'Categorie EPG' all'interno di EPGSearch. I fornitori di EPG esterni spesso inviano questa informazione. Questo ti permette di rifinire una ricerca e altre cosette, come la ricerca per il 'consiglio del giorno'. Per usarlo imposta 'Sì'." msgid "Help$The file epgsearchcats.conf specifies the search mode for this entry. One can search by text or by value. You can also edit a list of predefined values in this file that can be selected here." msgstr "Il file epgsearchcats.conf specifica la modalità di ricerca per questo valore. Uno può cercare per testo o per valore. Puoi anche modificare un elenco di valori predefiniti in questo file che può essere qui selezionato." msgid "Help$If a selected category is not part of the summary of an event this normally excludes this event from the search results. To avoid this, set this option to 'Yes', but please handle this with care to avoid a huge amount of results." msgstr "Se una categoria selezionata non è parte del sommario di un evento questo normalmente esclude questo evento dai risultati di ricerca. Per evitare ciò, imposta 'Sì' come opzione, ma gestiscilo con attenzione per evitare una grande quantità di risultati." msgid "Use in favorites menu" msgstr "Utilizza nel menu preferiti" msgid "Result menu layout" msgstr "Disposizione menu risultati" msgid "Use as search timer" msgstr "Utilizza come timer di ricerca" msgid "Action" msgstr "Azione" msgid "Switch ... minutes before start" msgstr "Cambia ... minuti prima dell'inizio" msgid "Unmute sound" msgstr "Togli suono muto" msgid "Ask ... minutes before start" msgstr "Chiedi ... minuti prima dell'inizio" msgid " Series recording" msgstr " Registrazione di serie" msgid "Delete recordings after ... days" msgstr "Elimina registrazioni dopo ... giorni" msgid "Keep ... recordings" msgstr "Mantieni ... registrazioni" msgid "Pause when ... recordings exist" msgstr "Pausa, quando ... la registrazione esiste" msgid "Avoid repeats" msgstr "Evita repliche" msgid "Allowed repeats" msgstr "Permetti repliche" msgid "Only repeats within ... days" msgstr "Solo repliche entro ... giorni" msgid "Compare title" msgstr "Confronta titolo" msgid "Compare subtitle" msgstr "Confronta sottotitolo" msgid "Compare summary" msgstr "Confronta sommario" msgid "Min. match in %" msgstr "Corrispondenza min. in %" msgid "Compare date" msgstr "Confronta date" msgid "Compare categories" msgstr "Confronta categorie" msgid "VPS" msgstr "VPS" msgid "Auto delete" msgstr "Auto elimina" msgid "after ... recordings" msgstr "dopo ... registrazioni" msgid "after ... days after first rec." msgstr "dopo ... giorni dopo prima reg." msgid "Edit user-defined days of week" msgstr "Modifica giorni della settimana definiti dall'utente" msgid "Compare" msgstr "Confronta" msgid "Select blacklists" msgstr "Seleziona lista esclusioni" msgid "Values for EPG category" msgstr "Valori per la categoria EPG" msgid "Button$Apply" msgstr "Applica" msgid "less" msgstr "minore" msgid "less or equal" msgstr "minore o uguale" msgid "greater" msgstr "maggiore" msgid "greater or equal" msgstr "maggiore o uguale" msgid "equal" msgstr "uguale" msgid "not equal" msgstr "non uguale" msgid "Activation of search timer" msgstr "Attivazione timer ricerca" msgid "First day" msgstr "Primo giorno" msgid "Last day" msgstr "Ultimo giorno" msgid "Button$all channels" msgstr "Tutti i canali" msgid "Button$only FTA" msgstr "Solo gratuiti" msgid "Button$Timer preview" msgstr "Anteprima timer" msgid "Blacklist results" msgstr "Risultati lista esclusioni" msgid "found recordings" msgstr "registrazioni trovate" msgid "Error while accessing recording!" msgstr "Errore durante l'accesso alla registrazione!" msgid "Button$Default" msgstr "Predefinito" msgid "Edit$Delete template?" msgstr "Eliminare modello?" msgid "Overwrite existing entries?" msgstr "Sovrascrivere valori esistenti?" msgid "Edit entry" msgstr "Modifica valore" msgid "Switch" msgstr "Cambia" msgid "Announce only" msgstr "Solo annuncio" msgid "Announce ... minutes before start" msgstr "Annuncia ... minuti prima dell'inizio" msgid "action at" msgstr "azione alle" msgid "Switch list" msgstr "Lista modifiche" msgid "Edit template" msgstr "Modifica modello" msgid "Timers" msgstr "Timer" msgid ">>> no info! <<<" msgstr ">>> nessuna informazione! <<<" msgid "Overview" msgstr "Sommario" msgid "Button$Favorites" msgstr "Preferiti" msgid "Quick search for broadcasts" msgstr "Ricerca veloce per emittenti" msgid "Quick search" msgstr "Ricerca veloce" msgid "Show in main menu" msgstr "Mostra nel menu principale" #, c-format msgid "%d new broadcast(s) found! Show them?" msgstr "%d nuove emittenti trovate! Mostrarle?" msgid "Search timer update done!" msgstr "Aggiornamento timer ricerca completato!" #, c-format msgid "small EPG content on:%s" msgstr "contenuto piccoli EPG su:%s" msgid "VDR EPG check warning" msgstr "Notifica verifica EPG di VDR" #, c-format msgid "Switch to (%d) '%s'?" msgstr "Cambiare a (%d) '%s'?" msgid "Programming timer failed!" msgstr "Programmazione timer fallito!" #~ msgid "in %02ldd" #~ msgstr "in %02ldd" #~ msgid "in %02ldh" #~ msgstr "in %02ldh" #~ msgid "in %02ldm" #~ msgstr "in %02ldm" #~ msgid "File" #~ msgstr "File" #~ msgid "Day" #~ msgstr "Giorno" vdr-plugin-epgsearch/po/pt_PT.po0000644000175000017500000005755113145412721016451 0ustar tobiastobias# VDR plugin language source file. # Copyright (C) 2007 Klaus Schmidinger # This file is distributed under the same license as the VDR package. # Paulo Lopes , 2001 # msgid "" msgstr "" "Project-Id-Version: VDR 1.5.7\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-06-15 11:15+0200\n" "PO-Revision-Date: 2007-08-14 20:21+0200\n" "Last-Translator: Paulo Lopes \n" "Language-Team: Portuguese \n" "Language: pt\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "Channel groups" msgstr "" msgid "Button$Select" msgstr "" msgid "Channel group used by:" msgstr "" msgid "Edit$Delete group?" msgstr "" msgid "Edit channel group" msgstr "" msgid "Group name" msgstr "" msgid "Button$Invert selection" msgstr "" msgid "Button$All yes" msgstr "" msgid "Button$All no" msgstr "" msgid "Group name is empty!" msgstr "" msgid "Group name already exists!" msgstr "" msgid "Direct access to epgsearch's conflict check menu" msgstr "" msgid "Timer conflicts" msgstr "" msgid "Conflict info in main menu" msgstr "" msgid "next" msgstr "" #, c-format msgid "timer conflict at %s! Show it?" msgstr "" #, c-format msgid "%d timer conflicts! First at %s. Show them?" msgstr "" msgid "search the EPG for repeats and more" msgstr "" msgid "Program guide" msgstr "" msgid "search timer update running" msgstr "" msgid "Direct access to epgsearch's search menu" msgstr "" msgid "Search" msgstr "" msgid "EpgSearch-Search in main menu" msgstr "" msgid "Button$Help" msgstr "" msgid "Standard" msgstr "" msgid "Button$Commands" msgstr "" msgid "Button$Search" msgstr "" msgid "never" msgstr "" msgid "always" msgstr "" msgid "smart" msgstr "" msgid "before user-def. times" msgstr "" msgid "after user-def. times" msgstr "" msgid "before 'next'" msgstr "" msgid "General" msgstr "" msgid "EPG menus" msgstr "" msgid "User-defined EPG times" msgstr "" msgid "Timer programming" msgstr "" msgid "Search and search timers" msgstr "" msgid "Timer conflict checking" msgstr "" msgid "Email notification" msgstr "" msgid "Hide main menu entry" msgstr "" msgid "Help$Hides the main menu entry and may be useful if this plugin is used to replace the original 'Schedule' entry." msgstr "" msgid "Main menu entry" msgstr "" msgid "Help$The name of the main menu entry which defaults to 'Programm guide'." msgstr "" msgid "Replace original schedule" msgstr "" msgid "Help$When VDR is patched to allow this plugin to replace the original 'Schedule' entry, you can de/activate this replacement here." msgstr "" msgid "Start menu" msgstr "" msgid "Help$Choose between 'Overview - Now' and 'Schedule' as start menu when this plugin is called." msgstr "" msgid "Ok key" msgstr "" msgid "" "Help$Choose here the behaviour of key 'Ok'. You can use it to display the summary or to switch to the corresponding channel.\n" "Note: the functionality of key 'blue' (Switch/Info/Search) depends on this setting." msgstr "" msgid "Red key" msgstr "" msgid "" "Help$Choose which standard function ('Record' or 'Commands') you like to have on the red key.\n" "(Can be toggled with key '0')" msgstr "" msgid "Blue key" msgstr "" msgid "" "Help$Choose which standard function ('Switch'/'Info' or 'Search') you like to have on the blue key.\n" "(Can be toggled with key '0')" msgstr "" msgid "Show progress in 'Now'" msgstr "" msgid "Help$Shows a progressbar in 'Overview - Now' that informs about the remaining time of the current event." msgstr "" msgid "Show channel numbers" msgstr "" msgid "" "Help$Display channel numbers in 'Overview - Now'.\n" "\n" "(To completely define your own menu look please inspect the MANUAL)" msgstr "" msgid "Show channel separators" msgstr "" msgid "Help$Display VDR channel groups as separators between your channels in 'Overview - Now'." msgstr "" msgid "Show day separators" msgstr "" msgid "Help$Display a separator line at day break in 'Schedule'." msgstr "" msgid "Show radio channels" msgstr "" msgid "Help$Show also radio channels." msgstr "" msgid "Limit channels from 1 to" msgstr "" msgid "Help$If you have a large channel set you can speed up things when you limit the displayed channels with this setting. Use '0' to disable the limit." msgstr "" msgid "'One press' timer creation" msgstr "" msgid "Help$When a timer is created with 'Record' you can choose between an immediate creation of the timer or the display of the timer edit menu." msgstr "" msgid "Show channels without EPG" msgstr "" msgid "Help$Choose 'yes' here if you want to display channels without EPG in 'Overview - Now'. 'Ok' on these entries switches the channel." msgstr "" msgid "Time interval for FRew/FFwd [min]" msgstr "" msgid "" "Help$Choose here the time interval which should be used for jumping through the EPG by pressing FRew/FFwd.\n" "\n" "(If you don't have those keys, you can toggle to this functionality pressing '0' and get '<<' and '>>' on the keys green and yellow)" msgstr "" msgid "Toggle Green/Yellow" msgstr "" msgid "Help$Specify if green and yellow shall also be switched when pressing '0'." msgstr "" msgid "Show favorites menu" msgstr "" msgid "" "Help$A favorites menu can display a list of your favorite broadcasts. Enable this if you want an additional menu besides 'Now' and 'Next'\n" "Any search can be used as a favorite. You only have to set the option 'Use in favorites menu' when editing a search." msgstr "" msgid "for the next ... hours" msgstr "" msgid "Help$This value controls the timespan used to display your favorites." msgstr "" msgid "Use user-defined time" msgstr "" msgid "Help$Besides 'Now' and 'Next' you can specify up to 4 other times in the EPG which can be used by repeatedly pressing the green key, e.g. 'prime time', 'late night',..." msgstr "" msgid "Description" msgstr "" msgid "Help$This is the description for your user-defined time as it will appear as label on the green button." msgstr "" msgid "Time" msgstr "" msgid "Help$Specify the user-defined time here in 'HH:MM'." msgstr "" msgid "Use VDR's timer edit menu" msgstr "" msgid "" "Help$This plugin has its own timer edit menu extending the original one with some extra functionality like\n" "- an additional directory entry\n" "- user-defined days of week for repeating timers\n" "- adding an episode name\n" "- support for EPG variables (see MANUAL)" msgstr "" msgid "Default recording dir" msgstr "" msgid "Help$When creating a timer you can specify here a default recording directory." msgstr "" msgid "Add episode to manual timers" msgstr "" msgid "" "Help$If you create a timer for a series, you can automatically add the episode name.\n" "\n" "- never: no addition\n" "- always: always add episode name if present\n" "- smart: add only if event lasts less than 80 mins." msgstr "" msgid "Default timer check method" msgstr "" msgid "" "Help$Manual timers can be checked for EPG changes. Here you can setup the default check method for each channel. Choose between\n" "\n" "- no checking\n" "- by event ID: checks by an event ID supplied by the channel provider.\n" "- by channel and time: check by the duration match." msgstr "" msgid "Button$Setup" msgstr "Configurar" msgid "Use search timers" msgstr "" msgid "Help$'Search timers' can be used to automatically create timers for events that match your search criterions." msgstr "" msgid " Update interval [min]" msgstr "" msgid "Help$Specify here the time intervall to be used when searching for events in the background." msgstr "" msgid " SVDRP port" msgstr "" msgid "Help$Programming of new timers or timer changes is done with SVDRP. The default value should be correct, so change it only if you know what you are doing." msgstr "" msgid "Help$Specify here the default priority of timers created with this plugin. This value can also be adjusted for each search itself." msgstr "" msgid "Help$Specify here the default lifetime of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "" msgid "Help$Specify here the default start recording margin of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "" msgid "Help$Specify here the default stop recording margin of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "" msgid "No announcements when replaying" msgstr "" msgid "Help$Set this to 'yes' if you don't like to get any announcements of broadcasts if you currently replay anything." msgstr "" msgid "Recreate timers after deletion" msgstr "" msgid "Help$Set this to 'yes' if you want timers to be recreated with the next search timer update after deleting them." msgstr "" msgid "Check if EPG exists for ... [h]" msgstr "" msgid "Help$Specify how many hours of future EPG there should be and get warned else after a search timer update." msgstr "" msgid "Warn by OSD" msgstr "" msgid "Help$Set this to 'yes' if you want get warnings from the EPG check via OSD." msgstr "" msgid "Warn by mail" msgstr "" msgid "Help$Set this to 'yes' if you want get warnings from the EPG check by mail." msgstr "" msgid "Channel group to check" msgstr "" msgid "Help$Specify the channel group to check." msgstr "" msgid "Ignore PayTV channels" msgstr "" msgid "Help$Set this to 'yes' if don't want to see events on PayTV channels when searching for repeats." msgstr "" msgid "Search templates" msgstr "" msgid "Help$Here you can setup templates for your searches." msgstr "" msgid "Blacklists" msgstr "" msgid "Help$Here you can setup blacklists which can be used within a search to exclude events you don't like." msgstr "" msgid "Help$Here you can setup channel groups which can be used within a search. These are different to VDR channel groups and represent a set of arbitrary channels, e.g. 'FreeTV'." msgstr "" msgid "Ignore below priority" msgstr "" msgid "Help$If a timer with priority below the given value will fail it will not be classified as important. Only important conflicts will produce an OSD message about the conflict after an automatic conflict check." msgstr "Lorsqu'une programmation dont la prioritée est en dessous de la valeur définie, n'aboutit pas, alors elle est qualifiée de 'non-importante'. Seulement les conflits importants sont affichés à l'écran lors de la vérification automatique." msgid "Ignore conflict duration less ... min." msgstr "" msgid "Help$If a conflicts duration is less then the given number of minutes it will not be classified as important. Only important conflicts will produce an OSD message about the conflict after an automatic conflict check." msgstr "" msgid "Only check within next ... days" msgstr "" msgid "Help$This value reduces the conflict check to the given range of days. All other conflicts are classified as 'not yet important'." msgstr "" msgid "Check also remote conflicts" msgstr "" msgid "Help$Set this to 'yes' if the conflict check should be done for timers set on remote hosts. This needs SVDRPPeering to be set in vdr and Plugin epgsearch running on the remote host." msgstr "" msgid "--- Automatic checking ---" msgstr "" msgid "After each timer programming" msgstr "" msgid "Help$Set this to 'yes' if the conflict check should be performed after each manual timer programming. In the case of a conflict you get immediately a message that informs you about it. The message is only displayed if this timer is involved in any conflict." msgstr "" msgid "When a recording starts" msgstr "" msgid "Help$Set this to 'yes' if the conflict check should be performed when a recording starts. In the case of a conflict you get immediately a message that informs you about it. The message is only displayed if the conflict is within the next 2 hours." msgstr "" msgid "After each search timer update" msgstr "" msgid "Help$Set this to 'yes' if the conflict check should be performed after each search timer update." msgstr "" msgid "every ... minutes" msgstr "" msgid "" "Help$Specify here the time intervall to be used for an automatic conflict check in the background.\n" "('0' disables an automatic check)" msgstr "" msgid "if conflicts within next ... minutes" msgstr "" msgid "Help$If the next conflict will appear in the given number of minutes you can specify here a shorter check intervall to get more OSD notifications about it." msgstr "" msgid "Avoid notification when replaying" msgstr "" msgid "Help$Set this to 'yes' if the don't want to get OSD messages about conflicts if you currently replay something. Nevertheless messages will be displayed if the first upcoming conflict is within the next 2 hours." msgstr "" msgid "Search timer notification" msgstr "" msgid "Help$Set this to 'yes' if you want to get an email notification about the search timers that where programmed automatically in the background." msgstr "" msgid "Time between mails [h]" msgstr "" msgid "" "Help$Specifiy how much time in [h] you would\n" "like to have atleast between two mails.\n" "With '0' you get a new mail after each\n" "search timer update with new results." msgstr "" msgid "Timer conflict notification" msgstr "" msgid "Help$Set this to 'yes' if you want to get an email notification about the timer conflicts." msgstr "" msgid "Send to" msgstr "" msgid "Help$Specify the email address where notifications should be sent to." msgstr "" msgid "Mail method" msgstr "" msgid "" "Help$Specify here the method to use when sending mails.\n" "You can choose between\n" " - 'sendmail': requires a properly configured email system\n" " - 'SendEmail.pl': simple script for mail delivery" msgstr "" msgid "--- Email account ---" msgstr "" msgid "Email address" msgstr "" msgid "Help$Specify the email address where notifications should be sent from." msgstr "" msgid "SMTP server" msgstr "" msgid "Help$Specify the SMTP server that should deliver the notifications. If it's using a port different from the default(25) append the port with \":port\"." msgstr "" msgid "Use SMTP authentication" msgstr "" msgid "Help$Set this to 'yes' if your account needs authentication to send mails." msgstr "" msgid "Auth user" msgstr "" msgid "Help$Specify the auth user, if this account needs authentication for SMTP." msgstr "" msgid "Auth password" msgstr "" msgid "Help$Specify the auth password, if this account needs authentication for SMTP." msgstr "" msgid "Mail account check failed!" msgstr "" msgid "Button$Test" msgstr "" msgid "$ abcdefghijklmnopqrstuvwxyz0123456789-.,#~\\^$[]|()*+?{}/:%@&_" msgstr "" msgid "Start/Stop time has changed" msgstr "" msgid "Title/episode has changed" msgstr "" msgid "No new timers were added." msgstr "" msgid "No timers were modified." msgstr "" msgid "No timers were deleted." msgstr "" msgid "No new events to announce." msgstr "" msgid "This version of EPGSearch does not support this service!" msgstr "" msgid "EPGSearch does not exist!" msgstr "" #, c-format msgid "%d new broadcast" msgstr "" msgid "Button$by channel" msgstr "" msgid "Button$by time" msgstr "" msgid "Button$Episode" msgstr "" msgid "Button$Title" msgstr "" msgid "announce details" msgstr "" msgid "announce again" msgstr "" msgid "with next update" msgstr "" msgid "again from" msgstr "" msgid "Search timer" msgstr "" msgid "Edit blacklist" msgstr "" msgid "phrase" msgstr "" msgid "all words" msgstr "" msgid "at least one word" msgstr "" msgid "match exactly" msgstr "" msgid "regular expression" msgstr "" msgid "fuzzy" msgstr "" msgid "user-defined" msgstr "" msgid "interval" msgstr "" msgid "channel group" msgstr "" msgid "only FTA" msgstr "" msgid "Search term" msgstr "" msgid "Search mode" msgstr "" msgid "Tolerance" msgstr "" msgid "Match case" msgstr "" msgid "Use title" msgstr "" msgid "Use subtitle" msgstr "" msgid "Use description" msgstr "" msgid "Use extended EPG info" msgstr "" msgid "Ignore missing categories" msgstr "" msgid "Use channel" msgstr "" msgid " from channel" msgstr "" msgid " to channel" msgstr "" msgid "Channel group" msgstr "" msgid "Use time" msgstr "" msgid " Start after" msgstr "" msgid " Start before" msgstr "" msgid "Use duration" msgstr "" msgid " Min. duration" msgstr "" msgid " Max. duration" msgstr "" msgid "Use day of week" msgstr "" msgid "Day of week" msgstr "" msgid "Use global" msgstr "" msgid "Button$Templates" msgstr "" msgid "*** Invalid Channel ***" msgstr "" msgid "Please check channel criteria!" msgstr "" msgid "Edit$Delete blacklist?" msgstr "" msgid "Repeats" msgstr "" msgid "Create search" msgstr "" msgid "Search in recordings" msgstr "" msgid "Mark as 'already recorded'?" msgstr "" msgid "Add/Remove to/from switch list?" msgstr "" msgid "Create blacklist" msgstr "" msgid "EPG Commands" msgstr "" msgid "Epgsearch: RemoteTimerModifications failed" msgstr "" msgid "Already running!" msgstr "" msgid "Add to switch list?" msgstr "" msgid "Delete from switch list?" msgstr "" msgid "Button$Details" msgstr "" msgid "Button$Filter" msgstr "Filtre" msgid "Button$Show all" msgstr "" msgid "conflicts" msgstr "" msgid "no conflicts!" msgstr "" msgid "no important conflicts!" msgstr "" msgid "C" msgstr "C" msgid "Button$Repeats" msgstr "" msgid "no check" msgstr "" msgid "by channel and time" msgstr "" msgid "by event ID" msgstr "" msgid "Select directory" msgstr "" msgid "Button$Level" msgstr "" msgid "Event" msgstr "" msgid "Favorites" msgstr "" msgid "Search results" msgstr "" msgid "Timer conflict! Show?" msgstr "" msgid "Directory" msgstr "" msgid "Channel" msgstr "" msgid "Childlock" msgstr "" msgid "Record on" msgstr "" msgid "Timer check" msgstr "" msgid "recording with device" msgstr "" msgid "Button$With subtitle" msgstr "" msgid "Button$Without subtitle" msgstr "" msgid "Timer has been deleted" msgstr "" msgid "Button$Extended" msgstr "" msgid "Button$Simple" msgstr "" msgid "Use blacklists" msgstr "" msgid "Edit$Search text too short - use anyway?" msgstr "" msgid "Button$Orphaned" msgstr "" msgid "Button$by name" msgstr "" msgid "Button$by date" msgstr "" msgid "Button$Delete all" msgstr "" msgid "Recordings" msgstr "" msgid "Edit$Delete entry?" msgstr "" msgid "Edit$Delete all entries?" msgstr "" msgid "Summary" msgstr "" msgid "Auxiliary info" msgstr "" msgid "Button$Aux info" msgstr "" msgid "Search actions" msgstr "" msgid "Execute search" msgstr "" msgid "Use as search timer on/off" msgstr "" msgid "Trigger search timer update" msgstr "" msgid "Show recordings done" msgstr "" msgid "Show timers created" msgstr "" msgid "Create a copy" msgstr "" msgid "Use as template" msgstr "" msgid "Show switch list" msgstr "" msgid "Show blacklists" msgstr "" msgid "Delete created timers?" msgstr "" msgid "Timer conflict check" msgstr "" msgid "Disable associated timers too?" msgstr "" msgid "Activate associated timers too?" msgstr "" msgid "Search timers activated in setup." msgstr "" msgid "Run search timer update?" msgstr "" msgid "Copy this entry?" msgstr "" msgid "Copy" msgstr "" msgid "Copy this entry to templates?" msgstr "" msgid "Delete all timers created from this search?" msgstr "" msgid "Button$Actions" msgstr "" msgid "Search entries" msgstr "" msgid "active" msgstr "" msgid "Edit$Delete search?" msgstr "" msgid "Edit search" msgstr "" msgid "Record" msgstr "Gravar" msgid "Announce by OSD" msgstr "" msgid "Switch only" msgstr "" msgid "Announce and switch" msgstr "" msgid "Announce by mail" msgstr "" msgid "Inactive record" msgstr "" msgid "only globals" msgstr "" msgid "Selection" msgstr "" msgid "all" msgstr "" msgid "count recordings" msgstr "" msgid "count days" msgstr "" msgid "if present" msgstr "" msgid "same day" msgstr "" msgid "same week" msgstr "" msgid "same month" msgstr "" msgid "Template name" msgstr "" msgid "Help$Specify the name of the template." msgstr "" msgid "Help$Specify here the term to search for." msgstr "" msgid "" "Help$The following search modes exist:\n" "\n" "- phrase: searches for sub terms\n" "- all words: all single words must appear\n" "- at least one word: at least one single word must appear\n" "- match exactly: must match exactly\n" "- regular expression: match a regular expression\n" "- fuzzy searching: searches approximately" msgstr "" msgid "Help$This sets the tolerance of fuzzy searching. The value represents the allowed errors." msgstr "" msgid "Help$Set this to 'Yes' if your search should match the case." msgstr "" msgid "Help$Set this to 'Yes' if you like to search in the title of an event." msgstr "" msgid "Help$Set this to 'Yes' if you like to search in the episode of an event." msgstr "" msgid "Help$Set this to 'Yes' if you like to search in the summary of an event." msgstr "" msgid "Use content descriptor" msgstr "" msgid "Help$Set this to 'Yes' if you want to search the contents by a descriptor." msgstr "" msgid "Help$The summary of an event, can contain additional information like 'Genre', 'Category', 'Year',... called 'EPG categories' within EPGSearch. External EPG providers often deliver this information. This allows refining a search and other nice things, like searching for the 'tip of the day'. To use it set this to 'Yes'." msgstr "" msgid "Help$The file epgsearchcats.conf specifies the search mode for this entry. One can search by text or by value. You can also edit a list of predefined values in this file that can be selected here." msgstr "" msgid "Help$If a selected category is not part of the summary of an event this normally excludes this event from the search results. To avoid this, set this option to 'Yes', but please handle this with care to avoid a huge amount of results." msgstr "" msgid "Use in favorites menu" msgstr "" msgid "Result menu layout" msgstr "" msgid "Use as search timer" msgstr "" msgid "Action" msgstr "" msgid "Switch ... minutes before start" msgstr "" msgid "Unmute sound" msgstr "" msgid "Ask ... minutes before start" msgstr "" msgid " Series recording" msgstr "" msgid "Delete recordings after ... days" msgstr "" msgid "Keep ... recordings" msgstr "" msgid "Pause when ... recordings exist" msgstr "" msgid "Avoid repeats" msgstr "" msgid "Allowed repeats" msgstr "" msgid "Only repeats within ... days" msgstr "" msgid "Compare title" msgstr "" msgid "Compare subtitle" msgstr "" msgid "Compare summary" msgstr "" msgid "Min. match in %" msgstr "" msgid "Compare date" msgstr "" msgid "Compare categories" msgstr "" msgid "VPS" msgstr "" msgid "Auto delete" msgstr "" msgid "after ... recordings" msgstr "" msgid "after ... days after first rec." msgstr "" msgid "Edit user-defined days of week" msgstr "" msgid "Compare" msgstr "" msgid "Select blacklists" msgstr "" msgid "Values for EPG category" msgstr "" msgid "Button$Apply" msgstr "" msgid "less" msgstr "" msgid "less or equal" msgstr "" msgid "greater" msgstr "" msgid "greater or equal" msgstr "" msgid "equal" msgstr "" msgid "not equal" msgstr "" msgid "Activation of search timer" msgstr "" msgid "First day" msgstr "" msgid "Last day" msgstr "" msgid "Button$all channels" msgstr "" msgid "Button$only FTA" msgstr "" msgid "Button$Timer preview" msgstr "" msgid "Blacklist results" msgstr "" msgid "found recordings" msgstr "" msgid "Error while accessing recording!" msgstr "" msgid "Button$Default" msgstr "" msgid "Edit$Delete template?" msgstr "" msgid "Overwrite existing entries?" msgstr "" msgid "Edit entry" msgstr "" msgid "Switch" msgstr "" msgid "Announce only" msgstr "" msgid "Announce ... minutes before start" msgstr "" msgid "action at" msgstr "" msgid "Switch list" msgstr "" msgid "Edit template" msgstr "" msgid "Timers" msgstr "" msgid ">>> no info! <<<" msgstr "" msgid "Overview" msgstr "" msgid "Button$Favorites" msgstr "" msgid "Quick search for broadcasts" msgstr "" msgid "Quick search" msgstr "" msgid "Show in main menu" msgstr "" #, c-format msgid "%d new broadcast(s) found! Show them?" msgstr "" msgid "Search timer update done!" msgstr "" #, c-format msgid "small EPG content on:%s" msgstr "" msgid "VDR EPG check warning" msgstr "" #, c-format msgid "Switch to (%d) '%s'?" msgstr "" msgid "Programming timer failed!" msgstr "" vdr-plugin-epgsearch/po/fi_FI.po0000644000175000017500000011744513145412721016376 0ustar tobiastobias# VDR plugin language source file. # Copyright (C) 2007 Klaus Schmidinger # This file is distributed under the same license as the VDR package. # Rolf Ahrenberg , 2003-2011 # Ville Skyttä , 2009, 2011 # msgid "" msgstr "" "Project-Id-Version: EPGSearch 0.9.25\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-06-15 11:15+0200\n" "PO-Revision-Date: 2011-01-04 21:07+0200\n" "Last-Translator: Ville Skyttä \n" "Language-Team: Finnish \n" "Language: fi\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Lokalize 1.1\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgid "Channel groups" msgstr "Kanavaryhmät" msgid "Button$Select" msgstr "Valitse" msgid "Channel group used by:" msgstr "Kanavaryhmä käytössä:" msgid "Edit$Delete group?" msgstr "Poistetaanko kanavaryhmä?" msgid "Edit channel group" msgstr "Muokkaa kanavaryhmää" msgid "Group name" msgstr "Kanavaryhmän nimi" msgid "Button$Invert selection" msgstr "Päinvastoin" msgid "Button$All yes" msgstr "Kaikki" msgid "Button$All no" msgstr "Ei yhtään" msgid "Group name is empty!" msgstr "Kanavaryhmältä puuttuu nimi!" msgid "Group name already exists!" msgstr "Samanniminen kanavaryhmä on jo olemassa!" msgid "Direct access to epgsearch's conflict check menu" msgstr "Suoratoiminto EPGSearch-laajennoksen ajastimien tarkistukselle" msgid "Timer conflicts" msgstr "Päällekkäiset ajastimet" msgid "Conflict info in main menu" msgstr "Näytä päällekkäisyydet päävalikossa" msgid "next" msgstr "seuraava" #, c-format msgid "timer conflict at %s! Show it?" msgstr "Päällekkäinen ajastin (%s)! Näytetäänkö?" #, c-format msgid "%d timer conflicts! First at %s. Show them?" msgstr "Päällekkäisiä ajastimia %d kpl (%s)! Näytetäänkö?" msgid "search the EPG for repeats and more" msgstr "Monipuolinen ohjelmaopas hakutoiminnolla" msgid "Program guide" msgstr "Ohjelmaopas" msgid "search timer update running" msgstr "hakuajastimien päivitys käynnissä" msgid "Direct access to epgsearch's search menu" msgstr "Suoratoiminto EPGSearch-laajennoksen haulle" msgid "Search" msgstr "Etsi ohjelmaoppaasta" msgid "EpgSearch-Search in main menu" msgstr "EpgSearch-laajennoksen hakutoiminto päävalikossa" msgid "Button$Help" msgstr "Opaste" msgid "Standard" msgstr "Vakio" msgid "Button$Commands" msgstr "Komennot" msgid "Button$Search" msgstr "Etsi" msgid "never" msgstr "ei koskaan" msgid "always" msgstr "aina" msgid "smart" msgstr "älykkäästi" msgid "before user-def. times" msgstr "ennen ajankohtia" msgid "after user-def. times" msgstr "ajankohtien jälkeen" msgid "before 'next'" msgstr "ennen seuraavia" msgid "General" msgstr "Yleiset" msgid "EPG menus" msgstr "Valikot" msgid "User-defined EPG times" msgstr "Käyttäjän määrittelemät ajankohdat" msgid "Timer programming" msgstr "Ajastimien luonti" msgid "Search and search timers" msgstr "Haut ja hakuajastimet" msgid "Timer conflict checking" msgstr "Päällekkäisten ajastimien tarkistus" msgid "Email notification" msgstr "Ilmoitukset sähköpostilla" msgid "Hide main menu entry" msgstr "Piilota valinta päävalikosta" msgid "Help$Hides the main menu entry and may be useful if this plugin is used to replace the original 'Schedule' entry." msgstr "Piilottaa valinnan päävalikosta. Suositellaan asetettavaksi päälle, jos laajennoksella korvataan alkuperäinen ohjelmaopas." msgid "Main menu entry" msgstr "Valinta päävalikossa" msgid "Help$The name of the main menu entry which defaults to 'Programm guide'." msgstr "Päävalikossa sijaitsevan valinnan nimi, joka on oletuksena 'Ohjelmaopas'." msgid "Replace original schedule" msgstr "Korvaa alkuperäinen ohjelmaopas" msgid "Help$When VDR is patched to allow this plugin to replace the original 'Schedule' entry, you can de/activate this replacement here." msgstr "Korvaa alkuperäisen ohjelmaoppaan päävalikossa tällä laajennoksella, jos VDR on paikattu asianmukaisesti." msgid "Start menu" msgstr "Oletusnäyttö" msgid "Help$Choose between 'Overview - Now' and 'Schedule' as start menu when this plugin is called." msgstr "Valitsee oletusnäytöksi joko tämänhetkisen yleiskatsauksen tai valitun kanavan ohjelmiston." msgid "Ok key" msgstr "OK-näppäin" msgid "" "Help$Choose here the behaviour of key 'Ok'. You can use it to display the summary or to switch to the corresponding channel.\n" "Note: the functionality of key 'blue' (Switch/Info/Search) depends on this setting." msgstr "" "Valitse toiminto OK-näppäimelle: näytä ohjelman tiedot tai vaihda kyseiselle kanavalle.\n" "Huomioi: sinisen näppäimen toiminto (Vaihda/Tiedot/Hae) riippuu tästä asetuksesta." msgid "Red key" msgstr "Punainen näppäin" msgid "" "Help$Choose which standard function ('Record' or 'Commands') you like to have on the red key.\n" "(Can be toggled with key '0')" msgstr "" "Valitsee oletustoiminnon ('Tallenna' tai 'Komennot') punaiselle näppäimelle.\n" "Punaisen näppäimen toimintoa voidaan vaihtaa myös lennossa painamalla näppäintä 0." msgid "Blue key" msgstr "Sininen näppäin" msgid "" "Help$Choose which standard function ('Switch'/'Info' or 'Search') you like to have on the blue key.\n" "(Can be toggled with key '0')" msgstr "" "Valitsee oletustoiminnon ('Valitse' tai 'Etsi') siniselle näppäimelle.\n" "Sinisen näppäimen toimintoa voidaan vaihtaa myös lennossa painamalla näppäintä 0." msgid "Show progress in 'Now'" msgstr "Näytä aikajana 'Nyt'-sivulla" msgid "Help$Shows a progressbar in 'Overview - Now' that informs about the remaining time of the current event." msgstr "Näyttää aikajanan tämänhetkisessä yleiskatsauksessa." msgid "Show channel numbers" msgstr "Näytä kanavien numerointi" msgid "" "Help$Display channel numbers in 'Overview - Now'.\n" "\n" "(To completely define your own menu look please inspect the MANUAL)" msgstr "" "Näyttää kanavien numeroinnin tämänhetkisessä yleiskatsauksessa.\n" "\n" "Lisätietoja valikon muokkauksesta löytyy MANUAL-tiedostosta." msgid "Show channel separators" msgstr "Näytä kanavaerottimet" msgid "Help$Display VDR channel groups as separators between your channels in 'Overview - Now'." msgstr "Näyttää erottimet yleiskatsauksessa kanaville." msgid "Show day separators" msgstr "Näytä päiväerottimet" msgid "Help$Display a separator line at day break in 'Schedule'." msgstr "Näyttää erottimet ohjelmistossa päivän vaihtuessa." msgid "Show radio channels" msgstr "Näytä radiokanavat" msgid "Help$Show also radio channels." msgstr "Näyttää myös radiokanavat listauksessa." msgid "Limit channels from 1 to" msgstr "Näytettävien kanavien rajoitus" msgid "Help$If you have a large channel set you can speed up things when you limit the displayed channels with this setting. Use '0' to disable the limit." msgstr "Voit nopeuttaa toimintoja rajoittamalla näytettävien kanavien lukumäärää tällä asetuksella. Poistat rajoituksen asettamalla arvoksi nollan." msgid "'One press' timer creation" msgstr "Luo ajastimet yhdellä painalluksella" msgid "Help$When a timer is created with 'Record' you can choose between an immediate creation of the timer or the display of the timer edit menu." msgstr "Valitsee oletustoiminnon ajastimen luonnille. Voit luoda ajastimen joko automaattisesti yhdellä painalluksella tai vaihtoehtoisesti avata ajastinvalikon." msgid "Show channels without EPG" msgstr "Näytä ohjelmaoppaattomat kanavat" msgid "Help$Choose 'yes' here if you want to display channels without EPG in 'Overview - Now'. 'Ok' on these entries switches the channel." msgstr "Näyttää tämänhetkisessä yleiskatsauksessa myöskin kanavat, joilta ei löydy ohjelmatietoja. Voit vaihtaa tällaiselle kanavalle OK-näppäimellä." msgid "Time interval for FRew/FFwd [min]" msgstr "Oletusaikasiirtymä [min]" msgid "" "Help$Choose here the time interval which should be used for jumping through the EPG by pressing FRew/FFwd.\n" "\n" "(If you don't have those keys, you can toggle to this functionality pressing '0' and get '<<' and '>>' on the keys green and yellow)" msgstr "" "Valitsee ohjelmaoppaan oletusaikasiirtymän pikakelausnäppäimille.\n" "\n" "Jos sinulla ei ole kyseisiä näppäimiä käytössäsi, voit asettaa kyseiset toiminnot vihreälle ja keltaiselle näppäimelle painamalla näppäintä 0." msgid "Toggle Green/Yellow" msgstr "Käytä aikasiirtymää värinäppäimillä" msgid "Help$Specify if green and yellow shall also be switched when pressing '0'." msgstr "Määrittelee vaihdetaanko vihreän ja keltaisen näppäimen toimintoja painamalla näppäintä 0." msgid "Show favorites menu" msgstr "Näytä suosikkivalikko" msgid "" "Help$A favorites menu can display a list of your favorite broadcasts. Enable this if you want an additional menu besides 'Now' and 'Next'\n" "Any search can be used as a favorite. You only have to set the option 'Use in favorites menu' when editing a search." msgstr "" "Suosikkivalikossa listataan suosikiksi merkityt ohjelmat. Jos tämä valinta on aktiivinen, suosikkivalikko löytyy 'Nyt'- ja 'Seuraavaksi'-valikkojen rinnalta. \n" "Mikä tahansa haku voidaan merkitä suosikiksi aktivoimalla 'Käytä suosikkina'-valinta." msgid "for the next ... hours" msgstr "seuraaville ... tunnille" msgid "Help$This value controls the timespan used to display your favorites." msgstr "Tämä arvo määrittelee käytetyn ajanjakson suosikkien näyttämiselle." msgid "Use user-defined time" msgstr "Määrittele ajankohta" msgid "Help$Besides 'Now' and 'Next' you can specify up to 4 other times in the EPG which can be used by repeatedly pressing the green key, e.g. 'prime time', 'late night',..." msgstr "Määrittelee käyttäjän muokattavissa olevat ajankohdat 'Nyt' ja 'Seuraavaksi' näyttöjen rinnalle ohjelmaoppaan yleiskatsaukseen." msgid "Description" msgstr "Kuvaus" msgid "Help$This is the description for your user-defined time as it will appear as label on the green button." msgstr "Asettaa kuvauksen vihreään näppäimeen käyttäjän muokkaamalle ajankohdalle." msgid "Time" msgstr "Kellonaika" msgid "Help$Specify the user-defined time here in 'HH:MM'." msgstr "Asettaa kellonajan käyttäjän muokkaamalle ajankohdalle." msgid "Use VDR's timer edit menu" msgstr "Käytä alkuperäistä ajastinvalikkoa" msgid "" "Help$This plugin has its own timer edit menu extending the original one with some extra functionality like\n" "- an additional directory entry\n" "- user-defined days of week for repeating timers\n" "- adding an episode name\n" "- support for EPG variables (see MANUAL)" msgstr "" "Tällä laajennoksella on oma laajennettu ajastinvalikko mm. seuraavilla lisätoiminnoilla:\n" "\n" "- hakemiston määritys\n" "- vapaasti määriteltävät viikonpäivät toistuville ajastimille\n" "- jakson nimen täydennys\n" "- erilaisten EPG-muuttujien tuki (ks. MANUAL-tiedostosta)" msgid "Default recording dir" msgstr "Oletushakemisto tallenteille" msgid "Help$When creating a timer you can specify here a default recording directory." msgstr "Määrittelee oletushakemiston tallenteille." msgid "Add episode to manual timers" msgstr "Lisää jakson nimi norm. ajastimiin" msgid "" "Help$If you create a timer for a series, you can automatically add the episode name.\n" "\n" "- never: no addition\n" "- always: always add episode name if present\n" "- smart: add only if event lasts less than 80 mins." msgstr "" "Asettaa toiminnon sarjatallennuksen jakson nimen lisäykselle:\n" "\n" "- ei koskaan: ei lisätä\n" "- aina: lisätään aina, jos olemassa\n" "- älykkäästi: lisätään vain, jos tapahtuman kesto on alle 80 min" msgid "Default timer check method" msgstr "Oletustapa ajastimen valvonnalle" msgid "" "Help$Manual timers can be checked for EPG changes. Here you can setup the default check method for each channel. Choose between\n" "\n" "- no checking\n" "- by event ID: checks by an event ID supplied by the channel provider.\n" "- by channel and time: check by the duration match." msgstr "" "Käsinluotuja ajastimia voidaan valvoa ohjelmaoppaan muutoksia vasten. Voit asettaa oletustavan jokaista kanavaa kohden:\n" "\n" "- ei valvontaa\n" "- tapahtuman tunniste: ohjelmisto-oppaassa lähetettävän tunnisteen mukaan\n" "- kanava ja aika: tapahtuman keston ja ajankohdan mukaan" msgid "Button$Setup" msgstr "Asetukset" msgid "Use search timers" msgstr "Käytä hakuajastimia" msgid "Help$'Search timers' can be used to automatically create timers for events that match your search criterions." msgstr "Hakuajastimilla luodaan automaattisesti ajastimia hakuehtoihin sopiviin tapahtumiin." msgid " Update interval [min]" msgstr " Päivitysväli [min]" msgid "Help$Specify here the time intervall to be used when searching for events in the background." msgstr "Määrittelee päivitysvälin hakuajastimien taustapäivitykselle." msgid " SVDRP port" msgstr " SVDRP-portti" msgid "Help$Programming of new timers or timer changes is done with SVDRP. The default value should be correct, so change it only if you know what you are doing." msgstr "Uusien ajastimien luonti ja olemassa olevien muokkaus on toteutettu SVDRP-protokollan kautta. Suositellaan käytettävän vain oletusarvoa." msgid "Help$Specify here the default priority of timers created with this plugin. This value can also be adjusted for each search itself." msgstr "Määrittelee oletusprioriteetin tämän laajennoksen kautta luotaville ajastimille. Prioriteettia voidaan muokata ajastinkohtaisesti." msgid "Help$Specify here the default lifetime of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "Määrittelee oletuseliniän tämän laajennoksen kautta luotaville ajastimille. Elinaikaa voidaan muokata ajastinkohtaisesti." msgid "Help$Specify here the default start recording margin of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "Määrittelee oletusmarginaalin tallennuksen aloitukselle tämän laajennoksen kautta luotaville ajastimille. Marginaaleja voidaan muokata ajastinkohtaisesti." msgid "Help$Specify here the default stop recording margin of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "Määrittelee oletusmarginaalin tallennuksen lopetukselle tämän laajennoksen kautta luotaville ajastimille. Marginaaleja voidaan muokata ajastinkohtaisesti." msgid "No announcements when replaying" msgstr "Älä muistuta toiston aikana" msgid "Help$Set this to 'yes' if you don't like to get any announcements of broadcasts if you currently replay anything." msgstr "Laittamalla tämän asetuksen päälle et saa ohjelmista muistutuksia toistettaessa tallenteita." msgid "Recreate timers after deletion" msgstr "Luo ajastimet uudelleen" msgid "Help$Set this to 'yes' if you want timers to be recreated with the next search timer update after deleting them." msgstr "Laittamalla tämän asetuksen päälle saat luotua ajastimet uudelleen seuraava hakuajastin päivityksen yhteydessä, jos olet poistanut ne." msgid "Check if EPG exists for ... [h]" msgstr "Tarkasta tulevat ohjelmatiedot... [h]" msgid "Help$Specify how many hours of future EPG there should be and get warned else after a search timer update." msgstr "Määrittelee vaadittavat tulevat ohjelmatiedot tunteina hakuajastimien päivityksen yhteydessä, jonka jälkeen käyttäjää varoitetaan." msgid "Warn by OSD" msgstr "Muistuta kuvaruutunäytöllä" msgid "Help$Set this to 'yes' if you want get warnings from the EPG check via OSD." msgstr "Laittamalla tämän asetuksen päälle saat varoitukset ohjelmatietojen tarkastuksesta kuvaruutunäytölle." msgid "Warn by mail" msgstr "Muistuta sähköpostitse" msgid "Help$Set this to 'yes' if you want get warnings from the EPG check by mail." msgstr "Laittamalla tämän asetuksen päälle saat varoitukset ohjelmatietojen tarkastuksesta sähköpostitse." msgid "Channel group to check" msgstr "Tarkastettava kanavaryhmä" msgid "Help$Specify the channel group to check." msgstr "Määrittelee tarkastettavan kanavaryhmän." msgid "Ignore PayTV channels" msgstr "Jätä salatut kanavat huomioimatta" msgid "Help$Set this to 'yes' if don't want to see events on PayTV channels when searching for repeats." msgstr "Piilottaa salatut kanavat haettaessa uusintoja." msgid "Search templates" msgstr "Mallipohjat hakuehdoille" msgid "Help$Here you can setup templates for your searches." msgstr "Määrittele mallipohjia hakuehdoille." msgid "Blacklists" msgstr "Mustat listat" msgid "Help$Here you can setup blacklists which can be used within a search to exclude events you don't like." msgstr "Määrittele mustia listoja hakuehdoille. Mustien listojen tapahtumia ei näytetä hakutuloksissa." msgid "Help$Here you can setup channel groups which can be used within a search. These are different to VDR channel groups and represent a set of arbitrary channels, e.g. 'FreeTV'." msgstr "Määrittele kanavaryhmiä hakuehdoille. Tämän laajennoksen kanavaryhmät eivät ole yhteydessä VDR:n omiin kanavaryhmiin." msgid "Ignore below priority" msgstr "Sivuuta alhaisemmat prioriteetit" msgid "Help$If a timer with priority below the given value will fail it will not be classified as important. Only important conflicts will produce an OSD message about the conflict after an automatic conflict check." msgstr "Asetusarvoa korkeammalla prioriteetilla olevat ajastimet ovat merkitseviä. Vain merkitsevät päällekkäisyydet aiheuttavat viestin kuvaruutunäytölle automaattisen tarkistuksen yhteydessä." msgid "Ignore conflict duration less ... min." msgstr "Sivuuta alle ... min. päällekkäisyydet" msgid "Help$If a conflicts duration is less then the given number of minutes it will not be classified as important. Only important conflicts will produce an OSD message about the conflict after an automatic conflict check." msgstr "Jos ajastimien päällekkäisyys on alle asetetun minuuttimäärän, sitä ei pidetä merkitsevänä. Vain merkitsevät päällekkäisyydet aiheuttavat viestin kuvaruutunäytölle tarkistuksen yhteydessä." msgid "Only check within next ... days" msgstr "Tarkista vain seuraavat ... päivää" msgid "Help$This value reduces the conflict check to the given range of days. All other conflicts are classified as 'not yet important'." msgstr "Asettaa ajanjakson päivinä päällekkäisyyksien tarkistukselle. Muita päällekkäisyyksiä ei pidetä vielä merkitsevinä." msgid "Check also remote conflicts" msgstr "" msgid "Help$Set this to 'yes' if the conflict check should be done for timers set on remote hosts. This needs SVDRPPeering to be set in vdr and Plugin epgsearch running on the remote host." msgstr "" msgid "--- Automatic checking ---" msgstr "--- Automaattinen tarkistus ---" msgid "After each timer programming" msgstr "Jokaisen ajastimen luonnin jälkeen" msgid "Help$Set this to 'yes' if the conflict check should be performed after each manual timer programming. In the case of a conflict you get immediately a message that informs you about it. The message is only displayed if this timer is involved in any conflict." msgstr "Päällekkäisten ajastimien tarkistus suoritaan aina jokaisen ajastimen luonnin jälkeen. Jos luodulle ajastimelle löydetään päällekkäisyyksiä, niin siitä tiedotetaan käyttäjälle heti." msgid "When a recording starts" msgstr "Tallennuksen alkaessa" msgid "Help$Set this to 'yes' if the conflict check should be performed when a recording starts. In the case of a conflict you get immediately a message that informs you about it. The message is only displayed if the conflict is within the next 2 hours." msgstr "Päällekkäisten ajastimien tarkistus suoritaan aina tallennuksen alkaessa. Jos luodulle ajastimelle löydetään päällekkäisyyksiä seuraavan kahden tunnin aikana, niin siitä tiedotetaan käyttäjälle heti." msgid "After each search timer update" msgstr "Päivitettäessä hakuajastimia" msgid "Help$Set this to 'yes' if the conflict check should be performed after each search timer update." msgstr "Suorittaa päällekkäisyyksien tarkistuksen jokaisen hakuajastimen päivityksen yhteydessä." msgid "every ... minutes" msgstr "joka ... minuutti" msgid "" "Help$Specify here the time intervall to be used for an automatic conflict check in the background.\n" "('0' disables an automatic check)" msgstr "" "Määrittää aikajakson taustalla tehtävälle automaattiselle päällekkäisyyksien tarkistukselle.\n" "Arvolla '0' saat asetettua automaattisen tarkistuksen pois päältä" msgid "if conflicts within next ... minutes" msgstr "jos päällekkäisyys ... min. kuluessa" msgid "Help$If the next conflict will appear in the given number of minutes you can specify here a shorter check intervall to get more OSD notifications about it." msgstr "Jos seuraava päällekkäisyys esiintyy asetetun ajan kuluessa, tällä asetuksella pystyt määrittämään lyhyemmän tarkistusvälin saadaksesi tarkempia kuvaruutuviestejä." msgid "Avoid notification when replaying" msgstr "Älä näytä ilmoituksia toiston aikana" msgid "Help$Set this to 'yes' if the don't want to get OSD messages about conflicts if you currently replay something. Nevertheless messages will be displayed if the first upcoming conflict is within the next 2 hours." msgstr "Laittamalla tämän asetuksen päälle saat estettyä kuvaruutuviestit päällekkäisistä ajastimista toiston aikana. Kuvaruutuviesti näytetään kuitenkin aina, jos päällekkäinen ajastin on alle kahden tunnin kuluttua." msgid "Search timer notification" msgstr "Ilmoitukset hakuajastimista" msgid "Help$Set this to 'yes' if you want to get an email notification about the search timers that where programmed automatically in the background." msgstr "Tällä asetuksella saat ilmoitukset automaattisesti lisätyistä hakuajastimista sähköpostiisi." msgid "Time between mails [h]" msgstr "Sähköpostin lähetysväli [h]" msgid "" "Help$Specifiy how much time in [h] you would\n" "like to have atleast between two mails.\n" "With '0' you get a new mail after each\n" "search timer update with new results." msgstr "" "Vähimmäisväliaika tunteina sähköpostien\n" "lähetykselle. Mikäli 0, uusi sähköposti\n" "lähetetään aina hakuajastimen päivittyessä\n" "uusilla tuloksilla." msgid "Timer conflict notification" msgstr "Ilmoitukset päällekkäisistä ajastimista" msgid "Help$Set this to 'yes' if you want to get an email notification about the timer conflicts." msgstr "Tällä asetuksella saat ilmoitukset päällekkäisistä ajastimista sähköpostiisi." msgid "Send to" msgstr "Vastaanottaja" msgid "Help$Specify the email address where notifications should be sent to." msgstr "Määrittelee sähköpostiosoitteen, jonne ilmoitukset lähetetään." msgid "Mail method" msgstr "Lähetystapa" msgid "" "Help$Specify here the method to use when sending mails.\n" "You can choose between\n" " - 'sendmail': requires a properly configured email system\n" " - 'SendEmail.pl': simple script for mail delivery" msgstr "" "Määrittelee lähetystavan sähköposteille.\n" "Voit valita kahden vaihtoehdon väliltä:\n" " - 'sendmail': vaatii oikein konfiguroidun sähköpostisysteemin\n" " - 'SendEmail.pl': yksinkertainen skriptitiedosto sähköpostin lähetykseen" msgid "--- Email account ---" msgstr "--- Sähköposti ---" msgid "Email address" msgstr "Sähköpostiosoite" msgid "Help$Specify the email address where notifications should be sent from." msgstr "Määrittelee sähköpostiosoitteen, josta ilmoitukset lähetetään." msgid "SMTP server" msgstr "SMTP-palvelin" msgid "Help$Specify the SMTP server that should deliver the notifications. If it's using a port different from the default(25) append the port with \":port\"." msgstr "Määrittelee käytettävän SMTP-palvelimen. Portti voidaan määritellä erikseen lisäämällä palvelimen osoitteen loppuun \":portti\", jos se eroaa oletuksesta (25)." msgid "Use SMTP authentication" msgstr "Käytä SMTP-autentikointia" msgid "Help$Set this to 'yes' if your account needs authentication to send mails." msgstr "Asettaa SMTP-autentikoinnin päälle sähköpostin lähetystä varten." msgid "Auth user" msgstr "SMTP-käyttäjätunnus" msgid "Help$Specify the auth user, if this account needs authentication for SMTP." msgstr "Määrittelee käyttäjätunnuksen, jos SMTP-palvelimelle pitää autentikoitua." msgid "Auth password" msgstr "SMTP-salasana" msgid "Help$Specify the auth password, if this account needs authentication for SMTP." msgstr "Määrittelee salasanan, jos SMTP-palvelimelle pitää autentikoitua." msgid "Mail account check failed!" msgstr "Sähköpostilaatikon tarkistus epäonnistui!" msgid "Button$Test" msgstr "Testaa" msgid "$ abcdefghijklmnopqrstuvwxyz0123456789-.,#~\\^$[]|()*+?{}/:%@&_" msgstr " abcdefghijklmnopqrstuvwxyzåäö0123456789-.,#~\\^$[]|()*+?{}/:%@&" msgid "Start/Stop time has changed" msgstr "Ohjelman aloitus/lopetusaika muuttunut" msgid "Title/episode has changed" msgstr "Ohjelman nimi/kuvaus muuttunut" msgid "No new timers were added." msgstr "Yhtään uutta ajastinta ei lisätty." msgid "No timers were modified." msgstr "Yhtään ajastinta ei muokattu." msgid "No timers were deleted." msgstr "Yhtään ajastinta ei poistettu." msgid "No new events to announce." msgstr "Ei uusia ilmoitettavia tapahtumia." msgid "This version of EPGSearch does not support this service!" msgstr "EPGSearch-laajennos ei tarjoa vaadittavaa palvelua!" msgid "EPGSearch does not exist!" msgstr "EPGSearch-laajennosta ei löydy!" #, c-format msgid "%d new broadcast" msgstr "%d uutta lähetystä" msgid "Button$by channel" msgstr "Kanavat" msgid "Button$by time" msgstr "Kellonajat" msgid "Button$Episode" msgstr "Jaksot" msgid "Button$Title" msgstr "Nimet" msgid "announce details" msgstr "Muistutuksen tiedot" msgid "announce again" msgstr "Muistuta uudelleen" msgid "with next update" msgstr "Seuraavassa päivityksessä" msgid "again from" msgstr "Alkaen taas" msgid "Search timer" msgstr "Hakuajastin" msgid "Edit blacklist" msgstr "Muokkaa mustaa listaa" msgid "phrase" msgstr "fraasi" msgid "all words" msgstr "kaikki sanat" msgid "at least one word" msgstr "yksi sana" msgid "match exactly" msgstr "täsmällinen" msgid "regular expression" msgstr "säännöllinen lauseke" msgid "fuzzy" msgstr "sumea" msgid "user-defined" msgstr "valitut" msgid "interval" msgstr "kyllä" msgid "channel group" msgstr "kanavaryhmä" msgid "only FTA" msgstr "vapaat kanavat" msgid "Search term" msgstr "Hakutermi" msgid "Search mode" msgstr "Hakutapa" msgid "Tolerance" msgstr "Toleranssi" msgid "Match case" msgstr "Huomioi kirjainkoko" msgid "Use title" msgstr "Käytä ohjelmanimeä" msgid "Use subtitle" msgstr "Käytä lyhyttä ohjelmakuvausta" msgid "Use description" msgstr "Käytä ohjelmakuvausta" msgid "Use extended EPG info" msgstr "Käytä laajennettua ohjelmaopasta" msgid "Ignore missing categories" msgstr "Jätä puuttuvat kategoriat huomioimatta" msgid "Use channel" msgstr "Käytä kanavaa" msgid " from channel" msgstr " Kanavasta" msgid " to channel" msgstr " Kanavaan" msgid "Channel group" msgstr "Kanavaryhmä" msgid "Use time" msgstr "Käytä aloitusaikaa" msgid " Start after" msgstr " Aloitusaika aikaisintaan" msgid " Start before" msgstr " Aloitusaika viimeistään" msgid "Use duration" msgstr "Käytä kestoaikaa" msgid " Min. duration" msgstr " Kestoaika vähintään" msgid " Max. duration" msgstr " Kestoaika enintään" msgid "Use day of week" msgstr "Käytä viikonpäivää" msgid "Day of week" msgstr "Viikonpäivä" msgid "Use global" msgstr "Käytä globaalina" msgid "Button$Templates" msgstr "Mallipohjat" msgid "*** Invalid Channel ***" msgstr "*** Virheellinen kanavavalinta ***" msgid "Please check channel criteria!" msgstr "Tarkasta hakuehdot!" msgid "Edit$Delete blacklist?" msgstr "Poistetaanko musta lista?" msgid "Repeats" msgstr "Toistuvat" msgid "Create search" msgstr "Luo haku" msgid "Search in recordings" msgstr "Etsi tallenteista" msgid "Mark as 'already recorded'?" msgstr "Merkitse tallennetuksi" msgid "Add/Remove to/from switch list?" msgstr "Lisää/poista kanavanvaihtolistalle" msgid "Create blacklist" msgstr "Lisää mustalle listalle" msgid "EPG Commands" msgstr "Komennot" msgid "Epgsearch: RemoteTimerModifications failed" msgstr "" msgid "Already running!" msgstr "Nyt menossa!" msgid "Add to switch list?" msgstr "Lisätäänkö kanavanvaihtolistalle?" msgid "Delete from switch list?" msgstr "Poistetaanko kanavanvaihtolistalta?" msgid "Button$Details" msgstr "Lisätiedot" msgid "Button$Filter" msgstr "Suodata" msgid "Button$Show all" msgstr "Näytä kaikki" msgid "conflicts" msgstr "päällekkäisyyttä" msgid "no conflicts!" msgstr "ei päällekkäisyyksiä!" msgid "no important conflicts!" msgstr "ei merkitseviä päällekkäisyyksiä!" msgid "C" msgstr "C" msgid "Button$Repeats" msgstr "Toistuvat" msgid "no check" msgstr "ei valvontaa" msgid "by channel and time" msgstr "kanava ja aika" msgid "by event ID" msgstr "tapahtuman tunniste" msgid "Select directory" msgstr "Valitse hakemisto" msgid "Button$Level" msgstr "Taso" msgid "Event" msgstr "Tapahtuma" msgid "Favorites" msgstr "Suosikit" msgid "Search results" msgstr "Hakutulokset" msgid "Timer conflict! Show?" msgstr "Päällekkäisiä ajastimia! Näytetäänkö?" msgid "Directory" msgstr "Hakemisto" msgid "Channel" msgstr "Kanava" msgid "Childlock" msgstr "Lapsilukko" msgid "Record on" msgstr "" msgid "Timer check" msgstr "Valvontatapa" msgid "recording with device" msgstr "Tallennetaan laitteella" msgid "Button$With subtitle" msgstr "Kuvaus" msgid "Button$Without subtitle" msgstr "Ei kuvausta" msgid "Timer has been deleted" msgstr "Ajastin on poistettu!" msgid "Button$Extended" msgstr "Laaja" msgid "Button$Simple" msgstr "Suppea" msgid "Use blacklists" msgstr "Käytä mustia listoja" msgid "Edit$Search text too short - use anyway?" msgstr "Liian suppea hakuehto - etsitäänkö silti?" msgid "Button$Orphaned" msgstr "Orvot" msgid "Button$by name" msgstr "Nimi" msgid "Button$by date" msgstr "Päivämäärä" msgid "Button$Delete all" msgstr "Poista kaikki" msgid "Recordings" msgstr "Tallenteet" msgid "Edit$Delete entry?" msgstr "Poista hakutermi" msgid "Edit$Delete all entries?" msgstr "Poista kaikki hakutermit" msgid "Summary" msgstr "Yhteenveto" msgid "Auxiliary info" msgstr "Lisätiedot" msgid "Button$Aux info" msgstr "Lisätiedot" msgid "Search actions" msgstr "Hakukomennot" msgid "Execute search" msgstr "Suorita haku" msgid "Use as search timer on/off" msgstr "Aseta/poista hakuajastintoiminto" msgid "Trigger search timer update" msgstr "Päivitä hakuajastimet" msgid "Show recordings done" msgstr "Näytä tehdyt tallennukset" msgid "Show timers created" msgstr "Näytä luodut ajastimet" msgid "Create a copy" msgstr "Kopioi" msgid "Use as template" msgstr "Käytä mallipohjana" msgid "Show switch list" msgstr "Näytä kanavanvaihtolista" msgid "Show blacklists" msgstr "Näytä mustat listat" msgid "Delete created timers?" msgstr "Poista haulla luodut ajastimet" msgid "Timer conflict check" msgstr "Tarkista päällekkäiset ajastimet" msgid "Disable associated timers too?" msgstr "Poistetaanko käytöstä myös assosioidut ajastimet?" msgid "Activate associated timers too?" msgstr "Otetaanko käyttöön myös assosioidut ajastimet?" msgid "Search timers activated in setup." msgstr "Hakuajastimet aktivoitu asetuksista" msgid "Run search timer update?" msgstr "Päivitetäänkö hakuajastimet?" msgid "Copy this entry?" msgstr "Kopioidaanko tämä hakuajastin?" msgid "Copy" msgstr "Kopio" msgid "Copy this entry to templates?" msgstr "Kopioidaanko hakutermi mallipohjaksi?" msgid "Delete all timers created from this search?" msgstr "Poistetaanko kaikki tällä haulla luodut ajastimet?" msgid "Button$Actions" msgstr "Komennot" msgid "Search entries" msgstr "Hakutermit" msgid "active" msgstr "aktiivista" msgid "Edit$Delete search?" msgstr "Poistetaanko haku?" msgid "Edit search" msgstr "Muokkaa hakua" msgid "Record" msgstr "Tallenna" msgid "Announce by OSD" msgstr "muistutus kuvaruutunäytölle" msgid "Switch only" msgstr "kanavanvaihto" msgid "Announce and switch" msgstr "muistutus ja kanavanvaihto" msgid "Announce by mail" msgstr "muistutus sähköpostitse" msgid "Inactive record" msgstr "" msgid "only globals" msgstr "vain globaalit" msgid "Selection" msgstr "valittu" msgid "all" msgstr "kaikki" msgid "count recordings" msgstr "lukumäärän mukaan" msgid "count days" msgstr "päivien mukaan" msgid "if present" msgstr "jos olemassa" msgid "same day" msgstr "sama päivä" msgid "same week" msgstr "sama viikko" msgid "same month" msgstr "sama kuukausi" msgid "Template name" msgstr "Mallipohjan nimi" msgid "Help$Specify the name of the template." msgstr "Määrittelee mallipohjan nimen." msgid "Help$Specify here the term to search for." msgstr "Määrittelee käytettävän hakutermin." msgid "" "Help$The following search modes exist:\n" "\n" "- phrase: searches for sub terms\n" "- all words: all single words must appear\n" "- at least one word: at least one single word must appear\n" "- match exactly: must match exactly\n" "- regular expression: match a regular expression\n" "- fuzzy searching: searches approximately" msgstr "" "Käytössä ovat seuraavat hakutavat:\n" "\n" "- fraasi: määritelty fraasi pitää löytyä\n" "- kaikki sanat: kaikkien määriteltyjen sanojen pitää löytyä\n" "- yksi sana: yksi määritellyistä sanoista pitää löytyä\n" "- täsmällinen: ehdon pitää löytyä täsmällisesti\n" "- säännöllinen lauseke: määritellyn säännöllisen lausekkeen pitää löytyä\n" "- sumea: samankaltaisia pitää löytyä määriteltyyn ehtoon nähden" msgid "Help$This sets the tolerance of fuzzy searching. The value represents the allowed errors." msgstr "Määrittelee toleranssin sumealle haulle. Arvo kertoo sallittujen virheiden lukumäärän." msgid "Help$Set this to 'Yes' if your search should match the case." msgstr "Tällä asetuksella pystyt huomioimaan kirjainkoon vaikutuksen hakutulokseen." msgid "Help$Set this to 'Yes' if you like to search in the title of an event." msgstr "Tällä asetuksella pystyt etsimään ohjelmanimestä." msgid "Help$Set this to 'Yes' if you like to search in the episode of an event." msgstr "Tällä asetuksella pystyt etsimään lyhyestä ohjelmakuvauksesta." msgid "Help$Set this to 'Yes' if you like to search in the summary of an event." msgstr "Tällä asetuksella pystyt etsimään ohjelmakuvauksesta." msgid "Use content descriptor" msgstr "Käytä sisältökuvausta" msgid "Help$Set this to 'Yes' if you want to search the contents by a descriptor." msgstr "Tällä asetuksella pystyt etsimään sisältökuvauksesta." msgid "Help$The summary of an event, can contain additional information like 'Genre', 'Category', 'Year',... called 'EPG categories' within EPGSearch. External EPG providers often deliver this information. This allows refining a search and other nice things, like searching for the 'tip of the day'. To use it set this to 'Yes'." msgstr "Ohjelmakuvaus voi sisältää ohjelmaoppaan kategoriatietoja ('lajityyppi', 'kategoria', 'valmistumisvuosi', ...), joita ulkoiset ohjelmaoppaat voivat tuottaa. Tällä asetuksella voit hakea myös niiden perusteella." msgid "Help$The file epgsearchcats.conf specifies the search mode for this entry. One can search by text or by value. You can also edit a list of predefined values in this file that can be selected here." msgstr "Tiedosto 'epgsearchcats.conf' määrittelee käytettävät hakutavat ja voit viitata niihin joko tekstinä tai pelkällä luvulla. Lisäksi pystyt myöskin muokkaamaan määriteltyjen kategorioiden listaa." msgid "Help$If a selected category is not part of the summary of an event this normally excludes this event from the search results. To avoid this, set this option to 'Yes', but please handle this with care to avoid a huge amount of results." msgstr "Jos valittua kategoriaa ei löydy ohjelmakuvauksesta, ei ohjelmaa normaalisti myöskään löydy hakutuloksista. Tällä asetuksella voit estää sen, mutta samalla voit saada huomattavan määrän halutuloksia." msgid "Use in favorites menu" msgstr "Käytä suosikkina" msgid "Result menu layout" msgstr "Hakutulosten ulkoasu" msgid "Use as search timer" msgstr "Käytä hakuajastimena" msgid "Action" msgstr "Toiminto" msgid "Switch ... minutes before start" msgstr "Vaihda ... minuuttia ennen alkua" msgid "Unmute sound" msgstr "Ota mykistys pois päältä" msgid "Ask ... minutes before start" msgstr "Kysy ... minuuttia ennen alkua" msgid " Series recording" msgstr " Sarjatallennus" msgid "Delete recordings after ... days" msgstr "Poista tallenteet ... päivän jälkeen" msgid "Keep ... recordings" msgstr "Säilytä ... tallennetta" msgid "Pause when ... recordings exist" msgstr "Keskeytä ... tallenteen jälkeen" msgid "Avoid repeats" msgstr "Estä uusinnat" msgid "Allowed repeats" msgstr "Sallittujen uusintojen lukumäärä" msgid "Only repeats within ... days" msgstr "Vain uusinnat ... päivän sisällä" msgid "Compare title" msgstr "Vertaa nimeä" msgid "Compare subtitle" msgstr "Vertaa jakson nimeä" msgid "Compare summary" msgstr "Vertaa kuvausta" msgid "Min. match in %" msgstr "Vaadittava yhdenmukaisuus [%]" msgid "Compare date" msgstr "Vertaa päivämäärää" msgid "Compare categories" msgstr "Vertaa kategorioita" msgid "VPS" msgstr "VPS" msgid "Auto delete" msgstr "Poista automaattisesti" msgid "after ... recordings" msgstr "... tallenteen jälkeen" msgid "after ... days after first rec." msgstr "... päivän jälkeen ensimmäisestä" msgid "Edit user-defined days of week" msgstr "Muokkaa valittuja viikonpäiviä" msgid "Compare" msgstr "Vertaa" msgid "Select blacklists" msgstr "Valitse mustat listat" msgid "Values for EPG category" msgstr "Valinnat ohjelmaoppaan kategorioille" msgid "Button$Apply" msgstr "Käytä" msgid "less" msgstr "pienempi" msgid "less or equal" msgstr "pienempi tai yhtä suuri" msgid "greater" msgstr "suurempi" msgid "greater or equal" msgstr "suurempi tai yhtä suuri" msgid "equal" msgstr "yhtä suuri" msgid "not equal" msgstr "erisuuri" msgid "Activation of search timer" msgstr "Hakuajastimien aktivointi" msgid "First day" msgstr "Aloituspäivä" msgid "Last day" msgstr "Lopetuspäivä" msgid "Button$all channels" msgstr "Kaikki" msgid "Button$only FTA" msgstr "Vapaat" msgid "Button$Timer preview" msgstr "Esikatselu" msgid "Blacklist results" msgstr "Mustan listan tulokset" msgid "found recordings" msgstr "löydetyt tallenteet" msgid "Error while accessing recording!" msgstr "Tallenteen toistaminen epäonnistui!" msgid "Button$Default" msgstr "Oletus" msgid "Edit$Delete template?" msgstr "Poistetaanko mallipohja?" msgid "Overwrite existing entries?" msgstr "Kirjoitetaanko olemassa olevan päälle?" msgid "Edit entry" msgstr "Muokkaa valintaa" msgid "Switch" msgstr "kanavanvaihto" msgid "Announce only" msgstr "muistutus" msgid "Announce ... minutes before start" msgstr "Muistuta ... minuuttia ennen alkua" msgid "action at" msgstr "Kellonaika kanavanvaihdolle" msgid "Switch list" msgstr "Kanavanvaihtolista" msgid "Edit template" msgstr "Muokkaa mallipohjaa" msgid "Timers" msgstr "Ajastimet" msgid ">>> no info! <<<" msgstr ">>> ei tietoja! <<<" msgid "Overview" msgstr "Yleiskatsaus" msgid "Button$Favorites" msgstr "Suosikit" msgid "Quick search for broadcasts" msgstr "Pikahaku ohjelmaoppaalle" msgid "Quick search" msgstr "Pikahaku" msgid "Show in main menu" msgstr "Näytä valinta päävalikossa" #, c-format msgid "%d new broadcast(s) found! Show them?" msgstr "Löydettiin %d uutta lähetystä! Näytetäänkö?" msgid "Search timer update done!" msgstr "Hakuajastimet päivitetty!" #, c-format msgid "small EPG content on:%s" msgstr "vajaat ohjelmatiedot: %s" msgid "VDR EPG check warning" msgstr "Varoitus VDR:n ohjelmatietojen tarkastuksesta" #, c-format msgid "Switch to (%d) '%s'?" msgstr "Vaihdetaanko kanavalle (%d) '%s'?" msgid "Programming timer failed!" msgstr "Ajastimen ohjelmointi epäonnistui!" #~ msgid "in %02ldd" #~ msgstr "%02ldd" #~ msgid "in %02ldh" #~ msgstr "%02ldh" #~ msgid "in %02ldm" #~ msgstr "%02ldm" vdr-plugin-epgsearch/po/fr_FR.po0000644000175000017500000011572013145412721016412 0ustar tobiastobias# VDR plugin language source file. # Copyright (C) 2007 Klaus Schmidinger # This file is distributed under the same license as the VDR package. # Jean-Claude Repetto , 2001 # Olivier Jacques , 2003 # Gregoire Favre , 2003 # Nicolas Huillard , 2005 , 2007 # Patrice Staudt , 2008 msgid "" msgstr "" "Project-Id-Version: VDR 1.5.7\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-06-15 11:15+0200\n" "PO-Revision-Date: 2008-04-30 08:36+0200\n" "Last-Translator: Patrice Staudt \n" "Language-Team: French \n" "Language: fr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "Channel groups" msgstr "Groupe de chaînes" msgid "Button$Select" msgstr "Selection" msgid "Channel group used by:" msgstr "Groupe est utilisé par:" msgid "Edit$Delete group?" msgstr "Effacer groupe $Delete?" msgid "Edit channel group" msgstr "Editer groupe de chaînes" msgid "Group name" msgstr "Nom de groupe" msgid "Button$Invert selection" msgstr "Inversion de la selection" msgid "Button$All yes" msgstr "Tous oui" msgid "Button$All no" msgstr "Tous non" msgid "Group name is empty!" msgstr "Le nom est vide" msgid "Group name already exists!" msgstr "Le groupe existe déjà!" msgid "Direct access to epgsearch's conflict check menu" msgstr "" msgid "Timer conflicts" msgstr "Conflits de programmation" msgid "Conflict info in main menu" msgstr "Conflits infos dans le menu principale" msgid "next" msgstr "prochain" #, c-format msgid "timer conflict at %s! Show it?" msgstr "conflit de programmation le %s! Afficher?" #, c-format msgid "%d timer conflicts! First at %s. Show them?" msgstr "%d de conflits de programmation! Le premier le %s. Afficher?" msgid "search the EPG for repeats and more" msgstr "Recherche de répétition dans EPG" msgid "Program guide" msgstr "Guide du programme" #, fuzzy msgid "search timer update running" msgstr "La mise à jours de recherche est effectuée!" msgid "Direct access to epgsearch's search menu" msgstr "Accès direct dans epgsearch dans le menu recherche" msgid "Search" msgstr "Recherche" msgid "EpgSearch-Search in main menu" msgstr "EpgSearch-Recherche dans le menu proncipale" msgid "Button$Help" msgstr "Aide" msgid "Standard" msgstr "Standart" msgid "Button$Commands" msgstr "Commandes" msgid "Button$Search" msgstr "Recherche" msgid "never" msgstr "jamais" msgid "always" msgstr "toujours" msgid "smart" msgstr "intelligent" msgid "before user-def. times" msgstr "avant le temp utilisateur" msgid "after user-def. times" msgstr "après le temp utilisateur" msgid "before 'next'" msgstr "avant 'le prochain'" msgid "General" msgstr "Général" msgid "EPG menus" msgstr "Menu EPG" msgid "User-defined EPG times" msgstr "Date utilisateur pour la progammation" msgid "Timer programming" msgstr "Programmation" msgid "Search and search timers" msgstr "Recherche et progammation de recherche" msgid "Timer conflict checking" msgstr "Vérification-Conflits-Programmation" msgid "Email notification" msgstr "Notification par mail" msgid "Hide main menu entry" msgstr "Invisible dans le menu principal" msgid "Help$Hides the main menu entry and may be useful if this plugin is used to replace the original 'Schedule' entry." msgstr "Rend le menu invisible. C'est utile lorsque le plugin remplace le menu programmme d'origine" msgid "Main menu entry" msgstr "Visible dans le menu principal" msgid "Help$The name of the main menu entry which defaults to 'Programm guide'." msgstr "Le nom dans le menu principale. La prédéfinition est 'Guide du programme'. " msgid "Replace original schedule" msgstr "Remplace le menu d'origine programme" msgid "Help$When VDR is patched to allow this plugin to replace the original 'Schedule' entry, you can de/activate this replacement here." msgstr "Lorsque le VDR est muni du patch pour autoriser le remplacement du menu original 'Programme' , vous pouvez activer ou déactiver celui-ci." msgid "Start menu" msgstr "Menue de départ" msgid "Help$Choose between 'Overview - Now' and 'Schedule' as start menu when this plugin is called." msgstr "Ici vous pouvez choisir entre 'Maintenant' et 'Programme' comme menu de départ pour le plugin." msgid "Ok key" msgstr "Touche Ok" msgid "" "Help$Choose here the behaviour of key 'Ok'. You can use it to display the summary or to switch to the corresponding channel.\n" "Note: the functionality of key 'blue' (Switch/Info/Search) depends on this setting." msgstr "" "Ici vous pouvez influencé le comportement de la touch 'Ok'. On peut afficher le continue d'information ou changer pour la chaînes proposée.\n" "Indice: La fonction de la touch 'bleu' (changer/Infos/Recherche) dépend de ce réglage." msgid "Red key" msgstr "Touche rouge" msgid "" "Help$Choose which standard function ('Record' or 'Commands') you like to have on the red key.\n" "(Can be toggled with key '0')" msgstr "" "Ici vous pouvez choisir entre la fonction standart 'Enregistrer' et 'Commande' comme menu de la touche rouge.\n" "(Changement possible avec la touch '0')" msgid "Blue key" msgstr "Touche bleu" msgid "" "Help$Choose which standard function ('Switch'/'Info' or 'Search') you like to have on the blue key.\n" "(Can be toggled with key '0')" msgstr "" "Ici vous pouvez choisir entre la fonction standart 'Changer de chaine' et 'Recherche' comme menu de la touche bleu.\n" "(Changement possible avec la touch '0')" msgid "Show progress in 'Now'" msgstr "Afficher le progrès dans 'Maintenant'" msgid "Help$Shows a progressbar in 'Overview - Now' that informs about the remaining time of the current event." msgstr "Affiche la barre de progression dans le menu 'Maintenant', qui indique l'avancement de l'émission en cours." msgid "Show channel numbers" msgstr "Afficher le numéro de la chaîne" msgid "" "Help$Display channel numbers in 'Overview - Now'.\n" "\n" "(To completely define your own menu look please inspect the MANUAL)" msgstr "" "Affiche du numéro de chaîne dans la vue 'Maintenant'.\n" "\n" "(Pour les réglages de l'affichage menu propre à l'utilisateur, lire le MANUAL)" msgid "Show channel separators" msgstr "Afficher le separateur de chaînes" msgid "Help$Display VDR channel groups as separators between your channels in 'Overview - Now'." msgstr "Afficher les groupes de chaines avec une ligne de séparation dans la vue 'Maintenant'." msgid "Show day separators" msgstr "Afficher les séparateur de jours" msgid "Help$Display a separator line at day break in 'Schedule'." msgstr "Afficher une ligne de séparation au changement de date dans la vue 'programme'." msgid "Show radio channels" msgstr "Afficher les chaînes de radio" msgid "Help$Show also radio channels." msgstr "Afficher aussi les chaînes de radio." msgid "Limit channels from 1 to" msgstr "Limiter aux chaînes de 1 à" msgid "Help$If you have a large channel set you can speed up things when you limit the displayed channels with this setting. Use '0' to disable the limit." msgstr "Avec cette limite vous rendez l'affichage du menu plus rapide si vous avez une liste de chaînes très longue. Avec '0' vous enlevez la limitation." msgid "'One press' timer creation" msgstr "Programmation immédiate avec enregistrement" msgid "Help$When a timer is created with 'Record' you can choose between an immediate creation of the timer or the display of the timer edit menu." msgstr "Lors de la programmation avec 'Enregistrer' vous pouvez choisir entre créer directement ou consulter les détails de la programmation." msgid "Show channels without EPG" msgstr "Afficher les chaînes sans EPG" msgid "Help$Choose 'yes' here if you want to display channels without EPG in 'Overview - Now'. 'Ok' on these entries switches the channel." msgstr "Ici vous pouvez faire disparaitre ou non les chaines sans infos EPG dans la vue 'Maintenant'. Un 'Ok' sur le programme change sur cette chaînes." msgid "Time interval for FRew/FFwd [min]" msgstr "Interval pour FRew/FFwd [min]" msgid "" "Help$Choose here the time interval which should be used for jumping through the EPG by pressing FRew/FFwd.\n" "\n" "(If you don't have those keys, you can toggle to this functionality pressing '0' and get '<<' and '>>' on the keys green and yellow)" msgstr "" "Ici vous règlez un laps de temps, qui est utilisé avec les touches '<<' et '>>' à travers les EPG.\n" "\n" "(Si vous n'avez pas ces touches sur votre télécommande, vous pouvez aussi atteindre ces fonctions par la touche '0' grâce à laquelle on obtient les fonctions '<<' et '>>' sur les touches Vert/Jaune)" msgid "Toggle Green/Yellow" msgstr "Commuter vert/jaune" msgid "Help$Specify if green and yellow shall also be switched when pressing '0'." msgstr "Ici vous indiquez, si les touches Verte/Jaune sont commutées avec la touches '0'." msgid "Show favorites menu" msgstr "Afficher le menu favoris" msgid "" "Help$A favorites menu can display a list of your favorite broadcasts. Enable this if you want an additional menu besides 'Now' and 'Next'\n" "Any search can be used as a favorite. You only have to set the option 'Use in favorites menu' when editing a search." msgstr "" "Un menu favori peut contenir la liste de vos émission préférée. Faire le choix ici, si vous voulez avoir un menu favori à coté de 'Maintenant' et 'plus tard.\n" "Chaque recherche peut être utilisé comme favori. Pour cela simplement utiliser l'option Favori lors de l'édition de recherche." msgid "for the next ... hours" msgstr "pour les prochaines ... heures" msgid "Help$This value controls the timespan used to display your favorites." msgstr "Avec cette valeur vous réglez un interval, pour afficher les favoris." msgid "Use user-defined time" msgstr "Utiliser le temps de l'utilisateur" msgid "Help$Besides 'Now' and 'Next' you can specify up to 4 other times in the EPG which can be used by repeatedly pressing the green key, e.g. 'prime time', 'late night',..." msgstr "En plus de 'Maintenant' et 'Après' vous pouvez définir encore 4 autres crénaux comme 'Le soir', 'La nuit' ou 'encore plus tard' en appuyant plusieurs fois sur la touche verte..." msgid "Description" msgstr "Description" msgid "Help$This is the description for your user-defined time as it will appear as label on the green button." msgstr "Ici la description des temps utilisateurs, accessible en appuyant plusieurs foix sur la touche verte" msgid "Time" msgstr "Temps" msgid "Help$Specify the user-defined time here in 'HH:MM'." msgstr "Ici vous définisez le temps utilisateur dans le format 'HH:MM' par exemple '20:45'" msgid "Use VDR's timer edit menu" msgstr "Utiliser le menu édition VDR-programme" msgid "" "Help$This plugin has its own timer edit menu extending the original one with some extra functionality like\n" "- an additional directory entry\n" "- user-defined days of week for repeating timers\n" "- adding an episode name\n" "- support for EPG variables (see MANUAL)" msgstr "" "Ce plugin a sont propre éditeur de programmation, qui enrichit l'originale avec beaucoup le fonctions interressantes:\n" "\n" "- une entrée de dossier supplèmentaire\n" "- des programmations hebdomadaires définies par l'utilisateur\n" "- l'utilisation de variable de l'EPG (voire MANUAL)" msgid "Default recording dir" msgstr "Dossier d'enregistrement standart" msgid "Help$When creating a timer you can specify here a default recording directory." msgstr "Lors de la programmation vous pouvez définir un dossier par défaut." msgid "Add episode to manual timers" msgstr "Ajouter sous-titre dans la programmation manuel" msgid "" "Help$If you create a timer for a series, you can automatically add the episode name.\n" "\n" "- never: no addition\n" "- always: always add episode name if present\n" "- smart: add only if event lasts less than 80 mins." msgstr "" "Lorsque l'on créé une programmation d'une série, on peut voir automatiquement le nom de l'épisode.\n" "\n" "- Jamais: sans nom d'épisode\n" "- Toujours:Compléter toujours avec le noms de l'épisode, si existant.\n" "- intelligent: compléter, si l'épisode dure moins de 80 min" msgid "Default timer check method" msgstr "Méthode standart de vérification de programmation" msgid "" "Help$Manual timers can be checked for EPG changes. Here you can setup the default check method for each channel. Choose between\n" "\n" "- no checking\n" "- by event ID: checks by an event ID supplied by the channel provider.\n" "- by channel and time: check by the duration match." msgstr "" "Des programmations manuelles peuvent être surveillés par rapport au changement d'EPG. Ici vous pouvez définir une méthode de vérification standart pour chaque chaîne. Les choix:\n" "\n" "- pas de vérification\n" "- à partir du numéro d'émission: la vérification se fait à partir d'un numéro délivré par l'émetteur.\n" "- à partir de la chaîne/heure: vérification à partir de l'émission, qui est la mieux adaptée avec la durée de l'émission initiale." msgid "Button$Setup" msgstr "Configuration" msgid "Use search timers" msgstr "Utiliser le programmeur de recherche" msgid "Help$'Search timers' can be used to automatically create timers for events that match your search criterions." msgstr "'Programmation de recherche' peut être utilisé pour programmer automatiquement des émissions, qui sont trouvées par la recherche." msgid " Update interval [min]" msgstr " Interval d'actualisation [min]" msgid "Help$Specify here the time intervall to be used when searching for events in the background." msgstr "Ici vous indiquez l'interval avec lequel de nouvelles émissions a programmer sont recherchées." msgid " SVDRP port" msgstr " SVDRP Port" msgid "Help$Programming of new timers or timer changes is done with SVDRP. The default value should be correct, so change it only if you know what you are doing." msgstr "La programmation de nouveaux enregistrements ou changements de programmation est réalisé avec SVDRP. La valeur par défaut doit absolument être correcte, ne la changez que si vous savez ce que vous faites." msgid "Help$Specify here the default priority of timers created with this plugin. This value can also be adjusted for each search itself." msgstr "Ici vous définissez la priorité standard de la programmation crée par le plugin. Cette valeur peut être réglée de facon individuelle pour chaque recherche." msgid "Help$Specify here the default lifetime of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "Ici vous définissez la durée de vie de l'enregistrement crée par le plugin. Cette valeur pe ut être réglée de facon individuelle pour chaque recherche." msgid "Help$Specify here the default start recording margin of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "Ici vous définissez la marge antérieure à la programmation crée par le plugin. Cette valeur peut être réglée de facon individuelle pour chaque recherche." msgid "Help$Specify here the default stop recording margin of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "Ici vous définissez la marge postérieure de la programmation crée par le plugin. Cette valeur peut être réglée de facon individuelle pour chaque recherche." msgid "No announcements when replaying" msgstr "Pas d'annonces lors de la lecture" msgid "Help$Set this to 'yes' if you don't like to get any announcements of broadcasts if you currently replay anything." msgstr "Mettez 'oui' si aucune annonce d'émission n'est voulue pendant la lecture." msgid "Recreate timers after deletion" msgstr "Recrer la programmation après l'éffacement" msgid "Help$Set this to 'yes' if you want timers to be recreated with the next search timer update after deleting them." msgstr "Choisissez 'oui' pour refaire les programmations de recherche lorsque vous les avez effacés." msgid "Check if EPG exists for ... [h]" msgstr "" #, fuzzy msgid "Help$Specify how many hours of future EPG there should be and get warned else after a search timer update." msgstr "Avec 'Oui' vous impliquez la vérification de conflits à la mise à jours de la recherche." #, fuzzy msgid "Warn by OSD" msgstr "Annoncer seulement début d'une programme" #, fuzzy msgid "Help$Set this to 'yes' if you want get warnings from the EPG check via OSD." msgstr "Mettez 'oui',si les conflits de programmation doivent être notifiés." #, fuzzy msgid "Warn by mail" msgstr "Annoncer seulement début d'une programme" #, fuzzy msgid "Help$Set this to 'yes' if you want get warnings from the EPG check by mail." msgstr "Mettez 'oui',si le compte mail utilise l'authentification pour les mails sortants." #, fuzzy msgid "Channel group to check" msgstr "Groupe de chaînes" #, fuzzy msgid "Help$Specify the channel group to check." msgstr "Spécifier le nom du modèle." msgid "Ignore PayTV channels" msgstr "Ignorer les chaînes payantes" msgid "Help$Set this to 'yes' if don't want to see events on PayTV channels when searching for repeats." msgstr "Pour éviter les recherches sur les chaînes payantes, vous mettez l'option sur 'oui'" msgid "Search templates" msgstr "Rechercher modèles" msgid "Help$Here you can setup templates for your searches." msgstr "Ici vous créer vos recherches comme modèles" msgid "Blacklists" msgstr "Listes des exclus" msgid "Help$Here you can setup blacklists which can be used within a search to exclude events you don't like." msgstr "Avec ceci vous changez les listes d'exclusions, qui sont utilisées par la recherche automatique, pour éviter des emissions que vous ne voulez pas voir." msgid "Help$Here you can setup channel groups which can be used within a search. These are different to VDR channel groups and represent a set of arbitrary channels, e.g. 'FreeTV'." msgstr "Ici vous définissez des groupes de chaînes qui sont utilisés par la recherche. Ce ne sont pas les groupes de chaînes définis dans VDR comme 'Cinéma', mais une sélection propre de l'utilisateur." msgid "Ignore below priority" msgstr "Ignorer la priorité inférieure" msgid "Help$If a timer with priority below the given value will fail it will not be classified as important. Only important conflicts will produce an OSD message about the conflict after an automatic conflict check." msgstr "" msgid "Ignore conflict duration less ... min." msgstr "Ignorer les conflits inférieurs à ... min." msgid "Help$If a conflicts duration is less then the given number of minutes it will not be classified as important. Only important conflicts will produce an OSD message about the conflict after an automatic conflict check." msgstr "Lorsque le temps de conflit est sous le nombre de minutes indiqué, ceci est considéré comme 'non-important'. Uniquement les conflits importants sont affichés à l'écran lors de la vérification automatique de la programmation." msgid "Only check within next ... days" msgstr "Ne vérifier que les prochains ... jours" msgid "Help$This value reduces the conflict check to the given range of days. All other conflicts are classified as 'not yet important'." msgstr "Avec cette valeur vous définissez l'interval de temps de la vérification de conflits. Tous ces conflits en dehors de cet interval sont qualifés comme 'pas encore importants." msgid "Check also remote conflicts" msgstr "" msgid "Help$Set this to 'yes' if the conflict check should be done for timers set on remote hosts. This needs SVDRPPeering to be set in vdr and Plugin epgsearch running on the remote host." msgstr "" msgid "--- Automatic checking ---" msgstr "--- Vérifications automatiques ---" msgid "After each timer programming" msgstr "Après chaque programmation" msgid "Help$Set this to 'yes' if the conflict check should be performed after each manual timer programming. In the case of a conflict you get immediately a message that informs you about it. The message is only displayed if this timer is involved in any conflict." msgstr "" msgid "When a recording starts" msgstr "" msgid "Help$Set this to 'yes' if the conflict check should be performed when a recording starts. In the case of a conflict you get immediately a message that informs you about it. The message is only displayed if the conflict is within the next 2 hours." msgstr "" msgid "After each search timer update" msgstr "Mise à jours après chaque recherche" msgid "Help$Set this to 'yes' if the conflict check should be performed after each search timer update." msgstr "Avec 'Oui' vous impliquez la vérification de conflits à la mise à jours de la recherche." msgid "every ... minutes" msgstr "toutes les ... minutes" msgid "" "Help$Specify here the time intervall to be used for an automatic conflict check in the background.\n" "('0' disables an automatic check)" msgstr "" "Ici vous indiquez l'interval de temps dans lequel la vérification de conflits est effectuée.\n" "(avec '0' vous déactivez la vérification.)" msgid "if conflicts within next ... minutes" msgstr "Si conflit dans ... minutes suivantes" msgid "Help$If the next conflict will appear in the given number of minutes you can specify here a shorter check intervall to get more OSD notifications about it." msgstr "Si le conflit à lieu dans l'interval de temp indiqué, alors il est possible de règler un interval de temps plus petit pour la vérification de conflits avec affichage à lécran." msgid "Avoid notification when replaying" msgstr "Eviter les messages pendant la lecture" msgid "Help$Set this to 'yes' if the don't want to get OSD messages about conflicts if you currently replay something. Nevertheless messages will be displayed if the first upcoming conflict is within the next 2 hours." msgstr "Mettez sur 'oui', si pendant la lecture vous ne voulez pas être dérangé par les affichages des conflits de programmation. L'affichage est fait si les conflits on lieu dans le 2 heures à venir." msgid "Search timer notification" msgstr "Notification de recherche" msgid "Help$Set this to 'yes' if you want to get an email notification about the search timers that where programmed automatically in the background." msgstr "Mettez 'oui',si vous voulez que les nouvelles programmations automatiques soient notifiées par mail." msgid "Time between mails [h]" msgstr "" msgid "" "Help$Specifiy how much time in [h] you would\n" "like to have atleast between two mails.\n" "With '0' you get a new mail after each\n" "search timer update with new results." msgstr "" msgid "Timer conflict notification" msgstr "Notification de conflit de programmation" msgid "Help$Set this to 'yes' if you want to get an email notification about the timer conflicts." msgstr "Mettez 'oui',si les conflits de programmation doivent être notifiés." msgid "Send to" msgstr "Envoyer à" msgid "Help$Specify the email address where notifications should be sent to." msgstr "Ici vous indiquez l'adresse mail, a laquelle les notifications sont envoyées." msgid "Mail method" msgstr "Méthode de couriel" msgid "" "Help$Specify here the method to use when sending mails.\n" "You can choose between\n" " - 'sendmail': requires a properly configured email system\n" " - 'SendEmail.pl': simple script for mail delivery" msgstr "" msgid "--- Email account ---" msgstr "--- Compte courriel ---" msgid "Email address" msgstr "Adresse courriel" msgid "Help$Specify the email address where notifications should be sent from." msgstr "Préciser l'adresse courriel de l'envoyeur des notifications" msgid "SMTP server" msgstr "Serveur SMTP" msgid "Help$Specify the SMTP server that should deliver the notifications. If it's using a port different from the default(25) append the port with \":port\"." msgstr "Ici vous indiquez le serveur de mail sortant SMTP, par lequel les notifications vont être envoyées. Si le port standart(25) n'est pas utilisé, alors ajoutez \":port\" par exemple smtp.orange.fr:2525. " msgid "Use SMTP authentication" msgstr "Utiliser l'authentification SMTP" msgid "Help$Set this to 'yes' if your account needs authentication to send mails." msgstr "Mettez 'oui',si le compte mail utilise l'authentification pour les mails sortants." msgid "Auth user" msgstr "Authentification: utilisateur" msgid "Help$Specify the auth user, if this account needs authentication for SMTP." msgstr "Ici vous indiquez l'utilisateur pour l'authentification, lorsque le compte mail sortant SMTP en a besoin." msgid "Auth password" msgstr "Authentification: mot de passe" msgid "Help$Specify the auth password, if this account needs authentication for SMTP." msgstr "Ici vous indiquez le mot de passe pour l'authentification, lorsque le compte mail sortant SMTP en a besoin." msgid "Mail account check failed!" msgstr "La vérification du compte mail a échoué" msgid "Button$Test" msgstr "Test" msgid "$ abcdefghijklmnopqrstuvwxyz0123456789-.,#~\\^$[]|()*+?{}/:%@&_" msgstr " aàbcçdeéèêfghiîjklmnoôpqrstuùûvwxyz0123456789-.,#~\\^$[]|()*+?{}/:%@&_" msgid "Start/Stop time has changed" msgstr "Start/Stop date a changé" msgid "Title/episode has changed" msgstr "Titre/épisode a changé" msgid "No new timers were added." msgstr "Il n'y a pas eu de nouvelle programmation." msgid "No timers were modified." msgstr "La programmation n'a pas été changée." msgid "No timers were deleted." msgstr "Aucune programmation n'a été effacée." msgid "No new events to announce." msgstr "" msgid "This version of EPGSearch does not support this service!" msgstr "Cette version de EPGSearch ne supporte pas ce service!" msgid "EPGSearch does not exist!" msgstr "EPGSearch n'existe pas!" #, c-format msgid "%d new broadcast" msgstr "%d nouvelle(s) émission(s)" msgid "Button$by channel" msgstr "de programme" msgid "Button$by time" msgstr "de début" msgid "Button$Episode" msgstr "Épisode" msgid "Button$Title" msgstr "Titre" msgid "announce details" msgstr "annoncer les détails" msgid "announce again" msgstr "Annoncer à nouveau" msgid "with next update" msgstr "lors de la prochaine mise à jour" msgid "again from" msgstr "recommencer à partir de" msgid "Search timer" msgstr "Programmation de recherche" msgid "Edit blacklist" msgstr "Editer la liste des exclus" msgid "phrase" msgstr "Phrase" msgid "all words" msgstr "tout les mots" msgid "at least one word" msgstr "un mot" msgid "match exactly" msgstr "correspond exactement" msgid "regular expression" msgstr "expression réguliere" msgid "fuzzy" msgstr "imprécis" msgid "user-defined" msgstr "definition d'utilisateur" msgid "interval" msgstr "interval" msgid "channel group" msgstr "Groupe de chaînes" msgid "only FTA" msgstr "sans TV-Payante" msgid "Search term" msgstr "Rechercher" msgid "Search mode" msgstr "Mode de recherche" msgid "Tolerance" msgstr "Tolérance" msgid "Match case" msgstr "Maj/Minuscule" msgid "Use title" msgstr "Utiliser titre" msgid "Use subtitle" msgstr "Utiliser sous-titre" msgid "Use description" msgstr "Utiliser la description" msgid "Use extended EPG info" msgstr "Utiliser les infos EPG avancées" msgid "Ignore missing categories" msgstr "Ignorer les catégories indisponible" msgid "Use channel" msgstr "Utiliser les chaînes" msgid " from channel" msgstr " de la Chaîne" msgid " to channel" msgstr " à la Chaîne" msgid "Channel group" msgstr "Groupe de chaînes" msgid "Use time" msgstr "Utiliser l'heure" msgid " Start after" msgstr " Départ après" msgid " Start before" msgstr " Départ avant" msgid "Use duration" msgstr "Durée d'utilisation" msgid " Min. duration" msgstr " Durée min." msgid " Max. duration" msgstr " Durée max." msgid "Use day of week" msgstr "Utiliser les jours de la semaine" msgid "Day of week" msgstr "Jours de la semaine" msgid "Use global" msgstr "" msgid "Button$Templates" msgstr "Modéles" msgid "*** Invalid Channel ***" msgstr "*** Chaîne indisponible ***" msgid "Please check channel criteria!" msgstr "Vérifier le critère de la chaîne!" msgid "Edit$Delete blacklist?" msgstr "Effacer la liste des exclus" msgid "Repeats" msgstr "Répétitions" msgid "Create search" msgstr "Créer une recherche" msgid "Search in recordings" msgstr "Recherche dans enregistrement" msgid "Mark as 'already recorded'?" msgstr "marquer comme 'déjà enregistré'?" msgid "Add/Remove to/from switch list?" msgstr "Ajouter/Effacer de la liste de changement?" msgid "Create blacklist" msgstr "Créer la liste d'exclusions" msgid "EPG Commands" msgstr "Commande EPG" msgid "Epgsearch: RemoteTimerModifications failed" msgstr "" msgid "Already running!" msgstr "Est déjà en cours" msgid "Add to switch list?" msgstr "Ajouter à la liste de changement de chaine?" msgid "Delete from switch list?" msgstr "Effacer de la liste de changement?" msgid "Button$Details" msgstr "Détails" msgid "Button$Filter" msgstr "Filtre" msgid "Button$Show all" msgstr "Montrer tous" msgid "conflicts" msgstr "Conflits" msgid "no conflicts!" msgstr "pas de conflits" msgid "no important conflicts!" msgstr "pas de conflits importants!" msgid "C" msgstr "C" msgid "Button$Repeats" msgstr "Répétitions" msgid "no check" msgstr "sans surveillance" msgid "by channel and time" msgstr "à partir chaînes/heures" msgid "by event ID" msgstr "à partir du numéro d'émission" msgid "Select directory" msgstr "Selectionner le dossier" msgid "Button$Level" msgstr "Niveau" msgid "Event" msgstr "Événement" msgid "Favorites" msgstr "Favoris" msgid "Search results" msgstr "Résultat de recherche" msgid "Timer conflict! Show?" msgstr "Afficher les conflits de programmation?" msgid "Directory" msgstr "Dossier" msgid "Channel" msgstr "Chaîne" msgid "Childlock" msgstr "Adulte" msgid "Record on" msgstr "" msgid "Timer check" msgstr "surveiller" msgid "recording with device" msgstr "Enregistrement avec appareil" msgid "Button$With subtitle" msgstr "Avec les sous-titres" msgid "Button$Without subtitle" msgstr "Sans sous-titres" msgid "Timer has been deleted" msgstr "" msgid "Button$Extended" msgstr "Extention" msgid "Button$Simple" msgstr "Simple" msgid "Use blacklists" msgstr "Utiliser la liste des exclus" msgid "Edit$Search text too short - use anyway?" msgstr "Texte de recherche est trop court - l'utiliser comme même?" #, fuzzy msgid "Button$Orphaned" msgstr "de programme" msgid "Button$by name" msgstr "par nom" msgid "Button$by date" msgstr "par la date" msgid "Button$Delete all" msgstr "Effacer toutes" msgid "Recordings" msgstr "Enregistrement" msgid "Edit$Delete entry?" msgstr "Effacer l'entrée" msgid "Edit$Delete all entries?" msgstr "Effacer toutes les entrées" msgid "Summary" msgstr "Contenu" msgid "Auxiliary info" msgstr "Informations supplémentaires" msgid "Button$Aux info" msgstr "Infos supplémentaires" msgid "Search actions" msgstr "Actions de recherche" msgid "Execute search" msgstr "Effectuer la recherche" msgid "Use as search timer on/off" msgstr "Utiliser comme recherche oui/non" msgid "Trigger search timer update" msgstr "Selection" msgid "Show recordings done" msgstr "Afficher les enregistrements effectués" msgid "Show timers created" msgstr "Afficher la programmation effectuée" msgid "Create a copy" msgstr "Créer une copie" msgid "Use as template" msgstr "Utiliser comme modèles" msgid "Show switch list" msgstr "Afficher liste de changement" msgid "Show blacklists" msgstr "Afficher la liste des exclus" msgid "Delete created timers?" msgstr "Effacer les programmations crées" msgid "Timer conflict check" msgstr "Vérifier les conflits de programmation" msgid "Disable associated timers too?" msgstr "Désactiver la programmation correspondante" msgid "Activate associated timers too?" msgstr "Activer la progammation correspondante" msgid "Search timers activated in setup." msgstr "La recherche a été activée dans la configuration." msgid "Run search timer update?" msgstr "Mise à jours programmation de recherche?" msgid "Copy this entry?" msgstr "Copier cette entrée" msgid "Copy" msgstr "Copier" msgid "Copy this entry to templates?" msgstr "Copier cette entrée dans modèles?" msgid "Delete all timers created from this search?" msgstr "Effacer les programmations issues de cette recherche?" msgid "Button$Actions" msgstr "Actions" msgid "Search entries" msgstr "Entrée de recherche" msgid "active" msgstr "actif" msgid "Edit$Delete search?" msgstr "Effacer la recherche" msgid "Edit search" msgstr "Edition recherche" msgid "Record" msgstr "Enregistre" #, fuzzy msgid "Announce by OSD" msgstr "Annoncer seulement début d'une programme" msgid "Switch only" msgstr "Seulement changer de chaine" #, fuzzy msgid "Announce and switch" msgstr "Annoncer seulement début d'une programme" #, fuzzy msgid "Announce by mail" msgstr "Annoncer seulement début d'une programme" msgid "Inactive record" msgstr "" msgid "only globals" msgstr "" msgid "Selection" msgstr "Selection" msgid "all" msgstr "tous" msgid "count recordings" msgstr "compter enregistrements" msgid "count days" msgstr "compter jours" msgid "if present" msgstr "" #, fuzzy msgid "same day" msgstr "Dernier jour" #, fuzzy msgid "same week" msgstr "Jours de la semaine" msgid "same month" msgstr "" msgid "Template name" msgstr "Nom du modèle" msgid "Help$Specify the name of the template." msgstr "Spécifier le nom du modèle." msgid "Help$Specify here the term to search for." msgstr "Spécifier ici le term de la recherche." msgid "" "Help$The following search modes exist:\n" "\n" "- phrase: searches for sub terms\n" "- all words: all single words must appear\n" "- at least one word: at least one single word must appear\n" "- match exactly: must match exactly\n" "- regular expression: match a regular expression\n" "- fuzzy searching: searches approximately" msgstr "" msgid "Help$This sets the tolerance of fuzzy searching. The value represents the allowed errors." msgstr "" msgid "Help$Set this to 'Yes' if your search should match the case." msgstr "" msgid "Help$Set this to 'Yes' if you like to search in the title of an event." msgstr "" msgid "Help$Set this to 'Yes' if you like to search in the episode of an event." msgstr "" msgid "Help$Set this to 'Yes' if you like to search in the summary of an event." msgstr "" #, fuzzy msgid "Use content descriptor" msgstr "Utiliser la description" #, fuzzy msgid "Help$Set this to 'Yes' if you want to search the contents by a descriptor." msgstr "Mettez 'oui',si le compte mail utilise l'authentification pour les mails sortants." msgid "Help$The summary of an event, can contain additional information like 'Genre', 'Category', 'Year',... called 'EPG categories' within EPGSearch. External EPG providers often deliver this information. This allows refining a search and other nice things, like searching for the 'tip of the day'. To use it set this to 'Yes'." msgstr "" msgid "Help$The file epgsearchcats.conf specifies the search mode for this entry. One can search by text or by value. You can also edit a list of predefined values in this file that can be selected here." msgstr "" msgid "Help$If a selected category is not part of the summary of an event this normally excludes this event from the search results. To avoid this, set this option to 'Yes', but please handle this with care to avoid a huge amount of results." msgstr "" msgid "Use in favorites menu" msgstr "Utiliser dans le menu favoris" msgid "Result menu layout" msgstr "Dispositon du menu de résultat" msgid "Use as search timer" msgstr "Utiliser la recherche" msgid "Action" msgstr "Action" msgid "Switch ... minutes before start" msgstr "Changer ... minutes avant le début" msgid "Unmute sound" msgstr "Remettre le son" #, fuzzy msgid "Ask ... minutes before start" msgstr "Changer ... minutes avant le début" msgid " Series recording" msgstr " Enregistrement de serie" msgid "Delete recordings after ... days" msgstr "Effacer l'enregistrement après ... jours" msgid "Keep ... recordings" msgstr "Garder .... enregistrements" msgid "Pause when ... recordings exist" msgstr "Pause, lorsque ... l'enregistrement existe." msgid "Avoid repeats" msgstr "Eviter les répétions" msgid "Allowed repeats" msgstr "Répétitions autorisées" msgid "Only repeats within ... days" msgstr "Que répétion, pendant ... jours" msgid "Compare title" msgstr "Comparer titres" msgid "Compare subtitle" msgstr "Comparer les sous-titres" msgid "Compare summary" msgstr "Comparer les descriptions" #, fuzzy msgid "Min. match in %" msgstr " Durée min." #, fuzzy msgid "Compare date" msgstr "Comparer titres" msgid "Compare categories" msgstr "Comparer categories" msgid "VPS" msgstr "iVPS" msgid "Auto delete" msgstr "Auto effacement" msgid "after ... recordings" msgstr "après ... enregistrements" msgid "after ... days after first rec." msgstr "après ... jours du premier enregistrement" msgid "Edit user-defined days of week" msgstr "Edition des journées définit par l'utilisateur" msgid "Compare" msgstr "Comparer" msgid "Select blacklists" msgstr "Choisir la liste des exclus" msgid "Values for EPG category" msgstr "Valeur pour la catégories EPG" msgid "Button$Apply" msgstr "Appliquer" msgid "less" msgstr "plus petit" msgid "less or equal" msgstr "plus petit ou égale" msgid "greater" msgstr "plus grand" msgid "greater or equal" msgstr "plus grand ou égale" msgid "equal" msgstr "égale" msgid "not equal" msgstr "pas égale" msgid "Activation of search timer" msgstr "Activation de la recherche de programmation" msgid "First day" msgstr "Premier jour" msgid "Last day" msgstr "Dernier jour" msgid "Button$all channels" msgstr "avec TV-Payante" msgid "Button$only FTA" msgstr "sans TV-Payante" msgid "Button$Timer preview" msgstr "Prévu de programmation" msgid "Blacklist results" msgstr "Résultats de la liste des exclus" msgid "found recordings" msgstr "Enregistrements trouvées" msgid "Error while accessing recording!" msgstr "Erreur lors de l'accès à l'enregistrement" msgid "Button$Default" msgstr "Standart" msgid "Edit$Delete template?" msgstr "Effacer le modèle" msgid "Overwrite existing entries?" msgstr "Ecraser les informations?" msgid "Edit entry" msgstr "Editer l'entrée" #, fuzzy msgid "Switch" msgstr "Seulement changer de chaine" msgid "Announce only" msgstr "Annoncer seulement début d'une programme" #, fuzzy msgid "Announce ... minutes before start" msgstr "Changer ... minutes avant le début" msgid "action at" msgstr "Effectuer à" msgid "Switch list" msgstr "Liste de changement de chaine" msgid "Edit template" msgstr "Editer modèles" msgid "Timers" msgstr "Programmations" msgid ">>> no info! <<<" msgstr ">>> Pas d'information! <<<" msgid "Overview" msgstr "Sommaire" msgid "Button$Favorites" msgstr "Favoris" msgid "Quick search for broadcasts" msgstr "Recherche rapide pour les radios" msgid "Quick search" msgstr "Recherche rapide" msgid "Show in main menu" msgstr "Visible dans le menu principale" #, c-format msgid "%d new broadcast(s) found! Show them?" msgstr "Afficher les %d nouvelles émissions trouvées?" msgid "Search timer update done!" msgstr "La mise à jours de recherche est effectuée!" #, c-format msgid "small EPG content on:%s" msgstr "" msgid "VDR EPG check warning" msgstr "" #, c-format msgid "Switch to (%d) '%s'?" msgstr "" msgid "Programming timer failed!" msgstr "La programmation a échoué" #~ msgid "in %02ldd" #~ msgstr "en %02ldd" #~ msgid "in %02ldh" #~ msgstr "en %02ldh" #~ msgid "in %02ldm" #~ msgstr "en %02ldm" #, fuzzy #~ msgid "Compare expression" #~ msgstr "expression réguliere" vdr-plugin-epgsearch/po/tr_TR.po0000644000175000017500000005715113145412721016451 0ustar tobiastobias# VDR plugin language source file. # Copyright (C) 2007 Klaus Schmidinger # This file is distributed under the same license as the VDR package. # Oktay Yolgeçen , 2007 # msgid "" msgstr "" "Project-Id-Version: VDR 1.5.7\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-06-15 11:15+0200\n" "PO-Revision-Date: 2007-08-14 20:21+0200\n" "Last-Translator: Oktay Yolgeçen \n" "Language-Team: Turkish \n" "Language: tr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "Channel groups" msgstr "" msgid "Button$Select" msgstr "" msgid "Channel group used by:" msgstr "" msgid "Edit$Delete group?" msgstr "" msgid "Edit channel group" msgstr "" msgid "Group name" msgstr "" msgid "Button$Invert selection" msgstr "" msgid "Button$All yes" msgstr "" msgid "Button$All no" msgstr "" msgid "Group name is empty!" msgstr "" msgid "Group name already exists!" msgstr "" msgid "Direct access to epgsearch's conflict check menu" msgstr "" msgid "Timer conflicts" msgstr "" msgid "Conflict info in main menu" msgstr "" msgid "next" msgstr "" #, c-format msgid "timer conflict at %s! Show it?" msgstr "" #, c-format msgid "%d timer conflicts! First at %s. Show them?" msgstr "" msgid "search the EPG for repeats and more" msgstr "" msgid "Program guide" msgstr "" msgid "search timer update running" msgstr "" msgid "Direct access to epgsearch's search menu" msgstr "" msgid "Search" msgstr "" msgid "EpgSearch-Search in main menu" msgstr "" msgid "Button$Help" msgstr "" msgid "Standard" msgstr "" msgid "Button$Commands" msgstr "" msgid "Button$Search" msgstr "" msgid "never" msgstr "" msgid "always" msgstr "" msgid "smart" msgstr "" msgid "before user-def. times" msgstr "" msgid "after user-def. times" msgstr "" msgid "before 'next'" msgstr "" msgid "General" msgstr "" msgid "EPG menus" msgstr "" msgid "User-defined EPG times" msgstr "" msgid "Timer programming" msgstr "" msgid "Search and search timers" msgstr "" msgid "Timer conflict checking" msgstr "" msgid "Email notification" msgstr "" msgid "Hide main menu entry" msgstr "" msgid "Help$Hides the main menu entry and may be useful if this plugin is used to replace the original 'Schedule' entry." msgstr "" msgid "Main menu entry" msgstr "" msgid "Help$The name of the main menu entry which defaults to 'Programm guide'." msgstr "" msgid "Replace original schedule" msgstr "" msgid "Help$When VDR is patched to allow this plugin to replace the original 'Schedule' entry, you can de/activate this replacement here." msgstr "" msgid "Start menu" msgstr "" msgid "Help$Choose between 'Overview - Now' and 'Schedule' as start menu when this plugin is called." msgstr "" msgid "Ok key" msgstr "" msgid "" "Help$Choose here the behaviour of key 'Ok'. You can use it to display the summary or to switch to the corresponding channel.\n" "Note: the functionality of key 'blue' (Switch/Info/Search) depends on this setting." msgstr "" msgid "Red key" msgstr "" msgid "" "Help$Choose which standard function ('Record' or 'Commands') you like to have on the red key.\n" "(Can be toggled with key '0')" msgstr "" msgid "Blue key" msgstr "" msgid "" "Help$Choose which standard function ('Switch'/'Info' or 'Search') you like to have on the blue key.\n" "(Can be toggled with key '0')" msgstr "" msgid "Show progress in 'Now'" msgstr "" msgid "Help$Shows a progressbar in 'Overview - Now' that informs about the remaining time of the current event." msgstr "" msgid "Show channel numbers" msgstr "" msgid "" "Help$Display channel numbers in 'Overview - Now'.\n" "\n" "(To completely define your own menu look please inspect the MANUAL)" msgstr "" msgid "Show channel separators" msgstr "" msgid "Help$Display VDR channel groups as separators between your channels in 'Overview - Now'." msgstr "" msgid "Show day separators" msgstr "" msgid "Help$Display a separator line at day break in 'Schedule'." msgstr "" msgid "Show radio channels" msgstr "" msgid "Help$Show also radio channels." msgstr "" msgid "Limit channels from 1 to" msgstr "" msgid "Help$If you have a large channel set you can speed up things when you limit the displayed channels with this setting. Use '0' to disable the limit." msgstr "" msgid "'One press' timer creation" msgstr "" msgid "Help$When a timer is created with 'Record' you can choose between an immediate creation of the timer or the display of the timer edit menu." msgstr "" msgid "Show channels without EPG" msgstr "" msgid "Help$Choose 'yes' here if you want to display channels without EPG in 'Overview - Now'. 'Ok' on these entries switches the channel." msgstr "" msgid "Time interval for FRew/FFwd [min]" msgstr "" msgid "" "Help$Choose here the time interval which should be used for jumping through the EPG by pressing FRew/FFwd.\n" "\n" "(If you don't have those keys, you can toggle to this functionality pressing '0' and get '<<' and '>>' on the keys green and yellow)" msgstr "" msgid "Toggle Green/Yellow" msgstr "" msgid "Help$Specify if green and yellow shall also be switched when pressing '0'." msgstr "" msgid "Show favorites menu" msgstr "" msgid "" "Help$A favorites menu can display a list of your favorite broadcasts. Enable this if you want an additional menu besides 'Now' and 'Next'\n" "Any search can be used as a favorite. You only have to set the option 'Use in favorites menu' when editing a search." msgstr "" msgid "for the next ... hours" msgstr "" msgid "Help$This value controls the timespan used to display your favorites." msgstr "" msgid "Use user-defined time" msgstr "" msgid "Help$Besides 'Now' and 'Next' you can specify up to 4 other times in the EPG which can be used by repeatedly pressing the green key, e.g. 'prime time', 'late night',..." msgstr "" msgid "Description" msgstr "" msgid "Help$This is the description for your user-defined time as it will appear as label on the green button." msgstr "" msgid "Time" msgstr "" msgid "Help$Specify the user-defined time here in 'HH:MM'." msgstr "" msgid "Use VDR's timer edit menu" msgstr "" msgid "" "Help$This plugin has its own timer edit menu extending the original one with some extra functionality like\n" "- an additional directory entry\n" "- user-defined days of week for repeating timers\n" "- adding an episode name\n" "- support for EPG variables (see MANUAL)" msgstr "" msgid "Default recording dir" msgstr "" msgid "Help$When creating a timer you can specify here a default recording directory." msgstr "" msgid "Add episode to manual timers" msgstr "" msgid "" "Help$If you create a timer for a series, you can automatically add the episode name.\n" "\n" "- never: no addition\n" "- always: always add episode name if present\n" "- smart: add only if event lasts less than 80 mins." msgstr "" msgid "Default timer check method" msgstr "" msgid "" "Help$Manual timers can be checked for EPG changes. Here you can setup the default check method for each channel. Choose between\n" "\n" "- no checking\n" "- by event ID: checks by an event ID supplied by the channel provider.\n" "- by channel and time: check by the duration match." msgstr "" msgid "Button$Setup" msgstr "" msgid "Use search timers" msgstr "" msgid "Help$'Search timers' can be used to automatically create timers for events that match your search criterions." msgstr "" msgid " Update interval [min]" msgstr "" msgid "Help$Specify here the time intervall to be used when searching for events in the background." msgstr "" msgid " SVDRP port" msgstr "" msgid "Help$Programming of new timers or timer changes is done with SVDRP. The default value should be correct, so change it only if you know what you are doing." msgstr "" msgid "Help$Specify here the default priority of timers created with this plugin. This value can also be adjusted for each search itself." msgstr "" msgid "Help$Specify here the default lifetime of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "" msgid "Help$Specify here the default start recording margin of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "" msgid "Help$Specify here the default stop recording margin of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "" msgid "No announcements when replaying" msgstr "" msgid "Help$Set this to 'yes' if you don't like to get any announcements of broadcasts if you currently replay anything." msgstr "" msgid "Recreate timers after deletion" msgstr "" msgid "Help$Set this to 'yes' if you want timers to be recreated with the next search timer update after deleting them." msgstr "" msgid "Check if EPG exists for ... [h]" msgstr "" msgid "Help$Specify how many hours of future EPG there should be and get warned else after a search timer update." msgstr "" msgid "Warn by OSD" msgstr "" msgid "Help$Set this to 'yes' if you want get warnings from the EPG check via OSD." msgstr "" msgid "Warn by mail" msgstr "" msgid "Help$Set this to 'yes' if you want get warnings from the EPG check by mail." msgstr "" msgid "Channel group to check" msgstr "" msgid "Help$Specify the channel group to check." msgstr "" msgid "Ignore PayTV channels" msgstr "" msgid "Help$Set this to 'yes' if don't want to see events on PayTV channels when searching for repeats." msgstr "" msgid "Search templates" msgstr "" msgid "Help$Here you can setup templates for your searches." msgstr "" msgid "Blacklists" msgstr "" msgid "Help$Here you can setup blacklists which can be used within a search to exclude events you don't like." msgstr "" msgid "Help$Here you can setup channel groups which can be used within a search. These are different to VDR channel groups and represent a set of arbitrary channels, e.g. 'FreeTV'." msgstr "" msgid "Ignore below priority" msgstr "" msgid "Help$If a timer with priority below the given value will fail it will not be classified as important. Only important conflicts will produce an OSD message about the conflict after an automatic conflict check." msgstr "" msgid "Ignore conflict duration less ... min." msgstr "" msgid "Help$If a conflicts duration is less then the given number of minutes it will not be classified as important. Only important conflicts will produce an OSD message about the conflict after an automatic conflict check." msgstr "" msgid "Only check within next ... days" msgstr "" msgid "Help$This value reduces the conflict check to the given range of days. All other conflicts are classified as 'not yet important'." msgstr "" msgid "Check also remote conflicts" msgstr "" msgid "Help$Set this to 'yes' if the conflict check should be done for timers set on remote hosts. This needs SVDRPPeering to be set in vdr and Plugin epgsearch running on the remote host." msgstr "" msgid "--- Automatic checking ---" msgstr "" msgid "After each timer programming" msgstr "" msgid "Help$Set this to 'yes' if the conflict check should be performed after each manual timer programming. In the case of a conflict you get immediately a message that informs you about it. The message is only displayed if this timer is involved in any conflict." msgstr "" msgid "When a recording starts" msgstr "" msgid "Help$Set this to 'yes' if the conflict check should be performed when a recording starts. In the case of a conflict you get immediately a message that informs you about it. The message is only displayed if the conflict is within the next 2 hours." msgstr "" msgid "After each search timer update" msgstr "" msgid "Help$Set this to 'yes' if the conflict check should be performed after each search timer update." msgstr "" msgid "every ... minutes" msgstr "" msgid "" "Help$Specify here the time intervall to be used for an automatic conflict check in the background.\n" "('0' disables an automatic check)" msgstr "" msgid "if conflicts within next ... minutes" msgstr "" msgid "Help$If the next conflict will appear in the given number of minutes you can specify here a shorter check intervall to get more OSD notifications about it." msgstr "" msgid "Avoid notification when replaying" msgstr "" msgid "Help$Set this to 'yes' if the don't want to get OSD messages about conflicts if you currently replay something. Nevertheless messages will be displayed if the first upcoming conflict is within the next 2 hours." msgstr "" msgid "Search timer notification" msgstr "" msgid "Help$Set this to 'yes' if you want to get an email notification about the search timers that where programmed automatically in the background." msgstr "" msgid "Time between mails [h]" msgstr "" msgid "" "Help$Specifiy how much time in [h] you would\n" "like to have atleast between two mails.\n" "With '0' you get a new mail after each\n" "search timer update with new results." msgstr "" msgid "Timer conflict notification" msgstr "" msgid "Help$Set this to 'yes' if you want to get an email notification about the timer conflicts." msgstr "" msgid "Send to" msgstr "" msgid "Help$Specify the email address where notifications should be sent to." msgstr "" msgid "Mail method" msgstr "" msgid "" "Help$Specify here the method to use when sending mails.\n" "You can choose between\n" " - 'sendmail': requires a properly configured email system\n" " - 'SendEmail.pl': simple script for mail delivery" msgstr "" msgid "--- Email account ---" msgstr "" msgid "Email address" msgstr "" msgid "Help$Specify the email address where notifications should be sent from." msgstr "" msgid "SMTP server" msgstr "" msgid "Help$Specify the SMTP server that should deliver the notifications. If it's using a port different from the default(25) append the port with \":port\"." msgstr "" msgid "Use SMTP authentication" msgstr "" msgid "Help$Set this to 'yes' if your account needs authentication to send mails." msgstr "" msgid "Auth user" msgstr "" msgid "Help$Specify the auth user, if this account needs authentication for SMTP." msgstr "" msgid "Auth password" msgstr "" msgid "Help$Specify the auth password, if this account needs authentication for SMTP." msgstr "" msgid "Mail account check failed!" msgstr "" msgid "Button$Test" msgstr "" msgid "$ abcdefghijklmnopqrstuvwxyz0123456789-.,#~\\^$[]|()*+?{}/:%@&_" msgstr "" msgid "Start/Stop time has changed" msgstr "" msgid "Title/episode has changed" msgstr "" msgid "No new timers were added." msgstr "" msgid "No timers were modified." msgstr "" msgid "No timers were deleted." msgstr "" msgid "No new events to announce." msgstr "" msgid "This version of EPGSearch does not support this service!" msgstr "" msgid "EPGSearch does not exist!" msgstr "" #, c-format msgid "%d new broadcast" msgstr "" msgid "Button$by channel" msgstr "" msgid "Button$by time" msgstr "" msgid "Button$Episode" msgstr "" msgid "Button$Title" msgstr "" msgid "announce details" msgstr "" msgid "announce again" msgstr "" msgid "with next update" msgstr "" msgid "again from" msgstr "" msgid "Search timer" msgstr "" msgid "Edit blacklist" msgstr "" msgid "phrase" msgstr "" msgid "all words" msgstr "" msgid "at least one word" msgstr "" msgid "match exactly" msgstr "" msgid "regular expression" msgstr "" msgid "fuzzy" msgstr "" msgid "user-defined" msgstr "" msgid "interval" msgstr "" msgid "channel group" msgstr "" msgid "only FTA" msgstr "" msgid "Search term" msgstr "" msgid "Search mode" msgstr "" msgid "Tolerance" msgstr "" msgid "Match case" msgstr "" msgid "Use title" msgstr "" msgid "Use subtitle" msgstr "" msgid "Use description" msgstr "" msgid "Use extended EPG info" msgstr "" msgid "Ignore missing categories" msgstr "" msgid "Use channel" msgstr "" msgid " from channel" msgstr "" msgid " to channel" msgstr "" msgid "Channel group" msgstr "" msgid "Use time" msgstr "" msgid " Start after" msgstr "" msgid " Start before" msgstr "" msgid "Use duration" msgstr "" msgid " Min. duration" msgstr "" msgid " Max. duration" msgstr "" msgid "Use day of week" msgstr "" msgid "Day of week" msgstr "" msgid "Use global" msgstr "" msgid "Button$Templates" msgstr "" msgid "*** Invalid Channel ***" msgstr "" msgid "Please check channel criteria!" msgstr "" msgid "Edit$Delete blacklist?" msgstr "" msgid "Repeats" msgstr "" msgid "Create search" msgstr "" msgid "Search in recordings" msgstr "" msgid "Mark as 'already recorded'?" msgstr "" msgid "Add/Remove to/from switch list?" msgstr "" msgid "Create blacklist" msgstr "" msgid "EPG Commands" msgstr "" msgid "Epgsearch: RemoteTimerModifications failed" msgstr "" msgid "Already running!" msgstr "" msgid "Add to switch list?" msgstr "" msgid "Delete from switch list?" msgstr "" msgid "Button$Details" msgstr "" msgid "Button$Filter" msgstr "" msgid "Button$Show all" msgstr "" msgid "conflicts" msgstr "" msgid "no conflicts!" msgstr "" msgid "no important conflicts!" msgstr "" msgid "C" msgstr "" msgid "Button$Repeats" msgstr "" msgid "no check" msgstr "" msgid "by channel and time" msgstr "" msgid "by event ID" msgstr "" msgid "Select directory" msgstr "" msgid "Button$Level" msgstr "" msgid "Event" msgstr "" msgid "Favorites" msgstr "" msgid "Search results" msgstr "" msgid "Timer conflict! Show?" msgstr "" msgid "Directory" msgstr "" msgid "Channel" msgstr "" msgid "Childlock" msgstr "" msgid "Record on" msgstr "" msgid "Timer check" msgstr "" msgid "recording with device" msgstr "" msgid "Button$With subtitle" msgstr "" msgid "Button$Without subtitle" msgstr "" msgid "Timer has been deleted" msgstr "" msgid "Button$Extended" msgstr "" msgid "Button$Simple" msgstr "" msgid "Use blacklists" msgstr "" msgid "Edit$Search text too short - use anyway?" msgstr "" msgid "Button$Orphaned" msgstr "" msgid "Button$by name" msgstr "" msgid "Button$by date" msgstr "" msgid "Button$Delete all" msgstr "" msgid "Recordings" msgstr "" msgid "Edit$Delete entry?" msgstr "" msgid "Edit$Delete all entries?" msgstr "" msgid "Summary" msgstr "" msgid "Auxiliary info" msgstr "" msgid "Button$Aux info" msgstr "" msgid "Search actions" msgstr "" msgid "Execute search" msgstr "" msgid "Use as search timer on/off" msgstr "" msgid "Trigger search timer update" msgstr "" msgid "Show recordings done" msgstr "" msgid "Show timers created" msgstr "" msgid "Create a copy" msgstr "" msgid "Use as template" msgstr "" msgid "Show switch list" msgstr "" msgid "Show blacklists" msgstr "" msgid "Delete created timers?" msgstr "" msgid "Timer conflict check" msgstr "" msgid "Disable associated timers too?" msgstr "" msgid "Activate associated timers too?" msgstr "" msgid "Search timers activated in setup." msgstr "" msgid "Run search timer update?" msgstr "" msgid "Copy this entry?" msgstr "" msgid "Copy" msgstr "" msgid "Copy this entry to templates?" msgstr "" msgid "Delete all timers created from this search?" msgstr "" msgid "Button$Actions" msgstr "" msgid "Search entries" msgstr "" msgid "active" msgstr "" msgid "Edit$Delete search?" msgstr "" msgid "Edit search" msgstr "" msgid "Record" msgstr "" msgid "Announce by OSD" msgstr "" msgid "Switch only" msgstr "" msgid "Announce and switch" msgstr "" msgid "Announce by mail" msgstr "" msgid "Inactive record" msgstr "" msgid "only globals" msgstr "" msgid "Selection" msgstr "" msgid "all" msgstr "" msgid "count recordings" msgstr "" msgid "count days" msgstr "" msgid "if present" msgstr "" msgid "same day" msgstr "" msgid "same week" msgstr "" msgid "same month" msgstr "" msgid "Template name" msgstr "" msgid "Help$Specify the name of the template." msgstr "" msgid "Help$Specify here the term to search for." msgstr "" msgid "" "Help$The following search modes exist:\n" "\n" "- phrase: searches for sub terms\n" "- all words: all single words must appear\n" "- at least one word: at least one single word must appear\n" "- match exactly: must match exactly\n" "- regular expression: match a regular expression\n" "- fuzzy searching: searches approximately" msgstr "" msgid "Help$This sets the tolerance of fuzzy searching. The value represents the allowed errors." msgstr "" msgid "Help$Set this to 'Yes' if your search should match the case." msgstr "" msgid "Help$Set this to 'Yes' if you like to search in the title of an event." msgstr "" msgid "Help$Set this to 'Yes' if you like to search in the episode of an event." msgstr "" msgid "Help$Set this to 'Yes' if you like to search in the summary of an event." msgstr "" msgid "Use content descriptor" msgstr "" msgid "Help$Set this to 'Yes' if you want to search the contents by a descriptor." msgstr "" msgid "Help$The summary of an event, can contain additional information like 'Genre', 'Category', 'Year',... called 'EPG categories' within EPGSearch. External EPG providers often deliver this information. This allows refining a search and other nice things, like searching for the 'tip of the day'. To use it set this to 'Yes'." msgstr "" msgid "Help$The file epgsearchcats.conf specifies the search mode for this entry. One can search by text or by value. You can also edit a list of predefined values in this file that can be selected here." msgstr "" msgid "Help$If a selected category is not part of the summary of an event this normally excludes this event from the search results. To avoid this, set this option to 'Yes', but please handle this with care to avoid a huge amount of results." msgstr "" msgid "Use in favorites menu" msgstr "" msgid "Result menu layout" msgstr "" msgid "Use as search timer" msgstr "" msgid "Action" msgstr "" msgid "Switch ... minutes before start" msgstr "" msgid "Unmute sound" msgstr "" msgid "Ask ... minutes before start" msgstr "" msgid " Series recording" msgstr "" msgid "Delete recordings after ... days" msgstr "" msgid "Keep ... recordings" msgstr "" msgid "Pause when ... recordings exist" msgstr "" msgid "Avoid repeats" msgstr "" msgid "Allowed repeats" msgstr "" msgid "Only repeats within ... days" msgstr "" msgid "Compare title" msgstr "" msgid "Compare subtitle" msgstr "" msgid "Compare summary" msgstr "" msgid "Min. match in %" msgstr "" msgid "Compare date" msgstr "" msgid "Compare categories" msgstr "" msgid "VPS" msgstr "" msgid "Auto delete" msgstr "" msgid "after ... recordings" msgstr "" msgid "after ... days after first rec." msgstr "" msgid "Edit user-defined days of week" msgstr "" msgid "Compare" msgstr "" msgid "Select blacklists" msgstr "" msgid "Values for EPG category" msgstr "" msgid "Button$Apply" msgstr "" msgid "less" msgstr "" msgid "less or equal" msgstr "" msgid "greater" msgstr "" msgid "greater or equal" msgstr "" msgid "equal" msgstr "" msgid "not equal" msgstr "" msgid "Activation of search timer" msgstr "" msgid "First day" msgstr "" msgid "Last day" msgstr "" msgid "Button$all channels" msgstr "" msgid "Button$only FTA" msgstr "" msgid "Button$Timer preview" msgstr "" msgid "Blacklist results" msgstr "" msgid "found recordings" msgstr "" msgid "Error while accessing recording!" msgstr "" msgid "Button$Default" msgstr "" msgid "Edit$Delete template?" msgstr "" msgid "Overwrite existing entries?" msgstr "" msgid "Edit entry" msgstr "" msgid "Switch" msgstr "" msgid "Announce only" msgstr "" msgid "Announce ... minutes before start" msgstr "" msgid "action at" msgstr "" msgid "Switch list" msgstr "" msgid "Edit template" msgstr "" msgid "Timers" msgstr "" msgid ">>> no info! <<<" msgstr "" msgid "Overview" msgstr "" msgid "Button$Favorites" msgstr "" msgid "Quick search for broadcasts" msgstr "" msgid "Quick search" msgstr "" msgid "Show in main menu" msgstr "" #, c-format msgid "%d new broadcast(s) found! Show them?" msgstr "" msgid "Search timer update done!" msgstr "" #, c-format msgid "small EPG content on:%s" msgstr "" msgid "VDR EPG check warning" msgstr "" #, c-format msgid "Switch to (%d) '%s'?" msgstr "" msgid "Programming timer failed!" msgstr "" vdr-plugin-epgsearch/po/cs_CZ.po0000644000175000017500000007405313145412721016420 0ustar tobiastobias# VDR plugin language source file. # Copyright (C) 2007 Klaus Schmidinger # This file is distributed under the same license as the VDR package. # Vladimír Bárta , 2006 # msgid "" msgstr "" "Project-Id-Version: VDR 1.7.21\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-06-15 11:15+0200\n" "PO-Revision-Date: 2011-10-31 20:21+0200\n" "Last-Translator: Radek Stastny \n" "Language-Team: Czech \n" "Language: cs\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "Channel groups" msgstr "Skupiny stanic" msgid "Button$Select" msgstr "Vyber" msgid "Channel group used by:" msgstr "Skupina použitá v:" msgid "Edit$Delete group?" msgstr "Smazat Skupinu stanic?" msgid "Edit channel group" msgstr "Uravit Skupinu stanic" msgid "Group name" msgstr "Jméno skupiny" msgid "Button$Invert selection" msgstr "Inverzní výběr" msgid "Button$All yes" msgstr "Ano vše" msgid "Button$All no" msgstr "Ne vše" msgid "Group name is empty!" msgstr "Jméno nemůže být prázdné!" msgid "Group name already exists!" msgstr "Jméno již použito!" msgid "Direct access to epgsearch's conflict check menu" msgstr "Přímý vstup do menu konfliktů epgsearch" msgid "Timer conflicts" msgstr "Konflikty v nahrávání" msgid "Conflict info in main menu" msgstr "Konflikty do hlavního menu" msgid "next" msgstr "další" #, c-format msgid "timer conflict at %s! Show it?" msgstr "Konflikt Nahrávání %s! Zobrazit?" #, c-format msgid "%d timer conflicts! First at %s. Show them?" msgstr "Nahrávání - konflikty (%d)! Od %s. Zobrazit?" msgid "search the EPG for repeats and more" msgstr "hledat opakování v programu a další" msgid "Program guide" msgstr "Průvodce programem (EPG)" msgid "search timer update running" msgstr "Probíhá aktualizace Nahrávání" msgid "Direct access to epgsearch's search menu" msgstr "Přímý vstup do menu hledání epgsearch" msgid "Search" msgstr "Automatické nahrávání" msgid "EpgSearch-Search in main menu" msgstr "EpgSearch hledání do hlavního menu" msgid "Button$Help" msgstr "Nápověda" msgid "Standard" msgstr "Výchozí" msgid "Button$Commands" msgstr "Příkazy" msgid "Button$Search" msgstr "Hledat" msgid "never" msgstr "nikdy" msgid "always" msgstr "vždy" msgid "smart" msgstr "chytře" msgid "before user-def. times" msgstr "před uživatelské časy" msgid "after user-def. times" msgstr "po uživatelských časech" msgid "before 'next'" msgstr "před 'Nyní'" msgid "General" msgstr "Základní" msgid "EPG menus" msgstr "Programový průvodce" msgid "User-defined EPG times" msgstr "Nastavení času" msgid "Timer programming" msgstr "Nastavení nahrávání" msgid "Search and search timers" msgstr "Hledání a Automatické nahrávání" msgid "Timer conflict checking" msgstr "Kontrola konfliktů nahrávání" msgid "Email notification" msgstr "Mailové zprávy" msgid "Hide main menu entry" msgstr "Skrýt položku v hlavním menu" msgid "Help$Hides the main menu entry and may be useful if this plugin is used to replace the original 'Schedule' entry." msgstr "Nezobrazovat v hlavním menu, používá se když tento plugin nahrazuje výchozího průvodce programem." msgid "Main menu entry" msgstr "Název položky hlavního menu" msgid "Help$The name of the main menu entry which defaults to 'Programm guide'." msgstr "Jméno položky hlavního menu - výchozí název je Průvodce programem (EPG) " msgid "Replace original schedule" msgstr "Nahradit výchozího průvodce programem" msgid "Help$When VDR is patched to allow this plugin to replace the original 'Schedule' entry, you can de/activate this replacement here." msgstr "Pokud je vdr upraveno, může tento plugin nahradit výchozí položku 'Program'" msgid "Start menu" msgstr "Výchozí menu" msgid "Help$Choose between 'Overview - Now' and 'Schedule' as start menu when this plugin is called." msgstr "Výběr mezi přehledem všech stanic - 'Nyní' a programem aktuální stanice - 'Program'" msgid "Ok key" msgstr "OK tlačítko" msgid "" "Help$Choose here the behaviour of key 'Ok'. You can use it to display the summary or to switch to the corresponding channel.\n" "Note: the functionality of key 'blue' (Switch/Info/Search) depends on this setting." msgstr "" msgid "Red key" msgstr "Červené tlačítko" msgid "" "Help$Choose which standard function ('Record' or 'Commands') you like to have on the red key.\n" "(Can be toggled with key '0')" msgstr "" msgid "Blue key" msgstr "Modré tlačítko" msgid "" "Help$Choose which standard function ('Switch'/'Info' or 'Search') you like to have on the blue key.\n" "(Can be toggled with key '0')" msgstr "" msgid "Show progress in 'Now'" msgstr "Zobrazit časové detaily v přehledu stanic 'Nyní'" msgid "Help$Shows a progressbar in 'Overview - Now' that informs about the remaining time of the current event." msgstr "" msgid "Show channel numbers" msgstr "Zobrazit čísla stanic" msgid "" "Help$Display channel numbers in 'Overview - Now'.\n" "\n" "(To completely define your own menu look please inspect the MANUAL)" msgstr "" msgid "Show channel separators" msgstr "Zobrazit oddělení mezi stanicemi" msgid "Help$Display VDR channel groups as separators between your channels in 'Overview - Now'." msgstr "" msgid "Show day separators" msgstr "Zobrazit oddělení mezi dny" msgid "Help$Display a separator line at day break in 'Schedule'." msgstr "" msgid "Show radio channels" msgstr "Zobrazit radio stanice" msgid "Help$Show also radio channels." msgstr "" msgid "Limit channels from 1 to" msgstr "Omezit zobrazení stanic od 1 do" msgid "Help$If you have a large channel set you can speed up things when you limit the displayed channels with this setting. Use '0' to disable the limit." msgstr "" msgid "'One press' timer creation" msgstr "Vytváření nahrávání 'Jedním stiskem'" msgid "Help$When a timer is created with 'Record' you can choose between an immediate creation of the timer or the display of the timer edit menu." msgstr "" msgid "Show channels without EPG" msgstr "Zobrazit stanice bez programu" msgid "Help$Choose 'yes' here if you want to display channels without EPG in 'Overview - Now'. 'Ok' on these entries switches the channel." msgstr "" msgid "Time interval for FRew/FFwd [min]" msgstr "Posun v průvodci po FRew/FFwd [min]" msgid "" "Help$Choose here the time interval which should be used for jumping through the EPG by pressing FRew/FFwd.\n" "\n" "(If you don't have those keys, you can toggle to this functionality pressing '0' and get '<<' and '>>' on the keys green and yellow)" msgstr "" msgid "Toggle Green/Yellow" msgstr "Prohodit Zelené/Žluté" msgid "Help$Specify if green and yellow shall also be switched when pressing '0'." msgstr "" msgid "Show favorites menu" msgstr "Zobrazovat volbu Oblíbené" msgid "" "Help$A favorites menu can display a list of your favorite broadcasts. Enable this if you want an additional menu besides 'Now' and 'Next'\n" "Any search can be used as a favorite. You only have to set the option 'Use in favorites menu' when editing a search." msgstr "" msgid "for the next ... hours" msgstr "na příštích ... hodin" msgid "Help$This value controls the timespan used to display your favorites." msgstr "" msgid "Use user-defined time" msgstr "Uživateské časy" msgid "Help$Besides 'Now' and 'Next' you can specify up to 4 other times in the EPG which can be used by repeatedly pressing the green key, e.g. 'prime time', 'late night',..." msgstr "" msgid "Description" msgstr "Popis" msgid "Help$This is the description for your user-defined time as it will appear as label on the green button." msgstr "" msgid "Time" msgstr "Čas" msgid "Help$Specify the user-defined time here in 'HH:MM'." msgstr "" msgid "Use VDR's timer edit menu" msgstr "Použít výchozí menu pro nahrávání" msgid "" "Help$This plugin has its own timer edit menu extending the original one with some extra functionality like\n" "- an additional directory entry\n" "- user-defined days of week for repeating timers\n" "- adding an episode name\n" "- support for EPG variables (see MANUAL)" msgstr "" msgid "Default recording dir" msgstr "Výchozí adresář pro nahrávky" msgid "Help$When creating a timer you can specify here a default recording directory." msgstr "" msgid "Add episode to manual timers" msgstr "Přidávat název dílu do Nahrávání" msgid "" "Help$If you create a timer for a series, you can automatically add the episode name.\n" "\n" "- never: no addition\n" "- always: always add episode name if present\n" "- smart: add only if event lasts less than 80 mins." msgstr "" msgid "Default timer check method" msgstr "Výchozí kontrola plán. Nahrávání" msgid "" "Help$Manual timers can be checked for EPG changes. Here you can setup the default check method for each channel. Choose between\n" "\n" "- no checking\n" "- by event ID: checks by an event ID supplied by the channel provider.\n" "- by channel and time: check by the duration match." msgstr "" msgid "Button$Setup" msgstr "Nastavení" msgid "Use search timers" msgstr "Používat Automatické nahrávání" msgid "Help$'Search timers' can be used to automatically create timers for events that match your search criterions." msgstr "" msgid " Update interval [min]" msgstr " Interval mezi hledáním [min]" msgid "Help$Specify here the time intervall to be used when searching for events in the background." msgstr "" msgid " SVDRP port" msgstr "" msgid "Help$Programming of new timers or timer changes is done with SVDRP. The default value should be correct, so change it only if you know what you are doing." msgstr "" msgid "Help$Specify here the default priority of timers created with this plugin. This value can also be adjusted for each search itself." msgstr "" msgid "Help$Specify here the default lifetime of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "" msgid "Help$Specify here the default start recording margin of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "" msgid "Help$Specify here the default stop recording margin of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "" msgid "No announcements when replaying" msgstr "Nezobrazovat infromace při přehrávání" msgid "Help$Set this to 'yes' if you don't like to get any announcements of broadcasts if you currently replay anything." msgstr "" msgid "Recreate timers after deletion" msgstr "Znovu vytvořit Nahrávání i po smazání" msgid "Help$Set this to 'yes' if you want timers to be recreated with the next search timer update after deleting them." msgstr "" msgid "Check if EPG exists for ... [h]" msgstr "Kontrolvat zda je .. [h] programu" msgid "Help$Specify how many hours of future EPG there should be and get warned else after a search timer update." msgstr "" msgid "Warn by OSD" msgstr "Informovat na obrazovce" msgid "Help$Set this to 'yes' if you want get warnings from the EPG check via OSD." msgstr "" msgid "Warn by mail" msgstr "Informovat mailem" msgid "Help$Set this to 'yes' if you want get warnings from the EPG check by mail." msgstr "" msgid "Channel group to check" msgstr "Skupina stanic ke hledání" msgid "Help$Specify the channel group to check." msgstr "" msgid "Ignore PayTV channels" msgstr "Ignorovat placené stanice" msgid "Help$Set this to 'yes' if don't want to see events on PayTV channels when searching for repeats." msgstr "" msgid "Search templates" msgstr "Vzory pro hledání" msgid "Help$Here you can setup templates for your searches." msgstr "" msgid "Blacklists" msgstr "Černé listiny (blacklist)" msgid "Help$Here you can setup blacklists which can be used within a search to exclude events you don't like." msgstr "" msgid "Help$Here you can setup channel groups which can be used within a search. These are different to VDR channel groups and represent a set of arbitrary channels, e.g. 'FreeTV'." msgstr "" msgid "Ignore below priority" msgstr "Ignorovat prioritu pod" msgid "Help$If a timer with priority below the given value will fail it will not be classified as important. Only important conflicts will produce an OSD message about the conflict after an automatic conflict check." msgstr "" msgid "Ignore conflict duration less ... min." msgstr "Vynechat konflikty kratší než ... min" msgid "Help$If a conflicts duration is less then the given number of minutes it will not be classified as important. Only important conflicts will produce an OSD message about the conflict after an automatic conflict check." msgstr "" msgid "Only check within next ... days" msgstr "Kontrolovat pouze během dalších . dní" msgid "Help$This value reduces the conflict check to the given range of days. All other conflicts are classified as 'not yet important'." msgstr "" msgid "Check also remote conflicts" msgstr "" msgid "Help$Set this to 'yes' if the conflict check should be done for timers set on remote hosts. This needs SVDRPPeering to be set in vdr and Plugin epgsearch running on the remote host." msgstr "" msgid "--- Automatic checking ---" msgstr "--- Automatická kontrola ---" msgid "After each timer programming" msgstr "Po vytvoření Nahrávání" msgid "Help$Set this to 'yes' if the conflict check should be performed after each manual timer programming. In the case of a conflict you get immediately a message that informs you about it. The message is only displayed if this timer is involved in any conflict." msgstr "" msgid "When a recording starts" msgstr "Když začne nahrávání" msgid "Help$Set this to 'yes' if the conflict check should be performed when a recording starts. In the case of a conflict you get immediately a message that informs you about it. The message is only displayed if the conflict is within the next 2 hours." msgstr "" msgid "After each search timer update" msgstr "Po každém hledání" msgid "Help$Set this to 'yes' if the conflict check should be performed after each search timer update." msgstr "" msgid "every ... minutes" msgstr "každých ... minut" msgid "" "Help$Specify here the time intervall to be used for an automatic conflict check in the background.\n" "('0' disables an automatic check)" msgstr "" msgid "if conflicts within next ... minutes" msgstr "pokud je konflikt během dalších ... minut" msgid "Help$If the next conflict will appear in the given number of minutes you can specify here a shorter check intervall to get more OSD notifications about it." msgstr "" msgid "Avoid notification when replaying" msgstr "Neinformaovat na obrazovce při přehrávání" msgid "Help$Set this to 'yes' if the don't want to get OSD messages about conflicts if you currently replay something. Nevertheless messages will be displayed if the first upcoming conflict is within the next 2 hours." msgstr "" msgid "Search timer notification" msgstr "Informovat o vytvoření Nahrávání" msgid "Help$Set this to 'yes' if you want to get an email notification about the search timers that where programmed automatically in the background." msgstr "" msgid "Time between mails [h]" msgstr "Interval mezi maily [h]" msgid "" "Help$Specifiy how much time in [h] you would\n" "like to have atleast between two mails.\n" "With '0' you get a new mail after each\n" "search timer update with new results." msgstr "" msgid "Timer conflict notification" msgstr "Informovat o konfliktech Nahrávání" msgid "Help$Set this to 'yes' if you want to get an email notification about the timer conflicts." msgstr "" msgid "Send to" msgstr "Adresát" msgid "Help$Specify the email address where notifications should be sent to." msgstr "" msgid "Mail method" msgstr "Způsob odeslání" msgid "" "Help$Specify here the method to use when sending mails.\n" "You can choose between\n" " - 'sendmail': requires a properly configured email system\n" " - 'SendEmail.pl': simple script for mail delivery" msgstr "" msgid "--- Email account ---" msgstr "--- Email účet ---" msgid "Email address" msgstr "adresa" msgid "Help$Specify the email address where notifications should be sent from." msgstr "" msgid "SMTP server" msgstr "SMTP server" msgid "Help$Specify the SMTP server that should deliver the notifications. If it's using a port different from the default(25) append the port with \":port\"." msgstr "" msgid "Use SMTP authentication" msgstr "Použít SMTP authentifikaci" msgid "Help$Set this to 'yes' if your account needs authentication to send mails." msgstr "" msgid "Auth user" msgstr "uživatel" msgid "Help$Specify the auth user, if this account needs authentication for SMTP." msgstr "" msgid "Auth password" msgstr "heslo" msgid "Help$Specify the auth password, if this account needs authentication for SMTP." msgstr "" msgid "Mail account check failed!" msgstr "Kontrola účtu selhala" msgid "Button$Test" msgstr "Test" msgid "$ abcdefghijklmnopqrstuvwxyz0123456789-.,#~\\^$[]|()*+?{}/:%@&_" msgstr "" msgid "Start/Stop time has changed" msgstr "Změnil se čas Začátku/konce" msgid "Title/episode has changed" msgstr "Změnil se Název/název dílu" msgid "No new timers were added." msgstr "Nevytvořeno nové Nahrávání." msgid "No timers were modified." msgstr "Neupraveno žádné Nahrávání." msgid "No timers were deleted." msgstr "Žádné nahrávání nebylo smazané." msgid "No new events to announce." msgstr "Zádné nová událost k oznámení. " msgid "This version of EPGSearch does not support this service!" msgstr "Tato verze EPGsearch nepodporuje tuto službu!" msgid "EPGSearch does not exist!" msgstr "EPGsearch neexistuje!" #, c-format msgid "%d new broadcast" msgstr "%d nové vysílání" msgid "Button$by channel" msgstr "Dle stanic" msgid "Button$by time" msgstr "Dle času" msgid "Button$Episode" msgstr "Název dílu" msgid "Button$Title" msgstr "Název" msgid "announce details" msgstr "informovat o podrobostech" msgid "announce again" msgstr "informovat znovu" msgid "with next update" msgstr "při dalších změnách" msgid "again from" msgstr "znovu od" msgid "Search timer" msgstr "Automatické nahrávání" msgid "Edit blacklist" msgstr "Upravit blacklist" msgid "phrase" msgstr "fráze" msgid "all words" msgstr "všechna slova" msgid "at least one word" msgstr "alespoň jedno slovo" msgid "match exactly" msgstr "přesný výraz" msgid "regular expression" msgstr "regulární výraz" msgid "fuzzy" msgstr "" msgid "user-defined" msgstr "více dní" msgid "interval" msgstr "" msgid "channel group" msgstr "skupina kanálů" msgid "only FTA" msgstr "jen volné" msgid "Search term" msgstr "Vyhledej" msgid "Search mode" msgstr "Vyhledávací režim" msgid "Tolerance" msgstr "" msgid "Match case" msgstr "Velikost písmen" msgid "Use title" msgstr "Název" msgid "Use subtitle" msgstr "Název dílu" msgid "Use description" msgstr "Popis" msgid "Use extended EPG info" msgstr "Použít rozšířené EPG informace" msgid "Ignore missing categories" msgstr "Ignorovat chybějící kategorie." msgid "Use channel" msgstr "Stanice" msgid " from channel" msgstr " od" msgid " to channel" msgstr " do" msgid "Channel group" msgstr "Skupina stanic" msgid "Use time" msgstr "Čas" msgid " Start after" msgstr " Začíná po" msgid " Start before" msgstr " Začíná před" msgid "Use duration" msgstr "Délka" msgid " Min. duration" msgstr " Min. délka" msgid " Max. duration" msgstr " Max. délka" msgid "Use day of week" msgstr "Den v týdnu" msgid "Day of week" msgstr "Den" msgid "Use global" msgstr "Použít globálně" msgid "Button$Templates" msgstr "Vzory" msgid "*** Invalid Channel ***" msgstr "*** špatná stanice ***" msgid "Please check channel criteria!" msgstr "Zkontrolujte nastavení stanic!" msgid "Edit$Delete blacklist?" msgstr "Smazat blacklist?" msgid "Repeats" msgstr "Opakování" msgid "Create search" msgstr "Vytvořit Hledání" msgid "Search in recordings" msgstr "Hledat v nahrávkách?" msgid "Mark as 'already recorded'?" msgstr "Označit jako 'již nahrané'" msgid "Add/Remove to/from switch list?" msgstr "Upravit seznam přepnutí?" msgid "Create blacklist" msgstr "Vytvořit blacklist" msgid "EPG Commands" msgstr "EPG příkazy" msgid "Epgsearch: RemoteTimerModifications failed" msgstr "" msgid "Already running!" msgstr "Již běží!" msgid "Add to switch list?" msgstr "Přidat do seznamu přepnutí?" msgid "Delete from switch list?" msgstr "Smazat ze seznamu přepnutí?" msgid "Button$Details" msgstr "Detaily" msgid "Button$Filter" msgstr "Filtr" msgid "Button$Show all" msgstr "Zobrazit vše" msgid "conflicts" msgstr "konflikty" msgid "no conflicts!" msgstr "žádné konflikty!" msgid "no important conflicts!" msgstr "zádné důležité konflikty!" msgid "C" msgstr "C" msgid "Button$Repeats" msgstr "Opakování" msgid "no check" msgstr "žádná kontrola" msgid "by channel and time" msgstr "dle stanice a času" msgid "by event ID" msgstr "dle ID události" msgid "Select directory" msgstr "Vyber adresář" msgid "Button$Level" msgstr "Úroveň" msgid "Event" msgstr "Událost" msgid "Favorites" msgstr "Oblíbené" msgid "Search results" msgstr "Výsledky hledání" msgid "Timer conflict! Show?" msgstr "Konflikt Nahrávání! Zobrazit?" msgid "Directory" msgstr "Adresář" msgid "Channel" msgstr "Stanice" msgid "Childlock" msgstr "Dětská pojistka" msgid "Record on" msgstr "" msgid "Timer check" msgstr "Kontrola Nahrávání" msgid "recording with device" msgstr "nahrávat zařízením" msgid "Button$With subtitle" msgstr "S Názvem dílu" msgid "Button$Without subtitle" msgstr "Bez Názvu dílu" msgid "Timer has been deleted" msgstr "" msgid "Button$Extended" msgstr "Rozšířené" msgid "Button$Simple" msgstr "Výchozí" msgid "Use blacklists" msgstr "Použít blacklist" msgid "Edit$Search text too short - use anyway?" msgstr "Text je příliš krátký - přesto použít?" #, fuzzy msgid "Button$Orphaned" msgstr "Dle stanic" msgid "Button$by name" msgstr "dle jména" msgid "Button$by date" msgstr "dle data" msgid "Button$Delete all" msgstr "Smazat vše" msgid "Recordings" msgstr "Nahrávky" msgid "Edit$Delete entry?" msgstr "Smazat?" msgid "Edit$Delete all entries?" msgstr "Smazat vše?" msgid "Summary" msgstr "Shrnutí" msgid "Auxiliary info" msgstr "Pomocné info" msgid "Button$Aux info" msgstr "Pom. info" msgid "Search actions" msgstr "Akce hledání" msgid "Execute search" msgstr "Hledat" msgid "Use as search timer on/off" msgstr "Povolit/Zakázat" msgid "Trigger search timer update" msgstr "Hledat změny" msgid "Show recordings done" msgstr "Zobrazit nahrávky" msgid "Show timers created" msgstr "Zobrazit Nahrávání" msgid "Create a copy" msgstr "Vytvořit kopii" msgid "Use as template" msgstr "Použít jako vzor" msgid "Show switch list" msgstr "Zobrazit seznam přepnutí" msgid "Show blacklists" msgstr "Zobrazit blacklisty" msgid "Delete created timers?" msgstr "Smazat vytvorená Nahrávání?" msgid "Timer conflict check" msgstr "Kontrola konfliktů" msgid "Disable associated timers too?" msgstr "Zakázat i vytvořená Nahrávání?" msgid "Activate associated timers too?" msgstr "Povolit i již vytvořená Nahrávání?" msgid "Search timers activated in setup." msgstr "Automatické nahrávání povoleno v nastavení." msgid "Run search timer update?" msgstr "Aktualizovat automatické nahrávání?" msgid "Copy this entry?" msgstr "Kopírovat položku?" msgid "Copy" msgstr "Kopírovat" msgid "Copy this entry to templates?" msgstr "Zkopírovat do vzorů?" msgid "Delete all timers created from this search?" msgstr "Smazat všechna Nahrávání z tohoto hledání?" msgid "Button$Actions" msgstr "Akce" msgid "Search entries" msgstr "Vyhledat položky" msgid "active" msgstr "povoleno" msgid "Edit$Delete search?" msgstr "Smazat?" msgid "Edit search" msgstr "Upravit hledání" msgid "Record" msgstr "Nahrát" msgid "Announce by OSD" msgstr "Informovat na obrazovce" msgid "Switch only" msgstr "Přepnout" msgid "Announce and switch" msgstr "Informovat a přepnout" msgid "Announce by mail" msgstr "Informovat mailem" msgid "Inactive record" msgstr "" msgid "only globals" msgstr "globální" msgid "Selection" msgstr "výběr" msgid "all" msgstr "vše" msgid "count recordings" msgstr "počítat nahrávky" msgid "count days" msgstr "počítat dny" msgid "if present" msgstr "pokud existuje" msgid "same day" msgstr "stejný den" msgid "same week" msgstr "stejný týden" msgid "same month" msgstr "stejný měsíc" msgid "Template name" msgstr "Jméno vzoru" msgid "Help$Specify the name of the template." msgstr "" msgid "Help$Specify here the term to search for." msgstr "" msgid "" "Help$The following search modes exist:\n" "\n" "- phrase: searches for sub terms\n" "- all words: all single words must appear\n" "- at least one word: at least one single word must appear\n" "- match exactly: must match exactly\n" "- regular expression: match a regular expression\n" "- fuzzy searching: searches approximately" msgstr "" msgid "Help$This sets the tolerance of fuzzy searching. The value represents the allowed errors." msgstr "" msgid "Help$Set this to 'Yes' if your search should match the case." msgstr "" msgid "Help$Set this to 'Yes' if you like to search in the title of an event." msgstr "" msgid "Help$Set this to 'Yes' if you like to search in the episode of an event." msgstr "" msgid "Help$Set this to 'Yes' if you like to search in the summary of an event." msgstr "" msgid "Use content descriptor" msgstr "Použít popis obsahu" msgid "Help$Set this to 'Yes' if you want to search the contents by a descriptor." msgstr "" msgid "Help$The summary of an event, can contain additional information like 'Genre', 'Category', 'Year',... called 'EPG categories' within EPGSearch. External EPG providers often deliver this information. This allows refining a search and other nice things, like searching for the 'tip of the day'. To use it set this to 'Yes'." msgstr "" msgid "Help$The file epgsearchcats.conf specifies the search mode for this entry. One can search by text or by value. You can also edit a list of predefined values in this file that can be selected here." msgstr "" msgid "Help$If a selected category is not part of the summary of an event this normally excludes this event from the search results. To avoid this, set this option to 'Yes', but please handle this with care to avoid a huge amount of results." msgstr "" msgid "Use in favorites menu" msgstr "Zobrazit v Oblíbených" msgid "Result menu layout" msgstr "Způsob zobrazení výsledků" msgid "Use as search timer" msgstr "Použít pro Automatické nahrávání" msgid "Action" msgstr "Akce" msgid "Switch ... minutes before start" msgstr "Přepnout ... minut před začátkem" msgid "Unmute sound" msgstr "Zrušit ztišení" msgid "Ask ... minutes before start" msgstr "Zeptat se ... minut před začátkem" msgid " Series recording" msgstr " Nahrávání sériálu" msgid "Delete recordings after ... days" msgstr "Smazat nahrávku po ... dnech" msgid "Keep ... recordings" msgstr "Ponechat ... nahrávek" msgid "Pause when ... recordings exist" msgstr "Vynechat pokud uloženo ... nahrávek" msgid "Avoid repeats" msgstr "Přeskočit opakování" msgid "Allowed repeats" msgstr "Povolených opakování" msgid "Only repeats within ... days" msgstr "Opakovat po ... dnech" msgid "Compare title" msgstr "Porovnat název" msgid "Compare subtitle" msgstr "Porovnat Název dílu" msgid "Compare summary" msgstr "Porovnat popis" msgid "Min. match in %" msgstr "Odpovídá na ... %" msgid "Compare date" msgstr "Porovnat datum" msgid "Compare categories" msgstr "Porovnat kategorii" msgid "VPS" msgstr "" msgid "Auto delete" msgstr "Automatické smazání" msgid "after ... recordings" msgstr "po ... nahrávkách" msgid "after ... days after first rec." msgstr "po ... dnech po první nahrávce" msgid "Edit user-defined days of week" msgstr "Upravit použité dny" msgid "Compare" msgstr "Porovnat" msgid "Select blacklists" msgstr "Vybrat blacklisty" msgid "Values for EPG category" msgstr "EPG kategorie" msgid "Button$Apply" msgstr "Použít" msgid "less" msgstr "menší" msgid "less or equal" msgstr "menší nebo stejný" msgid "greater" msgstr "větší" msgid "greater or equal" msgstr "větší nebo stejný" msgid "equal" msgstr "stejný" msgid "not equal" msgstr "jiný" msgid "Activation of search timer" msgstr "Povolit Automatické nahrávání?" msgid "First day" msgstr "První den" msgid "Last day" msgstr "Poslední den" msgid "Button$all channels" msgstr "Všechny stanice" msgid "Button$only FTA" msgstr "Jen volné" msgid "Button$Timer preview" msgstr "Náhled Nahrávání" msgid "Blacklist results" msgstr "Výsledky blacklist" msgid "found recordings" msgstr "nalezených nahrávek" msgid "Error while accessing recording!" msgstr "Chyba při přístupu k nahrávce!" msgid "Button$Default" msgstr "Výchozí" msgid "Edit$Delete template?" msgstr "Smazat vzor?" msgid "Overwrite existing entries?" msgstr "Přepsat existující položky!" msgid "Edit entry" msgstr "Upravit položku" msgid "Switch" msgstr "Přepnout" msgid "Announce only" msgstr "Informovat" msgid "Announce ... minutes before start" msgstr "Informovat ... minut předem" msgid "action at" msgstr "v" msgid "Switch list" msgstr "Seznam přepnutí" msgid "Edit template" msgstr "Upravit vzor" msgid "Timers" msgstr "Nahrávání" msgid ">>> no info! <<<" msgstr ">>> bez informací <<<" msgid "Overview" msgstr "Přehled" msgid "Button$Favorites" msgstr "Oblíbené" msgid "Quick search for broadcasts" msgstr "Rychlé hledání vysílání" msgid "Quick search" msgstr "Rychlé hledání" msgid "Show in main menu" msgstr "Zobrazit v hlavním menu" #, c-format msgid "%d new broadcast(s) found! Show them?" msgstr "Nalezeno %d nových vysílání! Zobrazit?" msgid "Search timer update done!" msgstr "Aktualizace Nahrávání dokončena!" #, c-format msgid "small EPG content on:%s" msgstr "krátký EPG obsah: %s" msgid "VDR EPG check warning" msgstr "Varování kontroly VDR EPG" #, c-format msgid "Switch to (%d) '%s'?" msgstr "Přepnout na (%d) '%s'?" msgid "Programming timer failed!" msgstr "Nastavení nahrávání selhalo!" #~ msgid "in %02ldd" #~ msgstr "%02ldd" #~ msgid "in %02ldh" #~ msgstr "%02ldh" #~ msgid "in %02ldm" #~ msgstr "%02ldm" vdr-plugin-epgsearch/po/nn_NO.po0000644000175000017500000005726613145412721016435 0ustar tobiastobias# VDR plugin language source file. # Copyright (C) 2007 Klaus Schmidinger # This file is distributed under the same license as the VDR package. # Jørgen Tvedt , 2001 # Truls Slevigen , 2002 # msgid "" msgstr "" "Project-Id-Version: VDR 1.5.7\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-06-15 11:15+0200\n" "PO-Revision-Date: 2007-08-14 20:21+0200\n" "Last-Translator: Truls Slevigen \n" "Language-Team: Norwegian Nynorsk \n" "Language: nn\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "Channel groups" msgstr "" msgid "Button$Select" msgstr "" msgid "Channel group used by:" msgstr "" msgid "Edit$Delete group?" msgstr "" msgid "Edit channel group" msgstr "" msgid "Group name" msgstr "" msgid "Button$Invert selection" msgstr "" msgid "Button$All yes" msgstr "" msgid "Button$All no" msgstr "" msgid "Group name is empty!" msgstr "" msgid "Group name already exists!" msgstr "" msgid "Direct access to epgsearch's conflict check menu" msgstr "" msgid "Timer conflicts" msgstr "" msgid "Conflict info in main menu" msgstr "" msgid "next" msgstr "" #, c-format msgid "timer conflict at %s! Show it?" msgstr "" #, c-format msgid "%d timer conflicts! First at %s. Show them?" msgstr "" msgid "search the EPG for repeats and more" msgstr "" msgid "Program guide" msgstr "" msgid "search timer update running" msgstr "" msgid "Direct access to epgsearch's search menu" msgstr "" msgid "Search" msgstr "" msgid "EpgSearch-Search in main menu" msgstr "" msgid "Button$Help" msgstr "" msgid "Standard" msgstr "" msgid "Button$Commands" msgstr "" msgid "Button$Search" msgstr "" msgid "never" msgstr "" msgid "always" msgstr "" msgid "smart" msgstr "" msgid "before user-def. times" msgstr "" msgid "after user-def. times" msgstr "" msgid "before 'next'" msgstr "" msgid "General" msgstr "" msgid "EPG menus" msgstr "" msgid "User-defined EPG times" msgstr "" msgid "Timer programming" msgstr "" msgid "Search and search timers" msgstr "" msgid "Timer conflict checking" msgstr "" msgid "Email notification" msgstr "" msgid "Hide main menu entry" msgstr "" msgid "Help$Hides the main menu entry and may be useful if this plugin is used to replace the original 'Schedule' entry." msgstr "" msgid "Main menu entry" msgstr "" msgid "Help$The name of the main menu entry which defaults to 'Programm guide'." msgstr "" msgid "Replace original schedule" msgstr "" msgid "Help$When VDR is patched to allow this plugin to replace the original 'Schedule' entry, you can de/activate this replacement here." msgstr "" msgid "Start menu" msgstr "" msgid "Help$Choose between 'Overview - Now' and 'Schedule' as start menu when this plugin is called." msgstr "" msgid "Ok key" msgstr "" msgid "" "Help$Choose here the behaviour of key 'Ok'. You can use it to display the summary or to switch to the corresponding channel.\n" "Note: the functionality of key 'blue' (Switch/Info/Search) depends on this setting." msgstr "" msgid "Red key" msgstr "" msgid "" "Help$Choose which standard function ('Record' or 'Commands') you like to have on the red key.\n" "(Can be toggled with key '0')" msgstr "" msgid "Blue key" msgstr "" msgid "" "Help$Choose which standard function ('Switch'/'Info' or 'Search') you like to have on the blue key.\n" "(Can be toggled with key '0')" msgstr "" msgid "Show progress in 'Now'" msgstr "" msgid "Help$Shows a progressbar in 'Overview - Now' that informs about the remaining time of the current event." msgstr "" msgid "Show channel numbers" msgstr "" msgid "" "Help$Display channel numbers in 'Overview - Now'.\n" "\n" "(To completely define your own menu look please inspect the MANUAL)" msgstr "" msgid "Show channel separators" msgstr "" msgid "Help$Display VDR channel groups as separators between your channels in 'Overview - Now'." msgstr "" msgid "Show day separators" msgstr "" msgid "Help$Display a separator line at day break in 'Schedule'." msgstr "" msgid "Show radio channels" msgstr "" msgid "Help$Show also radio channels." msgstr "" msgid "Limit channels from 1 to" msgstr "" msgid "Help$If you have a large channel set you can speed up things when you limit the displayed channels with this setting. Use '0' to disable the limit." msgstr "" msgid "'One press' timer creation" msgstr "" msgid "Help$When a timer is created with 'Record' you can choose between an immediate creation of the timer or the display of the timer edit menu." msgstr "" msgid "Show channels without EPG" msgstr "" msgid "Help$Choose 'yes' here if you want to display channels without EPG in 'Overview - Now'. 'Ok' on these entries switches the channel." msgstr "" msgid "Time interval for FRew/FFwd [min]" msgstr "" msgid "" "Help$Choose here the time interval which should be used for jumping through the EPG by pressing FRew/FFwd.\n" "\n" "(If you don't have those keys, you can toggle to this functionality pressing '0' and get '<<' and '>>' on the keys green and yellow)" msgstr "" msgid "Toggle Green/Yellow" msgstr "" msgid "Help$Specify if green and yellow shall also be switched when pressing '0'." msgstr "" msgid "Show favorites menu" msgstr "" msgid "" "Help$A favorites menu can display a list of your favorite broadcasts. Enable this if you want an additional menu besides 'Now' and 'Next'\n" "Any search can be used as a favorite. You only have to set the option 'Use in favorites menu' when editing a search." msgstr "" msgid "for the next ... hours" msgstr "" msgid "Help$This value controls the timespan used to display your favorites." msgstr "" msgid "Use user-defined time" msgstr "" msgid "Help$Besides 'Now' and 'Next' you can specify up to 4 other times in the EPG which can be used by repeatedly pressing the green key, e.g. 'prime time', 'late night',..." msgstr "" msgid "Description" msgstr "" msgid "Help$This is the description for your user-defined time as it will appear as label on the green button." msgstr "" msgid "Time" msgstr "" msgid "Help$Specify the user-defined time here in 'HH:MM'." msgstr "" msgid "Use VDR's timer edit menu" msgstr "" msgid "" "Help$This plugin has its own timer edit menu extending the original one with some extra functionality like\n" "- an additional directory entry\n" "- user-defined days of week for repeating timers\n" "- adding an episode name\n" "- support for EPG variables (see MANUAL)" msgstr "" msgid "Default recording dir" msgstr "" msgid "Help$When creating a timer you can specify here a default recording directory." msgstr "" msgid "Add episode to manual timers" msgstr "" msgid "" "Help$If you create a timer for a series, you can automatically add the episode name.\n" "\n" "- never: no addition\n" "- always: always add episode name if present\n" "- smart: add only if event lasts less than 80 mins." msgstr "" msgid "Default timer check method" msgstr "" msgid "" "Help$Manual timers can be checked for EPG changes. Here you can setup the default check method for each channel. Choose between\n" "\n" "- no checking\n" "- by event ID: checks by an event ID supplied by the channel provider.\n" "- by channel and time: check by the duration match." msgstr "" msgid "Button$Setup" msgstr "Konfigurasjon" msgid "Use search timers" msgstr "" msgid "Help$'Search timers' can be used to automatically create timers for events that match your search criterions." msgstr "" msgid " Update interval [min]" msgstr "" msgid "Help$Specify here the time intervall to be used when searching for events in the background." msgstr "" msgid " SVDRP port" msgstr "" msgid "Help$Programming of new timers or timer changes is done with SVDRP. The default value should be correct, so change it only if you know what you are doing." msgstr "" msgid "Help$Specify here the default priority of timers created with this plugin. This value can also be adjusted for each search itself." msgstr "" msgid "Help$Specify here the default lifetime of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "" msgid "Help$Specify here the default start recording margin of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "" msgid "Help$Specify here the default stop recording margin of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "" msgid "No announcements when replaying" msgstr "" msgid "Help$Set this to 'yes' if you don't like to get any announcements of broadcasts if you currently replay anything." msgstr "" msgid "Recreate timers after deletion" msgstr "" msgid "Help$Set this to 'yes' if you want timers to be recreated with the next search timer update after deleting them." msgstr "" msgid "Check if EPG exists for ... [h]" msgstr "" msgid "Help$Specify how many hours of future EPG there should be and get warned else after a search timer update." msgstr "" msgid "Warn by OSD" msgstr "" msgid "Help$Set this to 'yes' if you want get warnings from the EPG check via OSD." msgstr "" msgid "Warn by mail" msgstr "" msgid "Help$Set this to 'yes' if you want get warnings from the EPG check by mail." msgstr "" msgid "Channel group to check" msgstr "" msgid "Help$Specify the channel group to check." msgstr "" msgid "Ignore PayTV channels" msgstr "" msgid "Help$Set this to 'yes' if don't want to see events on PayTV channels when searching for repeats." msgstr "" msgid "Search templates" msgstr "" msgid "Help$Here you can setup templates for your searches." msgstr "" msgid "Blacklists" msgstr "" msgid "Help$Here you can setup blacklists which can be used within a search to exclude events you don't like." msgstr "" msgid "Help$Here you can setup channel groups which can be used within a search. These are different to VDR channel groups and represent a set of arbitrary channels, e.g. 'FreeTV'." msgstr "" msgid "Ignore below priority" msgstr "" msgid "Help$If a timer with priority below the given value will fail it will not be classified as important. Only important conflicts will produce an OSD message about the conflict after an automatic conflict check." msgstr "" msgid "Ignore conflict duration less ... min." msgstr "" msgid "Help$If a conflicts duration is less then the given number of minutes it will not be classified as important. Only important conflicts will produce an OSD message about the conflict after an automatic conflict check." msgstr "" msgid "Only check within next ... days" msgstr "" msgid "Help$This value reduces the conflict check to the given range of days. All other conflicts are classified as 'not yet important'." msgstr "" msgid "Check also remote conflicts" msgstr "" msgid "Help$Set this to 'yes' if the conflict check should be done for timers set on remote hosts. This needs SVDRPPeering to be set in vdr and Plugin epgsearch running on the remote host." msgstr "" msgid "--- Automatic checking ---" msgstr "" msgid "After each timer programming" msgstr "" msgid "Help$Set this to 'yes' if the conflict check should be performed after each manual timer programming. In the case of a conflict you get immediately a message that informs you about it. The message is only displayed if this timer is involved in any conflict." msgstr "" msgid "When a recording starts" msgstr "" msgid "Help$Set this to 'yes' if the conflict check should be performed when a recording starts. In the case of a conflict you get immediately a message that informs you about it. The message is only displayed if the conflict is within the next 2 hours." msgstr "" msgid "After each search timer update" msgstr "" msgid "Help$Set this to 'yes' if the conflict check should be performed after each search timer update." msgstr "" msgid "every ... minutes" msgstr "" msgid "" "Help$Specify here the time intervall to be used for an automatic conflict check in the background.\n" "('0' disables an automatic check)" msgstr "" msgid "if conflicts within next ... minutes" msgstr "" msgid "Help$If the next conflict will appear in the given number of minutes you can specify here a shorter check intervall to get more OSD notifications about it." msgstr "" msgid "Avoid notification when replaying" msgstr "" msgid "Help$Set this to 'yes' if the don't want to get OSD messages about conflicts if you currently replay something. Nevertheless messages will be displayed if the first upcoming conflict is within the next 2 hours." msgstr "" msgid "Search timer notification" msgstr "" msgid "Help$Set this to 'yes' if you want to get an email notification about the search timers that where programmed automatically in the background." msgstr "" msgid "Time between mails [h]" msgstr "" msgid "" "Help$Specifiy how much time in [h] you would\n" "like to have atleast between two mails.\n" "With '0' you get a new mail after each\n" "search timer update with new results." msgstr "" msgid "Timer conflict notification" msgstr "" msgid "Help$Set this to 'yes' if you want to get an email notification about the timer conflicts." msgstr "" msgid "Send to" msgstr "" msgid "Help$Specify the email address where notifications should be sent to." msgstr "" msgid "Mail method" msgstr "" msgid "" "Help$Specify here the method to use when sending mails.\n" "You can choose between\n" " - 'sendmail': requires a properly configured email system\n" " - 'SendEmail.pl': simple script for mail delivery" msgstr "" msgid "--- Email account ---" msgstr "" msgid "Email address" msgstr "" msgid "Help$Specify the email address where notifications should be sent from." msgstr "" msgid "SMTP server" msgstr "" msgid "Help$Specify the SMTP server that should deliver the notifications. If it's using a port different from the default(25) append the port with \":port\"." msgstr "" msgid "Use SMTP authentication" msgstr "" msgid "Help$Set this to 'yes' if your account needs authentication to send mails." msgstr "" msgid "Auth user" msgstr "" msgid "Help$Specify the auth user, if this account needs authentication for SMTP." msgstr "" msgid "Auth password" msgstr "" msgid "Help$Specify the auth password, if this account needs authentication for SMTP." msgstr "" msgid "Mail account check failed!" msgstr "" msgid "Button$Test" msgstr "" msgid "$ abcdefghijklmnopqrstuvwxyz0123456789-.,#~\\^$[]|()*+?{}/:%@&_" msgstr "" msgid "Start/Stop time has changed" msgstr "" msgid "Title/episode has changed" msgstr "" msgid "No new timers were added." msgstr "" msgid "No timers were modified." msgstr "" msgid "No timers were deleted." msgstr "" msgid "No new events to announce." msgstr "" msgid "This version of EPGSearch does not support this service!" msgstr "" msgid "EPGSearch does not exist!" msgstr "" #, c-format msgid "%d new broadcast" msgstr "" msgid "Button$by channel" msgstr "" msgid "Button$by time" msgstr "" msgid "Button$Episode" msgstr "" msgid "Button$Title" msgstr "" msgid "announce details" msgstr "" msgid "announce again" msgstr "" msgid "with next update" msgstr "" msgid "again from" msgstr "" msgid "Search timer" msgstr "" msgid "Edit blacklist" msgstr "" msgid "phrase" msgstr "" msgid "all words" msgstr "" msgid "at least one word" msgstr "" msgid "match exactly" msgstr "" msgid "regular expression" msgstr "" msgid "fuzzy" msgstr "" msgid "user-defined" msgstr "" msgid "interval" msgstr "" msgid "channel group" msgstr "" msgid "only FTA" msgstr "" msgid "Search term" msgstr "" msgid "Search mode" msgstr "" msgid "Tolerance" msgstr "" msgid "Match case" msgstr "" msgid "Use title" msgstr "" msgid "Use subtitle" msgstr "" msgid "Use description" msgstr "" msgid "Use extended EPG info" msgstr "" msgid "Ignore missing categories" msgstr "" msgid "Use channel" msgstr "" msgid " from channel" msgstr "" msgid " to channel" msgstr "" msgid "Channel group" msgstr "" msgid "Use time" msgstr "" msgid " Start after" msgstr "" msgid " Start before" msgstr "" msgid "Use duration" msgstr "" msgid " Min. duration" msgstr "" msgid " Max. duration" msgstr "" msgid "Use day of week" msgstr "" msgid "Day of week" msgstr "" msgid "Use global" msgstr "" msgid "Button$Templates" msgstr "" msgid "*** Invalid Channel ***" msgstr "" msgid "Please check channel criteria!" msgstr "" msgid "Edit$Delete blacklist?" msgstr "" msgid "Repeats" msgstr "" msgid "Create search" msgstr "" msgid "Search in recordings" msgstr "" msgid "Mark as 'already recorded'?" msgstr "" msgid "Add/Remove to/from switch list?" msgstr "" msgid "Create blacklist" msgstr "" msgid "EPG Commands" msgstr "" msgid "Epgsearch: RemoteTimerModifications failed" msgstr "" msgid "Already running!" msgstr "" msgid "Add to switch list?" msgstr "" msgid "Delete from switch list?" msgstr "" msgid "Button$Details" msgstr "" msgid "Button$Filter" msgstr "Suodata" msgid "Button$Show all" msgstr "" msgid "conflicts" msgstr "" msgid "no conflicts!" msgstr "" msgid "no important conflicts!" msgstr "" msgid "C" msgstr "C" msgid "Button$Repeats" msgstr "" msgid "no check" msgstr "" msgid "by channel and time" msgstr "" msgid "by event ID" msgstr "" msgid "Select directory" msgstr "" msgid "Button$Level" msgstr "" msgid "Event" msgstr "" msgid "Favorites" msgstr "" msgid "Search results" msgstr "" msgid "Timer conflict! Show?" msgstr "" msgid "Directory" msgstr "" msgid "Channel" msgstr "" msgid "Childlock" msgstr "" msgid "Record on" msgstr "" msgid "Timer check" msgstr "" msgid "recording with device" msgstr "" msgid "Button$With subtitle" msgstr "" msgid "Button$Without subtitle" msgstr "" msgid "Timer has been deleted" msgstr "" msgid "Button$Extended" msgstr "" msgid "Button$Simple" msgstr "" msgid "Use blacklists" msgstr "" msgid "Edit$Search text too short - use anyway?" msgstr "" msgid "Button$Orphaned" msgstr "" msgid "Button$by name" msgstr "" msgid "Button$by date" msgstr "" msgid "Button$Delete all" msgstr "" msgid "Recordings" msgstr "" msgid "Edit$Delete entry?" msgstr "" msgid "Edit$Delete all entries?" msgstr "" msgid "Summary" msgstr "" msgid "Auxiliary info" msgstr "" msgid "Button$Aux info" msgstr "" msgid "Search actions" msgstr "" msgid "Execute search" msgstr "" msgid "Use as search timer on/off" msgstr "" msgid "Trigger search timer update" msgstr "" msgid "Show recordings done" msgstr "" msgid "Show timers created" msgstr "" msgid "Create a copy" msgstr "" msgid "Use as template" msgstr "" msgid "Show switch list" msgstr "" msgid "Show blacklists" msgstr "" msgid "Delete created timers?" msgstr "" msgid "Timer conflict check" msgstr "" msgid "Disable associated timers too?" msgstr "" msgid "Activate associated timers too?" msgstr "" msgid "Search timers activated in setup." msgstr "" msgid "Run search timer update?" msgstr "" msgid "Copy this entry?" msgstr "" msgid "Copy" msgstr "" msgid "Copy this entry to templates?" msgstr "" msgid "Delete all timers created from this search?" msgstr "" msgid "Button$Actions" msgstr "" msgid "Search entries" msgstr "" msgid "active" msgstr "" msgid "Edit$Delete search?" msgstr "" msgid "Edit search" msgstr "" msgid "Record" msgstr "Ta opp" msgid "Announce by OSD" msgstr "" msgid "Switch only" msgstr "" msgid "Announce and switch" msgstr "" msgid "Announce by mail" msgstr "" msgid "Inactive record" msgstr "" msgid "only globals" msgstr "" msgid "Selection" msgstr "" msgid "all" msgstr "" msgid "count recordings" msgstr "" msgid "count days" msgstr "" msgid "if present" msgstr "" msgid "same day" msgstr "" msgid "same week" msgstr "" msgid "same month" msgstr "" msgid "Template name" msgstr "" msgid "Help$Specify the name of the template." msgstr "" msgid "Help$Specify here the term to search for." msgstr "" msgid "" "Help$The following search modes exist:\n" "\n" "- phrase: searches for sub terms\n" "- all words: all single words must appear\n" "- at least one word: at least one single word must appear\n" "- match exactly: must match exactly\n" "- regular expression: match a regular expression\n" "- fuzzy searching: searches approximately" msgstr "" msgid "Help$This sets the tolerance of fuzzy searching. The value represents the allowed errors." msgstr "" msgid "Help$Set this to 'Yes' if your search should match the case." msgstr "" msgid "Help$Set this to 'Yes' if you like to search in the title of an event." msgstr "" msgid "Help$Set this to 'Yes' if you like to search in the episode of an event." msgstr "" msgid "Help$Set this to 'Yes' if you like to search in the summary of an event." msgstr "" msgid "Use content descriptor" msgstr "" msgid "Help$Set this to 'Yes' if you want to search the contents by a descriptor." msgstr "" msgid "Help$The summary of an event, can contain additional information like 'Genre', 'Category', 'Year',... called 'EPG categories' within EPGSearch. External EPG providers often deliver this information. This allows refining a search and other nice things, like searching for the 'tip of the day'. To use it set this to 'Yes'." msgstr "" msgid "Help$The file epgsearchcats.conf specifies the search mode for this entry. One can search by text or by value. You can also edit a list of predefined values in this file that can be selected here." msgstr "" msgid "Help$If a selected category is not part of the summary of an event this normally excludes this event from the search results. To avoid this, set this option to 'Yes', but please handle this with care to avoid a huge amount of results." msgstr "" msgid "Use in favorites menu" msgstr "" msgid "Result menu layout" msgstr "" msgid "Use as search timer" msgstr "" msgid "Action" msgstr "" msgid "Switch ... minutes before start" msgstr "" msgid "Unmute sound" msgstr "" msgid "Ask ... minutes before start" msgstr "" msgid " Series recording" msgstr "" msgid "Delete recordings after ... days" msgstr "" msgid "Keep ... recordings" msgstr "" msgid "Pause when ... recordings exist" msgstr "" msgid "Avoid repeats" msgstr "" msgid "Allowed repeats" msgstr "" msgid "Only repeats within ... days" msgstr "" msgid "Compare title" msgstr "" msgid "Compare subtitle" msgstr "" msgid "Compare summary" msgstr "" msgid "Min. match in %" msgstr "" msgid "Compare date" msgstr "" msgid "Compare categories" msgstr "" msgid "VPS" msgstr "" msgid "Auto delete" msgstr "" msgid "after ... recordings" msgstr "" msgid "after ... days after first rec." msgstr "" msgid "Edit user-defined days of week" msgstr "" msgid "Compare" msgstr "" msgid "Select blacklists" msgstr "" msgid "Values for EPG category" msgstr "" msgid "Button$Apply" msgstr "" msgid "less" msgstr "" msgid "less or equal" msgstr "" msgid "greater" msgstr "" msgid "greater or equal" msgstr "" msgid "equal" msgstr "" msgid "not equal" msgstr "" msgid "Activation of search timer" msgstr "" msgid "First day" msgstr "" msgid "Last day" msgstr "" msgid "Button$all channels" msgstr "" msgid "Button$only FTA" msgstr "" msgid "Button$Timer preview" msgstr "" msgid "Blacklist results" msgstr "" msgid "found recordings" msgstr "" msgid "Error while accessing recording!" msgstr "" msgid "Button$Default" msgstr "" msgid "Edit$Delete template?" msgstr "" msgid "Overwrite existing entries?" msgstr "" msgid "Edit entry" msgstr "" msgid "Switch" msgstr "" msgid "Announce only" msgstr "" msgid "Announce ... minutes before start" msgstr "" msgid "action at" msgstr "" msgid "Switch list" msgstr "" msgid "Edit template" msgstr "" msgid "Timers" msgstr "" msgid ">>> no info! <<<" msgstr "" msgid "Overview" msgstr "" msgid "Button$Favorites" msgstr "" msgid "Quick search for broadcasts" msgstr "" msgid "Quick search" msgstr "" msgid "Show in main menu" msgstr "" #, c-format msgid "%d new broadcast(s) found! Show them?" msgstr "" msgid "Search timer update done!" msgstr "" #, c-format msgid "small EPG content on:%s" msgstr "" msgid "VDR EPG check warning" msgstr "" #, c-format msgid "Switch to (%d) '%s'?" msgstr "" msgid "Programming timer failed!" msgstr "" vdr-plugin-epgsearch/po/de_DE.po0000644000175000017500000012165713145412721016362 0ustar tobiastobias# VDR plugin language source file. # Copyright (C) 2007 Klaus Schmidinger # This file is distributed under the same license as the VDR package. # Klaus Schmidinger , 2000 # msgid "" msgstr "" "Project-Id-Version: VDR 1.5.7\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-06-15 11:33+0200\n" "PO-Revision-Date: 2007-08-14 20:21+0200\n" "Last-Translator: Klaus Schmidinger \n" "Language-Team: German \n" "Language: de\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "Channel groups" msgstr "Kanalgruppen" msgid "Button$Select" msgstr "Auswahl" msgid "Channel group used by:" msgstr "Gruppe wird verwendet von:" msgid "Edit$Delete group?" msgstr "Gruppe löschen?" msgid "Edit channel group" msgstr "Kanalgruppe editieren" msgid "Group name" msgstr "Gruppenname" msgid "Button$Invert selection" msgstr "Ausw. umdrehen" msgid "Button$All yes" msgstr "Alle ja" msgid "Button$All no" msgstr "Alle nein" msgid "Group name is empty!" msgstr "Gruppenname ist leer!" msgid "Group name already exists!" msgstr "Gruppe existiert bereits!" msgid "Direct access to epgsearch's conflict check menu" msgstr "Direkter Zugriff auf epgsearch's Konflikt-Prüfungs-Menü" msgid "Timer conflicts" msgstr "Timer-Konflikte" msgid "Conflict info in main menu" msgstr "Konflikt-Info im Hauptmenü" msgid "next" msgstr "nächster" #, c-format msgid "timer conflict at %s! Show it?" msgstr "Timer-Konflikt am %s! Anzeigen?" #, c-format msgid "%d timer conflicts! First at %s. Show them?" msgstr "%d Timer-Konflikte! Erster am %s. Anzeigen?" msgid "search the EPG for repeats and more" msgstr "Suche im EPG nach Wiederholungen und anderem" msgid "Program guide" msgstr "Programmführer" msgid "search timer update running" msgstr "Suchtimer-Update läuft" msgid "Direct access to epgsearch's search menu" msgstr "Direkter Zugriff auf epgsearch's Suchenmenu" msgid "Search" msgstr "Suche" msgid "EpgSearch-Search in main menu" msgstr "EpgSearch-Suche im Hauptmenü" msgid "Button$Help" msgstr "Hilfe" msgid "Standard" msgstr "Standard" msgid "Button$Commands" msgstr "Befehle" msgid "Button$Search" msgstr "Suche" msgid "never" msgstr "nie" msgid "always" msgstr "immer" msgid "smart" msgstr "intelligent" msgid "before user-def. times" msgstr "vor ben.-def. Zeiten" msgid "after user-def. times" msgstr "nach ben.-def. Zeiten" msgid "before 'next'" msgstr "vor 'Nächste'" msgid "General" msgstr "Allgemein" msgid "EPG menus" msgstr "EPG Menüs" msgid "User-defined EPG times" msgstr "Benutzerdef. EPG-Zeiten" msgid "Timer programming" msgstr "Timer-Programmierung" msgid "Search and search timers" msgstr "Suche und Suchtimer" msgid "Timer conflict checking" msgstr "Timer-Konflikt-Prüfung" msgid "Email notification" msgstr "Email-Benachrichtigung" msgid "Hide main menu entry" msgstr "Hauptmenüeintrag verstecken" msgid "Help$Hides the main menu entry and may be useful if this plugin is used to replace the original 'Schedule' entry." msgstr "Blendet den Hauptmenüeintrag aus. Das kann nützlich sein, falls dieses Plugin verwendet wird, um den originalen 'Programm'-Eintrag zu ersetzen." msgid "Main menu entry" msgstr "Hauptmenü-Eintrag" msgid "Help$The name of the main menu entry which defaults to 'Programm guide'." msgstr "Der Name des Hauptmenüeintrags. Die Standard-Vorgabe ist 'Programmführer'." msgid "Replace original schedule" msgstr "Originale Programmübersicht ersetzen" msgid "Help$When VDR is patched to allow this plugin to replace the original 'Schedule' entry, you can de/activate this replacement here." msgstr "Falls VDR gepatched wurde, um dem Plugin zu erlauben, den originalen 'Programm'-Eintrag zu ersetzen, so kann hier diese Ersetzung de/aktiviert werden." msgid "Start menu" msgstr "Starte mit" msgid "Help$Choose between 'Overview - Now' and 'Schedule' as start menu when this plugin is called." msgstr "Hier kann zwischen 'Übersicht - Jetzt' und 'Programm' als Start-Menü für das Plugin gewählt werden." msgid "Ok key" msgstr "Taste Ok" msgid "" "Help$Choose here the behaviour of key 'Ok'. You can use it to display the summary or to switch to the corresponding channel.\n" "Note: the functionality of key 'blue' (Switch/Info/Search) depends on this setting." msgstr "" "Hier kann das Verhalten der 'Ok'-Taste bestimmt werden. Man kann damit die Inhaltsangabe anzeigen oder zum entsprechenden Sender wechseln.\n" "Hinweis: Die Funktion der Taste 'Blau' (Umschalten/Info/Suche) hängt von dieser Einstellung ab." msgid "Red key" msgstr "Taste Rot" msgid "" "Help$Choose which standard function ('Record' or 'Commands') you like to have on the red key.\n" "(Can be toggled with key '0')" msgstr "" "Hier kann ausgewählt werden, welche Standardfunktion ('Aufnehmen' oder 'Befehle') auf der roten Taste liegen soll.\n" "(Umschalten auch mit Taste '0' möglich)" msgid "Blue key" msgstr "Taste Blau" msgid "" "Help$Choose which standard function ('Switch'/'Info' or 'Search') you like to have on the blue key.\n" "(Can be toggled with key '0')" msgstr "" "Hier kann ausgewählt werden, welche Standardfunktion ('Umschalten'/'Info' oder 'Suche') auf der blauen Taste liegen soll.\n" "(Umschalten auch mit Taste '0' möglich)" msgid "Show progress in 'Now'" msgstr "Zeige Fortschritt in 'Jetzt'" msgid "Help$Shows a progressbar in 'Overview - Now' that informs about the remaining time of the current event." msgstr "Zeigt einen Fortschrittsbalken in 'Übersicht - Jetzt' an, der wiedergibt wieweit die Sendung bereits fortgeschritten ist." msgid "Show channel numbers" msgstr "Zeige Kanalnummern" msgid "" "Help$Display channel numbers in 'Overview - Now'.\n" "\n" "(To completely define your own menu look please inspect the MANUAL)" msgstr "" "Anzeige von Kanalnummern in 'Übersicht - Jetzt'.\n" "\n" "(Zur vollständigen Anpassung einer eigenen Menüdarstellung, bitte das MANUAL lesen)" msgid "Show channel separators" msgstr "Zeige Kanal-Separatoren" msgid "Help$Display VDR channel groups as separators between your channels in 'Overview - Now'." msgstr "Anzeige von VDR-Kanalgruppen als Trennlinien zwischen den Programmen in 'Übersicht - Jetzt'." msgid "Show day separators" msgstr "Zeige Tages-Separatoren" msgid "Help$Display a separator line at day break in 'Schedule'." msgstr "Anzeige von Trennlinien beim Datumswechsel in der Programmübersicht." msgid "Show radio channels" msgstr "Zeige Radiokanäle" msgid "Help$Show also radio channels." msgstr "Auch Radio-Kanäle anzeigen." msgid "Limit channels from 1 to" msgstr "Kanäle begrenzen von 1 bis" msgid "Help$If you have a large channel set you can speed up things when you limit the displayed channels with this setting. Use '0' to disable the limit." msgstr "Bei einer sehr großen Kanalliste läßt sich der Menü-Aufbau mit dieser Einstellung durch eine Einschränkung der angezeigten Kanäle beschleunigen. Mit '0' wird das Limit aufgehoben." msgid "'One press' timer creation" msgstr "Timer mit 'Aufnehmen' sofort anlegen" msgid "Help$When a timer is created with 'Record' you can choose between an immediate creation of the timer or the display of the timer edit menu." msgstr "Beim Erzeugen eines Timers mit 'Aufnehmen' kann hier zwischen dem sofortigen Anlegen des Timers oder der Anzeige des Timer-Edit-Menüs gewählt werden." msgid "Show channels without EPG" msgstr "Zeige Kanäle ohne EPG" msgid "Help$Choose 'yes' here if you want to display channels without EPG in 'Overview - Now'. 'Ok' on these entries switches the channel." msgstr "Hier kann eingestellt werden, ob auch Programme ohne EPG in 'Übersicht - Jetzt' erscheinen sollen. Ein 'Ok' auf diesen Einträgen schaltet zu diesem Kanal um." msgid "Time interval for FRew/FFwd [min]" msgstr "Zeitintervall für FRew/FFwd [min]" msgid "" "Help$Choose here the time interval which should be used for jumping through the EPG by pressing FRew/FFwd.\n" "\n" "(If you don't have those keys, you can toggle to this functionality pressing '0' and get '<<' and '>>' on the keys green and yellow)" msgstr "" "Hier kann die Zeitspanne eingestellt werden, die beim Drücken von FRew/FFwd als Sprung durch den EPG benutzt werden soll.\n" "\n" "(Falls diese Tasten nicht vorhanden sind, kann mit '0' ebenfalls diese Funktion erreicht werden. Man erhält dann '<<' und '>>' auf den Tasten Grün/Gelb)" msgid "Toggle Green/Yellow" msgstr "Grün/Gelb umschalten" msgid "Help$Specify if green and yellow shall also be switched when pressing '0'." msgstr "Hiermit wird angegeben, ob die Tasten Grün/Gelb beim Drücken von '0' mitumgeschaltet werden sollen." msgid "Show favorites menu" msgstr "Zeige Favoriten-Menü" msgid "" "Help$A favorites menu can display a list of your favorite broadcasts. Enable this if you want an additional menu besides 'Now' and 'Next'\n" "Any search can be used as a favorite. You only have to set the option 'Use in favorites menu' when editing a search." msgstr "" "Ein Favoriten-Menü kann eine Liste der Lieblingssendungen anzeigen. Hier auswählen, wenn neben 'Jetzt' und 'Nächste' ein solches Menü gewünscht wird.\n" "Jede Suche kann als Favorit verwendet werden. Dazu einfach die Option 'In Favoritenmenü verw.' beim Editieren einer Suche setzen." msgid "for the next ... hours" msgstr "für die nächsten ... Stunden" msgid "Help$This value controls the timespan used to display your favorites." msgstr "Mit diesem Wert wird die Zeitspanne eingestellt, für die Favoriten angezeigt werden sollen." msgid "Use user-defined time" msgstr "Verw. benutzerdef. Zeit" msgid "Help$Besides 'Now' and 'Next' you can specify up to 4 other times in the EPG which can be used by repeatedly pressing the green key, e.g. 'prime time', 'late night',..." msgstr "Neben 'Jetzt' und 'Nächste' können bis zu 4 weitere Zeiten im EPG angegeben werden, die durch wiederholtes Drücken der Taste Grün verwendet werden können, z.B. 'Abends', 'Spätabend',..." msgid "Description" msgstr "Beschreibung" msgid "Help$This is the description for your user-defined time as it will appear as label on the green button." msgstr "Dies ist die Beschreibung für die benutzer-definierte Zeit, wie sie als Beschriftung für die Taste Grün verwendet werden soll." msgid "Time" msgstr "Zeit" msgid "Help$Specify the user-defined time here in 'HH:MM'." msgstr "Hier wird die benutzer-definierte Zeit im Format 'HH:MM' angegeben." msgid "Use VDR's timer edit menu" msgstr "VDR's Timer-Edit-Menu verw." msgid "" "Help$This plugin has its own timer edit menu extending the original one with some extra functionality like\n" "- an additional directory entry\n" "- user-defined days of week for repeating timers\n" "- adding an episode name\n" "- support for EPG variables (see MANUAL)" msgstr "" "Diese Plugin hat sein eigenes Timer-Edit-Menü, das das orginale um einige zusätzliche Funktionen erweitert:\n" "\n" "- ein zusätzlicher Verzeichniseintrag\n" "- benutzerdef. Wochentage für Wiederh.-Timer\n" "- Ergänzung um Episodenname\n" "- Unterstützung von EPG-Variablen (s.MANUAL)" msgid "Default recording dir" msgstr "Standard Aufn.-Verzeichnis" msgid "Help$When creating a timer you can specify here a default recording directory." msgstr "Beim Anlegen eines Timers kann hier ein Standard-Aufnahmeverzeichnis vorgegeben werden." msgid "Add episode to manual timers" msgstr "Untertitel in manuellen Timern" msgid "" "Help$If you create a timer for a series, you can automatically add the episode name.\n" "\n" "- never: no addition\n" "- always: always add episode name if present\n" "- smart: add only if event lasts less than 80 mins." msgstr "" "Wenn man einen Timer für eine Serie erzeugt, kann mit dieser Option automatisch der Episodenname ergänzt werden.\n" "\n" "- niemals: keine Ergänzung\n" "- immer: immer ergänzen, falls Episodenname vorhanden.\n" "- intelligent: nur ergänzen, wenn Sendung weniger als 80 min dauert" msgid "Default timer check method" msgstr "Standard-Timer-Prüfmethode" msgid "" "Help$Manual timers can be checked for EPG changes. Here you can setup the default check method for each channel. Choose between\n" "\n" "- no checking\n" "- by event ID: checks by an event ID supplied by the channel provider.\n" "- by channel and time: check by the duration match." msgstr "" "Manuelle Timer können hinsichtlich EPG-Änderungen überwacht werden. Hier kann die Standard-Prüfmethode für jeden Kanal hinterlegt werden. Zur Wahl stehen:\n" "\n" "- keine Prüfung\n" "- anhand Sendungskennung: geprüft wird anhand einer Kennung, die durch den Sender vergeben wird.\n" "- anhand Sender/Uhrzeit: geprüft wird anhand der Sendung, die am besten zur Dauer der ursprünglichen Sendung passt." msgid "Button$Setup" msgstr "Einstellungen" msgid "Use search timers" msgstr "Verwende Suchtimer" msgid "Help$'Search timers' can be used to automatically create timers for events that match your search criterions." msgstr "'Suchtimer' können verwendet werden um automatisch Timer für Sendungen zu erstellen, die von einer Suche gefunden werden." msgid " Update interval [min]" msgstr " Aktualisierungsintervall [min]" msgid "Help$Specify here the time intervall to be used when searching for events in the background." msgstr "Hier kann das Zeitintervall angegeben werden, in dem im Hintergrund automatisch nach neuen Sendungen gesucht werden soll." msgid " SVDRP port" msgstr " SVDRP Port" msgid "Help$Programming of new timers or timer changes is done with SVDRP. The default value should be correct, so change it only if you know what you are doing." msgstr "Die Programmierung neuer Timer oder Timer-Änderungen erfolgt mit SVDRP. Der Vorgabewert hier sollte immer korrekt sein, also nur ändern, wenn man weiß, was man tut." msgid "Help$Specify here the default priority of timers created with this plugin. This value can also be adjusted for each search itself." msgstr "Hier wird die Standard-Priorität für Timer angegeben, die von diesem Plugin erzeugt werden. Dieser Wert kann aber auch bei jeder Suche einzeln gesetzt werden." msgid "Help$Specify here the default lifetime of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "Hier wird die Standard-Lebensdauer für Timer angegeben, die von diesem Plugin erzeugt werden. Dieser Wert kann aber auch bei jeder Suche einzeln gesetzt werden." msgid "Help$Specify here the default start recording margin of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "Hier wird die Standard-Vorlaufzeit für Timer angegeben, die von diesem Plugin erzeugt werden. Dieser Wert kann aber auch bei jeder Suche einzeln gesetzt werden." msgid "Help$Specify here the default stop recording margin of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "Hier wird die Standard-Nachlaufzeit für Timer angegeben, die von diesem Plugin erzeugt werden. Dieser Wert kann aber auch bei jeder Suche einzeln gesetzt werden." msgid "No announcements when replaying" msgstr "Keine Ankündigungen bei Wiedergabe" msgid "Help$Set this to 'yes' if you don't like to get any announcements of broadcasts if you currently replay anything." msgstr "Bitte auf 'Ja' setzen, wenn während einer Wiedergabe keine Ankündigungen über Sendungen erwünscht sind." msgid "Recreate timers after deletion" msgstr "Timer nach Löschen neuprogrammieren" msgid "Help$Set this to 'yes' if you want timers to be recreated with the next search timer update after deleting them." msgstr "Hier 'Ja' wählen, wenn gelöschte Timer mit dem nächsten Suchtimer-Update neu programmiert werden sollen." msgid "Check if EPG exists for ... [h]" msgstr "Prüfe ob EPG für ... [h] existiert" msgid "Help$Specify how many hours of future EPG there should be and get warned else after a search timer update." msgstr "Hier kann angeben werden wie viele Stunden zukünftigen EPGs existieren sollen und andernfalls nach einem Suchtimer Update gewarnt werden." msgid "Warn by OSD" msgstr "per OSD warnen" msgid "Help$Set this to 'yes' if you want get warnings from the EPG check via OSD." msgstr "Hier mit 'Ja' auswählen, ob eine Warnung zum EPG Check per OSD gewünscht ist." msgid "Warn by mail" msgstr "per Mail warnen" msgid "Help$Set this to 'yes' if you want get warnings from the EPG check by mail." msgstr "Hier mit 'Ja' auswählen, ob eine Warnung zum EPG Check per Mail gewünscht ist." msgid "Channel group to check" msgstr "zu prüfende Kanalgruppe" msgid "Help$Specify the channel group to check." msgstr "Hier die zu prüfende Kanalgruppe auswählen." msgid "Ignore PayTV channels" msgstr "PayTV-Sender ignorieren" msgid "Help$Set this to 'yes' if don't want to see events on PayTV channels when searching for repeats." msgstr "Um bei der Suche nach Wiederholungen Sendungen von PayTV-Kanälen zu ignorieren, kann hier die Option auf 'Ja' gesetzt werden." msgid "Search templates" msgstr "Such-Vorlagen" msgid "Help$Here you can setup templates for your searches." msgstr "Hier können Vorlagen für Suchen erstellt werden." msgid "Blacklists" msgstr "Ausschlusslisten" msgid "Help$Here you can setup blacklists which can be used within a search to exclude events you don't like." msgstr "Hiermit können Ausschlusslisten erstellt werden, die innerhalb einer Suche verwendet werden können, um Sendungen auszuschließen, die man nicht haben will." msgid "Help$Here you can setup channel groups which can be used within a search. These are different to VDR channel groups and represent a set of arbitrary channels, e.g. 'FreeTV'." msgstr "Hier können Kanalgruppen erstellt werden, die innerhalb einer Suche verwendet werden können. Die Kanalgruppen sind nicht mit den VDR-Kanalgruppen zu vergleichen, sondern stellen einfach eine Gruppe von beliebigen Sendern dar, z.B. 'FreeTV'." msgid "Ignore below priority" msgstr "Ignoriere unter Priorität" msgid "Help$If a timer with priority below the given value will fail it will not be classified as important. Only important conflicts will produce an OSD message about the conflict after an automatic conflict check." msgstr "Falls ein Timer fehlschlagen wird, dessen Priorität unter dem angegeben Wert liegt, wird er als 'nicht wichtig' eingestuft. Nur bei wichtigen Konflikten erfolgt eine Nachricht per OSD bei der automatischen Konfliktprüfung." msgid "Ignore conflict duration less ... min." msgstr "Ignoriere Konfliktdauer unter ... Min." msgid "Help$If a conflicts duration is less then the given number of minutes it will not be classified as important. Only important conflicts will produce an OSD message about the conflict after an automatic conflict check." msgstr "Falls die Konfliktdauer unter der angegebenen Anzahl an Minuten liegt, wird er als 'nicht wichtig' eingestuft. Nur bei wichtigen Konflikten erfolgt eine Nachricht per OSD bei der automatischen Konfliktprüfung." msgid "Only check within next ... days" msgstr "Prüfe nur die nächsten ... Tage" msgid "Help$This value reduces the conflict check to the given range of days. All other conflicts are classified as 'not yet important'." msgstr "Mit diesem Wert kann der Zeitbereich der Konfliktprüfung eingestellt werden. Alle Konflikte ausserhalb des Bereichs werden als 'noch nicht wichtig' eingestuft." msgid "Check also remote conflicts" msgstr "Konflikte auch für Remote-Timer prüfen" msgid "Help$Set this to 'yes' if the conflict check should be done for timers set on remote hosts. This needs SVDRPPeering to be set in vdr and Plugin epgsearch running on the remote host." msgstr "Mit 'ja' wird der Konfliktcheck auf für Timer auf entfernten Rechnern gemacht. Dazu muss SVDRPPeering gesetzt sein und das Plugin epgsearch am entfernten Rechner laufen" msgid "--- Automatic checking ---" msgstr "--- Automatische Prüfung ---" msgid "After each timer programming" msgstr "Nach jeder Timer-Programmierung" msgid "Help$Set this to 'yes' if the conflict check should be performed after each manual timer programming. In the case of a conflict you get immediately a message that informs you about it. The message is only displayed if this timer is involved in any conflict." msgstr "Hier auf 'Ja' setzen, wenn die Konfliktprüfung nach jeder manuellen Timer-Programmierung erfolgen soll. Im Falle eines Konflikts wird dann sofort eine Nachricht angezeigt. Diese erscheint nur, wenn dieser Timer in einen Konflikt verwickelt ist." msgid "When a recording starts" msgstr "Beim Beginn einer Aufnahme" msgid "Help$Set this to 'yes' if the conflict check should be performed when a recording starts. In the case of a conflict you get immediately a message that informs you about it. The message is only displayed if the conflict is within the next 2 hours." msgstr "Hier auf 'Ja' setzen, wenn die Konfliktprüfung beim Beginn jeder Aufnahme erfolgen soll. Im Falle eines Konflikts wird dann sofort eine Nachricht angezeigt. Diese erscheint nur, wenn der Konflikt innerhalb der nächsten 2 Stunden auftritt." msgid "After each search timer update" msgstr "Nach jedem Suchtimer-Update" msgid "Help$Set this to 'yes' if the conflict check should be performed after each search timer update." msgstr "Hier auf 'Ja' setzen, wenn die Konfliktprüfung nach jedem Suchtimer-Update erfolgen soll." msgid "every ... minutes" msgstr "alle ... Minuten" msgid "" "Help$Specify here the time intervall to be used for an automatic conflict check in the background.\n" "('0' disables an automatic check)" msgstr "" "Hier kann das Zeitintervall angegeben werden, in dem eine automatische Konfliktprüfung im Hintergrund erfolgen soll.\n" "(mit '0' wird die automatsiche Prüfung deaktiviert.)" msgid "if conflicts within next ... minutes" msgstr "Wenn nächster Konflikt in ... Minuten" msgid "Help$If the next conflict will appear in the given number of minutes you can specify here a shorter check intervall to get more OSD notifications about it." msgstr "Wenn der nächste Konflikt innerhalb der angegebenen Anzahl von Minuten liegt, kann man hiermit ein kürzeres Prüfintervall angeben, damit man häufiger über den Konflikt per OSD benachrichtigt wird." msgid "Avoid notification when replaying" msgstr "Vermeide Nachricht bei Wiedergabe" msgid "Help$Set this to 'yes' if the don't want to get OSD messages about conflicts if you currently replay something. Nevertheless messages will be displayed if the first upcoming conflict is within the next 2 hours." msgstr "Bitte auf 'Ja' setzen, wenn während einer Wiedergabe keine OSD-Benachrichtigungen über Timer-Konflikte gewünscht sind. Die Benachrichtigung erfolgt trotzdem, wenn der nächste Konflikt innerhalb der nächsten 2 Stunden auftritt." msgid "Search timer notification" msgstr "Suchtimer-Benachrichtigung" msgid "Help$Set this to 'yes' if you want to get an email notification about the search timers that where programmed automatically in the background." msgstr "Hier mit 'Ja' auswählen, ob eine Email-Benachrichtigung über automatisch im Hintergrund programmierte Suchtimer versandt werden soll." msgid "Time between mails [h]" msgstr "Zeit zwischen Mails [h]" msgid "" "Help$Specifiy how much time in [h] you would\n" "like to have atleast between two mails.\n" "With '0' you get a new mail after each\n" "search timer update with new results." msgstr "" "Hier die gewünschte Zeit in [h] zwischen\n" "zwei Mails angeben. Mit '0' erhält man eine\n" "neue Mail nach jedem Suchtimer-Update\n" "mit neuen Ergebnissen." msgid "Timer conflict notification" msgstr "Timer-Konflikt-Benachrichtigung" msgid "Help$Set this to 'yes' if you want to get an email notification about the timer conflicts." msgstr "Hier mit 'Ja' auswählen, ob eine Email-Benachrichtigung über Timer-Konflikte versändet werden soll." msgid "Send to" msgstr "Senden an" msgid "Help$Specify the email address where notifications should be sent to." msgstr "Hier wird die Email-Adresse angegeben, an welche die Benachrichtigungen versandt werden." msgid "Mail method" msgstr "Mail-Methode" msgid "" "Help$Specify here the method to use when sending mails.\n" "You can choose between\n" " - 'sendmail': requires a properly configured email system\n" " - 'SendEmail.pl': simple script for mail delivery" msgstr "" "Bitte hier die gewünschte Methode zum Emailversand auswählen. Verfügbar sind:\n" " - 'sendmail': erfordert ein korrekt konfiguriertes Mailsystem\n" " - 'SendEmail.pl': ein einfaches Skript zum Mailversand" msgid "--- Email account ---" msgstr "--- Email-Konto ---" msgid "Email address" msgstr "Email-Adresse" msgid "Help$Specify the email address where notifications should be sent from." msgstr "Hier wird die Email-Adresse angegeben, mit der die Benachrichtigungen versandt werden." msgid "SMTP server" msgstr "SMTP Server" msgid "Help$Specify the SMTP server that should deliver the notifications. If it's using a port different from the default(25) append the port with \":port\"." msgstr "Hier wird der SMTP Server hinterlegt, über den die Benachrichtigungen versandt werden. Falls dieser einen anderen Port als den Standard(25) verwendet, dann mit \":port\" anhängen." msgid "Use SMTP authentication" msgstr "Verw. SMTP-Authentifizierung" msgid "Help$Set this to 'yes' if your account needs authentication to send mails." msgstr "Hier auf 'Ja' setzen, wenn das Emailkonto SMTP-Authentifizierung zum Emailversand benötigt." msgid "Auth user" msgstr "Auth-Benutzer" msgid "Help$Specify the auth user, if this account needs authentication for SMTP." msgstr "Hier wird der Auth-Benutzername angegeben, falls dieses Emailkonto eine Authentifizierung für SMTP benötigt." msgid "Auth password" msgstr "Auth-Passwort" msgid "Help$Specify the auth password, if this account needs authentication for SMTP." msgstr "Hier wird das Auth-Passwort angegeben, falls dieses Emailkonto eine Authentifizierung für SMTP benötigt." msgid "Mail account check failed!" msgstr "Mailkonto-Prüfung fehlgeschlagen!" msgid "Button$Test" msgstr "Test" msgid "$ abcdefghijklmnopqrstuvwxyz0123456789-.,#~\\^$[]|()*+?{}/:%@&_" msgstr " aäbcdefghijklmnoöpqrsßtuüvwxyz0123456789-.,#~\\^$[]|()*+?{}/:%@&_" msgid "Start/Stop time has changed" msgstr "Start/Stop-Zeit hat sich geändert" msgid "Title/episode has changed" msgstr "Titel/Episode hat sich geändert" msgid "No new timers were added." msgstr "Es wurden keine neuen Timer angelegt." msgid "No timers were modified." msgstr "Es wurden keine Timer geändert." msgid "No timers were deleted." msgstr "Es wurden keine Timer gelöscht." msgid "No new events to announce." msgstr "Keine neuen Sendungen anzukündigen." msgid "This version of EPGSearch does not support this service!" msgstr "" msgid "EPGSearch does not exist!" msgstr "" #, c-format msgid "%d new broadcast" msgstr "%d neue Sendung(en)" msgid "Button$by channel" msgstr "nach Programm" msgid "Button$by time" msgstr "nach Beginn" msgid "Button$Episode" msgstr "Episode" msgid "Button$Title" msgstr "Titel" msgid "announce details" msgstr "Ankündigungsdetails" msgid "announce again" msgstr "Erneut ankündigen" msgid "with next update" msgstr "beim nächsten Update" msgid "again from" msgstr "erneut ab" msgid "Search timer" msgstr "Suchtimer" msgid "Edit blacklist" msgstr "Ausschlussliste editieren" msgid "phrase" msgstr "Ausdruck" msgid "all words" msgstr "alle Worte" msgid "at least one word" msgstr "ein Wort" msgid "match exactly" msgstr "exakt" msgid "regular expression" msgstr "regulärer Ausdruck" msgid "fuzzy" msgstr "unscharf" msgid "user-defined" msgstr "benutzerdefiniert" msgid "interval" msgstr "Bereich" msgid "channel group" msgstr "Kanalgruppe" msgid "only FTA" msgstr "ohne PayTV" msgid "Search term" msgstr "Suche" msgid "Search mode" msgstr "Suchmodus" msgid "Tolerance" msgstr "Toleranz" msgid "Match case" msgstr "Groß/klein" msgid "Use title" msgstr "Verw. Titel" msgid "Use subtitle" msgstr "Verw. Untertitel" msgid "Use description" msgstr "Verw. Beschreibung" msgid "Use extended EPG info" msgstr "Verw. erweiterte EPG Info" msgid "Ignore missing categories" msgstr "Ignoriere fehlende Kat." msgid "Use channel" msgstr "Verw. Kanal" msgid " from channel" msgstr " von Kanal" msgid " to channel" msgstr " bis Kanal" msgid "Channel group" msgstr "Kanalgruppe" msgid "Use time" msgstr "Verw. Uhrzeit" msgid " Start after" msgstr " Start nach" msgid " Start before" msgstr " Start vor" msgid "Use duration" msgstr "Verw. Dauer" msgid " Min. duration" msgstr " Min. Dauer" msgid " Max. duration" msgstr " Max. Dauer" msgid "Use day of week" msgstr "Verw. Wochentag" msgid "Day of week" msgstr "Wochentag" msgid "Use global" msgstr "Global verwenden" msgid "Button$Templates" msgstr "Vorlagen" msgid "*** Invalid Channel ***" msgstr "" msgid "Please check channel criteria!" msgstr "Bitte Senderkriterien prüfen!" msgid "Edit$Delete blacklist?" msgstr "Ausschlussliste löschen?" msgid "Repeats" msgstr "Wiederholung" msgid "Create search" msgstr "Suche anlegen" msgid "Search in recordings" msgstr "Suche in Aufnahmen" msgid "Mark as 'already recorded'?" msgstr "als 'bereits aufgezeichnet' markieren?" msgid "Add/Remove to/from switch list?" msgstr "In/Aus Umschaltliste?" msgid "Create blacklist" msgstr "Ausschlussliste anlegen" msgid "EPG Commands" msgstr "EPG Befehle" msgid "Epgsearch: RemoteTimerModifications failed" msgstr "Epgsearch: Problem bei RemoteTimerModifications" msgid "Already running!" msgstr "Läuft bereits!" msgid "Add to switch list?" msgstr "In Umschaltliste aufnehmen?" msgid "Delete from switch list?" msgstr "Aus Umschaltliste entfernen?" msgid "Button$Details" msgstr "Details" msgid "Button$Filter" msgstr "Filter" msgid "Button$Show all" msgstr "Zeige alle" msgid "conflicts" msgstr "Konflikte" msgid "no conflicts!" msgstr "keine Konflikte!" msgid "no important conflicts!" msgstr "keine wichtigen Konflikte!" msgid "C" msgstr "K" msgid "Button$Repeats" msgstr "Wiederh." msgid "no check" msgstr "ohne Überwachung" msgid "by channel and time" msgstr "anhand Sender/Uhrzeit" msgid "by event ID" msgstr "anhand Sendungskennung" msgid "Select directory" msgstr "Verzeichnis wählen" msgid "Button$Level" msgstr "Ebene" msgid "Event" msgstr "" msgid "Favorites" msgstr "Favoriten" msgid "Search results" msgstr "Suchergebnisse" msgid "Timer conflict! Show?" msgstr "Timer-Konflikt! Anzeigen?" msgid "Directory" msgstr "Verzeichnis" msgid "Channel" msgstr "" msgid "Childlock" msgstr "Kindersicherung" msgid "Record on" msgstr "Aufnehmen auf" msgid "Timer check" msgstr "Überwachung" msgid "recording with device" msgstr "Aufnahme mit Gerät" msgid "Button$With subtitle" msgstr "Mit Untertitel" msgid "Button$Without subtitle" msgstr "Ohne Untertitel" msgid "Timer has been deleted" msgstr "Timer wurde gelöscht!" msgid "Button$Extended" msgstr "Erweitert" msgid "Button$Simple" msgstr "Einfach" msgid "Use blacklists" msgstr "Verw. Ausschlusslisten" msgid "Edit$Search text too short - use anyway?" msgstr "Suchtext zu kurz - trotzdem verwenden?" msgid "Button$Orphaned" msgstr "Verwaiste" msgid "Button$by name" msgstr "nach Name" msgid "Button$by date" msgstr "nach Datum" msgid "Button$Delete all" msgstr "Alle löschen" msgid "Recordings" msgstr "" msgid "Edit$Delete entry?" msgstr "Eintrag löschen?" msgid "Edit$Delete all entries?" msgstr "Alle Einträge löschen?" msgid "Summary" msgstr "Inhalt" msgid "Auxiliary info" msgstr "Zusatzinfo" msgid "Button$Aux info" msgstr "Zusatzinfo" msgid "Search actions" msgstr "Suchaktionen" msgid "Execute search" msgstr "Suche ausführen" msgid "Use as search timer on/off" msgstr "Als Suchtimer verwenden an/aus" msgid "Trigger search timer update" msgstr "Suchtimer jetzt aktualisieren" msgid "Show recordings done" msgstr "Zeige erledigte Aufnahmen" msgid "Show timers created" msgstr "Zeige erstellte Timer" msgid "Create a copy" msgstr "Kopie anlegen" msgid "Use as template" msgstr "Als Vorlage verwenden" msgid "Show switch list" msgstr "Zeige Umschaltliste" msgid "Show blacklists" msgstr "Zeige Ausschlusslisten" msgid "Delete created timers?" msgstr "Erstellte Timer löschen?" msgid "Timer conflict check" msgstr "Auf Timer-Konflikte prüfen" msgid "Disable associated timers too?" msgstr "Zugehörige Timer auch deaktivieren?" msgid "Activate associated timers too?" msgstr "Zugehörige Timer auch aktivieren?" msgid "Search timers activated in setup." msgstr "Suchtimer wurden im Setup aktiviert." msgid "Run search timer update?" msgstr "Suchtimer-Update ausführen?" msgid "Copy this entry?" msgstr "Diesen Eintrag kopieren?" msgid "Copy" msgstr "Kopie" msgid "Copy this entry to templates?" msgstr "Diesen Eintrag in Vorlagen kopieren?" msgid "Delete all timers created from this search?" msgstr "Alle Timer löschen, die von dieser Suche erzeugt wurden?" msgid "Button$Actions" msgstr "Aktionen" msgid "Search entries" msgstr "Sucheinträge" msgid "active" msgstr "aktiv" msgid "Edit$Delete search?" msgstr "Suche löschen?" msgid "Edit search" msgstr "Suche editieren" msgid "Record" msgstr "Aufnehmen" msgid "Announce by OSD" msgstr "per OSD ankündigen" msgid "Switch only" msgstr "Nur umschalten" msgid "Announce and switch" msgstr "Ankündigen und Umschalten" msgid "Announce by mail" msgstr "per Mail ankündigen" msgid "Inactive record" msgstr "inaktive Aufnahme" msgid "only globals" msgstr "nur globale" msgid "Selection" msgstr "Auswahl" msgid "all" msgstr "alle" msgid "count recordings" msgstr "Anzahl Aufnahmen" msgid "count days" msgstr "Anzahl Tage" msgid "if present" msgstr "wenn vorhanden" msgid "same day" msgstr "gleicher Tag" msgid "same week" msgstr "gleiche Woche" msgid "same month" msgstr "gleicher Monat" msgid "Template name" msgstr "Vorlagenname" msgid "Help$Specify the name of the template." msgstr "Hier den Namen für die Vorlage angeben." msgid "Help$Specify here the term to search for." msgstr "Hier den Begriff angeben, nach dem gesucht werden soll." msgid "" "Help$The following search modes exist:\n" "\n" "- phrase: searches for sub terms\n" "- all words: all single words must appear\n" "- at least one word: at least one single word must appear\n" "- match exactly: must match exactly\n" "- regular expression: match a regular expression\n" "- fuzzy searching: searches approximately" msgstr "" "Es gibt folgende Such-Modi:\n" "\n" "- Ausdruck: sucht nach einem Teil-Ausdruck\n" "- alle Worte: alle einzelnen Worte müssen auftauchen\n" "- ein Wort: nur ein Wort muss auftauchen\n" "- exakt: genaue Übereinstimmung\n" "- regulärer Ausdruck: sucht nach reg. Ausdruck\n" "- unscharf: sucht nach ungefährer Übereinstimmung" msgid "Help$This sets the tolerance of fuzzy searching. The value represents the allowed errors." msgstr "Hiermit wird die Toleranz für die unscharfe Suche angegeben. Der Wert entspricht den erlaubten Fehlern." msgid "Help$Set this to 'Yes' if your search should match the case." msgstr "Auf 'Ja' setzen, wenn die Suche die Groß-/Kleinschreibung beachtet soll." msgid "Help$Set this to 'Yes' if you like to search in the title of an event." msgstr "Auf 'Ja' setzen, wenn die Suche im Titel einer Sendung stattfinden soll." msgid "Help$Set this to 'Yes' if you like to search in the episode of an event." msgstr "Auf 'Ja' setzen, wenn die Suche im Untertitel einer Sendung stattfinden soll." msgid "Help$Set this to 'Yes' if you like to search in the summary of an event." msgstr "Auf 'Ja' setzen, wenn die Suche in der Zusammenfassung einer Sendung stattfinden soll." msgid "Use content descriptor" msgstr "Verw. Kennung für Inhalt" msgid "Help$Set this to 'Yes' if you want to search the contents by a descriptor." msgstr "Auf 'Ja' setzen, wenn die Suche anhand Kennungen zum Inhalt der Sendung stattfinden soll." msgid "Help$The summary of an event, can contain additional information like 'Genre', 'Category', 'Year',... called 'EPG categories' within EPGSearch. External EPG providers often deliver this information. This allows refining a search and other nice things, like searching for the 'tip of the day'. To use it set this to 'Yes'." msgstr "Die Zusammenfassung einer Sendung kann Zusatz-Informationen wie 'Genre', 'Kategorie', 'Jahr', ... enthalten, welche in EPGSearch 'EPG-Kategorien' genannt werden. Externe EPG-Anbieter liefern diese Informationen häufig mit aus. Damit läßt sich eine Suche verfeinern und auch andere Dinge, wie die Suche nach dem Tagestipp, sind möglich. Zur Verwendung auf 'Ja' setzen." msgid "Help$The file epgsearchcats.conf specifies the search mode for this entry. One can search by text or by value. You can also edit a list of predefined values in this file that can be selected here." msgstr "In der Datei epgsearchcats.conf kann der Suchmodus für diesen Eintrag festgelegt werden. Man kann textuell oder numerisch suchen. Ausserdem kann in dieser Datei eine Liste vordefinierter Werte angegeben werden, die hier zur Auswahl stehen." msgid "Help$If a selected category is not part of the summary of an event this normally excludes this event from the search results. To avoid this, set this option to 'Yes', but please handle this with care to avoid a huge amount of results." msgstr "Falls eine gewählte Kategorie nicht in der Zusammenfassung einer Sendung vorhanden ist, wird diese normalerweise aus den Suchergebnissen ausgeschlossen. Um das zu vermeiden, bitte die Option auf 'Ja' setzen. Aber bitte mit Vorsicht verwenden, um eine riesige Menge an Ergebnissen zu vermeiden." msgid "Use in favorites menu" msgstr "In Favoritenmenü verw." msgid "Result menu layout" msgstr "Layout des Ergebnismenüs" msgid "Use as search timer" msgstr "Als Suchtimer verwenden" msgid "Action" msgstr "Aktion" msgid "Switch ... minutes before start" msgstr "Umschalten ... Minuten vor Start" msgid "Unmute sound" msgstr "Ton anschalten" msgid "Ask ... minutes before start" msgstr "Nachfrage ... Minuten vor Start" msgid " Series recording" msgstr " Serienaufnahme" msgid "Delete recordings after ... days" msgstr "Aufn. nach ... Tagen löschen" msgid "Keep ... recordings" msgstr "Behalte ... Aufnahmen" msgid "Pause when ... recordings exist" msgstr "Pause, wenn ... Aufnahmen exist." msgid "Avoid repeats" msgstr "Vermeide Wiederholung" msgid "Allowed repeats" msgstr "Erlaubte Wiederholungen" msgid "Only repeats within ... days" msgstr "Nur Wiederh. innerhalb ... Tagen" msgid "Compare title" msgstr "Vergleiche Titel" msgid "Compare subtitle" msgstr "Vergleiche Untertitel" msgid "Compare summary" msgstr "Vergleiche Beschreibung" msgid "Min. match in %" msgstr "Min. Übereinstimmung in %" msgid "Compare date" msgstr "Vergleiche Zeitpunkt" msgid "Compare categories" msgstr "Vergl. Kategorien" msgid "VPS" msgstr "" msgid "Auto delete" msgstr "automatisch löschen" msgid "after ... recordings" msgstr "nach ... Aufnahmen" msgid "after ... days after first rec." msgstr "nach ... Tagen nach erster Aufn." msgid "Edit user-defined days of week" msgstr "Benutzerdefinierte Wochentage editieren" msgid "Compare" msgstr "Vergleiche" msgid "Select blacklists" msgstr "Ausschlusslisten auswählen" msgid "Values for EPG category" msgstr "Werte für EPG-Kategorie" msgid "Button$Apply" msgstr "Übernehmen" msgid "less" msgstr "kleiner" msgid "less or equal" msgstr "kleiner oder gleich" msgid "greater" msgstr "größer" msgid "greater or equal" msgstr "größer oder gleich" msgid "equal" msgstr "gleich" msgid "not equal" msgstr "ungleich" msgid "Activation of search timer" msgstr "Aktivierung des Suchtimers" msgid "First day" msgstr "Erster Tag" msgid "Last day" msgstr "Letzter Tag" msgid "Button$all channels" msgstr "mit PayTV" msgid "Button$only FTA" msgstr "ohne PayTV" msgid "Button$Timer preview" msgstr "Timer-Vorsch." msgid "Blacklist results" msgstr "Ausschluss-Ergebnisse" msgid "found recordings" msgstr "gefundene Aufnahmen" msgid "Error while accessing recording!" msgstr "" msgid "Button$Default" msgstr "Standard" msgid "Edit$Delete template?" msgstr "Vorlage löschen?" msgid "Overwrite existing entries?" msgstr "Vorhandene Werte überschreiben?" msgid "Edit entry" msgstr "Eintrag editieren" msgid "Switch" msgstr "Nur umschalten" msgid "Announce only" msgstr "Nur ankündigen" msgid "Announce ... minutes before start" msgstr "Ankündigen ... Minuten vor Start" msgid "action at" msgstr "Ausführung um" msgid "Switch list" msgstr "Umschaltliste" msgid "Edit template" msgstr "Vorlage editieren" msgid "Timers" msgstr "" msgid ">>> no info! <<<" msgstr ">>> keine Info! <<<" msgid "Overview" msgstr "Übersicht" msgid "Button$Favorites" msgstr "Favoriten" msgid "Quick search for broadcasts" msgstr "Schnelle Suche nach Sendungen" msgid "Quick search" msgstr "Schnellsuche" msgid "Show in main menu" msgstr "Im Hauptmenü anzeigen" #, c-format msgid "%d new broadcast(s) found! Show them?" msgstr "%d neue Sendung(en) gefunden! Anzeigen?" msgid "Search timer update done!" msgstr "Suchtimer-Update durchgeführt!" #, c-format msgid "small EPG content on:%s" msgstr "wenig EPG Inhalt für:%s" msgid "VDR EPG check warning" msgstr "VDR EPG Check Warnung" #, c-format msgid "Switch to (%d) '%s'?" msgstr "Umschalten zu (%d) '%s'?" msgid "Programming timer failed!" msgstr "Timer-Programmierung fehlschlagen!" #~ msgid "Epgsearch: recursive TIMERS LOCK" #~ msgstr "Epgsearch: Rekursiver TIMER Lock" #~ msgid "Epgsearch: Recursive LOCK DeleteTimer failed" #~ msgstr "Epgsearch: Rekursiver LOCK Problem beim Löschen eines Timers" #~ msgid "in %02ldd" #~ msgstr "in %02ldd" #~ msgid "in %02ldh" #~ msgstr "in %02ldh" #~ msgid "in %02ldm" #~ msgstr "in %02ldm" vdr-plugin-epgsearch/po/ro_RO.po0000644000175000017500000005730613145412721016441 0ustar tobiastobias# VDR plugin language source file. # Copyright (C) 2007 Klaus Schmidinger # This file is distributed under the same license as the VDR package. # Paul Lacatus , 2002 # Lucian Muresan , 2004 # msgid "" msgstr "" "Project-Id-Version: VDR 1.5.7\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-06-15 11:15+0200\n" "PO-Revision-Date: 2007-08-14 20:21+0200\n" "Last-Translator: Lucian Muresan \n" "Language-Team: Romanian \n" "Language: ro\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "Channel groups" msgstr "" msgid "Button$Select" msgstr "" msgid "Channel group used by:" msgstr "" msgid "Edit$Delete group?" msgstr "" msgid "Edit channel group" msgstr "" msgid "Group name" msgstr "" msgid "Button$Invert selection" msgstr "" msgid "Button$All yes" msgstr "" msgid "Button$All no" msgstr "" msgid "Group name is empty!" msgstr "" msgid "Group name already exists!" msgstr "" msgid "Direct access to epgsearch's conflict check menu" msgstr "" msgid "Timer conflicts" msgstr "" msgid "Conflict info in main menu" msgstr "" msgid "next" msgstr "" #, c-format msgid "timer conflict at %s! Show it?" msgstr "" #, c-format msgid "%d timer conflicts! First at %s. Show them?" msgstr "" msgid "search the EPG for repeats and more" msgstr "" msgid "Program guide" msgstr "" msgid "search timer update running" msgstr "" msgid "Direct access to epgsearch's search menu" msgstr "" msgid "Search" msgstr "" msgid "EpgSearch-Search in main menu" msgstr "" msgid "Button$Help" msgstr "" msgid "Standard" msgstr "" msgid "Button$Commands" msgstr "" msgid "Button$Search" msgstr "" msgid "never" msgstr "" msgid "always" msgstr "" msgid "smart" msgstr "" msgid "before user-def. times" msgstr "" msgid "after user-def. times" msgstr "" msgid "before 'next'" msgstr "" msgid "General" msgstr "" msgid "EPG menus" msgstr "" msgid "User-defined EPG times" msgstr "" msgid "Timer programming" msgstr "" msgid "Search and search timers" msgstr "" msgid "Timer conflict checking" msgstr "" msgid "Email notification" msgstr "" msgid "Hide main menu entry" msgstr "" msgid "Help$Hides the main menu entry and may be useful if this plugin is used to replace the original 'Schedule' entry." msgstr "" msgid "Main menu entry" msgstr "" msgid "Help$The name of the main menu entry which defaults to 'Programm guide'." msgstr "" msgid "Replace original schedule" msgstr "" msgid "Help$When VDR is patched to allow this plugin to replace the original 'Schedule' entry, you can de/activate this replacement here." msgstr "" msgid "Start menu" msgstr "" msgid "Help$Choose between 'Overview - Now' and 'Schedule' as start menu when this plugin is called." msgstr "" msgid "Ok key" msgstr "" msgid "" "Help$Choose here the behaviour of key 'Ok'. You can use it to display the summary or to switch to the corresponding channel.\n" "Note: the functionality of key 'blue' (Switch/Info/Search) depends on this setting." msgstr "" msgid "Red key" msgstr "" msgid "" "Help$Choose which standard function ('Record' or 'Commands') you like to have on the red key.\n" "(Can be toggled with key '0')" msgstr "" msgid "Blue key" msgstr "" msgid "" "Help$Choose which standard function ('Switch'/'Info' or 'Search') you like to have on the blue key.\n" "(Can be toggled with key '0')" msgstr "" msgid "Show progress in 'Now'" msgstr "" msgid "Help$Shows a progressbar in 'Overview - Now' that informs about the remaining time of the current event." msgstr "" msgid "Show channel numbers" msgstr "" msgid "" "Help$Display channel numbers in 'Overview - Now'.\n" "\n" "(To completely define your own menu look please inspect the MANUAL)" msgstr "" msgid "Show channel separators" msgstr "" msgid "Help$Display VDR channel groups as separators between your channels in 'Overview - Now'." msgstr "" msgid "Show day separators" msgstr "" msgid "Help$Display a separator line at day break in 'Schedule'." msgstr "" msgid "Show radio channels" msgstr "" msgid "Help$Show also radio channels." msgstr "" msgid "Limit channels from 1 to" msgstr "" msgid "Help$If you have a large channel set you can speed up things when you limit the displayed channels with this setting. Use '0' to disable the limit." msgstr "" msgid "'One press' timer creation" msgstr "" msgid "Help$When a timer is created with 'Record' you can choose between an immediate creation of the timer or the display of the timer edit menu." msgstr "" msgid "Show channels without EPG" msgstr "" msgid "Help$Choose 'yes' here if you want to display channels without EPG in 'Overview - Now'. 'Ok' on these entries switches the channel." msgstr "" msgid "Time interval for FRew/FFwd [min]" msgstr "" msgid "" "Help$Choose here the time interval which should be used for jumping through the EPG by pressing FRew/FFwd.\n" "\n" "(If you don't have those keys, you can toggle to this functionality pressing '0' and get '<<' and '>>' on the keys green and yellow)" msgstr "" msgid "Toggle Green/Yellow" msgstr "" msgid "Help$Specify if green and yellow shall also be switched when pressing '0'." msgstr "" msgid "Show favorites menu" msgstr "" msgid "" "Help$A favorites menu can display a list of your favorite broadcasts. Enable this if you want an additional menu besides 'Now' and 'Next'\n" "Any search can be used as a favorite. You only have to set the option 'Use in favorites menu' when editing a search." msgstr "" msgid "for the next ... hours" msgstr "" msgid "Help$This value controls the timespan used to display your favorites." msgstr "" msgid "Use user-defined time" msgstr "" msgid "Help$Besides 'Now' and 'Next' you can specify up to 4 other times in the EPG which can be used by repeatedly pressing the green key, e.g. 'prime time', 'late night',..." msgstr "" msgid "Description" msgstr "" msgid "Help$This is the description for your user-defined time as it will appear as label on the green button." msgstr "" msgid "Time" msgstr "" msgid "Help$Specify the user-defined time here in 'HH:MM'." msgstr "" msgid "Use VDR's timer edit menu" msgstr "" msgid "" "Help$This plugin has its own timer edit menu extending the original one with some extra functionality like\n" "- an additional directory entry\n" "- user-defined days of week for repeating timers\n" "- adding an episode name\n" "- support for EPG variables (see MANUAL)" msgstr "" msgid "Default recording dir" msgstr "" msgid "Help$When creating a timer you can specify here a default recording directory." msgstr "" msgid "Add episode to manual timers" msgstr "" msgid "" "Help$If you create a timer for a series, you can automatically add the episode name.\n" "\n" "- never: no addition\n" "- always: always add episode name if present\n" "- smart: add only if event lasts less than 80 mins." msgstr "" msgid "Default timer check method" msgstr "" msgid "" "Help$Manual timers can be checked for EPG changes. Here you can setup the default check method for each channel. Choose between\n" "\n" "- no checking\n" "- by event ID: checks by an event ID supplied by the channel provider.\n" "- by channel and time: check by the duration match." msgstr "" msgid "Button$Setup" msgstr "Configuraţie" msgid "Use search timers" msgstr "" msgid "Help$'Search timers' can be used to automatically create timers for events that match your search criterions." msgstr "" msgid " Update interval [min]" msgstr "" msgid "Help$Specify here the time intervall to be used when searching for events in the background." msgstr "" msgid " SVDRP port" msgstr "" msgid "Help$Programming of new timers or timer changes is done with SVDRP. The default value should be correct, so change it only if you know what you are doing." msgstr "" msgid "Help$Specify here the default priority of timers created with this plugin. This value can also be adjusted for each search itself." msgstr "" msgid "Help$Specify here the default lifetime of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "" msgid "Help$Specify here the default start recording margin of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "" msgid "Help$Specify here the default stop recording margin of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "" msgid "No announcements when replaying" msgstr "" msgid "Help$Set this to 'yes' if you don't like to get any announcements of broadcasts if you currently replay anything." msgstr "" msgid "Recreate timers after deletion" msgstr "" msgid "Help$Set this to 'yes' if you want timers to be recreated with the next search timer update after deleting them." msgstr "" msgid "Check if EPG exists for ... [h]" msgstr "" msgid "Help$Specify how many hours of future EPG there should be and get warned else after a search timer update." msgstr "" msgid "Warn by OSD" msgstr "" msgid "Help$Set this to 'yes' if you want get warnings from the EPG check via OSD." msgstr "" msgid "Warn by mail" msgstr "" msgid "Help$Set this to 'yes' if you want get warnings from the EPG check by mail." msgstr "" msgid "Channel group to check" msgstr "" msgid "Help$Specify the channel group to check." msgstr "" msgid "Ignore PayTV channels" msgstr "" msgid "Help$Set this to 'yes' if don't want to see events on PayTV channels when searching for repeats." msgstr "" msgid "Search templates" msgstr "" msgid "Help$Here you can setup templates for your searches." msgstr "" msgid "Blacklists" msgstr "" msgid "Help$Here you can setup blacklists which can be used within a search to exclude events you don't like." msgstr "" msgid "Help$Here you can setup channel groups which can be used within a search. These are different to VDR channel groups and represent a set of arbitrary channels, e.g. 'FreeTV'." msgstr "" msgid "Ignore below priority" msgstr "" msgid "Help$If a timer with priority below the given value will fail it will not be classified as important. Only important conflicts will produce an OSD message about the conflict after an automatic conflict check." msgstr "" msgid "Ignore conflict duration less ... min." msgstr "" msgid "Help$If a conflicts duration is less then the given number of minutes it will not be classified as important. Only important conflicts will produce an OSD message about the conflict after an automatic conflict check." msgstr "" msgid "Only check within next ... days" msgstr "" msgid "Help$This value reduces the conflict check to the given range of days. All other conflicts are classified as 'not yet important'." msgstr "" msgid "Check also remote conflicts" msgstr "" msgid "Help$Set this to 'yes' if the conflict check should be done for timers set on remote hosts. This needs SVDRPPeering to be set in vdr and Plugin epgsearch running on the remote host." msgstr "" msgid "--- Automatic checking ---" msgstr "" msgid "After each timer programming" msgstr "" msgid "Help$Set this to 'yes' if the conflict check should be performed after each manual timer programming. In the case of a conflict you get immediately a message that informs you about it. The message is only displayed if this timer is involved in any conflict." msgstr "" msgid "When a recording starts" msgstr "" msgid "Help$Set this to 'yes' if the conflict check should be performed when a recording starts. In the case of a conflict you get immediately a message that informs you about it. The message is only displayed if the conflict is within the next 2 hours." msgstr "" msgid "After each search timer update" msgstr "" msgid "Help$Set this to 'yes' if the conflict check should be performed after each search timer update." msgstr "" msgid "every ... minutes" msgstr "" msgid "" "Help$Specify here the time intervall to be used for an automatic conflict check in the background.\n" "('0' disables an automatic check)" msgstr "" msgid "if conflicts within next ... minutes" msgstr "" msgid "Help$If the next conflict will appear in the given number of minutes you can specify here a shorter check intervall to get more OSD notifications about it." msgstr "" msgid "Avoid notification when replaying" msgstr "" msgid "Help$Set this to 'yes' if the don't want to get OSD messages about conflicts if you currently replay something. Nevertheless messages will be displayed if the first upcoming conflict is within the next 2 hours." msgstr "" msgid "Search timer notification" msgstr "" msgid "Help$Set this to 'yes' if you want to get an email notification about the search timers that where programmed automatically in the background." msgstr "" msgid "Time between mails [h]" msgstr "" msgid "" "Help$Specifiy how much time in [h] you would\n" "like to have atleast between two mails.\n" "With '0' you get a new mail after each\n" "search timer update with new results." msgstr "" msgid "Timer conflict notification" msgstr "" msgid "Help$Set this to 'yes' if you want to get an email notification about the timer conflicts." msgstr "" msgid "Send to" msgstr "" msgid "Help$Specify the email address where notifications should be sent to." msgstr "" msgid "Mail method" msgstr "" msgid "" "Help$Specify here the method to use when sending mails.\n" "You can choose between\n" " - 'sendmail': requires a properly configured email system\n" " - 'SendEmail.pl': simple script for mail delivery" msgstr "" msgid "--- Email account ---" msgstr "" msgid "Email address" msgstr "" msgid "Help$Specify the email address where notifications should be sent from." msgstr "" msgid "SMTP server" msgstr "" msgid "Help$Specify the SMTP server that should deliver the notifications. If it's using a port different from the default(25) append the port with \":port\"." msgstr "" msgid "Use SMTP authentication" msgstr "" msgid "Help$Set this to 'yes' if your account needs authentication to send mails." msgstr "" msgid "Auth user" msgstr "" msgid "Help$Specify the auth user, if this account needs authentication for SMTP." msgstr "" msgid "Auth password" msgstr "" msgid "Help$Specify the auth password, if this account needs authentication for SMTP." msgstr "" msgid "Mail account check failed!" msgstr "" msgid "Button$Test" msgstr "" msgid "$ abcdefghijklmnopqrstuvwxyz0123456789-.,#~\\^$[]|()*+?{}/:%@&_" msgstr "" msgid "Start/Stop time has changed" msgstr "" msgid "Title/episode has changed" msgstr "" msgid "No new timers were added." msgstr "" msgid "No timers were modified." msgstr "" msgid "No timers were deleted." msgstr "" msgid "No new events to announce." msgstr "" msgid "This version of EPGSearch does not support this service!" msgstr "" msgid "EPGSearch does not exist!" msgstr "" #, c-format msgid "%d new broadcast" msgstr "" msgid "Button$by channel" msgstr "" msgid "Button$by time" msgstr "" msgid "Button$Episode" msgstr "" msgid "Button$Title" msgstr "" msgid "announce details" msgstr "" msgid "announce again" msgstr "" msgid "with next update" msgstr "" msgid "again from" msgstr "" msgid "Search timer" msgstr "" msgid "Edit blacklist" msgstr "" msgid "phrase" msgstr "" msgid "all words" msgstr "" msgid "at least one word" msgstr "" msgid "match exactly" msgstr "" msgid "regular expression" msgstr "" msgid "fuzzy" msgstr "" msgid "user-defined" msgstr "" msgid "interval" msgstr "" msgid "channel group" msgstr "" msgid "only FTA" msgstr "" msgid "Search term" msgstr "" msgid "Search mode" msgstr "" msgid "Tolerance" msgstr "" msgid "Match case" msgstr "" msgid "Use title" msgstr "" msgid "Use subtitle" msgstr "" msgid "Use description" msgstr "" msgid "Use extended EPG info" msgstr "" msgid "Ignore missing categories" msgstr "" msgid "Use channel" msgstr "" msgid " from channel" msgstr "" msgid " to channel" msgstr "" msgid "Channel group" msgstr "" msgid "Use time" msgstr "" msgid " Start after" msgstr "" msgid " Start before" msgstr "" msgid "Use duration" msgstr "" msgid " Min. duration" msgstr "" msgid " Max. duration" msgstr "" msgid "Use day of week" msgstr "" msgid "Day of week" msgstr "" msgid "Use global" msgstr "" msgid "Button$Templates" msgstr "" msgid "*** Invalid Channel ***" msgstr "" msgid "Please check channel criteria!" msgstr "" msgid "Edit$Delete blacklist?" msgstr "" msgid "Repeats" msgstr "" msgid "Create search" msgstr "" msgid "Search in recordings" msgstr "" msgid "Mark as 'already recorded'?" msgstr "" msgid "Add/Remove to/from switch list?" msgstr "" msgid "Create blacklist" msgstr "" msgid "EPG Commands" msgstr "" msgid "Epgsearch: RemoteTimerModifications failed" msgstr "" msgid "Already running!" msgstr "" msgid "Add to switch list?" msgstr "" msgid "Delete from switch list?" msgstr "" msgid "Button$Details" msgstr "" msgid "Button$Filter" msgstr "" msgid "Button$Show all" msgstr "" msgid "conflicts" msgstr "" msgid "no conflicts!" msgstr "" msgid "no important conflicts!" msgstr "" msgid "C" msgstr "C" msgid "Button$Repeats" msgstr "" msgid "no check" msgstr "" msgid "by channel and time" msgstr "" msgid "by event ID" msgstr "" msgid "Select directory" msgstr "" msgid "Button$Level" msgstr "" msgid "Event" msgstr "" msgid "Favorites" msgstr "" msgid "Search results" msgstr "" msgid "Timer conflict! Show?" msgstr "" msgid "Directory" msgstr "" msgid "Channel" msgstr "" msgid "Childlock" msgstr "" msgid "Record on" msgstr "" msgid "Timer check" msgstr "" msgid "recording with device" msgstr "" msgid "Button$With subtitle" msgstr "" msgid "Button$Without subtitle" msgstr "" msgid "Timer has been deleted" msgstr "" msgid "Button$Extended" msgstr "" msgid "Button$Simple" msgstr "" msgid "Use blacklists" msgstr "" msgid "Edit$Search text too short - use anyway?" msgstr "" msgid "Button$Orphaned" msgstr "" msgid "Button$by name" msgstr "" msgid "Button$by date" msgstr "" msgid "Button$Delete all" msgstr "" msgid "Recordings" msgstr "" msgid "Edit$Delete entry?" msgstr "" msgid "Edit$Delete all entries?" msgstr "" msgid "Summary" msgstr "" msgid "Auxiliary info" msgstr "" msgid "Button$Aux info" msgstr "" msgid "Search actions" msgstr "" msgid "Execute search" msgstr "" msgid "Use as search timer on/off" msgstr "" msgid "Trigger search timer update" msgstr "" msgid "Show recordings done" msgstr "" msgid "Show timers created" msgstr "" msgid "Create a copy" msgstr "" msgid "Use as template" msgstr "" msgid "Show switch list" msgstr "" msgid "Show blacklists" msgstr "" msgid "Delete created timers?" msgstr "" msgid "Timer conflict check" msgstr "" msgid "Disable associated timers too?" msgstr "" msgid "Activate associated timers too?" msgstr "" msgid "Search timers activated in setup." msgstr "" msgid "Run search timer update?" msgstr "" msgid "Copy this entry?" msgstr "" msgid "Copy" msgstr "" msgid "Copy this entry to templates?" msgstr "" msgid "Delete all timers created from this search?" msgstr "" msgid "Button$Actions" msgstr "" msgid "Search entries" msgstr "" msgid "active" msgstr "" msgid "Edit$Delete search?" msgstr "" msgid "Edit search" msgstr "" msgid "Record" msgstr "Înregistr." msgid "Announce by OSD" msgstr "" msgid "Switch only" msgstr "" msgid "Announce and switch" msgstr "" msgid "Announce by mail" msgstr "" msgid "Inactive record" msgstr "" msgid "only globals" msgstr "" msgid "Selection" msgstr "" msgid "all" msgstr "" msgid "count recordings" msgstr "" msgid "count days" msgstr "" msgid "if present" msgstr "" msgid "same day" msgstr "" msgid "same week" msgstr "" msgid "same month" msgstr "" msgid "Template name" msgstr "" msgid "Help$Specify the name of the template." msgstr "" msgid "Help$Specify here the term to search for." msgstr "" msgid "" "Help$The following search modes exist:\n" "\n" "- phrase: searches for sub terms\n" "- all words: all single words must appear\n" "- at least one word: at least one single word must appear\n" "- match exactly: must match exactly\n" "- regular expression: match a regular expression\n" "- fuzzy searching: searches approximately" msgstr "" msgid "Help$This sets the tolerance of fuzzy searching. The value represents the allowed errors." msgstr "" msgid "Help$Set this to 'Yes' if your search should match the case." msgstr "" msgid "Help$Set this to 'Yes' if you like to search in the title of an event." msgstr "" msgid "Help$Set this to 'Yes' if you like to search in the episode of an event." msgstr "" msgid "Help$Set this to 'Yes' if you like to search in the summary of an event." msgstr "" msgid "Use content descriptor" msgstr "" msgid "Help$Set this to 'Yes' if you want to search the contents by a descriptor." msgstr "" msgid "Help$The summary of an event, can contain additional information like 'Genre', 'Category', 'Year',... called 'EPG categories' within EPGSearch. External EPG providers often deliver this information. This allows refining a search and other nice things, like searching for the 'tip of the day'. To use it set this to 'Yes'." msgstr "" msgid "Help$The file epgsearchcats.conf specifies the search mode for this entry. One can search by text or by value. You can also edit a list of predefined values in this file that can be selected here." msgstr "" msgid "Help$If a selected category is not part of the summary of an event this normally excludes this event from the search results. To avoid this, set this option to 'Yes', but please handle this with care to avoid a huge amount of results." msgstr "" msgid "Use in favorites menu" msgstr "" msgid "Result menu layout" msgstr "" msgid "Use as search timer" msgstr "" msgid "Action" msgstr "" msgid "Switch ... minutes before start" msgstr "" msgid "Unmute sound" msgstr "" msgid "Ask ... minutes before start" msgstr "" msgid " Series recording" msgstr "" msgid "Delete recordings after ... days" msgstr "" msgid "Keep ... recordings" msgstr "" msgid "Pause when ... recordings exist" msgstr "" msgid "Avoid repeats" msgstr "" msgid "Allowed repeats" msgstr "" msgid "Only repeats within ... days" msgstr "" msgid "Compare title" msgstr "" msgid "Compare subtitle" msgstr "" msgid "Compare summary" msgstr "" msgid "Min. match in %" msgstr "" msgid "Compare date" msgstr "" msgid "Compare categories" msgstr "" msgid "VPS" msgstr "" msgid "Auto delete" msgstr "" msgid "after ... recordings" msgstr "" msgid "after ... days after first rec." msgstr "" msgid "Edit user-defined days of week" msgstr "" msgid "Compare" msgstr "" msgid "Select blacklists" msgstr "" msgid "Values for EPG category" msgstr "" msgid "Button$Apply" msgstr "" msgid "less" msgstr "" msgid "less or equal" msgstr "" msgid "greater" msgstr "" msgid "greater or equal" msgstr "" msgid "equal" msgstr "" msgid "not equal" msgstr "" msgid "Activation of search timer" msgstr "" msgid "First day" msgstr "" msgid "Last day" msgstr "" msgid "Button$all channels" msgstr "" msgid "Button$only FTA" msgstr "" msgid "Button$Timer preview" msgstr "" msgid "Blacklist results" msgstr "" msgid "found recordings" msgstr "" msgid "Error while accessing recording!" msgstr "" msgid "Button$Default" msgstr "" msgid "Edit$Delete template?" msgstr "" msgid "Overwrite existing entries?" msgstr "" msgid "Edit entry" msgstr "" msgid "Switch" msgstr "" msgid "Announce only" msgstr "" msgid "Announce ... minutes before start" msgstr "" msgid "action at" msgstr "" msgid "Switch list" msgstr "" msgid "Edit template" msgstr "" msgid "Timers" msgstr "" msgid ">>> no info! <<<" msgstr "" msgid "Overview" msgstr "" msgid "Button$Favorites" msgstr "" msgid "Quick search for broadcasts" msgstr "" msgid "Quick search" msgstr "" msgid "Show in main menu" msgstr "" #, c-format msgid "%d new broadcast(s) found! Show them?" msgstr "" msgid "Search timer update done!" msgstr "" #, c-format msgid "small EPG content on:%s" msgstr "" msgid "VDR EPG check warning" msgstr "" #, c-format msgid "Switch to (%d) '%s'?" msgstr "" msgid "Programming timer failed!" msgstr "" vdr-plugin-epgsearch/po/ru_RU.po0000644000175000017500000005721413145412721016453 0ustar tobiastobias# VDR plugin language source file. # Copyright (C) 2007 Klaus Schmidinger # This file is distributed under the same license as the VDR package. # Vyacheslav Dikonov , 2004 # msgid "" msgstr "" "Project-Id-Version: VDR 1.5.7\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-06-15 11:15+0200\n" "PO-Revision-Date: 2007-08-14 20:21+0200\n" "Last-Translator: Vyacheslav Dikonov \n" "Language-Team: Russian \n" "Language: ru\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "Channel groups" msgstr "" msgid "Button$Select" msgstr "" msgid "Channel group used by:" msgstr "" msgid "Edit$Delete group?" msgstr "" msgid "Edit channel group" msgstr "" msgid "Group name" msgstr "" msgid "Button$Invert selection" msgstr "" msgid "Button$All yes" msgstr "" msgid "Button$All no" msgstr "" msgid "Group name is empty!" msgstr "" msgid "Group name already exists!" msgstr "" msgid "Direct access to epgsearch's conflict check menu" msgstr "" msgid "Timer conflicts" msgstr "" msgid "Conflict info in main menu" msgstr "" msgid "next" msgstr "" #, c-format msgid "timer conflict at %s! Show it?" msgstr "" #, c-format msgid "%d timer conflicts! First at %s. Show them?" msgstr "" msgid "search the EPG for repeats and more" msgstr "" msgid "Program guide" msgstr "" msgid "search timer update running" msgstr "" msgid "Direct access to epgsearch's search menu" msgstr "" msgid "Search" msgstr "" msgid "EpgSearch-Search in main menu" msgstr "" msgid "Button$Help" msgstr "" msgid "Standard" msgstr "" msgid "Button$Commands" msgstr "" msgid "Button$Search" msgstr "" msgid "never" msgstr "" msgid "always" msgstr "" msgid "smart" msgstr "" msgid "before user-def. times" msgstr "" msgid "after user-def. times" msgstr "" msgid "before 'next'" msgstr "" msgid "General" msgstr "" msgid "EPG menus" msgstr "" msgid "User-defined EPG times" msgstr "" msgid "Timer programming" msgstr "" msgid "Search and search timers" msgstr "" msgid "Timer conflict checking" msgstr "" msgid "Email notification" msgstr "" msgid "Hide main menu entry" msgstr "" msgid "Help$Hides the main menu entry and may be useful if this plugin is used to replace the original 'Schedule' entry." msgstr "" msgid "Main menu entry" msgstr "" msgid "Help$The name of the main menu entry which defaults to 'Programm guide'." msgstr "" msgid "Replace original schedule" msgstr "" msgid "Help$When VDR is patched to allow this plugin to replace the original 'Schedule' entry, you can de/activate this replacement here." msgstr "" msgid "Start menu" msgstr "" msgid "Help$Choose between 'Overview - Now' and 'Schedule' as start menu when this plugin is called." msgstr "" msgid "Ok key" msgstr "" msgid "" "Help$Choose here the behaviour of key 'Ok'. You can use it to display the summary or to switch to the corresponding channel.\n" "Note: the functionality of key 'blue' (Switch/Info/Search) depends on this setting." msgstr "" msgid "Red key" msgstr "" msgid "" "Help$Choose which standard function ('Record' or 'Commands') you like to have on the red key.\n" "(Can be toggled with key '0')" msgstr "" msgid "Blue key" msgstr "" msgid "" "Help$Choose which standard function ('Switch'/'Info' or 'Search') you like to have on the blue key.\n" "(Can be toggled with key '0')" msgstr "" msgid "Show progress in 'Now'" msgstr "" msgid "Help$Shows a progressbar in 'Overview - Now' that informs about the remaining time of the current event." msgstr "" msgid "Show channel numbers" msgstr "" msgid "" "Help$Display channel numbers in 'Overview - Now'.\n" "\n" "(To completely define your own menu look please inspect the MANUAL)" msgstr "" msgid "Show channel separators" msgstr "" msgid "Help$Display VDR channel groups as separators between your channels in 'Overview - Now'." msgstr "" msgid "Show day separators" msgstr "" msgid "Help$Display a separator line at day break in 'Schedule'." msgstr "" msgid "Show radio channels" msgstr "" msgid "Help$Show also radio channels." msgstr "" msgid "Limit channels from 1 to" msgstr "" msgid "Help$If you have a large channel set you can speed up things when you limit the displayed channels with this setting. Use '0' to disable the limit." msgstr "" msgid "'One press' timer creation" msgstr "" msgid "Help$When a timer is created with 'Record' you can choose between an immediate creation of the timer or the display of the timer edit menu." msgstr "" msgid "Show channels without EPG" msgstr "" msgid "Help$Choose 'yes' here if you want to display channels without EPG in 'Overview - Now'. 'Ok' on these entries switches the channel." msgstr "" msgid "Time interval for FRew/FFwd [min]" msgstr "" msgid "" "Help$Choose here the time interval which should be used for jumping through the EPG by pressing FRew/FFwd.\n" "\n" "(If you don't have those keys, you can toggle to this functionality pressing '0' and get '<<' and '>>' on the keys green and yellow)" msgstr "" msgid "Toggle Green/Yellow" msgstr "" msgid "Help$Specify if green and yellow shall also be switched when pressing '0'." msgstr "" msgid "Show favorites menu" msgstr "" msgid "" "Help$A favorites menu can display a list of your favorite broadcasts. Enable this if you want an additional menu besides 'Now' and 'Next'\n" "Any search can be used as a favorite. You only have to set the option 'Use in favorites menu' when editing a search." msgstr "" msgid "for the next ... hours" msgstr "" msgid "Help$This value controls the timespan used to display your favorites." msgstr "" msgid "Use user-defined time" msgstr "" msgid "Help$Besides 'Now' and 'Next' you can specify up to 4 other times in the EPG which can be used by repeatedly pressing the green key, e.g. 'prime time', 'late night',..." msgstr "" msgid "Description" msgstr "" msgid "Help$This is the description for your user-defined time as it will appear as label on the green button." msgstr "" msgid "Time" msgstr "" msgid "Help$Specify the user-defined time here in 'HH:MM'." msgstr "" msgid "Use VDR's timer edit menu" msgstr "" msgid "" "Help$This plugin has its own timer edit menu extending the original one with some extra functionality like\n" "- an additional directory entry\n" "- user-defined days of week for repeating timers\n" "- adding an episode name\n" "- support for EPG variables (see MANUAL)" msgstr "" msgid "Default recording dir" msgstr "" msgid "Help$When creating a timer you can specify here a default recording directory." msgstr "" msgid "Add episode to manual timers" msgstr "" msgid "" "Help$If you create a timer for a series, you can automatically add the episode name.\n" "\n" "- never: no addition\n" "- always: always add episode name if present\n" "- smart: add only if event lasts less than 80 mins." msgstr "" msgid "Default timer check method" msgstr "" msgid "" "Help$Manual timers can be checked for EPG changes. Here you can setup the default check method for each channel. Choose between\n" "\n" "- no checking\n" "- by event ID: checks by an event ID supplied by the channel provider.\n" "- by channel and time: check by the duration match." msgstr "" msgid "Button$Setup" msgstr "Настройка" msgid "Use search timers" msgstr "" msgid "Help$'Search timers' can be used to automatically create timers for events that match your search criterions." msgstr "" msgid " Update interval [min]" msgstr "" msgid "Help$Specify here the time intervall to be used when searching for events in the background." msgstr "" msgid " SVDRP port" msgstr "" msgid "Help$Programming of new timers or timer changes is done with SVDRP. The default value should be correct, so change it only if you know what you are doing." msgstr "" msgid "Help$Specify here the default priority of timers created with this plugin. This value can also be adjusted for each search itself." msgstr "" msgid "Help$Specify here the default lifetime of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "" msgid "Help$Specify here the default start recording margin of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "" msgid "Help$Specify here the default stop recording margin of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "" msgid "No announcements when replaying" msgstr "" msgid "Help$Set this to 'yes' if you don't like to get any announcements of broadcasts if you currently replay anything." msgstr "" msgid "Recreate timers after deletion" msgstr "" msgid "Help$Set this to 'yes' if you want timers to be recreated with the next search timer update after deleting them." msgstr "" msgid "Check if EPG exists for ... [h]" msgstr "" msgid "Help$Specify how many hours of future EPG there should be and get warned else after a search timer update." msgstr "" msgid "Warn by OSD" msgstr "" msgid "Help$Set this to 'yes' if you want get warnings from the EPG check via OSD." msgstr "" msgid "Warn by mail" msgstr "" msgid "Help$Set this to 'yes' if you want get warnings from the EPG check by mail." msgstr "" msgid "Channel group to check" msgstr "" msgid "Help$Specify the channel group to check." msgstr "" msgid "Ignore PayTV channels" msgstr "" msgid "Help$Set this to 'yes' if don't want to see events on PayTV channels when searching for repeats." msgstr "" msgid "Search templates" msgstr "" msgid "Help$Here you can setup templates for your searches." msgstr "" msgid "Blacklists" msgstr "" msgid "Help$Here you can setup blacklists which can be used within a search to exclude events you don't like." msgstr "" msgid "Help$Here you can setup channel groups which can be used within a search. These are different to VDR channel groups and represent a set of arbitrary channels, e.g. 'FreeTV'." msgstr "" msgid "Ignore below priority" msgstr "" msgid "Help$If a timer with priority below the given value will fail it will not be classified as important. Only important conflicts will produce an OSD message about the conflict after an automatic conflict check." msgstr "" msgid "Ignore conflict duration less ... min." msgstr "" msgid "Help$If a conflicts duration is less then the given number of minutes it will not be classified as important. Only important conflicts will produce an OSD message about the conflict after an automatic conflict check." msgstr "" msgid "Only check within next ... days" msgstr "" msgid "Help$This value reduces the conflict check to the given range of days. All other conflicts are classified as 'not yet important'." msgstr "" msgid "Check also remote conflicts" msgstr "" msgid "Help$Set this to 'yes' if the conflict check should be done for timers set on remote hosts. This needs SVDRPPeering to be set in vdr and Plugin epgsearch running on the remote host." msgstr "" msgid "--- Automatic checking ---" msgstr "" msgid "After each timer programming" msgstr "" msgid "Help$Set this to 'yes' if the conflict check should be performed after each manual timer programming. In the case of a conflict you get immediately a message that informs you about it. The message is only displayed if this timer is involved in any conflict." msgstr "" msgid "When a recording starts" msgstr "" msgid "Help$Set this to 'yes' if the conflict check should be performed when a recording starts. In the case of a conflict you get immediately a message that informs you about it. The message is only displayed if the conflict is within the next 2 hours." msgstr "" msgid "After each search timer update" msgstr "" msgid "Help$Set this to 'yes' if the conflict check should be performed after each search timer update." msgstr "" msgid "every ... minutes" msgstr "" msgid "" "Help$Specify here the time intervall to be used for an automatic conflict check in the background.\n" "('0' disables an automatic check)" msgstr "" msgid "if conflicts within next ... minutes" msgstr "" msgid "Help$If the next conflict will appear in the given number of minutes you can specify here a shorter check intervall to get more OSD notifications about it." msgstr "" msgid "Avoid notification when replaying" msgstr "" msgid "Help$Set this to 'yes' if the don't want to get OSD messages about conflicts if you currently replay something. Nevertheless messages will be displayed if the first upcoming conflict is within the next 2 hours." msgstr "" msgid "Search timer notification" msgstr "" msgid "Help$Set this to 'yes' if you want to get an email notification about the search timers that where programmed automatically in the background." msgstr "" msgid "Time between mails [h]" msgstr "" msgid "" "Help$Specifiy how much time in [h] you would\n" "like to have atleast between two mails.\n" "With '0' you get a new mail after each\n" "search timer update with new results." msgstr "" msgid "Timer conflict notification" msgstr "" msgid "Help$Set this to 'yes' if you want to get an email notification about the timer conflicts." msgstr "" msgid "Send to" msgstr "" msgid "Help$Specify the email address where notifications should be sent to." msgstr "" msgid "Mail method" msgstr "" msgid "" "Help$Specify here the method to use when sending mails.\n" "You can choose between\n" " - 'sendmail': requires a properly configured email system\n" " - 'SendEmail.pl': simple script for mail delivery" msgstr "" msgid "--- Email account ---" msgstr "" msgid "Email address" msgstr "" msgid "Help$Specify the email address where notifications should be sent from." msgstr "" msgid "SMTP server" msgstr "" msgid "Help$Specify the SMTP server that should deliver the notifications. If it's using a port different from the default(25) append the port with \":port\"." msgstr "" msgid "Use SMTP authentication" msgstr "" msgid "Help$Set this to 'yes' if your account needs authentication to send mails." msgstr "" msgid "Auth user" msgstr "" msgid "Help$Specify the auth user, if this account needs authentication for SMTP." msgstr "" msgid "Auth password" msgstr "" msgid "Help$Specify the auth password, if this account needs authentication for SMTP." msgstr "" msgid "Mail account check failed!" msgstr "" msgid "Button$Test" msgstr "" msgid "$ abcdefghijklmnopqrstuvwxyz0123456789-.,#~\\^$[]|()*+?{}/:%@&_" msgstr "" msgid "Start/Stop time has changed" msgstr "" msgid "Title/episode has changed" msgstr "" msgid "No new timers were added." msgstr "" msgid "No timers were modified." msgstr "" msgid "No timers were deleted." msgstr "" msgid "No new events to announce." msgstr "" msgid "This version of EPGSearch does not support this service!" msgstr "" msgid "EPGSearch does not exist!" msgstr "" #, c-format msgid "%d new broadcast" msgstr "" msgid "Button$by channel" msgstr "" msgid "Button$by time" msgstr "" msgid "Button$Episode" msgstr "" msgid "Button$Title" msgstr "" msgid "announce details" msgstr "" msgid "announce again" msgstr "" msgid "with next update" msgstr "" msgid "again from" msgstr "" msgid "Search timer" msgstr "" msgid "Edit blacklist" msgstr "" msgid "phrase" msgstr "" msgid "all words" msgstr "" msgid "at least one word" msgstr "" msgid "match exactly" msgstr "" msgid "regular expression" msgstr "" msgid "fuzzy" msgstr "" msgid "user-defined" msgstr "" msgid "interval" msgstr "" msgid "channel group" msgstr "" msgid "only FTA" msgstr "" msgid "Search term" msgstr "" msgid "Search mode" msgstr "" msgid "Tolerance" msgstr "" msgid "Match case" msgstr "" msgid "Use title" msgstr "" msgid "Use subtitle" msgstr "" msgid "Use description" msgstr "" msgid "Use extended EPG info" msgstr "" msgid "Ignore missing categories" msgstr "" msgid "Use channel" msgstr "" msgid " from channel" msgstr "" msgid " to channel" msgstr "" msgid "Channel group" msgstr "" msgid "Use time" msgstr "" msgid " Start after" msgstr "" msgid " Start before" msgstr "" msgid "Use duration" msgstr "" msgid " Min. duration" msgstr "" msgid " Max. duration" msgstr "" msgid "Use day of week" msgstr "" msgid "Day of week" msgstr "" msgid "Use global" msgstr "" msgid "Button$Templates" msgstr "" msgid "*** Invalid Channel ***" msgstr "" msgid "Please check channel criteria!" msgstr "" msgid "Edit$Delete blacklist?" msgstr "" msgid "Repeats" msgstr "" msgid "Create search" msgstr "" msgid "Search in recordings" msgstr "" msgid "Mark as 'already recorded'?" msgstr "" msgid "Add/Remove to/from switch list?" msgstr "" msgid "Create blacklist" msgstr "" msgid "EPG Commands" msgstr "" msgid "Epgsearch: RemoteTimerModifications failed" msgstr "" msgid "Already running!" msgstr "" msgid "Add to switch list?" msgstr "" msgid "Delete from switch list?" msgstr "" msgid "Button$Details" msgstr "" msgid "Button$Filter" msgstr "" msgid "Button$Show all" msgstr "" msgid "conflicts" msgstr "" msgid "no conflicts!" msgstr "" msgid "no important conflicts!" msgstr "" msgid "C" msgstr "C" msgid "Button$Repeats" msgstr "" msgid "no check" msgstr "" msgid "by channel and time" msgstr "" msgid "by event ID" msgstr "" msgid "Select directory" msgstr "" msgid "Button$Level" msgstr "" msgid "Event" msgstr "" msgid "Favorites" msgstr "" msgid "Search results" msgstr "" msgid "Timer conflict! Show?" msgstr "" msgid "Directory" msgstr "" msgid "Channel" msgstr "" msgid "Childlock" msgstr "" msgid "Record on" msgstr "" msgid "Timer check" msgstr "" msgid "recording with device" msgstr "" msgid "Button$With subtitle" msgstr "" msgid "Button$Without subtitle" msgstr "" msgid "Timer has been deleted" msgstr "" msgid "Button$Extended" msgstr "" msgid "Button$Simple" msgstr "" msgid "Use blacklists" msgstr "" msgid "Edit$Search text too short - use anyway?" msgstr "" msgid "Button$Orphaned" msgstr "" msgid "Button$by name" msgstr "" msgid "Button$by date" msgstr "" msgid "Button$Delete all" msgstr "" msgid "Recordings" msgstr "" msgid "Edit$Delete entry?" msgstr "" msgid "Edit$Delete all entries?" msgstr "" msgid "Summary" msgstr "" msgid "Auxiliary info" msgstr "" msgid "Button$Aux info" msgstr "" msgid "Search actions" msgstr "" msgid "Execute search" msgstr "" msgid "Use as search timer on/off" msgstr "" msgid "Trigger search timer update" msgstr "" msgid "Show recordings done" msgstr "" msgid "Show timers created" msgstr "" msgid "Create a copy" msgstr "" msgid "Use as template" msgstr "" msgid "Show switch list" msgstr "" msgid "Show blacklists" msgstr "" msgid "Delete created timers?" msgstr "" msgid "Timer conflict check" msgstr "" msgid "Disable associated timers too?" msgstr "" msgid "Activate associated timers too?" msgstr "" msgid "Search timers activated in setup." msgstr "" msgid "Run search timer update?" msgstr "" msgid "Copy this entry?" msgstr "" msgid "Copy" msgstr "" msgid "Copy this entry to templates?" msgstr "" msgid "Delete all timers created from this search?" msgstr "" msgid "Button$Actions" msgstr "" msgid "Search entries" msgstr "" msgid "active" msgstr "" msgid "Edit$Delete search?" msgstr "" msgid "Edit search" msgstr "" msgid "Record" msgstr "Запись" msgid "Announce by OSD" msgstr "" msgid "Switch only" msgstr "" msgid "Announce and switch" msgstr "" msgid "Announce by mail" msgstr "" msgid "Inactive record" msgstr "" msgid "only globals" msgstr "" msgid "Selection" msgstr "" msgid "all" msgstr "" msgid "count recordings" msgstr "" msgid "count days" msgstr "" msgid "if present" msgstr "" msgid "same day" msgstr "" msgid "same week" msgstr "" msgid "same month" msgstr "" msgid "Template name" msgstr "" msgid "Help$Specify the name of the template." msgstr "" msgid "Help$Specify here the term to search for." msgstr "" msgid "" "Help$The following search modes exist:\n" "\n" "- phrase: searches for sub terms\n" "- all words: all single words must appear\n" "- at least one word: at least one single word must appear\n" "- match exactly: must match exactly\n" "- regular expression: match a regular expression\n" "- fuzzy searching: searches approximately" msgstr "" msgid "Help$This sets the tolerance of fuzzy searching. The value represents the allowed errors." msgstr "" msgid "Help$Set this to 'Yes' if your search should match the case." msgstr "" msgid "Help$Set this to 'Yes' if you like to search in the title of an event." msgstr "" msgid "Help$Set this to 'Yes' if you like to search in the episode of an event." msgstr "" msgid "Help$Set this to 'Yes' if you like to search in the summary of an event." msgstr "" msgid "Use content descriptor" msgstr "" msgid "Help$Set this to 'Yes' if you want to search the contents by a descriptor." msgstr "" msgid "Help$The summary of an event, can contain additional information like 'Genre', 'Category', 'Year',... called 'EPG categories' within EPGSearch. External EPG providers often deliver this information. This allows refining a search and other nice things, like searching for the 'tip of the day'. To use it set this to 'Yes'." msgstr "" msgid "Help$The file epgsearchcats.conf specifies the search mode for this entry. One can search by text or by value. You can also edit a list of predefined values in this file that can be selected here." msgstr "" msgid "Help$If a selected category is not part of the summary of an event this normally excludes this event from the search results. To avoid this, set this option to 'Yes', but please handle this with care to avoid a huge amount of results." msgstr "" msgid "Use in favorites menu" msgstr "" msgid "Result menu layout" msgstr "" msgid "Use as search timer" msgstr "" msgid "Action" msgstr "" msgid "Switch ... minutes before start" msgstr "" msgid "Unmute sound" msgstr "" msgid "Ask ... minutes before start" msgstr "" msgid " Series recording" msgstr "" msgid "Delete recordings after ... days" msgstr "" msgid "Keep ... recordings" msgstr "" msgid "Pause when ... recordings exist" msgstr "" msgid "Avoid repeats" msgstr "" msgid "Allowed repeats" msgstr "" msgid "Only repeats within ... days" msgstr "" msgid "Compare title" msgstr "" msgid "Compare subtitle" msgstr "" msgid "Compare summary" msgstr "" msgid "Min. match in %" msgstr "" msgid "Compare date" msgstr "" msgid "Compare categories" msgstr "" msgid "VPS" msgstr "" msgid "Auto delete" msgstr "" msgid "after ... recordings" msgstr "" msgid "after ... days after first rec." msgstr "" msgid "Edit user-defined days of week" msgstr "" msgid "Compare" msgstr "" msgid "Select blacklists" msgstr "" msgid "Values for EPG category" msgstr "" msgid "Button$Apply" msgstr "" msgid "less" msgstr "" msgid "less or equal" msgstr "" msgid "greater" msgstr "" msgid "greater or equal" msgstr "" msgid "equal" msgstr "" msgid "not equal" msgstr "" msgid "Activation of search timer" msgstr "" msgid "First day" msgstr "" msgid "Last day" msgstr "" msgid "Button$all channels" msgstr "" msgid "Button$only FTA" msgstr "" msgid "Button$Timer preview" msgstr "" msgid "Blacklist results" msgstr "" msgid "found recordings" msgstr "" msgid "Error while accessing recording!" msgstr "" msgid "Button$Default" msgstr "" msgid "Edit$Delete template?" msgstr "" msgid "Overwrite existing entries?" msgstr "" msgid "Edit entry" msgstr "" msgid "Switch" msgstr "" msgid "Announce only" msgstr "" msgid "Announce ... minutes before start" msgstr "" msgid "action at" msgstr "" msgid "Switch list" msgstr "" msgid "Edit template" msgstr "" msgid "Timers" msgstr "" msgid ">>> no info! <<<" msgstr "" msgid "Overview" msgstr "" msgid "Button$Favorites" msgstr "" msgid "Quick search for broadcasts" msgstr "" msgid "Quick search" msgstr "" msgid "Show in main menu" msgstr "" #, c-format msgid "%d new broadcast(s) found! Show them?" msgstr "" msgid "Search timer update done!" msgstr "" #, c-format msgid "small EPG content on:%s" msgstr "" msgid "VDR EPG check warning" msgstr "" #, c-format msgid "Switch to (%d) '%s'?" msgstr "" msgid "Programming timer failed!" msgstr "" vdr-plugin-epgsearch/po/nl_NL.po0000644000175000017500000011613113145412721016413 0ustar tobiastobias# VDR plugin language source file. # Copyright (C) 2007 Klaus Schmidinger # This file is distributed under the same license as the VDR package. # Arnold Niessen , 2001 # Hans Dingemans , 2003 # Maarten Wisse , 2005 # msgid "" msgstr "" "Project-Id-Version: VDR 1.5.7\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-06-15 11:15+0200\n" "PO-Revision-Date: 2007-08-14 20:21+0200\n" "Last-Translator: Maarten Wisse \n" "Language-Team: Dutch \n" "Language: nl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "Channel groups" msgstr "Kanaal groepen" msgid "Button$Select" msgstr "Selecteer" msgid "Channel group used by:" msgstr "Kanaalgroep gebruikt door:" msgid "Edit$Delete group?" msgstr "Groep wissen?" msgid "Edit channel group" msgstr "Bewerk kanaalgroep" msgid "Group name" msgstr "Groep naam" msgid "Button$Invert selection" msgstr "Selectie omdraaien" msgid "Button$All yes" msgstr "Alles ja" msgid "Button$All no" msgstr "Alles nee" msgid "Group name is empty!" msgstr "Groep naam is leeg!" msgid "Group name already exists!" msgstr "Groep naam bestaat al!" msgid "Direct access to epgsearch's conflict check menu" msgstr "Directe toegang tot epgsearch's conflict controle menu" msgid "Timer conflicts" msgstr "Timer conflicten" msgid "Conflict info in main menu" msgstr "Conflict info tonen in hoofdmenu" msgid "next" msgstr "volgende" #, c-format msgid "timer conflict at %s! Show it?" msgstr "Timerconflict op %s! Tonen?" #, c-format msgid "%d timer conflicts! First at %s. Show them?" msgstr "%d timer conflicten! eerste op %s. Tonen?" msgid "search the EPG for repeats and more" msgstr "Zoek in de EPG naar herhalingen en meer" msgid "Program guide" msgstr "Programmagids" #, fuzzy msgid "search timer update running" msgstr "Verversen zoektimer gereed!" msgid "Direct access to epgsearch's search menu" msgstr "Direct toegang tot epgsearch's zoek menu" msgid "Search" msgstr "Zoek" msgid "EpgSearch-Search in main menu" msgstr "EpgSearch-Search in hoofdmenu" msgid "Button$Help" msgstr "Help" msgid "Standard" msgstr "Standaard" msgid "Button$Commands" msgstr "Commando's" msgid "Button$Search" msgstr "Zoek" msgid "never" msgstr "nooit" msgid "always" msgstr "altijd" msgid "smart" msgstr "slim" msgid "before user-def. times" msgstr "vóór gebruiker-gedef. tijden" msgid "after user-def. times" msgstr "ná gebruiker-gedef. tijden" msgid "before 'next'" msgstr "" msgid "General" msgstr "Algemeen" msgid "EPG menus" msgstr "EPG menu's" msgid "User-defined EPG times" msgstr "Gebruiker-gedefinieerde EPG tijden" msgid "Timer programming" msgstr "Timer programmering" msgid "Search and search timers" msgstr "Zoek en zoektimers" msgid "Timer conflict checking" msgstr "Timer conflict controle" msgid "Email notification" msgstr "E-mail notificatie" msgid "Hide main menu entry" msgstr "Verberg vermelding in hoofdmenu" msgid "Help$Hides the main menu entry and may be useful if this plugin is used to replace the original 'Schedule' entry." msgstr "Verbergt de vermelding in het hoofdmenu en kan van pas komen als deze plugin wordt gebruikt om de originele programmagids te vervangen." msgid "Main menu entry" msgstr "Hoofdmenu vermelding" msgid "Help$The name of the main menu entry which defaults to 'Programm guide'." msgstr "De naam van de regel in het hoofdmenu welke gerelateerd is aan 'programmagids'" msgid "Replace original schedule" msgstr "Originele 'Programmagids' vervangen" msgid "Help$When VDR is patched to allow this plugin to replace the original 'Schedule' entry, you can de/activate this replacement here." msgstr "Als VDR gepatcht is om deze plugin de originele 'Programmagids' menu te laten vervangen dan kan dat hier ge(de)activeerd worden" msgid "Start menu" msgstr "Startmenu" msgid "Help$Choose between 'Overview - Now' and 'Schedule' as start menu when this plugin is called." msgstr "Maak een keuze tussen 'Overzicht', 'Nu' en 'programmagids' als startmenu wanneer plugin wordt geactiveerd." msgid "Ok key" msgstr "OK toets" msgid "" "Help$Choose here the behaviour of key 'Ok'. You can use it to display the summary or to switch to the corresponding channel.\n" "Note: the functionality of key 'blue' (Switch/Info/Search) depends on this setting." msgstr "" "Kies hier het gedrag van de 'OK' toets. Hij kan gebruikt worden om een samenvatting te tonen of om te schakelen naar het betreffende kanaal.\n" "Letop: de functionaliteit van de 'BLAUW' toets (Schakel/Info/Zoek) is afhankelijk van deze instelling." msgid "Red key" msgstr "Rode toets" msgid "" "Help$Choose which standard function ('Record' or 'Commands') you like to have on the red key.\n" "(Can be toggled with key '0')" msgstr "" "Kies welke standaard functie (Opname of Commando's) aan de rode toets moet worden toegewezen.\n" "(Kan worden omgeschakeld met de '0' toets)" msgid "Blue key" msgstr "Blauwe toets" msgid "" "Help$Choose which standard function ('Switch'/'Info' or 'Search') you like to have on the blue key.\n" "(Can be toggled with key '0')" msgstr "" "Kies welke standaard functie ('Schakel'/'Info' of 'Zoek') aan de blauwe toets moet worden toegewezen.\n" "(Kan worden omgeschakeld met de '0' toets)" msgid "Show progress in 'Now'" msgstr "Toon voortgang in 'Nu'" msgid "Help$Shows a progressbar in 'Overview - Now' that informs about the remaining time of the current event." msgstr "Toont een voortschreidingsbalk in 'Overzicht - Nu' welke de resterende tijd van het huidige programma weergeeft." msgid "Show channel numbers" msgstr "Toon kanaal nummers" msgid "" "Help$Display channel numbers in 'Overview - Now'.\n" "\n" "(To completely define your own menu look please inspect the MANUAL)" msgstr "" "Toon kanaal nummers in 'Overzicht - Nu.\n" "\n" "(Raadpleeg de MANUAL om het hele menu naar eigen inzicht te veranderen)" msgid "Show channel separators" msgstr "Toon kanaal scheidingstekens" msgid "Help$Display VDR channel groups as separators between your channels in 'Overview - Now'." msgstr "Toon VDR kanaal groepen als scheidingstekens tussen de kanalen in 'Overzicht - Nu'." msgid "Show day separators" msgstr "Toon schedingstekens tussen dagovergangen" msgid "Help$Display a separator line at day break in 'Schedule'." msgstr "Toon een scheidingsteken tussen dagovergangen in 'Programmaoverzicht'" msgid "Show radio channels" msgstr "Toon radiokanalen" msgid "Help$Show also radio channels." msgstr "Toon ook radiokanalen" msgid "Limit channels from 1 to" msgstr "Beperk aantal kanalenvan 1 tot" msgid "Help$If you have a large channel set you can speed up things when you limit the displayed channels with this setting. Use '0' to disable the limit." msgstr "Als er sprake is van een groot aantal kanalen dan kan de snelheid worden bevorderd als het aantal kanalen wordt beperkt. Gebruik '0' om de limitering op te heffen" msgid "'One press' timer creation" msgstr "Maak met één toetsdruk een nieuwe timer aan" msgid "Help$When a timer is created with 'Record' you can choose between an immediate creation of the timer or the display of the timer edit menu." msgstr "Als er een timer is gemaakt met 'Opname' dan kan er gekozen worden de timer direct aan te maken of eerst het 'Wijzig timer' menu te tonen." msgid "Show channels without EPG" msgstr "Toon kanalen zonder EPG" msgid "Help$Choose 'yes' here if you want to display channels without EPG in 'Overview - Now'. 'Ok' on these entries switches the channel." msgstr "Kies 'ja' als er in 'Overzicht - Nu' kanalen zonder EPG moeten worden getoond. 'OK' op deze regels schakelt het kanaal in" msgid "Time interval for FRew/FFwd [min]" msgstr "Tijd interval voor FRew/FFwd [min]" msgid "" "Help$Choose here the time interval which should be used for jumping through the EPG by pressing FRew/FFwd.\n" "\n" "(If you don't have those keys, you can toggle to this functionality pressing '0' and get '<<' and '>>' on the keys green and yellow)" msgstr "" "Kies hier het tijdsinterval wat gebruikt wordt om met FRew/FFwd door de EPG te springen.\n" "\n" "(Als deze toetsen niet beschikbaar druk dan eerst op de '0' toets en daarna op 'Groen' en 'Geel' om heen en terug te springem" msgid "Toggle Green/Yellow" msgstr "Groen/Geel verwisselen" msgid "Help$Specify if green and yellow shall also be switched when pressing '0'." msgstr "Geef aan of 'Groen' en 'Geel' ook moeten worden geschakeld als op '0' wordt gedrukt" msgid "Show favorites menu" msgstr "Toon favorieten menu" msgid "" "Help$A favorites menu can display a list of your favorite broadcasts. Enable this if you want an additional menu besides 'Now' and 'Next'\n" "Any search can be used as a favorite. You only have to set the option 'Use in favorites menu' when editing a search." msgstr "" "Een favorieten menu kan een lijst van favoriete uitzendingen tonen. Activeer dit als er extra menu's naast 'Nu' en 'Next' gewenst zijn\n" "Iedere willekeurige zoekactie kan ingezet worden als favoriet\n" "Daarvoor hoeft enkel de optie 'Gebruik in favorieten menu' geactiveerd te worden tijdens het aanmaken of wijzigen van een zoekactie." msgid "for the next ... hours" msgstr "de komende ... uur" msgid "Help$This value controls the timespan used to display your favorites." msgstr "Deze waarde regelt het interval dat wordt gebruikt voor het tonen van de favorieten" msgid "Use user-defined time" msgstr "Gebruik gebruiker's tijd" msgid "Help$Besides 'Now' and 'Next' you can specify up to 4 other times in the EPG which can be used by repeatedly pressing the green key, e.g. 'prime time', 'late night',..." msgstr "Naast 'Nu' en 'Straks' kunnen nog 4 andere tijden in de EPG worden gespeficiteerd. Deze kunnen worden benaderd door herhaaldelijk op de 'Groene'toets te drukken, bv 'prime time', 'late night'..." msgid "Description" msgstr "Beschrijving" msgid "Help$This is the description for your user-defined time as it will appear as label on the green button." msgstr "Dit is de beschrijving van de gebruiker-gedefinieerde tijd zoals het als label bij de toets 'Groen' verschijnt" msgid "Time" msgstr "Tijd" msgid "Help$Specify the user-defined time here in 'HH:MM'." msgstr "Specificeer hier de gebruiker-gedefinieerde tijd als 'HH:MM'" msgid "Use VDR's timer edit menu" msgstr "Gebruik VDR's timer bewerkingsmenu" msgid "" "Help$This plugin has its own timer edit menu extending the original one with some extra functionality like\n" "- an additional directory entry\n" "- user-defined days of week for repeating timers\n" "- adding an episode name\n" "- support for EPG variables (see MANUAL)" msgstr "" "Deze plugin beschikt over zijn eigen timer bewerkingsmenu die de originele uitbreid met extra functionaliteit zoals\n" "- een extra regel voor een map\n" "- gebruiker-gedefinieerde dagen van de week voor herhaal-timers\n" "- toevoegen van een 'episode naam'\n" "- ondersteuning voor EPG variabelen (see MANUAL)" msgid "Default recording dir" msgstr "Standaard map voor opnames" msgid "Help$When creating a timer you can specify here a default recording directory." msgstr "Bij het aanmaken van een timer kan hier de standaard opname map worden opgegeven" msgid "Add episode to manual timers" msgstr "Voeg episode toe aan handmatige timers" msgid "" "Help$If you create a timer for a series, you can automatically add the episode name.\n" "\n" "- never: no addition\n" "- always: always add episode name if present\n" "- smart: add only if event lasts less than 80 mins." msgstr "" "Als er een herhaaltimer wordt aangemaakt voor series, dan kan er automatisch de episode naam worden toegevoegd.\n" "\n" "- nooit: voeg niets toe\n" "- altijd: voeg altijd de episode naam toe indien aanwezig\n" "- smart: voeg alleen toe wanneer programma minder dan 80 min duurt." msgid "Default timer check method" msgstr "Standaard timer controle methode" msgid "" "Help$Manual timers can be checked for EPG changes. Here you can setup the default check method for each channel. Choose between\n" "\n" "- no checking\n" "- by event ID: checks by an event ID supplied by the channel provider.\n" "- by channel and time: check by the duration match." msgstr "" "Handmatige timers kunnen worden gecontroleerd op EPG veranderingen. Hier kan de standaard methode voor ieder kanaal ingesteld worden. Kies uit\n" "\n" "- geen controle\n" "- op event-ID: kontroleert m.b.v. een event-ID meegzonden door de TV Provider.\n" "- op kanaal an tijd: controleer of de tijdsduur overeenkomt." msgid "Button$Setup" msgstr "Instellingen" msgid "Use search timers" msgstr "Gebruik zoektimers" msgid "Help$'Search timers' can be used to automatically create timers for events that match your search criterions." msgstr "Zoektimers kunnen worden gebruikt om automatisch timers te maken o.b.v. programma's die voldoen aan bepaalde zoekcriteria." msgid " Update interval [min]" msgstr " Update interval [min]" msgid "Help$Specify here the time intervall to be used when searching for events in the background." msgstr "Geef hier het tijdsinterval op dat wordt gebruikt om op de achtergrond te zoeken naar programma's" msgid " SVDRP port" msgstr " SVDRP poort" msgid "Help$Programming of new timers or timer changes is done with SVDRP. The default value should be correct, so change it only if you know what you are doing." msgstr "Het programmeren of wijzigen van timers wordt gedaan met SVDRP. De standaard waarde moet goed staan, dus wijzig dit allen als er echt reden toe is." msgid "Help$Specify here the default priority of timers created with this plugin. This value can also be adjusted for each search itself." msgstr "Bepaal hier de standaard prioriteit van timers aangemaakt met deze plugin. Deze waarde kan ook worden aangepast voor iedere afzonderlijke zoekactie" msgid "Help$Specify here the default lifetime of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "Bepaal hier de standaard levensduur van timers/opnames aangemaakt door deze plugin. Deze waarde kan ook worden aangepast voor iedere afzonderlijke zoekactie" msgid "Help$Specify here the default start recording margin of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "Bepaal hier de standaard start opname-marge van timers/opnames aangemaakt door deze plugin. Deze waarde kan ook worden aangepast voor iedere afzonderlijke zoekactie" msgid "Help$Specify here the default stop recording margin of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "Bepaal hier de standaard stop opname-marge van timers/opnames aangemaakt door deze plugin. Deze waarde kan ook worden aangepast voor iedere afzonderlijke zoekactie" msgid "No announcements when replaying" msgstr "Geen meldingen tijdens afspelen" msgid "Help$Set this to 'yes' if you don't like to get any announcements of broadcasts if you currently replay anything." msgstr "Kies 'ja' indien er geen meldingen van toekomstige uitzendingen gewenst zijn als er op dat moment iets wordt afgespeeld" msgid "Recreate timers after deletion" msgstr "Maak timer opnieuw aan na verwijderen" msgid "Help$Set this to 'yes' if you want timers to be recreated with the next search timer update after deleting them." msgstr "Kies 'ja' als timers na het verwijderen opnieuw moeten worden aangemaakt met een nieuwe zoek-timer update" msgid "Check if EPG exists for ... [h]" msgstr "" #, fuzzy msgid "Help$Specify how many hours of future EPG there should be and get warned else after a search timer update." msgstr "Kies 'ja' als de conflict controle moet worden uitgevoerd na het verversen van iedere zoek-timer" #, fuzzy msgid "Warn by OSD" msgstr "Alleen aankondigen (geen timer)" #, fuzzy msgid "Help$Set this to 'yes' if you want get warnings from the EPG check via OSD." msgstr "Kies 'ja' indien er een notificatie e-mail verstuurd moet worden bij timer conflicten" #, fuzzy msgid "Warn by mail" msgstr "Alleen aankondigen (geen timer)" #, fuzzy msgid "Help$Set this to 'yes' if you want get warnings from the EPG check by mail." msgstr "kies 'ja' indien uw abonnement authenticatie vereist voor het verzenden van e-mails." #, fuzzy msgid "Channel group to check" msgstr "Kanaal groep" #, fuzzy msgid "Help$Specify the channel group to check." msgstr "Geef de naam op van het sjabloon" msgid "Ignore PayTV channels" msgstr "Negeer PayTV kanalen" msgid "Help$Set this to 'yes' if don't want to see events on PayTV channels when searching for repeats." msgstr "Kies 'ja' als er geen programma's van payTV kanalen mogen worden getoond tijdens het zoeken naar herhalingen" msgid "Search templates" msgstr "Zoek sjabloon" msgid "Help$Here you can setup templates for your searches." msgstr "Hier kunnen sjablonen worden aangemaakt voor zoekacties." msgid "Blacklists" msgstr "Blacklists" msgid "Help$Here you can setup blacklists which can be used within a search to exclude events you don't like." msgstr "Hier kunnen 'Blacklists' worden aangemaakt die kunnen worden gebruikt om programma's uit te sluiten van zoekactie's " msgid "Help$Here you can setup channel groups which can be used within a search. These are different to VDR channel groups and represent a set of arbitrary channels, e.g. 'FreeTV'." msgstr "Hier kunnen groepen van kanalen worden opgegeven die kunnen worden gebruikt binnen een zoekactie. Deze groepen wijken af van de VDR kanaal groepen en bestaan uit willekeurig kanalen zoals 'FreeTV." msgid "Ignore below priority" msgstr "Negeer onder de prioriteit" msgid "Help$If a timer with priority below the given value will fail it will not be classified as important. Only important conflicts will produce an OSD message about the conflict after an automatic conflict check." msgstr "Als een timer met een prioriteit onder de gegeven waarde mislukt dan wordt hij niet gemerkt als 'belangrijk'. Alleen belangrijke conflicten zullen een OSD melding tot gevolg hebben." msgid "Ignore conflict duration less ... min." msgstr "Negeer conflictduur van minder dan ... min." msgid "Help$If a conflicts duration is less then the given number of minutes it will not be classified as important. Only important conflicts will produce an OSD message about the conflict after an automatic conflict check." msgstr "Indien de duur van conflict(en) kleiner is dan het gegeven aantal minuten dan worden deze niet gemerkt als 'belangrijk' Alleen belangrijke conflicten zullen een OSD melding tot gevolg hebben." msgid "Only check within next ... days" msgstr "Controleer alleen vóór de volgende ... dagen" msgid "Help$This value reduces the conflict check to the given range of days. All other conflicts are classified as 'not yet important'." msgstr "Deze waarde beperkt de conflict controle tot het gegeven aantal dagen. Alle andere conflicten worden als 'nog niet belangrijk' bestempeld." msgid "Check also remote conflicts" msgstr "" msgid "Help$Set this to 'yes' if the conflict check should be done for timers set on remote hosts. This needs SVDRPPeering to be set in vdr and Plugin epgsearch running on the remote host." msgstr "" msgid "--- Automatic checking ---" msgstr "--- Automatische controle ---" msgid "After each timer programming" msgstr "Na iedere aangemaakte timer" msgid "Help$Set this to 'yes' if the conflict check should be performed after each manual timer programming. In the case of a conflict you get immediately a message that informs you about it. The message is only displayed if this timer is involved in any conflict." msgstr "Kies 'ja' als de conflict controle bij iedere handmatig aangemaakte timer moet worden uitgevoerd. In het geval van een conflict verschijnt er direct een waarschuwing. Deze waarschuwing wordt alleen getoond als de timer betrokken is bij een willekeurig conflict." msgid "When a recording starts" msgstr "Wanneer een opname start" msgid "Help$Set this to 'yes' if the conflict check should be performed when a recording starts. In the case of a conflict you get immediately a message that informs you about it. The message is only displayed if the conflict is within the next 2 hours." msgstr "Kies 'ja' als de conflict controle moet worden uitgevoerd bij iedere startende opname. In het geval van een conflict verschijnt er direct een waarschuwing. Deze waarschuwing wordt alleen getoond als de timer betrokken is bij een willekeurig conflict." msgid "After each search timer update" msgstr "Na het verversen van iedere zoek-timer" msgid "Help$Set this to 'yes' if the conflict check should be performed after each search timer update." msgstr "Kies 'ja' als de conflict controle moet worden uitgevoerd na het verversen van iedere zoek-timer" msgid "every ... minutes" msgstr "iedere ... minuten" msgid "" "Help$Specify here the time intervall to be used for an automatic conflict check in the background.\n" "('0' disables an automatic check)" msgstr "Bepaal hier de tijdsduur gebruikt voor de automatische conflict controle in de achtergrond" msgid "if conflicts within next ... minutes" msgstr "indien conflict optreed binnen ... minuten" msgid "Help$If the next conflict will appear in the given number of minutes you can specify here a shorter check intervall to get more OSD notifications about it." msgstr "Als het volgende conflict binnen het gegeven aantal minuten optreedt dan kan hier een korter interval worden gespecificeerd om meer OSD notificaties te verkrijgen." msgid "Avoid notification when replaying" msgstr "Vermijdt notificatie tijdens afspelen" msgid "Help$Set this to 'yes' if the don't want to get OSD messages about conflicts if you currently replay something. Nevertheless messages will be displayed if the first upcoming conflict is within the next 2 hours." msgstr "Kies 'ja' indien er geen OSD berichten mogen verschijnen tijdens het afspelen. Desondanks zullen berichten wel verschijnen indien het volgende conflict binnen 2 uur optreedt" msgid "Search timer notification" msgstr "Zoektimer notificatie" msgid "Help$Set this to 'yes' if you want to get an email notification about the search timers that where programmed automatically in the background." msgstr "Kies 'ja' wanneer er een notificatie e-mail verstuurd moet worden over zoektimers die automatisch op de achtergrond werden aangenaakt." msgid "Time between mails [h]" msgstr "" msgid "" "Help$Specifiy how much time in [h] you would\n" "like to have atleast between two mails.\n" "With '0' you get a new mail after each\n" "search timer update with new results." msgstr "" msgid "Timer conflict notification" msgstr "Timer conflict notificatie" msgid "Help$Set this to 'yes' if you want to get an email notification about the timer conflicts." msgstr "Kies 'ja' indien er een notificatie e-mail verstuurd moet worden bij timer conflicten" msgid "Send to" msgstr "Zend naar" msgid "Help$Specify the email address where notifications should be sent to." msgstr "Geef het e-mail adres op waar de notificaties naartoe gestuurd moeen worden" msgid "Mail method" msgstr "Mail methode" msgid "" "Help$Specify here the method to use when sending mails.\n" "You can choose between\n" " - 'sendmail': requires a properly configured email system\n" " - 'SendEmail.pl': simple script for mail delivery" msgstr "" msgid "--- Email account ---" msgstr "--- E-mail gebruiker ---" msgid "Email address" msgstr "E-mail adres" msgid "Help$Specify the email address where notifications should be sent from." msgstr "Geef het e-mail adres op waar vandaan de e-mail notificaties verzonden worden" msgid "SMTP server" msgstr "SMTP server" msgid "Help$Specify the SMTP server that should deliver the notifications. If it's using a port different from the default(25) append the port with \":port\"." msgstr "Geef de SMTP server voor het verzenden van de notificaties. Indien een andere dan de standaard poort (25) wordt gebruik voeg dan toe \":port\"" msgid "Use SMTP authentication" msgstr "Gebruik SMTP authenticatie" msgid "Help$Set this to 'yes' if your account needs authentication to send mails." msgstr "kies 'ja' indien uw abonnement authenticatie vereist voor het verzenden van e-mails." msgid "Auth user" msgstr "Auth gebruiker" msgid "Help$Specify the auth user, if this account needs authentication for SMTP." msgstr "Geef de e-mail gebruikernaam op, indien SMTP authenticatie voor het abonnement vereist is." msgid "Auth password" msgstr "Auth wachtwoord" msgid "Help$Specify the auth password, if this account needs authentication for SMTP." msgstr "Geef het e-mail wachtwoord op, indien SMTP authenticatie voor het abonnement vereist is." msgid "Mail account check failed!" msgstr "Mail abonnement verificatie mislukt!" msgid "Button$Test" msgstr "Test" #, fuzzy msgid "$ abcdefghijklmnopqrstuvwxyz0123456789-.,#~\\^$[]|()*+?{}/:%@&_" msgstr " abcdefghijklmnopqrstuvwxyz0123456789-.,#~\\^$[]|()*+?{}/:%@&" msgid "Start/Stop time has changed" msgstr "" msgid "Title/episode has changed" msgstr "" msgid "No new timers were added." msgstr "Geen nieuwe timers aangemaakt" msgid "No timers were modified." msgstr "Er zijn geen timers aangepast" msgid "No timers were deleted." msgstr "Er zijn geen timers gewist" msgid "No new events to announce." msgstr "" msgid "This version of EPGSearch does not support this service!" msgstr "Deze versie van EPGSearch ondersteunt deze mogelijkheid niet!" msgid "EPGSearch does not exist!" msgstr "EPGsearch is niet aanwezig!" #, c-format msgid "%d new broadcast" msgstr "%d nieuwe uitzending" msgid "Button$by channel" msgstr "per kanaal" msgid "Button$by time" msgstr "op tijd" msgid "Button$Episode" msgstr "Aflevering" msgid "Button$Title" msgstr "Titel" msgid "announce details" msgstr "vermeldt details" msgid "announce again" msgstr "vermeldt nogmaals" msgid "with next update" msgstr "bij volgende herziening" msgid "again from" msgstr "nogmaals vanaf" msgid "Search timer" msgstr "Zoektimer" msgid "Edit blacklist" msgstr "Wijzig blacklist" msgid "phrase" msgstr "uitdruk" msgid "all words" msgstr "alle woorden" msgid "at least one word" msgstr "tenminste een woord" msgid "match exactly" msgstr "precies passend" msgid "regular expression" msgstr "reguliere uitdrukking" msgid "fuzzy" msgstr "fuzzy" msgid "user-defined" msgstr "gebruiker-gedefinieerd" msgid "interval" msgstr "interval" msgid "channel group" msgstr "kanaalgroep" msgid "only FTA" msgstr "alleen FTA" msgid "Search term" msgstr "Zoekterm" msgid "Search mode" msgstr "Zoekinstellingen" msgid "Tolerance" msgstr "Tolerantie" msgid "Match case" msgstr "Case sensitive" msgid "Use title" msgstr "Gebruik titel" msgid "Use subtitle" msgstr "Gebruik ondertitel" msgid "Use description" msgstr "Gebruik beschrijving" msgid "Use extended EPG info" msgstr "Gebruik uitgebreide EPG info" msgid "Ignore missing categories" msgstr "Negeer ontbrekende categoriëen" msgid "Use channel" msgstr "Gebruik kanaal" msgid " from channel" msgstr " van kanaal" msgid " to channel" msgstr " tot kanaal" msgid "Channel group" msgstr "Kanaal groep" msgid "Use time" msgstr "Gebruik tijd" msgid " Start after" msgstr " Start na" msgid " Start before" msgstr " Start voor" msgid "Use duration" msgstr "Gebruik tijdsduur" msgid " Min. duration" msgstr " Min. duur" msgid " Max. duration" msgstr " Max. tijdsduur" msgid "Use day of week" msgstr "Gebruik dag van de week" msgid "Day of week" msgstr "Dag van de week" msgid "Use global" msgstr "" msgid "Button$Templates" msgstr "Sjablonen" msgid "*** Invalid Channel ***" msgstr "*** Ongeldig Kanaal ***" msgid "Please check channel criteria!" msgstr "AUB kanaal criteria nakijken" msgid "Edit$Delete blacklist?" msgstr "Verwijder blacklist?" msgid "Repeats" msgstr "Herhalingen" msgid "Create search" msgstr "Maak een zoekactie aan" msgid "Search in recordings" msgstr "Zoek in opname's" msgid "Mark as 'already recorded'?" msgstr "Markeer als 'reeds opgenomen'?" msgid "Add/Remove to/from switch list?" msgstr "" msgid "Create blacklist" msgstr "Maak nieuwe blacklist" msgid "EPG Commands" msgstr "EPG commando's" msgid "Epgsearch: RemoteTimerModifications failed" msgstr "" msgid "Already running!" msgstr "Reeds actief!" msgid "Add to switch list?" msgstr "Voeg toe aan schakellijst?" msgid "Delete from switch list?" msgstr "Verwijder van schakellijst?" msgid "Button$Details" msgstr "Details" msgid "Button$Filter" msgstr "Filter" msgid "Button$Show all" msgstr "Toon alles" msgid "conflicts" msgstr "conflicten" msgid "no conflicts!" msgstr "geen conflicten!" msgid "no important conflicts!" msgstr "geen belangrijke conflicten!" msgid "C" msgstr "C" msgid "Button$Repeats" msgstr "Herhalingen" msgid "no check" msgstr "geen controle" msgid "by channel and time" msgstr "op kanaal en tijd" msgid "by event ID" msgstr "op event-ID" msgid "Select directory" msgstr "Selecteer map" msgid "Button$Level" msgstr "Niveau" msgid "Event" msgstr "Gebeurtenis" msgid "Favorites" msgstr "Favorieten" msgid "Search results" msgstr "Zoekresultaten" msgid "Timer conflict! Show?" msgstr "Timerconflict! Tonen?" msgid "Directory" msgstr "Map" msgid "Channel" msgstr "Kanaal" msgid "Childlock" msgstr "Kinderslot" msgid "Record on" msgstr "" msgid "Timer check" msgstr "Timercontrole" msgid "recording with device" msgstr "neemt op met kaart" msgid "Button$With subtitle" msgstr "Met ondertitel" msgid "Button$Without subtitle" msgstr "Zonder ondertitel" msgid "Timer has been deleted" msgstr "" msgid "Button$Extended" msgstr "Uitgebreid" msgid "Button$Simple" msgstr "Eenvoudig" msgid "Use blacklists" msgstr "Gebruik blacklists" msgid "Edit$Search text too short - use anyway?" msgstr "Zoektekst te kort - toch gebruiken?" #, fuzzy msgid "Button$Orphaned" msgstr "per kanaal" msgid "Button$by name" msgstr "op naam" msgid "Button$by date" msgstr "op datum" msgid "Button$Delete all" msgstr "Verwijder alles" msgid "Recordings" msgstr "Opnames" msgid "Edit$Delete entry?" msgstr "Verwijder regel?" msgid "Edit$Delete all entries?" msgstr "Verwijder alle regels?" msgid "Summary" msgstr "Samenvatting" msgid "Auxiliary info" msgstr "Reserve info" msgid "Button$Aux info" msgstr "Res. info" msgid "Search actions" msgstr "Zoekcriteria acties" msgid "Execute search" msgstr "Voer zoekcriterium uit" msgid "Use as search timer on/off" msgstr "Gebruik als zoek-timer aan/uit" msgid "Trigger search timer update" msgstr "Start verversen zoektimer" msgid "Show recordings done" msgstr "Tonen opnames gereed" msgid "Show timers created" msgstr "Toon aangemaakte timers" msgid "Create a copy" msgstr "Maak een kopie" msgid "Use as template" msgstr "Gebruik als sjabloon" msgid "Show switch list" msgstr "Toon schakellijst" msgid "Show blacklists" msgstr "Toon blacklists" msgid "Delete created timers?" msgstr "Verwijder aangemaakte timers?" msgid "Timer conflict check" msgstr "Timerconflict controle" msgid "Disable associated timers too?" msgstr "Schakel gemeenschappelijke timers ook uit?" msgid "Activate associated timers too?" msgstr "Activeer gemeenschappelijke timers ook?" msgid "Search timers activated in setup." msgstr "Zoektimers geactiveerd in instellingen" msgid "Run search timer update?" msgstr "Start verversen zoektimer? " msgid "Copy this entry?" msgstr "Kopiëer deze regel?" msgid "Copy" msgstr "Kopiëer" msgid "Copy this entry to templates?" msgstr "Kopiëer deze regel naar sjablonen" msgid "Delete all timers created from this search?" msgstr "Verwijder alle timers aangemaakt door dit zoekcriterium?" msgid "Button$Actions" msgstr "Acties" msgid "Search entries" msgstr "Zoekregels" msgid "active" msgstr "actief" msgid "Edit$Delete search?" msgstr "Zoekcriterium wissen?" msgid "Edit search" msgstr "Bewerk zoekcriteria" msgid "Record" msgstr "Opnemen" #, fuzzy msgid "Announce by OSD" msgstr "Alleen aankondigen (geen timer)" msgid "Switch only" msgstr "Alleen schakelen" #, fuzzy msgid "Announce and switch" msgstr "Alleen aankondigen (geen timer)" #, fuzzy msgid "Announce by mail" msgstr "Alleen aankondigen (geen timer)" msgid "Inactive record" msgstr "" msgid "only globals" msgstr "" msgid "Selection" msgstr "Selectie" msgid "all" msgstr "alles" msgid "count recordings" msgstr "tel opnames" msgid "count days" msgstr "tel dagen" msgid "if present" msgstr "" #, fuzzy msgid "same day" msgstr "Eerste dag" #, fuzzy msgid "same week" msgstr "Dag van de week" msgid "same month" msgstr "" msgid "Template name" msgstr "Naam van sjabloon" msgid "Help$Specify the name of the template." msgstr "Geef de naam op van het sjabloon" msgid "Help$Specify here the term to search for." msgstr "Vul hier de zoekterm in." msgid "" "Help$The following search modes exist:\n" "\n" "- phrase: searches for sub terms\n" "- all words: all single words must appear\n" "- at least one word: at least one single word must appear\n" "- match exactly: must match exactly\n" "- regular expression: match a regular expression\n" "- fuzzy searching: searches approximately" msgstr "" "Er kan gekozen worden uit de volgende zoekinstellingen:\n" "- alle woorden: alle los voorkomende woorden moeten gevonden worden\n" "- minstens één woord: minstens én woord moet worden gevonden\n" "- past precies: de hele zoekterm komt exact overeen\n" "- reguliere expressie: resultaat past bij uitkomst expressie\n" "- 'fuzzy' zoeken: zoek naar mogelijke matches" msgid "Help$This sets the tolerance of fuzzy searching. The value represents the allowed errors." msgstr "Hier wordt de tolerantie van de 'fuzzy'zoekactie opgegeven. De waarde vertegenwoordigd de toegestane fouten" msgid "Help$Set this to 'Yes' if your search should match the case." msgstr "Kies 'ja' idien de zoekactie case-sensitive moet zijn" msgid "Help$Set this to 'Yes' if you like to search in the title of an event." msgstr "Kies 'ja' indien de zoekactie moet zoeken in de titel van het programma" msgid "Help$Set this to 'Yes' if you like to search in the episode of an event." msgstr "Kies 'ja' indien de zoakactie moet zoeken in de aflevering van een programma" msgid "Help$Set this to 'Yes' if you like to search in the summary of an event." msgstr "Kies 'ja' indien de zoekactie moet zoeken in de samenvatting van een programma." #, fuzzy msgid "Use content descriptor" msgstr "Gebruik beschrijving" #, fuzzy msgid "Help$Set this to 'Yes' if you want to search the contents by a descriptor." msgstr "Kies 'ja' indien de zoekactie moet zoeken in de titel van het programma" msgid "Help$The summary of an event, can contain additional information like 'Genre', 'Category', 'Year',... called 'EPG categories' within EPGSearch. External EPG providers often deliver this information. This allows refining a search and other nice things, like searching for the 'tip of the day'. To use it set this to 'Yes'." msgstr "De samenvatting van een programma kan extra informatie bevatten zoals 'Genre', 'Jaar',... binnen EPGsearch 'EPG categoriëen' genoemd. " msgid "Help$The file epgsearchcats.conf specifies the search mode for this entry. One can search by text or by value. You can also edit a list of predefined values in this file that can be selected here." msgstr "Het bestand epgsearchcats.conf omschrijft de zoekinstellingen voor deze regel. Men kan zoeken op tekst of waarde. Er kan ook een lijst van voorgedefinieerde waarden geselecteerd en aangepast worden" msgid "Help$If a selected category is not part of the summary of an event this normally excludes this event from the search results. To avoid this, set this option to 'Yes', but please handle this with care to avoid a huge amount of results." msgstr "Als een gekozen categorie geen onderdeel is van een samenvatting van een programma, dan zal dit programma niet verschijnen in de zoekresultaten. Om dit te voorkomen kan deze optie worden ingesteld, maar het kan leiden tot heel veel resultaten!" msgid "Use in favorites menu" msgstr "Gebruik in favorieten menu" msgid "Result menu layout" msgstr "Uiterlijk menu resultaten" msgid "Use as search timer" msgstr "Gebruik als zoektimer" msgid "Action" msgstr "Actie" msgid "Switch ... minutes before start" msgstr "Schakel ... minuten voor start" msgid "Unmute sound" msgstr "" #, fuzzy msgid "Ask ... minutes before start" msgstr "Schakel ... minuten voor start" msgid " Series recording" msgstr " Serie's opnemen" msgid "Delete recordings after ... days" msgstr "Verwijder opnames na ... dagen" msgid "Keep ... recordings" msgstr "Bewaar ... opnames" msgid "Pause when ... recordings exist" msgstr "Pauzeer wanneer ... opnames bestaan" msgid "Avoid repeats" msgstr "Vermijdt herhalingen" msgid "Allowed repeats" msgstr "Toegestane herhalingen" msgid "Only repeats within ... days" msgstr "Alleen herhalingen binnen ... dagen" msgid "Compare title" msgstr "Vergelijk titel" msgid "Compare subtitle" msgstr "Vergelijk ondertiteling" msgid "Compare summary" msgstr "Vergelijk samenvatting" #, fuzzy msgid "Min. match in %" msgstr " Min. duur" #, fuzzy msgid "Compare date" msgstr "Vergelijk titel" msgid "Compare categories" msgstr "vergelijk categoriëen" msgid "VPS" msgstr "VPS" msgid "Auto delete" msgstr "Automatisch wissen" msgid "after ... recordings" msgstr "na ... opnames" msgid "after ... days after first rec." msgstr "na ... dagen na eerste opname" msgid "Edit user-defined days of week" msgstr "Bewerk door gebruiker gedefinieerde dagen van de week" msgid "Compare" msgstr "Vergelijk" msgid "Select blacklists" msgstr "Kies blacklists" msgid "Values for EPG category" msgstr "" msgid "Button$Apply" msgstr "Toepassen" msgid "less" msgstr "minder" msgid "less or equal" msgstr "minder of gelijk" msgid "greater" msgstr "meer" msgid "greater or equal" msgstr "meer of gelijk" msgid "equal" msgstr "gelijk" msgid "not equal" msgstr "niet geljk" msgid "Activation of search timer" msgstr "Activering van zoektimer" msgid "First day" msgstr "" msgid "Last day" msgstr "Eerste dag" msgid "Button$all channels" msgstr "alle kanalen" msgid "Button$only FTA" msgstr "alleen FTA" msgid "Button$Timer preview" msgstr "Timer preview" msgid "Blacklist results" msgstr "Blacklists resultaten" msgid "found recordings" msgstr "gevonden opname's" msgid "Error while accessing recording!" msgstr "Fout tijdens benaderen opnames!" msgid "Button$Default" msgstr "" msgid "Edit$Delete template?" msgstr "Verwijder sjabloon?" msgid "Overwrite existing entries?" msgstr "Overschrijf bestaande invoer?" msgid "Edit entry" msgstr "Wijzig invoer" #, fuzzy msgid "Switch" msgstr "Alleen schakelen" msgid "Announce only" msgstr "Alleen aankondigen (geen timer)" #, fuzzy msgid "Announce ... minutes before start" msgstr "Schakel ... minuten voor start" msgid "action at" msgstr "actie op" msgid "Switch list" msgstr "Schakellijst" msgid "Edit template" msgstr "Wijzig sjabloon" msgid "Timers" msgstr "Timers" msgid ">>> no info! <<<" msgstr ">>> geen info! <<<" msgid "Overview" msgstr "Overzicht" msgid "Button$Favorites" msgstr "Favorieten" msgid "Quick search for broadcasts" msgstr "Snel zoeken naar uitzendingen" msgid "Quick search" msgstr "Snel zoeken" msgid "Show in main menu" msgstr "Toon vermelding in hoofdmenu" #, c-format msgid "%d new broadcast(s) found! Show them?" msgstr "%d nieuwe uitzending(en) gevonden! Tonen?" msgid "Search timer update done!" msgstr "Verversen zoektimer gereed!" #, c-format msgid "small EPG content on:%s" msgstr "" msgid "VDR EPG check warning" msgstr "" #, c-format msgid "Switch to (%d) '%s'?" msgstr "" msgid "Programming timer failed!" msgstr "Programmeren timer mislukt!" #~ msgid "in %02ldd" #~ msgstr "in %02ldd" #~ msgid "in %02ldh" #~ msgstr "in %02ldh" #~ msgid "in %02ldm" #~ msgstr "in %02ldm" #, fuzzy #~ msgid "Compare expression" #~ msgstr "reguliere uitdrukking" vdr-plugin-epgsearch/po/sv_SE.po0000644000175000017500000005727513145412721016445 0ustar tobiastobias# VDR plugin language source file. # Copyright (C) 2007 Klaus Schmidinger # This file is distributed under the same license as the VDR package. # Tomas Prybil , 2002 # Jan Ekholm , 2003 # msgid "" msgstr "" "Project-Id-Version: VDR 1.5.7\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-06-15 11:15+0200\n" "PO-Revision-Date: 2007-08-14 20:21+0200\n" "Last-Translator: Tomas Prybil \n" "Language-Team: Swedish \n" "Language: sv\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "Channel groups" msgstr "" msgid "Button$Select" msgstr "" msgid "Channel group used by:" msgstr "" msgid "Edit$Delete group?" msgstr "" msgid "Edit channel group" msgstr "" msgid "Group name" msgstr "" msgid "Button$Invert selection" msgstr "" msgid "Button$All yes" msgstr "" msgid "Button$All no" msgstr "" msgid "Group name is empty!" msgstr "" msgid "Group name already exists!" msgstr "" msgid "Direct access to epgsearch's conflict check menu" msgstr "" msgid "Timer conflicts" msgstr "" msgid "Conflict info in main menu" msgstr "" msgid "next" msgstr "" #, c-format msgid "timer conflict at %s! Show it?" msgstr "" #, c-format msgid "%d timer conflicts! First at %s. Show them?" msgstr "" msgid "search the EPG for repeats and more" msgstr "" msgid "Program guide" msgstr "" msgid "search timer update running" msgstr "" msgid "Direct access to epgsearch's search menu" msgstr "" msgid "Search" msgstr "" msgid "EpgSearch-Search in main menu" msgstr "" msgid "Button$Help" msgstr "" msgid "Standard" msgstr "" msgid "Button$Commands" msgstr "Inspelning" msgid "Button$Search" msgstr "" msgid "never" msgstr "" msgid "always" msgstr "" msgid "smart" msgstr "" msgid "before user-def. times" msgstr "" msgid "after user-def. times" msgstr "" msgid "before 'next'" msgstr "" msgid "General" msgstr "" msgid "EPG menus" msgstr "" msgid "User-defined EPG times" msgstr "" msgid "Timer programming" msgstr "" msgid "Search and search timers" msgstr "" msgid "Timer conflict checking" msgstr "" msgid "Email notification" msgstr "" msgid "Hide main menu entry" msgstr "" msgid "Help$Hides the main menu entry and may be useful if this plugin is used to replace the original 'Schedule' entry." msgstr "" msgid "Main menu entry" msgstr "" msgid "Help$The name of the main menu entry which defaults to 'Programm guide'." msgstr "" msgid "Replace original schedule" msgstr "" msgid "Help$When VDR is patched to allow this plugin to replace the original 'Schedule' entry, you can de/activate this replacement here." msgstr "" msgid "Start menu" msgstr "" msgid "Help$Choose between 'Overview - Now' and 'Schedule' as start menu when this plugin is called." msgstr "" msgid "Ok key" msgstr "" msgid "" "Help$Choose here the behaviour of key 'Ok'. You can use it to display the summary or to switch to the corresponding channel.\n" "Note: the functionality of key 'blue' (Switch/Info/Search) depends on this setting." msgstr "" msgid "Red key" msgstr "" msgid "" "Help$Choose which standard function ('Record' or 'Commands') you like to have on the red key.\n" "(Can be toggled with key '0')" msgstr "" msgid "Blue key" msgstr "" msgid "" "Help$Choose which standard function ('Switch'/'Info' or 'Search') you like to have on the blue key.\n" "(Can be toggled with key '0')" msgstr "" msgid "Show progress in 'Now'" msgstr "" msgid "Help$Shows a progressbar in 'Overview - Now' that informs about the remaining time of the current event." msgstr "" msgid "Show channel numbers" msgstr "" msgid "" "Help$Display channel numbers in 'Overview - Now'.\n" "\n" "(To completely define your own menu look please inspect the MANUAL)" msgstr "" msgid "Show channel separators" msgstr "" msgid "Help$Display VDR channel groups as separators between your channels in 'Overview - Now'." msgstr "" msgid "Show day separators" msgstr "" msgid "Help$Display a separator line at day break in 'Schedule'." msgstr "" msgid "Show radio channels" msgstr "" msgid "Help$Show also radio channels." msgstr "" msgid "Limit channels from 1 to" msgstr "" msgid "Help$If you have a large channel set you can speed up things when you limit the displayed channels with this setting. Use '0' to disable the limit." msgstr "" msgid "'One press' timer creation" msgstr "" msgid "Help$When a timer is created with 'Record' you can choose between an immediate creation of the timer or the display of the timer edit menu." msgstr "" msgid "Show channels without EPG" msgstr "" msgid "Help$Choose 'yes' here if you want to display channels without EPG in 'Overview - Now'. 'Ok' on these entries switches the channel." msgstr "" msgid "Time interval for FRew/FFwd [min]" msgstr "" msgid "" "Help$Choose here the time interval which should be used for jumping through the EPG by pressing FRew/FFwd.\n" "\n" "(If you don't have those keys, you can toggle to this functionality pressing '0' and get '<<' and '>>' on the keys green and yellow)" msgstr "" msgid "Toggle Green/Yellow" msgstr "" msgid "Help$Specify if green and yellow shall also be switched when pressing '0'." msgstr "" msgid "Show favorites menu" msgstr "" msgid "" "Help$A favorites menu can display a list of your favorite broadcasts. Enable this if you want an additional menu besides 'Now' and 'Next'\n" "Any search can be used as a favorite. You only have to set the option 'Use in favorites menu' when editing a search." msgstr "" msgid "for the next ... hours" msgstr "" msgid "Help$This value controls the timespan used to display your favorites." msgstr "" msgid "Use user-defined time" msgstr "" msgid "Help$Besides 'Now' and 'Next' you can specify up to 4 other times in the EPG which can be used by repeatedly pressing the green key, e.g. 'prime time', 'late night',..." msgstr "" msgid "Description" msgstr "" msgid "Help$This is the description for your user-defined time as it will appear as label on the green button." msgstr "" msgid "Time" msgstr "" msgid "Help$Specify the user-defined time here in 'HH:MM'." msgstr "" msgid "Use VDR's timer edit menu" msgstr "" msgid "" "Help$This plugin has its own timer edit menu extending the original one with some extra functionality like\n" "- an additional directory entry\n" "- user-defined days of week for repeating timers\n" "- adding an episode name\n" "- support for EPG variables (see MANUAL)" msgstr "" msgid "Default recording dir" msgstr "" msgid "Help$When creating a timer you can specify here a default recording directory." msgstr "" msgid "Add episode to manual timers" msgstr "" msgid "" "Help$If you create a timer for a series, you can automatically add the episode name.\n" "\n" "- never: no addition\n" "- always: always add episode name if present\n" "- smart: add only if event lasts less than 80 mins." msgstr "" msgid "Default timer check method" msgstr "" msgid "" "Help$Manual timers can be checked for EPG changes. Here you can setup the default check method for each channel. Choose between\n" "\n" "- no checking\n" "- by event ID: checks by an event ID supplied by the channel provider.\n" "- by channel and time: check by the duration match." msgstr "" msgid "Button$Setup" msgstr "Inställningar" msgid "Use search timers" msgstr "" msgid "Help$'Search timers' can be used to automatically create timers for events that match your search criterions." msgstr "" msgid " Update interval [min]" msgstr "" msgid "Help$Specify here the time intervall to be used when searching for events in the background." msgstr "" msgid " SVDRP port" msgstr "" msgid "Help$Programming of new timers or timer changes is done with SVDRP. The default value should be correct, so change it only if you know what you are doing." msgstr "" msgid "Help$Specify here the default priority of timers created with this plugin. This value can also be adjusted for each search itself." msgstr "" msgid "Help$Specify here the default lifetime of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "" msgid "Help$Specify here the default start recording margin of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "" msgid "Help$Specify here the default stop recording margin of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "" msgid "No announcements when replaying" msgstr "" msgid "Help$Set this to 'yes' if you don't like to get any announcements of broadcasts if you currently replay anything." msgstr "" msgid "Recreate timers after deletion" msgstr "" msgid "Help$Set this to 'yes' if you want timers to be recreated with the next search timer update after deleting them." msgstr "" msgid "Check if EPG exists for ... [h]" msgstr "" msgid "Help$Specify how many hours of future EPG there should be and get warned else after a search timer update." msgstr "" msgid "Warn by OSD" msgstr "" msgid "Help$Set this to 'yes' if you want get warnings from the EPG check via OSD." msgstr "" msgid "Warn by mail" msgstr "" msgid "Help$Set this to 'yes' if you want get warnings from the EPG check by mail." msgstr "" msgid "Channel group to check" msgstr "" msgid "Help$Specify the channel group to check." msgstr "" msgid "Ignore PayTV channels" msgstr "" msgid "Help$Set this to 'yes' if don't want to see events on PayTV channels when searching for repeats." msgstr "" msgid "Search templates" msgstr "" msgid "Help$Here you can setup templates for your searches." msgstr "" msgid "Blacklists" msgstr "" msgid "Help$Here you can setup blacklists which can be used within a search to exclude events you don't like." msgstr "" msgid "Help$Here you can setup channel groups which can be used within a search. These are different to VDR channel groups and represent a set of arbitrary channels, e.g. 'FreeTV'." msgstr "" msgid "Ignore below priority" msgstr "" msgid "Help$If a timer with priority below the given value will fail it will not be classified as important. Only important conflicts will produce an OSD message about the conflict after an automatic conflict check." msgstr "" msgid "Ignore conflict duration less ... min." msgstr "" msgid "Help$If a conflicts duration is less then the given number of minutes it will not be classified as important. Only important conflicts will produce an OSD message about the conflict after an automatic conflict check." msgstr "" msgid "Only check within next ... days" msgstr "" msgid "Help$This value reduces the conflict check to the given range of days. All other conflicts are classified as 'not yet important'." msgstr "" msgid "Check also remote conflicts" msgstr "" msgid "Help$Set this to 'yes' if the conflict check should be done for timers set on remote hosts. This needs SVDRPPeering to be set in vdr and Plugin epgsearch running on the remote host." msgstr "" msgid "--- Automatic checking ---" msgstr "" msgid "After each timer programming" msgstr "" msgid "Help$Set this to 'yes' if the conflict check should be performed after each manual timer programming. In the case of a conflict you get immediately a message that informs you about it. The message is only displayed if this timer is involved in any conflict." msgstr "" msgid "When a recording starts" msgstr "" msgid "Help$Set this to 'yes' if the conflict check should be performed when a recording starts. In the case of a conflict you get immediately a message that informs you about it. The message is only displayed if the conflict is within the next 2 hours." msgstr "" msgid "After each search timer update" msgstr "" msgid "Help$Set this to 'yes' if the conflict check should be performed after each search timer update." msgstr "" msgid "every ... minutes" msgstr "" msgid "" "Help$Specify here the time intervall to be used for an automatic conflict check in the background.\n" "('0' disables an automatic check)" msgstr "" msgid "if conflicts within next ... minutes" msgstr "" msgid "Help$If the next conflict will appear in the given number of minutes you can specify here a shorter check intervall to get more OSD notifications about it." msgstr "" msgid "Avoid notification when replaying" msgstr "" msgid "Help$Set this to 'yes' if the don't want to get OSD messages about conflicts if you currently replay something. Nevertheless messages will be displayed if the first upcoming conflict is within the next 2 hours." msgstr "" msgid "Search timer notification" msgstr "" msgid "Help$Set this to 'yes' if you want to get an email notification about the search timers that where programmed automatically in the background." msgstr "" msgid "Time between mails [h]" msgstr "" msgid "" "Help$Specifiy how much time in [h] you would\n" "like to have atleast between two mails.\n" "With '0' you get a new mail after each\n" "search timer update with new results." msgstr "" msgid "Timer conflict notification" msgstr "" msgid "Help$Set this to 'yes' if you want to get an email notification about the timer conflicts." msgstr "" msgid "Send to" msgstr "" msgid "Help$Specify the email address where notifications should be sent to." msgstr "" msgid "Mail method" msgstr "" msgid "" "Help$Specify here the method to use when sending mails.\n" "You can choose between\n" " - 'sendmail': requires a properly configured email system\n" " - 'SendEmail.pl': simple script for mail delivery" msgstr "" msgid "--- Email account ---" msgstr "" msgid "Email address" msgstr "" msgid "Help$Specify the email address where notifications should be sent from." msgstr "" msgid "SMTP server" msgstr "" msgid "Help$Specify the SMTP server that should deliver the notifications. If it's using a port different from the default(25) append the port with \":port\"." msgstr "" msgid "Use SMTP authentication" msgstr "" msgid "Help$Set this to 'yes' if your account needs authentication to send mails." msgstr "" msgid "Auth user" msgstr "" msgid "Help$Specify the auth user, if this account needs authentication for SMTP." msgstr "" msgid "Auth password" msgstr "" msgid "Help$Specify the auth password, if this account needs authentication for SMTP." msgstr "" msgid "Mail account check failed!" msgstr "" msgid "Button$Test" msgstr "" msgid "$ abcdefghijklmnopqrstuvwxyz0123456789-.,#~\\^$[]|()*+?{}/:%@&_" msgstr "" msgid "Start/Stop time has changed" msgstr "" msgid "Title/episode has changed" msgstr "" msgid "No new timers were added." msgstr "" msgid "No timers were modified." msgstr "" msgid "No timers were deleted." msgstr "" msgid "No new events to announce." msgstr "" msgid "This version of EPGSearch does not support this service!" msgstr "" msgid "EPGSearch does not exist!" msgstr "" #, c-format msgid "%d new broadcast" msgstr "" msgid "Button$by channel" msgstr "" msgid "Button$by time" msgstr "" msgid "Button$Episode" msgstr "" msgid "Button$Title" msgstr "" msgid "announce details" msgstr "" msgid "announce again" msgstr "" msgid "with next update" msgstr "" msgid "again from" msgstr "" msgid "Search timer" msgstr "" msgid "Edit blacklist" msgstr "" msgid "phrase" msgstr "" msgid "all words" msgstr "" msgid "at least one word" msgstr "" msgid "match exactly" msgstr "" msgid "regular expression" msgstr "" msgid "fuzzy" msgstr "" msgid "user-defined" msgstr "" msgid "interval" msgstr "" msgid "channel group" msgstr "" msgid "only FTA" msgstr "" msgid "Search term" msgstr "" msgid "Search mode" msgstr "" msgid "Tolerance" msgstr "" msgid "Match case" msgstr "" msgid "Use title" msgstr "" msgid "Use subtitle" msgstr "" msgid "Use description" msgstr "" msgid "Use extended EPG info" msgstr "" msgid "Ignore missing categories" msgstr "" msgid "Use channel" msgstr "" msgid " from channel" msgstr "" msgid " to channel" msgstr "" msgid "Channel group" msgstr "" msgid "Use time" msgstr "" msgid " Start after" msgstr "" msgid " Start before" msgstr "" msgid "Use duration" msgstr "" msgid " Min. duration" msgstr "" msgid " Max. duration" msgstr "" msgid "Use day of week" msgstr "" msgid "Day of week" msgstr "" msgid "Use global" msgstr "" msgid "Button$Templates" msgstr "" msgid "*** Invalid Channel ***" msgstr "" msgid "Please check channel criteria!" msgstr "" msgid "Edit$Delete blacklist?" msgstr "" msgid "Repeats" msgstr "" msgid "Create search" msgstr "" msgid "Search in recordings" msgstr "" msgid "Mark as 'already recorded'?" msgstr "" msgid "Add/Remove to/from switch list?" msgstr "" msgid "Create blacklist" msgstr "" msgid "EPG Commands" msgstr "" msgid "Epgsearch: RemoteTimerModifications failed" msgstr "" msgid "Already running!" msgstr "" msgid "Add to switch list?" msgstr "" msgid "Delete from switch list?" msgstr "" msgid "Button$Details" msgstr "" msgid "Button$Filter" msgstr "" msgid "Button$Show all" msgstr "" msgid "conflicts" msgstr "" msgid "no conflicts!" msgstr "" msgid "no important conflicts!" msgstr "" msgid "C" msgstr "C" msgid "Button$Repeats" msgstr "" msgid "no check" msgstr "" msgid "by channel and time" msgstr "" msgid "by event ID" msgstr "" msgid "Select directory" msgstr "" msgid "Button$Level" msgstr "" msgid "Event" msgstr "" msgid "Favorites" msgstr "" msgid "Search results" msgstr "" msgid "Timer conflict! Show?" msgstr "" msgid "Directory" msgstr "" msgid "Channel" msgstr "" msgid "Childlock" msgstr "" msgid "Record on" msgstr "" msgid "Timer check" msgstr "" msgid "recording with device" msgstr "" msgid "Button$With subtitle" msgstr "" msgid "Button$Without subtitle" msgstr "" msgid "Timer has been deleted" msgstr "" msgid "Button$Extended" msgstr "" msgid "Button$Simple" msgstr "" msgid "Use blacklists" msgstr "" msgid "Edit$Search text too short - use anyway?" msgstr "" #, fuzzy msgid "Button$Orphaned" msgstr "Inspelning" msgid "Button$by name" msgstr "" msgid "Button$by date" msgstr "" msgid "Button$Delete all" msgstr "" msgid "Recordings" msgstr "" msgid "Edit$Delete entry?" msgstr "" msgid "Edit$Delete all entries?" msgstr "" msgid "Summary" msgstr "" msgid "Auxiliary info" msgstr "" msgid "Button$Aux info" msgstr "" msgid "Search actions" msgstr "" msgid "Execute search" msgstr "" msgid "Use as search timer on/off" msgstr "" msgid "Trigger search timer update" msgstr "" msgid "Show recordings done" msgstr "" msgid "Show timers created" msgstr "" msgid "Create a copy" msgstr "" msgid "Use as template" msgstr "" msgid "Show switch list" msgstr "" msgid "Show blacklists" msgstr "" msgid "Delete created timers?" msgstr "" msgid "Timer conflict check" msgstr "" msgid "Disable associated timers too?" msgstr "" msgid "Activate associated timers too?" msgstr "" msgid "Search timers activated in setup." msgstr "" msgid "Run search timer update?" msgstr "" msgid "Copy this entry?" msgstr "" msgid "Copy" msgstr "" msgid "Copy this entry to templates?" msgstr "" msgid "Delete all timers created from this search?" msgstr "" msgid "Button$Actions" msgstr "" msgid "Search entries" msgstr "" msgid "active" msgstr "" msgid "Edit$Delete search?" msgstr "" msgid "Edit search" msgstr "" msgid "Record" msgstr "Inspelning" msgid "Announce by OSD" msgstr "" msgid "Switch only" msgstr "" msgid "Announce and switch" msgstr "" msgid "Announce by mail" msgstr "" msgid "Inactive record" msgstr "" msgid "only globals" msgstr "" msgid "Selection" msgstr "" msgid "all" msgstr "" msgid "count recordings" msgstr "" msgid "count days" msgstr "" msgid "if present" msgstr "" msgid "same day" msgstr "" msgid "same week" msgstr "" msgid "same month" msgstr "" msgid "Template name" msgstr "" msgid "Help$Specify the name of the template." msgstr "" msgid "Help$Specify here the term to search for." msgstr "" msgid "" "Help$The following search modes exist:\n" "\n" "- phrase: searches for sub terms\n" "- all words: all single words must appear\n" "- at least one word: at least one single word must appear\n" "- match exactly: must match exactly\n" "- regular expression: match a regular expression\n" "- fuzzy searching: searches approximately" msgstr "" msgid "Help$This sets the tolerance of fuzzy searching. The value represents the allowed errors." msgstr "" msgid "Help$Set this to 'Yes' if your search should match the case." msgstr "" msgid "Help$Set this to 'Yes' if you like to search in the title of an event." msgstr "" msgid "Help$Set this to 'Yes' if you like to search in the episode of an event." msgstr "" msgid "Help$Set this to 'Yes' if you like to search in the summary of an event." msgstr "" msgid "Use content descriptor" msgstr "" msgid "Help$Set this to 'Yes' if you want to search the contents by a descriptor." msgstr "" msgid "Help$The summary of an event, can contain additional information like 'Genre', 'Category', 'Year',... called 'EPG categories' within EPGSearch. External EPG providers often deliver this information. This allows refining a search and other nice things, like searching for the 'tip of the day'. To use it set this to 'Yes'." msgstr "" msgid "Help$The file epgsearchcats.conf specifies the search mode for this entry. One can search by text or by value. You can also edit a list of predefined values in this file that can be selected here." msgstr "" msgid "Help$If a selected category is not part of the summary of an event this normally excludes this event from the search results. To avoid this, set this option to 'Yes', but please handle this with care to avoid a huge amount of results." msgstr "" msgid "Use in favorites menu" msgstr "" msgid "Result menu layout" msgstr "" msgid "Use as search timer" msgstr "" msgid "Action" msgstr "" msgid "Switch ... minutes before start" msgstr "" msgid "Unmute sound" msgstr "" msgid "Ask ... minutes before start" msgstr "" msgid " Series recording" msgstr "" msgid "Delete recordings after ... days" msgstr "" msgid "Keep ... recordings" msgstr "" msgid "Pause when ... recordings exist" msgstr "" msgid "Avoid repeats" msgstr "" msgid "Allowed repeats" msgstr "" msgid "Only repeats within ... days" msgstr "" msgid "Compare title" msgstr "" msgid "Compare subtitle" msgstr "" msgid "Compare summary" msgstr "" msgid "Min. match in %" msgstr "" msgid "Compare date" msgstr "" msgid "Compare categories" msgstr "" msgid "VPS" msgstr "" msgid "Auto delete" msgstr "" msgid "after ... recordings" msgstr "" msgid "after ... days after first rec." msgstr "" msgid "Edit user-defined days of week" msgstr "" msgid "Compare" msgstr "" msgid "Select blacklists" msgstr "" msgid "Values for EPG category" msgstr "" msgid "Button$Apply" msgstr "" msgid "less" msgstr "" msgid "less or equal" msgstr "" msgid "greater" msgstr "" msgid "greater or equal" msgstr "" msgid "equal" msgstr "" msgid "not equal" msgstr "" msgid "Activation of search timer" msgstr "" msgid "First day" msgstr "" msgid "Last day" msgstr "" msgid "Button$all channels" msgstr "" msgid "Button$only FTA" msgstr "" msgid "Button$Timer preview" msgstr "" msgid "Blacklist results" msgstr "" msgid "found recordings" msgstr "" msgid "Error while accessing recording!" msgstr "" msgid "Button$Default" msgstr "" msgid "Edit$Delete template?" msgstr "" msgid "Overwrite existing entries?" msgstr "" msgid "Edit entry" msgstr "" msgid "Switch" msgstr "" msgid "Announce only" msgstr "" msgid "Announce ... minutes before start" msgstr "" msgid "action at" msgstr "" msgid "Switch list" msgstr "" msgid "Edit template" msgstr "" msgid "Timers" msgstr "" msgid ">>> no info! <<<" msgstr "" msgid "Overview" msgstr "" msgid "Button$Favorites" msgstr "" msgid "Quick search for broadcasts" msgstr "" msgid "Quick search" msgstr "" msgid "Show in main menu" msgstr "" #, c-format msgid "%d new broadcast(s) found! Show them?" msgstr "" msgid "Search timer update done!" msgstr "" #, c-format msgid "small EPG content on:%s" msgstr "" msgid "VDR EPG check warning" msgstr "" #, c-format msgid "Switch to (%d) '%s'?" msgstr "" msgid "Programming timer failed!" msgstr "" vdr-plugin-epgsearch/po/et_EE.po0000644000175000017500000005722613145412721016403 0ustar tobiastobias# VDR plugin language source file. # Copyright (C) 2007 Klaus Schmidinger # This file is distributed under the same license as the VDR package. # Arthur Konovalov , 2004 # msgid "" msgstr "" "Project-Id-Version: VDR 1.5.7\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-06-15 11:15+0200\n" "PO-Revision-Date: 2007-08-14 20:21+0200\n" "Last-Translator: Arthur Konovalov \n" "Language-Team: Estonian \n" "Language: et\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "Channel groups" msgstr "" msgid "Button$Select" msgstr "" msgid "Channel group used by:" msgstr "" msgid "Edit$Delete group?" msgstr "" msgid "Edit channel group" msgstr "" msgid "Group name" msgstr "" msgid "Button$Invert selection" msgstr "" msgid "Button$All yes" msgstr "" msgid "Button$All no" msgstr "" msgid "Group name is empty!" msgstr "" msgid "Group name already exists!" msgstr "" msgid "Direct access to epgsearch's conflict check menu" msgstr "" msgid "Timer conflicts" msgstr "" msgid "Conflict info in main menu" msgstr "" msgid "next" msgstr "" #, c-format msgid "timer conflict at %s! Show it?" msgstr "" #, c-format msgid "%d timer conflicts! First at %s. Show them?" msgstr "" msgid "search the EPG for repeats and more" msgstr "" msgid "Program guide" msgstr "" msgid "search timer update running" msgstr "" msgid "Direct access to epgsearch's search menu" msgstr "" msgid "Search" msgstr "" msgid "EpgSearch-Search in main menu" msgstr "" msgid "Button$Help" msgstr "" msgid "Standard" msgstr "" #, fuzzy msgid "Button$Commands" msgstr "Salvesta" msgid "Button$Search" msgstr "" msgid "never" msgstr "" msgid "always" msgstr "" msgid "smart" msgstr "" msgid "before user-def. times" msgstr "" msgid "after user-def. times" msgstr "" msgid "before 'next'" msgstr "" msgid "General" msgstr "" msgid "EPG menus" msgstr "" msgid "User-defined EPG times" msgstr "" msgid "Timer programming" msgstr "" msgid "Search and search timers" msgstr "" msgid "Timer conflict checking" msgstr "" msgid "Email notification" msgstr "" msgid "Hide main menu entry" msgstr "" msgid "Help$Hides the main menu entry and may be useful if this plugin is used to replace the original 'Schedule' entry." msgstr "" msgid "Main menu entry" msgstr "" msgid "Help$The name of the main menu entry which defaults to 'Programm guide'." msgstr "" msgid "Replace original schedule" msgstr "" msgid "Help$When VDR is patched to allow this plugin to replace the original 'Schedule' entry, you can de/activate this replacement here." msgstr "" msgid "Start menu" msgstr "" msgid "Help$Choose between 'Overview - Now' and 'Schedule' as start menu when this plugin is called." msgstr "" msgid "Ok key" msgstr "" msgid "" "Help$Choose here the behaviour of key 'Ok'. You can use it to display the summary or to switch to the corresponding channel.\n" "Note: the functionality of key 'blue' (Switch/Info/Search) depends on this setting." msgstr "" msgid "Red key" msgstr "" msgid "" "Help$Choose which standard function ('Record' or 'Commands') you like to have on the red key.\n" "(Can be toggled with key '0')" msgstr "" msgid "Blue key" msgstr "" msgid "" "Help$Choose which standard function ('Switch'/'Info' or 'Search') you like to have on the blue key.\n" "(Can be toggled with key '0')" msgstr "" msgid "Show progress in 'Now'" msgstr "" msgid "Help$Shows a progressbar in 'Overview - Now' that informs about the remaining time of the current event." msgstr "" msgid "Show channel numbers" msgstr "" msgid "" "Help$Display channel numbers in 'Overview - Now'.\n" "\n" "(To completely define your own menu look please inspect the MANUAL)" msgstr "" msgid "Show channel separators" msgstr "" msgid "Help$Display VDR channel groups as separators between your channels in 'Overview - Now'." msgstr "" msgid "Show day separators" msgstr "" msgid "Help$Display a separator line at day break in 'Schedule'." msgstr "" msgid "Show radio channels" msgstr "" msgid "Help$Show also radio channels." msgstr "" msgid "Limit channels from 1 to" msgstr "" msgid "Help$If you have a large channel set you can speed up things when you limit the displayed channels with this setting. Use '0' to disable the limit." msgstr "" msgid "'One press' timer creation" msgstr "" msgid "Help$When a timer is created with 'Record' you can choose between an immediate creation of the timer or the display of the timer edit menu." msgstr "" msgid "Show channels without EPG" msgstr "" msgid "Help$Choose 'yes' here if you want to display channels without EPG in 'Overview - Now'. 'Ok' on these entries switches the channel." msgstr "" msgid "Time interval for FRew/FFwd [min]" msgstr "" msgid "" "Help$Choose here the time interval which should be used for jumping through the EPG by pressing FRew/FFwd.\n" "\n" "(If you don't have those keys, you can toggle to this functionality pressing '0' and get '<<' and '>>' on the keys green and yellow)" msgstr "" msgid "Toggle Green/Yellow" msgstr "" msgid "Help$Specify if green and yellow shall also be switched when pressing '0'." msgstr "" msgid "Show favorites menu" msgstr "" msgid "" "Help$A favorites menu can display a list of your favorite broadcasts. Enable this if you want an additional menu besides 'Now' and 'Next'\n" "Any search can be used as a favorite. You only have to set the option 'Use in favorites menu' when editing a search." msgstr "" msgid "for the next ... hours" msgstr "" msgid "Help$This value controls the timespan used to display your favorites." msgstr "" msgid "Use user-defined time" msgstr "" msgid "Help$Besides 'Now' and 'Next' you can specify up to 4 other times in the EPG which can be used by repeatedly pressing the green key, e.g. 'prime time', 'late night',..." msgstr "" msgid "Description" msgstr "" msgid "Help$This is the description for your user-defined time as it will appear as label on the green button." msgstr "" msgid "Time" msgstr "" msgid "Help$Specify the user-defined time here in 'HH:MM'." msgstr "" msgid "Use VDR's timer edit menu" msgstr "" msgid "" "Help$This plugin has its own timer edit menu extending the original one with some extra functionality like\n" "- an additional directory entry\n" "- user-defined days of week for repeating timers\n" "- adding an episode name\n" "- support for EPG variables (see MANUAL)" msgstr "" msgid "Default recording dir" msgstr "" msgid "Help$When creating a timer you can specify here a default recording directory." msgstr "" msgid "Add episode to manual timers" msgstr "" msgid "" "Help$If you create a timer for a series, you can automatically add the episode name.\n" "\n" "- never: no addition\n" "- always: always add episode name if present\n" "- smart: add only if event lasts less than 80 mins." msgstr "" msgid "Default timer check method" msgstr "" msgid "" "Help$Manual timers can be checked for EPG changes. Here you can setup the default check method for each channel. Choose between\n" "\n" "- no checking\n" "- by event ID: checks by an event ID supplied by the channel provider.\n" "- by channel and time: check by the duration match." msgstr "" msgid "Button$Setup" msgstr "Sätted" msgid "Use search timers" msgstr "" msgid "Help$'Search timers' can be used to automatically create timers for events that match your search criterions." msgstr "" msgid " Update interval [min]" msgstr "" msgid "Help$Specify here the time intervall to be used when searching for events in the background." msgstr "" msgid " SVDRP port" msgstr "" msgid "Help$Programming of new timers or timer changes is done with SVDRP. The default value should be correct, so change it only if you know what you are doing." msgstr "" msgid "Help$Specify here the default priority of timers created with this plugin. This value can also be adjusted for each search itself." msgstr "" msgid "Help$Specify here the default lifetime of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "" msgid "Help$Specify here the default start recording margin of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "" msgid "Help$Specify here the default stop recording margin of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "" msgid "No announcements when replaying" msgstr "" msgid "Help$Set this to 'yes' if you don't like to get any announcements of broadcasts if you currently replay anything." msgstr "" msgid "Recreate timers after deletion" msgstr "" msgid "Help$Set this to 'yes' if you want timers to be recreated with the next search timer update after deleting them." msgstr "" msgid "Check if EPG exists for ... [h]" msgstr "" msgid "Help$Specify how many hours of future EPG there should be and get warned else after a search timer update." msgstr "" msgid "Warn by OSD" msgstr "" msgid "Help$Set this to 'yes' if you want get warnings from the EPG check via OSD." msgstr "" msgid "Warn by mail" msgstr "" msgid "Help$Set this to 'yes' if you want get warnings from the EPG check by mail." msgstr "" msgid "Channel group to check" msgstr "" msgid "Help$Specify the channel group to check." msgstr "" msgid "Ignore PayTV channels" msgstr "" msgid "Help$Set this to 'yes' if don't want to see events on PayTV channels when searching for repeats." msgstr "" msgid "Search templates" msgstr "" msgid "Help$Here you can setup templates for your searches." msgstr "" msgid "Blacklists" msgstr "" msgid "Help$Here you can setup blacklists which can be used within a search to exclude events you don't like." msgstr "" msgid "Help$Here you can setup channel groups which can be used within a search. These are different to VDR channel groups and represent a set of arbitrary channels, e.g. 'FreeTV'." msgstr "" msgid "Ignore below priority" msgstr "" msgid "Help$If a timer with priority below the given value will fail it will not be classified as important. Only important conflicts will produce an OSD message about the conflict after an automatic conflict check." msgstr "" msgid "Ignore conflict duration less ... min." msgstr "" msgid "Help$If a conflicts duration is less then the given number of minutes it will not be classified as important. Only important conflicts will produce an OSD message about the conflict after an automatic conflict check." msgstr "" msgid "Only check within next ... days" msgstr "" msgid "Help$This value reduces the conflict check to the given range of days. All other conflicts are classified as 'not yet important'." msgstr "" msgid "Check also remote conflicts" msgstr "" msgid "Help$Set this to 'yes' if the conflict check should be done for timers set on remote hosts. This needs SVDRPPeering to be set in vdr and Plugin epgsearch running on the remote host." msgstr "" msgid "--- Automatic checking ---" msgstr "" msgid "After each timer programming" msgstr "" msgid "Help$Set this to 'yes' if the conflict check should be performed after each manual timer programming. In the case of a conflict you get immediately a message that informs you about it. The message is only displayed if this timer is involved in any conflict." msgstr "" msgid "When a recording starts" msgstr "" msgid "Help$Set this to 'yes' if the conflict check should be performed when a recording starts. In the case of a conflict you get immediately a message that informs you about it. The message is only displayed if the conflict is within the next 2 hours." msgstr "" msgid "After each search timer update" msgstr "" msgid "Help$Set this to 'yes' if the conflict check should be performed after each search timer update." msgstr "" msgid "every ... minutes" msgstr "" msgid "" "Help$Specify here the time intervall to be used for an automatic conflict check in the background.\n" "('0' disables an automatic check)" msgstr "" msgid "if conflicts within next ... minutes" msgstr "" msgid "Help$If the next conflict will appear in the given number of minutes you can specify here a shorter check intervall to get more OSD notifications about it." msgstr "" msgid "Avoid notification when replaying" msgstr "" msgid "Help$Set this to 'yes' if the don't want to get OSD messages about conflicts if you currently replay something. Nevertheless messages will be displayed if the first upcoming conflict is within the next 2 hours." msgstr "" msgid "Search timer notification" msgstr "" msgid "Help$Set this to 'yes' if you want to get an email notification about the search timers that where programmed automatically in the background." msgstr "" msgid "Time between mails [h]" msgstr "" msgid "" "Help$Specifiy how much time in [h] you would\n" "like to have atleast between two mails.\n" "With '0' you get a new mail after each\n" "search timer update with new results." msgstr "" msgid "Timer conflict notification" msgstr "" msgid "Help$Set this to 'yes' if you want to get an email notification about the timer conflicts." msgstr "" msgid "Send to" msgstr "" msgid "Help$Specify the email address where notifications should be sent to." msgstr "" msgid "Mail method" msgstr "" msgid "" "Help$Specify here the method to use when sending mails.\n" "You can choose between\n" " - 'sendmail': requires a properly configured email system\n" " - 'SendEmail.pl': simple script for mail delivery" msgstr "" msgid "--- Email account ---" msgstr "" msgid "Email address" msgstr "" msgid "Help$Specify the email address where notifications should be sent from." msgstr "" msgid "SMTP server" msgstr "" msgid "Help$Specify the SMTP server that should deliver the notifications. If it's using a port different from the default(25) append the port with \":port\"." msgstr "" msgid "Use SMTP authentication" msgstr "" msgid "Help$Set this to 'yes' if your account needs authentication to send mails." msgstr "" msgid "Auth user" msgstr "" msgid "Help$Specify the auth user, if this account needs authentication for SMTP." msgstr "" msgid "Auth password" msgstr "" msgid "Help$Specify the auth password, if this account needs authentication for SMTP." msgstr "" msgid "Mail account check failed!" msgstr "" msgid "Button$Test" msgstr "" msgid "$ abcdefghijklmnopqrstuvwxyz0123456789-.,#~\\^$[]|()*+?{}/:%@&_" msgstr "" msgid "Start/Stop time has changed" msgstr "" msgid "Title/episode has changed" msgstr "" msgid "No new timers were added." msgstr "" msgid "No timers were modified." msgstr "" msgid "No timers were deleted." msgstr "" msgid "No new events to announce." msgstr "" msgid "This version of EPGSearch does not support this service!" msgstr "" msgid "EPGSearch does not exist!" msgstr "" #, c-format msgid "%d new broadcast" msgstr "" msgid "Button$by channel" msgstr "" msgid "Button$by time" msgstr "" msgid "Button$Episode" msgstr "" msgid "Button$Title" msgstr "" msgid "announce details" msgstr "" msgid "announce again" msgstr "" msgid "with next update" msgstr "" msgid "again from" msgstr "" msgid "Search timer" msgstr "" msgid "Edit blacklist" msgstr "" msgid "phrase" msgstr "" msgid "all words" msgstr "" msgid "at least one word" msgstr "" msgid "match exactly" msgstr "" msgid "regular expression" msgstr "" msgid "fuzzy" msgstr "" msgid "user-defined" msgstr "" msgid "interval" msgstr "" msgid "channel group" msgstr "" msgid "only FTA" msgstr "" msgid "Search term" msgstr "" msgid "Search mode" msgstr "" msgid "Tolerance" msgstr "" msgid "Match case" msgstr "" msgid "Use title" msgstr "" msgid "Use subtitle" msgstr "" msgid "Use description" msgstr "" msgid "Use extended EPG info" msgstr "" msgid "Ignore missing categories" msgstr "" msgid "Use channel" msgstr "" msgid " from channel" msgstr "" msgid " to channel" msgstr "" msgid "Channel group" msgstr "" msgid "Use time" msgstr "" msgid " Start after" msgstr "" msgid " Start before" msgstr "" msgid "Use duration" msgstr "" msgid " Min. duration" msgstr "" msgid " Max. duration" msgstr "" msgid "Use day of week" msgstr "" msgid "Day of week" msgstr "" msgid "Use global" msgstr "" msgid "Button$Templates" msgstr "" msgid "*** Invalid Channel ***" msgstr "" msgid "Please check channel criteria!" msgstr "" msgid "Edit$Delete blacklist?" msgstr "" msgid "Repeats" msgstr "" msgid "Create search" msgstr "" msgid "Search in recordings" msgstr "" msgid "Mark as 'already recorded'?" msgstr "" msgid "Add/Remove to/from switch list?" msgstr "" msgid "Create blacklist" msgstr "" msgid "EPG Commands" msgstr "" msgid "Epgsearch: RemoteTimerModifications failed" msgstr "" msgid "Already running!" msgstr "" msgid "Add to switch list?" msgstr "" msgid "Delete from switch list?" msgstr "" msgid "Button$Details" msgstr "" msgid "Button$Filter" msgstr "" msgid "Button$Show all" msgstr "" msgid "conflicts" msgstr "" msgid "no conflicts!" msgstr "" msgid "no important conflicts!" msgstr "" msgid "C" msgstr "C" msgid "Button$Repeats" msgstr "" msgid "no check" msgstr "" msgid "by channel and time" msgstr "" msgid "by event ID" msgstr "" msgid "Select directory" msgstr "" msgid "Button$Level" msgstr "" msgid "Event" msgstr "" msgid "Favorites" msgstr "" msgid "Search results" msgstr "" msgid "Timer conflict! Show?" msgstr "" msgid "Directory" msgstr "" msgid "Channel" msgstr "" msgid "Childlock" msgstr "" msgid "Record on" msgstr "" msgid "Timer check" msgstr "" msgid "recording with device" msgstr "" msgid "Button$With subtitle" msgstr "" msgid "Button$Without subtitle" msgstr "" msgid "Timer has been deleted" msgstr "" msgid "Button$Extended" msgstr "" msgid "Button$Simple" msgstr "" msgid "Use blacklists" msgstr "" msgid "Edit$Search text too short - use anyway?" msgstr "" #, fuzzy msgid "Button$Orphaned" msgstr "Salvesta" msgid "Button$by name" msgstr "" msgid "Button$by date" msgstr "" msgid "Button$Delete all" msgstr "" msgid "Recordings" msgstr "" msgid "Edit$Delete entry?" msgstr "" msgid "Edit$Delete all entries?" msgstr "" msgid "Summary" msgstr "" msgid "Auxiliary info" msgstr "" msgid "Button$Aux info" msgstr "" msgid "Search actions" msgstr "" msgid "Execute search" msgstr "" msgid "Use as search timer on/off" msgstr "" msgid "Trigger search timer update" msgstr "" msgid "Show recordings done" msgstr "" msgid "Show timers created" msgstr "" msgid "Create a copy" msgstr "" msgid "Use as template" msgstr "" msgid "Show switch list" msgstr "" msgid "Show blacklists" msgstr "" msgid "Delete created timers?" msgstr "" msgid "Timer conflict check" msgstr "" msgid "Disable associated timers too?" msgstr "" msgid "Activate associated timers too?" msgstr "" msgid "Search timers activated in setup." msgstr "" msgid "Run search timer update?" msgstr "" msgid "Copy this entry?" msgstr "" msgid "Copy" msgstr "" msgid "Copy this entry to templates?" msgstr "" msgid "Delete all timers created from this search?" msgstr "" msgid "Button$Actions" msgstr "" msgid "Search entries" msgstr "" msgid "active" msgstr "" msgid "Edit$Delete search?" msgstr "" msgid "Edit search" msgstr "" msgid "Record" msgstr "Salvesta" msgid "Announce by OSD" msgstr "" msgid "Switch only" msgstr "" msgid "Announce and switch" msgstr "" msgid "Announce by mail" msgstr "" msgid "Inactive record" msgstr "" msgid "only globals" msgstr "" msgid "Selection" msgstr "" msgid "all" msgstr "" msgid "count recordings" msgstr "" msgid "count days" msgstr "" msgid "if present" msgstr "" msgid "same day" msgstr "" msgid "same week" msgstr "" msgid "same month" msgstr "" msgid "Template name" msgstr "" msgid "Help$Specify the name of the template." msgstr "" msgid "Help$Specify here the term to search for." msgstr "" msgid "" "Help$The following search modes exist:\n" "\n" "- phrase: searches for sub terms\n" "- all words: all single words must appear\n" "- at least one word: at least one single word must appear\n" "- match exactly: must match exactly\n" "- regular expression: match a regular expression\n" "- fuzzy searching: searches approximately" msgstr "" msgid "Help$This sets the tolerance of fuzzy searching. The value represents the allowed errors." msgstr "" msgid "Help$Set this to 'Yes' if your search should match the case." msgstr "" msgid "Help$Set this to 'Yes' if you like to search in the title of an event." msgstr "" msgid "Help$Set this to 'Yes' if you like to search in the episode of an event." msgstr "" msgid "Help$Set this to 'Yes' if you like to search in the summary of an event." msgstr "" msgid "Use content descriptor" msgstr "" msgid "Help$Set this to 'Yes' if you want to search the contents by a descriptor." msgstr "" msgid "Help$The summary of an event, can contain additional information like 'Genre', 'Category', 'Year',... called 'EPG categories' within EPGSearch. External EPG providers often deliver this information. This allows refining a search and other nice things, like searching for the 'tip of the day'. To use it set this to 'Yes'." msgstr "" msgid "Help$The file epgsearchcats.conf specifies the search mode for this entry. One can search by text or by value. You can also edit a list of predefined values in this file that can be selected here." msgstr "" msgid "Help$If a selected category is not part of the summary of an event this normally excludes this event from the search results. To avoid this, set this option to 'Yes', but please handle this with care to avoid a huge amount of results." msgstr "" msgid "Use in favorites menu" msgstr "" msgid "Result menu layout" msgstr "" msgid "Use as search timer" msgstr "" msgid "Action" msgstr "" msgid "Switch ... minutes before start" msgstr "" msgid "Unmute sound" msgstr "" msgid "Ask ... minutes before start" msgstr "" msgid " Series recording" msgstr "" msgid "Delete recordings after ... days" msgstr "" msgid "Keep ... recordings" msgstr "" msgid "Pause when ... recordings exist" msgstr "" msgid "Avoid repeats" msgstr "" msgid "Allowed repeats" msgstr "" msgid "Only repeats within ... days" msgstr "" msgid "Compare title" msgstr "" msgid "Compare subtitle" msgstr "" msgid "Compare summary" msgstr "" msgid "Min. match in %" msgstr "" msgid "Compare date" msgstr "" msgid "Compare categories" msgstr "" msgid "VPS" msgstr "" msgid "Auto delete" msgstr "" msgid "after ... recordings" msgstr "" msgid "after ... days after first rec." msgstr "" msgid "Edit user-defined days of week" msgstr "" msgid "Compare" msgstr "" msgid "Select blacklists" msgstr "" msgid "Values for EPG category" msgstr "" msgid "Button$Apply" msgstr "" msgid "less" msgstr "" msgid "less or equal" msgstr "" msgid "greater" msgstr "" msgid "greater or equal" msgstr "" msgid "equal" msgstr "" msgid "not equal" msgstr "" msgid "Activation of search timer" msgstr "" msgid "First day" msgstr "" msgid "Last day" msgstr "" msgid "Button$all channels" msgstr "" msgid "Button$only FTA" msgstr "" msgid "Button$Timer preview" msgstr "" msgid "Blacklist results" msgstr "" msgid "found recordings" msgstr "" msgid "Error while accessing recording!" msgstr "" msgid "Button$Default" msgstr "" msgid "Edit$Delete template?" msgstr "" msgid "Overwrite existing entries?" msgstr "" msgid "Edit entry" msgstr "" msgid "Switch" msgstr "" msgid "Announce only" msgstr "" msgid "Announce ... minutes before start" msgstr "" msgid "action at" msgstr "" msgid "Switch list" msgstr "" msgid "Edit template" msgstr "" msgid "Timers" msgstr "" msgid ">>> no info! <<<" msgstr "" msgid "Overview" msgstr "" msgid "Button$Favorites" msgstr "" msgid "Quick search for broadcasts" msgstr "" msgid "Quick search" msgstr "" msgid "Show in main menu" msgstr "" #, c-format msgid "%d new broadcast(s) found! Show them?" msgstr "" msgid "Search timer update done!" msgstr "" #, c-format msgid "small EPG content on:%s" msgstr "" msgid "VDR EPG check warning" msgstr "" #, c-format msgid "Switch to (%d) '%s'?" msgstr "" msgid "Programming timer failed!" msgstr "" vdr-plugin-epgsearch/po/da_DK.po0000644000175000017500000005722113145412721016357 0ustar tobiastobias# VDR plugin language source file. # Copyright (C) 2007 Klaus Schmidinger # This file is distributed under the same license as the VDR package. # Mogens Elneff , 2004 # msgid "" msgstr "" "Project-Id-Version: VDR 1.5.7\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-06-15 11:15+0200\n" "PO-Revision-Date: 2007-08-14 20:21+0200\n" "Last-Translator: Mogens Elneff \n" "Language-Team: Danish \n" "Language: da\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "Channel groups" msgstr "" msgid "Button$Select" msgstr "" msgid "Channel group used by:" msgstr "" msgid "Edit$Delete group?" msgstr "" msgid "Edit channel group" msgstr "" msgid "Group name" msgstr "" msgid "Button$Invert selection" msgstr "" msgid "Button$All yes" msgstr "" msgid "Button$All no" msgstr "" msgid "Group name is empty!" msgstr "" msgid "Group name already exists!" msgstr "" msgid "Direct access to epgsearch's conflict check menu" msgstr "" msgid "Timer conflicts" msgstr "" msgid "Conflict info in main menu" msgstr "" msgid "next" msgstr "" #, c-format msgid "timer conflict at %s! Show it?" msgstr "" #, c-format msgid "%d timer conflicts! First at %s. Show them?" msgstr "" msgid "search the EPG for repeats and more" msgstr "" msgid "Program guide" msgstr "" msgid "search timer update running" msgstr "" msgid "Direct access to epgsearch's search menu" msgstr "" msgid "Search" msgstr "" msgid "EpgSearch-Search in main menu" msgstr "" msgid "Button$Help" msgstr "" msgid "Standard" msgstr "" #, fuzzy msgid "Button$Commands" msgstr "Optag" msgid "Button$Search" msgstr "" msgid "never" msgstr "" msgid "always" msgstr "" msgid "smart" msgstr "" msgid "before user-def. times" msgstr "" msgid "after user-def. times" msgstr "" msgid "before 'next'" msgstr "" msgid "General" msgstr "" msgid "EPG menus" msgstr "" msgid "User-defined EPG times" msgstr "" msgid "Timer programming" msgstr "" msgid "Search and search timers" msgstr "" msgid "Timer conflict checking" msgstr "" msgid "Email notification" msgstr "" msgid "Hide main menu entry" msgstr "" msgid "Help$Hides the main menu entry and may be useful if this plugin is used to replace the original 'Schedule' entry." msgstr "" msgid "Main menu entry" msgstr "" msgid "Help$The name of the main menu entry which defaults to 'Programm guide'." msgstr "" msgid "Replace original schedule" msgstr "" msgid "Help$When VDR is patched to allow this plugin to replace the original 'Schedule' entry, you can de/activate this replacement here." msgstr "" msgid "Start menu" msgstr "" msgid "Help$Choose between 'Overview - Now' and 'Schedule' as start menu when this plugin is called." msgstr "" msgid "Ok key" msgstr "" msgid "" "Help$Choose here the behaviour of key 'Ok'. You can use it to display the summary or to switch to the corresponding channel.\n" "Note: the functionality of key 'blue' (Switch/Info/Search) depends on this setting." msgstr "" msgid "Red key" msgstr "" msgid "" "Help$Choose which standard function ('Record' or 'Commands') you like to have on the red key.\n" "(Can be toggled with key '0')" msgstr "" msgid "Blue key" msgstr "" msgid "" "Help$Choose which standard function ('Switch'/'Info' or 'Search') you like to have on the blue key.\n" "(Can be toggled with key '0')" msgstr "" msgid "Show progress in 'Now'" msgstr "" msgid "Help$Shows a progressbar in 'Overview - Now' that informs about the remaining time of the current event." msgstr "" msgid "Show channel numbers" msgstr "" msgid "" "Help$Display channel numbers in 'Overview - Now'.\n" "\n" "(To completely define your own menu look please inspect the MANUAL)" msgstr "" msgid "Show channel separators" msgstr "" msgid "Help$Display VDR channel groups as separators between your channels in 'Overview - Now'." msgstr "" msgid "Show day separators" msgstr "" msgid "Help$Display a separator line at day break in 'Schedule'." msgstr "" msgid "Show radio channels" msgstr "" msgid "Help$Show also radio channels." msgstr "" msgid "Limit channels from 1 to" msgstr "" msgid "Help$If you have a large channel set you can speed up things when you limit the displayed channels with this setting. Use '0' to disable the limit." msgstr "" msgid "'One press' timer creation" msgstr "" msgid "Help$When a timer is created with 'Record' you can choose between an immediate creation of the timer or the display of the timer edit menu." msgstr "" msgid "Show channels without EPG" msgstr "" msgid "Help$Choose 'yes' here if you want to display channels without EPG in 'Overview - Now'. 'Ok' on these entries switches the channel." msgstr "" msgid "Time interval for FRew/FFwd [min]" msgstr "" msgid "" "Help$Choose here the time interval which should be used for jumping through the EPG by pressing FRew/FFwd.\n" "\n" "(If you don't have those keys, you can toggle to this functionality pressing '0' and get '<<' and '>>' on the keys green and yellow)" msgstr "" msgid "Toggle Green/Yellow" msgstr "" msgid "Help$Specify if green and yellow shall also be switched when pressing '0'." msgstr "" msgid "Show favorites menu" msgstr "" msgid "" "Help$A favorites menu can display a list of your favorite broadcasts. Enable this if you want an additional menu besides 'Now' and 'Next'\n" "Any search can be used as a favorite. You only have to set the option 'Use in favorites menu' when editing a search." msgstr "" msgid "for the next ... hours" msgstr "" msgid "Help$This value controls the timespan used to display your favorites." msgstr "" msgid "Use user-defined time" msgstr "" msgid "Help$Besides 'Now' and 'Next' you can specify up to 4 other times in the EPG which can be used by repeatedly pressing the green key, e.g. 'prime time', 'late night',..." msgstr "" msgid "Description" msgstr "" msgid "Help$This is the description for your user-defined time as it will appear as label on the green button." msgstr "" msgid "Time" msgstr "" msgid "Help$Specify the user-defined time here in 'HH:MM'." msgstr "" msgid "Use VDR's timer edit menu" msgstr "" msgid "" "Help$This plugin has its own timer edit menu extending the original one with some extra functionality like\n" "- an additional directory entry\n" "- user-defined days of week for repeating timers\n" "- adding an episode name\n" "- support for EPG variables (see MANUAL)" msgstr "" msgid "Default recording dir" msgstr "" msgid "Help$When creating a timer you can specify here a default recording directory." msgstr "" msgid "Add episode to manual timers" msgstr "" msgid "" "Help$If you create a timer for a series, you can automatically add the episode name.\n" "\n" "- never: no addition\n" "- always: always add episode name if present\n" "- smart: add only if event lasts less than 80 mins." msgstr "" msgid "Default timer check method" msgstr "" msgid "" "Help$Manual timers can be checked for EPG changes. Here you can setup the default check method for each channel. Choose between\n" "\n" "- no checking\n" "- by event ID: checks by an event ID supplied by the channel provider.\n" "- by channel and time: check by the duration match." msgstr "" msgid "Button$Setup" msgstr "Indstillinger" msgid "Use search timers" msgstr "" msgid "Help$'Search timers' can be used to automatically create timers for events that match your search criterions." msgstr "" msgid " Update interval [min]" msgstr "" msgid "Help$Specify here the time intervall to be used when searching for events in the background." msgstr "" msgid " SVDRP port" msgstr "" msgid "Help$Programming of new timers or timer changes is done with SVDRP. The default value should be correct, so change it only if you know what you are doing." msgstr "" msgid "Help$Specify here the default priority of timers created with this plugin. This value can also be adjusted for each search itself." msgstr "" msgid "Help$Specify here the default lifetime of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "" msgid "Help$Specify here the default start recording margin of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "" msgid "Help$Specify here the default stop recording margin of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "" msgid "No announcements when replaying" msgstr "" msgid "Help$Set this to 'yes' if you don't like to get any announcements of broadcasts if you currently replay anything." msgstr "" msgid "Recreate timers after deletion" msgstr "" msgid "Help$Set this to 'yes' if you want timers to be recreated with the next search timer update after deleting them." msgstr "" msgid "Check if EPG exists for ... [h]" msgstr "" msgid "Help$Specify how many hours of future EPG there should be and get warned else after a search timer update." msgstr "" msgid "Warn by OSD" msgstr "" msgid "Help$Set this to 'yes' if you want get warnings from the EPG check via OSD." msgstr "" msgid "Warn by mail" msgstr "" msgid "Help$Set this to 'yes' if you want get warnings from the EPG check by mail." msgstr "" msgid "Channel group to check" msgstr "" msgid "Help$Specify the channel group to check." msgstr "" msgid "Ignore PayTV channels" msgstr "" msgid "Help$Set this to 'yes' if don't want to see events on PayTV channels when searching for repeats." msgstr "" msgid "Search templates" msgstr "" msgid "Help$Here you can setup templates for your searches." msgstr "" msgid "Blacklists" msgstr "" msgid "Help$Here you can setup blacklists which can be used within a search to exclude events you don't like." msgstr "" msgid "Help$Here you can setup channel groups which can be used within a search. These are different to VDR channel groups and represent a set of arbitrary channels, e.g. 'FreeTV'." msgstr "" msgid "Ignore below priority" msgstr "" msgid "Help$If a timer with priority below the given value will fail it will not be classified as important. Only important conflicts will produce an OSD message about the conflict after an automatic conflict check." msgstr "" msgid "Ignore conflict duration less ... min." msgstr "" msgid "Help$If a conflicts duration is less then the given number of minutes it will not be classified as important. Only important conflicts will produce an OSD message about the conflict after an automatic conflict check." msgstr "" msgid "Only check within next ... days" msgstr "" msgid "Help$This value reduces the conflict check to the given range of days. All other conflicts are classified as 'not yet important'." msgstr "" msgid "Check also remote conflicts" msgstr "" msgid "Help$Set this to 'yes' if the conflict check should be done for timers set on remote hosts. This needs SVDRPPeering to be set in vdr and Plugin epgsearch running on the remote host." msgstr "" msgid "--- Automatic checking ---" msgstr "" msgid "After each timer programming" msgstr "" msgid "Help$Set this to 'yes' if the conflict check should be performed after each manual timer programming. In the case of a conflict you get immediately a message that informs you about it. The message is only displayed if this timer is involved in any conflict." msgstr "" msgid "When a recording starts" msgstr "" msgid "Help$Set this to 'yes' if the conflict check should be performed when a recording starts. In the case of a conflict you get immediately a message that informs you about it. The message is only displayed if the conflict is within the next 2 hours." msgstr "" msgid "After each search timer update" msgstr "" msgid "Help$Set this to 'yes' if the conflict check should be performed after each search timer update." msgstr "" msgid "every ... minutes" msgstr "" msgid "" "Help$Specify here the time intervall to be used for an automatic conflict check in the background.\n" "('0' disables an automatic check)" msgstr "" msgid "if conflicts within next ... minutes" msgstr "" msgid "Help$If the next conflict will appear in the given number of minutes you can specify here a shorter check intervall to get more OSD notifications about it." msgstr "" msgid "Avoid notification when replaying" msgstr "" msgid "Help$Set this to 'yes' if the don't want to get OSD messages about conflicts if you currently replay something. Nevertheless messages will be displayed if the first upcoming conflict is within the next 2 hours." msgstr "" msgid "Search timer notification" msgstr "" msgid "Help$Set this to 'yes' if you want to get an email notification about the search timers that where programmed automatically in the background." msgstr "" msgid "Time between mails [h]" msgstr "" msgid "" "Help$Specifiy how much time in [h] you would\n" "like to have atleast between two mails.\n" "With '0' you get a new mail after each\n" "search timer update with new results." msgstr "" msgid "Timer conflict notification" msgstr "" msgid "Help$Set this to 'yes' if you want to get an email notification about the timer conflicts." msgstr "" msgid "Send to" msgstr "" msgid "Help$Specify the email address where notifications should be sent to." msgstr "" msgid "Mail method" msgstr "" msgid "" "Help$Specify here the method to use when sending mails.\n" "You can choose between\n" " - 'sendmail': requires a properly configured email system\n" " - 'SendEmail.pl': simple script for mail delivery" msgstr "" msgid "--- Email account ---" msgstr "" msgid "Email address" msgstr "" msgid "Help$Specify the email address where notifications should be sent from." msgstr "" msgid "SMTP server" msgstr "" msgid "Help$Specify the SMTP server that should deliver the notifications. If it's using a port different from the default(25) append the port with \":port\"." msgstr "" msgid "Use SMTP authentication" msgstr "" msgid "Help$Set this to 'yes' if your account needs authentication to send mails." msgstr "" msgid "Auth user" msgstr "" msgid "Help$Specify the auth user, if this account needs authentication for SMTP." msgstr "" msgid "Auth password" msgstr "" msgid "Help$Specify the auth password, if this account needs authentication for SMTP." msgstr "" msgid "Mail account check failed!" msgstr "" msgid "Button$Test" msgstr "" msgid "$ abcdefghijklmnopqrstuvwxyz0123456789-.,#~\\^$[]|()*+?{}/:%@&_" msgstr "" msgid "Start/Stop time has changed" msgstr "" msgid "Title/episode has changed" msgstr "" msgid "No new timers were added." msgstr "" msgid "No timers were modified." msgstr "" msgid "No timers were deleted." msgstr "" msgid "No new events to announce." msgstr "" msgid "This version of EPGSearch does not support this service!" msgstr "" msgid "EPGSearch does not exist!" msgstr "" #, c-format msgid "%d new broadcast" msgstr "" msgid "Button$by channel" msgstr "" msgid "Button$by time" msgstr "" msgid "Button$Episode" msgstr "" msgid "Button$Title" msgstr "" msgid "announce details" msgstr "" msgid "announce again" msgstr "" msgid "with next update" msgstr "" msgid "again from" msgstr "" msgid "Search timer" msgstr "" msgid "Edit blacklist" msgstr "" msgid "phrase" msgstr "" msgid "all words" msgstr "" msgid "at least one word" msgstr "" msgid "match exactly" msgstr "" msgid "regular expression" msgstr "" msgid "fuzzy" msgstr "" msgid "user-defined" msgstr "" msgid "interval" msgstr "" msgid "channel group" msgstr "" msgid "only FTA" msgstr "" msgid "Search term" msgstr "" msgid "Search mode" msgstr "" msgid "Tolerance" msgstr "" msgid "Match case" msgstr "" msgid "Use title" msgstr "" msgid "Use subtitle" msgstr "" msgid "Use description" msgstr "" msgid "Use extended EPG info" msgstr "" msgid "Ignore missing categories" msgstr "" msgid "Use channel" msgstr "" msgid " from channel" msgstr "" msgid " to channel" msgstr "" msgid "Channel group" msgstr "" msgid "Use time" msgstr "" msgid " Start after" msgstr "" msgid " Start before" msgstr "" msgid "Use duration" msgstr "" msgid " Min. duration" msgstr "" msgid " Max. duration" msgstr "" msgid "Use day of week" msgstr "" msgid "Day of week" msgstr "" msgid "Use global" msgstr "" msgid "Button$Templates" msgstr "" msgid "*** Invalid Channel ***" msgstr "" msgid "Please check channel criteria!" msgstr "" msgid "Edit$Delete blacklist?" msgstr "" msgid "Repeats" msgstr "" msgid "Create search" msgstr "" msgid "Search in recordings" msgstr "" msgid "Mark as 'already recorded'?" msgstr "" msgid "Add/Remove to/from switch list?" msgstr "" msgid "Create blacklist" msgstr "" msgid "EPG Commands" msgstr "" msgid "Epgsearch: RemoteTimerModifications failed" msgstr "" msgid "Already running!" msgstr "" msgid "Add to switch list?" msgstr "" msgid "Delete from switch list?" msgstr "" msgid "Button$Details" msgstr "" msgid "Button$Filter" msgstr "" msgid "Button$Show all" msgstr "" msgid "conflicts" msgstr "" msgid "no conflicts!" msgstr "" msgid "no important conflicts!" msgstr "" msgid "C" msgstr "C" msgid "Button$Repeats" msgstr "" msgid "no check" msgstr "" msgid "by channel and time" msgstr "" msgid "by event ID" msgstr "" msgid "Select directory" msgstr "" msgid "Button$Level" msgstr "" msgid "Event" msgstr "" msgid "Favorites" msgstr "" msgid "Search results" msgstr "" msgid "Timer conflict! Show?" msgstr "" msgid "Directory" msgstr "" msgid "Channel" msgstr "" msgid "Childlock" msgstr "" msgid "Record on" msgstr "" msgid "Timer check" msgstr "" msgid "recording with device" msgstr "" msgid "Button$With subtitle" msgstr "" msgid "Button$Without subtitle" msgstr "" msgid "Timer has been deleted" msgstr "" msgid "Button$Extended" msgstr "" msgid "Button$Simple" msgstr "" msgid "Use blacklists" msgstr "" msgid "Edit$Search text too short - use anyway?" msgstr "" #, fuzzy msgid "Button$Orphaned" msgstr "Optag" msgid "Button$by name" msgstr "" msgid "Button$by date" msgstr "" msgid "Button$Delete all" msgstr "" msgid "Recordings" msgstr "" msgid "Edit$Delete entry?" msgstr "" msgid "Edit$Delete all entries?" msgstr "" msgid "Summary" msgstr "" msgid "Auxiliary info" msgstr "" msgid "Button$Aux info" msgstr "" msgid "Search actions" msgstr "" msgid "Execute search" msgstr "" msgid "Use as search timer on/off" msgstr "" msgid "Trigger search timer update" msgstr "" msgid "Show recordings done" msgstr "" msgid "Show timers created" msgstr "" msgid "Create a copy" msgstr "" msgid "Use as template" msgstr "" msgid "Show switch list" msgstr "" msgid "Show blacklists" msgstr "" msgid "Delete created timers?" msgstr "" msgid "Timer conflict check" msgstr "" msgid "Disable associated timers too?" msgstr "" msgid "Activate associated timers too?" msgstr "" msgid "Search timers activated in setup." msgstr "" msgid "Run search timer update?" msgstr "" msgid "Copy this entry?" msgstr "" msgid "Copy" msgstr "" msgid "Copy this entry to templates?" msgstr "" msgid "Delete all timers created from this search?" msgstr "" msgid "Button$Actions" msgstr "" msgid "Search entries" msgstr "" msgid "active" msgstr "" msgid "Edit$Delete search?" msgstr "" msgid "Edit search" msgstr "" msgid "Record" msgstr "Optag" msgid "Announce by OSD" msgstr "" msgid "Switch only" msgstr "" msgid "Announce and switch" msgstr "" msgid "Announce by mail" msgstr "" msgid "Inactive record" msgstr "" msgid "only globals" msgstr "" msgid "Selection" msgstr "" msgid "all" msgstr "" msgid "count recordings" msgstr "" msgid "count days" msgstr "" msgid "if present" msgstr "" msgid "same day" msgstr "" msgid "same week" msgstr "" msgid "same month" msgstr "" msgid "Template name" msgstr "" msgid "Help$Specify the name of the template." msgstr "" msgid "Help$Specify here the term to search for." msgstr "" msgid "" "Help$The following search modes exist:\n" "\n" "- phrase: searches for sub terms\n" "- all words: all single words must appear\n" "- at least one word: at least one single word must appear\n" "- match exactly: must match exactly\n" "- regular expression: match a regular expression\n" "- fuzzy searching: searches approximately" msgstr "" msgid "Help$This sets the tolerance of fuzzy searching. The value represents the allowed errors." msgstr "" msgid "Help$Set this to 'Yes' if your search should match the case." msgstr "" msgid "Help$Set this to 'Yes' if you like to search in the title of an event." msgstr "" msgid "Help$Set this to 'Yes' if you like to search in the episode of an event." msgstr "" msgid "Help$Set this to 'Yes' if you like to search in the summary of an event." msgstr "" msgid "Use content descriptor" msgstr "" msgid "Help$Set this to 'Yes' if you want to search the contents by a descriptor." msgstr "" msgid "Help$The summary of an event, can contain additional information like 'Genre', 'Category', 'Year',... called 'EPG categories' within EPGSearch. External EPG providers often deliver this information. This allows refining a search and other nice things, like searching for the 'tip of the day'. To use it set this to 'Yes'." msgstr "" msgid "Help$The file epgsearchcats.conf specifies the search mode for this entry. One can search by text or by value. You can also edit a list of predefined values in this file that can be selected here." msgstr "" msgid "Help$If a selected category is not part of the summary of an event this normally excludes this event from the search results. To avoid this, set this option to 'Yes', but please handle this with care to avoid a huge amount of results." msgstr "" msgid "Use in favorites menu" msgstr "" msgid "Result menu layout" msgstr "" msgid "Use as search timer" msgstr "" msgid "Action" msgstr "" msgid "Switch ... minutes before start" msgstr "" msgid "Unmute sound" msgstr "" msgid "Ask ... minutes before start" msgstr "" msgid " Series recording" msgstr "" msgid "Delete recordings after ... days" msgstr "" msgid "Keep ... recordings" msgstr "" msgid "Pause when ... recordings exist" msgstr "" msgid "Avoid repeats" msgstr "" msgid "Allowed repeats" msgstr "" msgid "Only repeats within ... days" msgstr "" msgid "Compare title" msgstr "" msgid "Compare subtitle" msgstr "" msgid "Compare summary" msgstr "" msgid "Min. match in %" msgstr "" msgid "Compare date" msgstr "" msgid "Compare categories" msgstr "" msgid "VPS" msgstr "" msgid "Auto delete" msgstr "" msgid "after ... recordings" msgstr "" msgid "after ... days after first rec." msgstr "" msgid "Edit user-defined days of week" msgstr "" msgid "Compare" msgstr "" msgid "Select blacklists" msgstr "" msgid "Values for EPG category" msgstr "" msgid "Button$Apply" msgstr "" msgid "less" msgstr "" msgid "less or equal" msgstr "" msgid "greater" msgstr "" msgid "greater or equal" msgstr "" msgid "equal" msgstr "" msgid "not equal" msgstr "" msgid "Activation of search timer" msgstr "" msgid "First day" msgstr "" msgid "Last day" msgstr "" msgid "Button$all channels" msgstr "" msgid "Button$only FTA" msgstr "" msgid "Button$Timer preview" msgstr "" msgid "Blacklist results" msgstr "" msgid "found recordings" msgstr "" msgid "Error while accessing recording!" msgstr "" msgid "Button$Default" msgstr "" msgid "Edit$Delete template?" msgstr "" msgid "Overwrite existing entries?" msgstr "" msgid "Edit entry" msgstr "" msgid "Switch" msgstr "" msgid "Announce only" msgstr "" msgid "Announce ... minutes before start" msgstr "" msgid "action at" msgstr "" msgid "Switch list" msgstr "" msgid "Edit template" msgstr "" msgid "Timers" msgstr "" msgid ">>> no info! <<<" msgstr "" msgid "Overview" msgstr "" msgid "Button$Favorites" msgstr "" msgid "Quick search for broadcasts" msgstr "" msgid "Quick search" msgstr "" msgid "Show in main menu" msgstr "" #, c-format msgid "%d new broadcast(s) found! Show them?" msgstr "" msgid "Search timer update done!" msgstr "" #, c-format msgid "small EPG content on:%s" msgstr "" msgid "VDR EPG check warning" msgstr "" #, c-format msgid "Switch to (%d) '%s'?" msgstr "" msgid "Programming timer failed!" msgstr "" vdr-plugin-epgsearch/po/sl_SI.po0000644000175000017500000005740313145412721016430 0ustar tobiastobias# VDR plugin language source file. # Copyright (C) 2007 Klaus Schmidinger # This file is distributed under the same license as the VDR package. # Miha Setina , 2000 # Matjaz Thaler , 2003 # msgid "" msgstr "" "Project-Id-Version: VDR 1.5.7\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-06-15 11:15+0200\n" "PO-Revision-Date: 2007-08-14 20:21+0200\n" "Last-Translator: Matjaz Thaler \n" "Language-Team: Slovenian \n" "Language: sl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "Channel groups" msgstr "" msgid "Button$Select" msgstr "" msgid "Channel group used by:" msgstr "" msgid "Edit$Delete group?" msgstr "" msgid "Edit channel group" msgstr "" msgid "Group name" msgstr "" msgid "Button$Invert selection" msgstr "" msgid "Button$All yes" msgstr "" msgid "Button$All no" msgstr "" msgid "Group name is empty!" msgstr "" msgid "Group name already exists!" msgstr "" msgid "Direct access to epgsearch's conflict check menu" msgstr "" msgid "Timer conflicts" msgstr "" msgid "Conflict info in main menu" msgstr "" msgid "next" msgstr "" #, c-format msgid "timer conflict at %s! Show it?" msgstr "" #, c-format msgid "%d timer conflicts! First at %s. Show them?" msgstr "" msgid "search the EPG for repeats and more" msgstr "" msgid "Program guide" msgstr "" msgid "search timer update running" msgstr "" msgid "Direct access to epgsearch's search menu" msgstr "" msgid "Search" msgstr "" msgid "EpgSearch-Search in main menu" msgstr "" msgid "Button$Help" msgstr "" msgid "Standard" msgstr "" msgid "Button$Commands" msgstr "" msgid "Button$Search" msgstr "" msgid "never" msgstr "" msgid "always" msgstr "" msgid "smart" msgstr "" msgid "before user-def. times" msgstr "" msgid "after user-def. times" msgstr "" msgid "before 'next'" msgstr "" msgid "General" msgstr "" msgid "EPG menus" msgstr "" msgid "User-defined EPG times" msgstr "" msgid "Timer programming" msgstr "" msgid "Search and search timers" msgstr "" msgid "Timer conflict checking" msgstr "" msgid "Email notification" msgstr "" msgid "Hide main menu entry" msgstr "" msgid "Help$Hides the main menu entry and may be useful if this plugin is used to replace the original 'Schedule' entry." msgstr "" msgid "Main menu entry" msgstr "" msgid "Help$The name of the main menu entry which defaults to 'Programm guide'." msgstr "" msgid "Replace original schedule" msgstr "" msgid "Help$When VDR is patched to allow this plugin to replace the original 'Schedule' entry, you can de/activate this replacement here." msgstr "" msgid "Start menu" msgstr "" msgid "Help$Choose between 'Overview - Now' and 'Schedule' as start menu when this plugin is called." msgstr "" msgid "Ok key" msgstr "" msgid "" "Help$Choose here the behaviour of key 'Ok'. You can use it to display the summary or to switch to the corresponding channel.\n" "Note: the functionality of key 'blue' (Switch/Info/Search) depends on this setting." msgstr "" msgid "Red key" msgstr "" msgid "" "Help$Choose which standard function ('Record' or 'Commands') you like to have on the red key.\n" "(Can be toggled with key '0')" msgstr "" msgid "Blue key" msgstr "" msgid "" "Help$Choose which standard function ('Switch'/'Info' or 'Search') you like to have on the blue key.\n" "(Can be toggled with key '0')" msgstr "" msgid "Show progress in 'Now'" msgstr "" msgid "Help$Shows a progressbar in 'Overview - Now' that informs about the remaining time of the current event." msgstr "" msgid "Show channel numbers" msgstr "" msgid "" "Help$Display channel numbers in 'Overview - Now'.\n" "\n" "(To completely define your own menu look please inspect the MANUAL)" msgstr "" msgid "Show channel separators" msgstr "" msgid "Help$Display VDR channel groups as separators between your channels in 'Overview - Now'." msgstr "" msgid "Show day separators" msgstr "" msgid "Help$Display a separator line at day break in 'Schedule'." msgstr "" msgid "Show radio channels" msgstr "" msgid "Help$Show also radio channels." msgstr "" msgid "Limit channels from 1 to" msgstr "" msgid "Help$If you have a large channel set you can speed up things when you limit the displayed channels with this setting. Use '0' to disable the limit." msgstr "" msgid "'One press' timer creation" msgstr "" msgid "Help$When a timer is created with 'Record' you can choose between an immediate creation of the timer or the display of the timer edit menu." msgstr "" msgid "Show channels without EPG" msgstr "" msgid "Help$Choose 'yes' here if you want to display channels without EPG in 'Overview - Now'. 'Ok' on these entries switches the channel." msgstr "" msgid "Time interval for FRew/FFwd [min]" msgstr "" msgid "" "Help$Choose here the time interval which should be used for jumping through the EPG by pressing FRew/FFwd.\n" "\n" "(If you don't have those keys, you can toggle to this functionality pressing '0' and get '<<' and '>>' on the keys green and yellow)" msgstr "" msgid "Toggle Green/Yellow" msgstr "" msgid "Help$Specify if green and yellow shall also be switched when pressing '0'." msgstr "" msgid "Show favorites menu" msgstr "" msgid "" "Help$A favorites menu can display a list of your favorite broadcasts. Enable this if you want an additional menu besides 'Now' and 'Next'\n" "Any search can be used as a favorite. You only have to set the option 'Use in favorites menu' when editing a search." msgstr "" msgid "for the next ... hours" msgstr "" msgid "Help$This value controls the timespan used to display your favorites." msgstr "" msgid "Use user-defined time" msgstr "" msgid "Help$Besides 'Now' and 'Next' you can specify up to 4 other times in the EPG which can be used by repeatedly pressing the green key, e.g. 'prime time', 'late night',..." msgstr "" msgid "Description" msgstr "" msgid "Help$This is the description for your user-defined time as it will appear as label on the green button." msgstr "" msgid "Time" msgstr "" msgid "Help$Specify the user-defined time here in 'HH:MM'." msgstr "" msgid "Use VDR's timer edit menu" msgstr "" msgid "" "Help$This plugin has its own timer edit menu extending the original one with some extra functionality like\n" "- an additional directory entry\n" "- user-defined days of week for repeating timers\n" "- adding an episode name\n" "- support for EPG variables (see MANUAL)" msgstr "" msgid "Default recording dir" msgstr "" msgid "Help$When creating a timer you can specify here a default recording directory." msgstr "" msgid "Add episode to manual timers" msgstr "" msgid "" "Help$If you create a timer for a series, you can automatically add the episode name.\n" "\n" "- never: no addition\n" "- always: always add episode name if present\n" "- smart: add only if event lasts less than 80 mins." msgstr "" msgid "Default timer check method" msgstr "" msgid "" "Help$Manual timers can be checked for EPG changes. Here you can setup the default check method for each channel. Choose between\n" "\n" "- no checking\n" "- by event ID: checks by an event ID supplied by the channel provider.\n" "- by channel and time: check by the duration match." msgstr "" msgid "Button$Setup" msgstr "Nastavitve" msgid "Use search timers" msgstr "" msgid "Help$'Search timers' can be used to automatically create timers for events that match your search criterions." msgstr "" msgid " Update interval [min]" msgstr "" msgid "Help$Specify here the time intervall to be used when searching for events in the background." msgstr "" msgid " SVDRP port" msgstr "" msgid "Help$Programming of new timers or timer changes is done with SVDRP. The default value should be correct, so change it only if you know what you are doing." msgstr "" msgid "Help$Specify here the default priority of timers created with this plugin. This value can also be adjusted for each search itself." msgstr "" msgid "Help$Specify here the default lifetime of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "" msgid "Help$Specify here the default start recording margin of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "" msgid "Help$Specify here the default stop recording margin of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "" msgid "No announcements when replaying" msgstr "" msgid "Help$Set this to 'yes' if you don't like to get any announcements of broadcasts if you currently replay anything." msgstr "" msgid "Recreate timers after deletion" msgstr "" msgid "Help$Set this to 'yes' if you want timers to be recreated with the next search timer update after deleting them." msgstr "" msgid "Check if EPG exists for ... [h]" msgstr "" msgid "Help$Specify how many hours of future EPG there should be and get warned else after a search timer update." msgstr "" msgid "Warn by OSD" msgstr "" msgid "Help$Set this to 'yes' if you want get warnings from the EPG check via OSD." msgstr "" msgid "Warn by mail" msgstr "" msgid "Help$Set this to 'yes' if you want get warnings from the EPG check by mail." msgstr "" msgid "Channel group to check" msgstr "" msgid "Help$Specify the channel group to check." msgstr "" msgid "Ignore PayTV channels" msgstr "" msgid "Help$Set this to 'yes' if don't want to see events on PayTV channels when searching for repeats." msgstr "" msgid "Search templates" msgstr "" msgid "Help$Here you can setup templates for your searches." msgstr "" msgid "Blacklists" msgstr "" msgid "Help$Here you can setup blacklists which can be used within a search to exclude events you don't like." msgstr "" msgid "Help$Here you can setup channel groups which can be used within a search. These are different to VDR channel groups and represent a set of arbitrary channels, e.g. 'FreeTV'." msgstr "" msgid "Ignore below priority" msgstr "" msgid "Help$If a timer with priority below the given value will fail it will not be classified as important. Only important conflicts will produce an OSD message about the conflict after an automatic conflict check." msgstr "" msgid "Ignore conflict duration less ... min." msgstr "" msgid "Help$If a conflicts duration is less then the given number of minutes it will not be classified as important. Only important conflicts will produce an OSD message about the conflict after an automatic conflict check." msgstr "" msgid "Only check within next ... days" msgstr "" msgid "Help$This value reduces the conflict check to the given range of days. All other conflicts are classified as 'not yet important'." msgstr "" msgid "Check also remote conflicts" msgstr "" msgid "Help$Set this to 'yes' if the conflict check should be done for timers set on remote hosts. This needs SVDRPPeering to be set in vdr and Plugin epgsearch running on the remote host." msgstr "" msgid "--- Automatic checking ---" msgstr "" msgid "After each timer programming" msgstr "" msgid "Help$Set this to 'yes' if the conflict check should be performed after each manual timer programming. In the case of a conflict you get immediately a message that informs you about it. The message is only displayed if this timer is involved in any conflict." msgstr "" msgid "When a recording starts" msgstr "" msgid "Help$Set this to 'yes' if the conflict check should be performed when a recording starts. In the case of a conflict you get immediately a message that informs you about it. The message is only displayed if the conflict is within the next 2 hours." msgstr "" msgid "After each search timer update" msgstr "" msgid "Help$Set this to 'yes' if the conflict check should be performed after each search timer update." msgstr "" msgid "every ... minutes" msgstr "" msgid "" "Help$Specify here the time intervall to be used for an automatic conflict check in the background.\n" "('0' disables an automatic check)" msgstr "" msgid "if conflicts within next ... minutes" msgstr "" msgid "Help$If the next conflict will appear in the given number of minutes you can specify here a shorter check intervall to get more OSD notifications about it." msgstr "" msgid "Avoid notification when replaying" msgstr "" msgid "Help$Set this to 'yes' if the don't want to get OSD messages about conflicts if you currently replay something. Nevertheless messages will be displayed if the first upcoming conflict is within the next 2 hours." msgstr "" msgid "Search timer notification" msgstr "" msgid "Help$Set this to 'yes' if you want to get an email notification about the search timers that where programmed automatically in the background." msgstr "" msgid "Time between mails [h]" msgstr "" msgid "" "Help$Specifiy how much time in [h] you would\n" "like to have atleast between two mails.\n" "With '0' you get a new mail after each\n" "search timer update with new results." msgstr "" msgid "Timer conflict notification" msgstr "" msgid "Help$Set this to 'yes' if you want to get an email notification about the timer conflicts." msgstr "" msgid "Send to" msgstr "" msgid "Help$Specify the email address where notifications should be sent to." msgstr "" msgid "Mail method" msgstr "" msgid "" "Help$Specify here the method to use when sending mails.\n" "You can choose between\n" " - 'sendmail': requires a properly configured email system\n" " - 'SendEmail.pl': simple script for mail delivery" msgstr "" msgid "--- Email account ---" msgstr "" msgid "Email address" msgstr "" msgid "Help$Specify the email address where notifications should be sent from." msgstr "" msgid "SMTP server" msgstr "" msgid "Help$Specify the SMTP server that should deliver the notifications. If it's using a port different from the default(25) append the port with \":port\"." msgstr "" msgid "Use SMTP authentication" msgstr "" msgid "Help$Set this to 'yes' if your account needs authentication to send mails." msgstr "" msgid "Auth user" msgstr "" msgid "Help$Specify the auth user, if this account needs authentication for SMTP." msgstr "" msgid "Auth password" msgstr "" msgid "Help$Specify the auth password, if this account needs authentication for SMTP." msgstr "" msgid "Mail account check failed!" msgstr "" msgid "Button$Test" msgstr "" #, fuzzy msgid "$ abcdefghijklmnopqrstuvwxyz0123456789-.,#~\\^$[]|()*+?{}/:%@&_" msgstr " abcdefghijklmnopqrstuvwxyz0123456789-.,#~\\^$[]|()*+?{}/:%@&" msgid "Start/Stop time has changed" msgstr "" msgid "Title/episode has changed" msgstr "" msgid "No new timers were added." msgstr "" msgid "No timers were modified." msgstr "" msgid "No timers were deleted." msgstr "" msgid "No new events to announce." msgstr "" msgid "This version of EPGSearch does not support this service!" msgstr "" msgid "EPGSearch does not exist!" msgstr "" #, c-format msgid "%d new broadcast" msgstr "" msgid "Button$by channel" msgstr "" msgid "Button$by time" msgstr "" msgid "Button$Episode" msgstr "" msgid "Button$Title" msgstr "" msgid "announce details" msgstr "" msgid "announce again" msgstr "" msgid "with next update" msgstr "" msgid "again from" msgstr "" msgid "Search timer" msgstr "" msgid "Edit blacklist" msgstr "" msgid "phrase" msgstr "" msgid "all words" msgstr "" msgid "at least one word" msgstr "" msgid "match exactly" msgstr "" msgid "regular expression" msgstr "" msgid "fuzzy" msgstr "" msgid "user-defined" msgstr "" msgid "interval" msgstr "" msgid "channel group" msgstr "" msgid "only FTA" msgstr "" msgid "Search term" msgstr "" msgid "Search mode" msgstr "" msgid "Tolerance" msgstr "" msgid "Match case" msgstr "" msgid "Use title" msgstr "" msgid "Use subtitle" msgstr "" msgid "Use description" msgstr "" msgid "Use extended EPG info" msgstr "" msgid "Ignore missing categories" msgstr "" msgid "Use channel" msgstr "" msgid " from channel" msgstr "" msgid " to channel" msgstr "" msgid "Channel group" msgstr "" msgid "Use time" msgstr "" msgid " Start after" msgstr "" msgid " Start before" msgstr "" msgid "Use duration" msgstr "" msgid " Min. duration" msgstr "" msgid " Max. duration" msgstr "" msgid "Use day of week" msgstr "" msgid "Day of week" msgstr "" msgid "Use global" msgstr "" msgid "Button$Templates" msgstr "" msgid "*** Invalid Channel ***" msgstr "" msgid "Please check channel criteria!" msgstr "" msgid "Edit$Delete blacklist?" msgstr "" msgid "Repeats" msgstr "" msgid "Create search" msgstr "" msgid "Search in recordings" msgstr "" msgid "Mark as 'already recorded'?" msgstr "" msgid "Add/Remove to/from switch list?" msgstr "" msgid "Create blacklist" msgstr "" msgid "EPG Commands" msgstr "" msgid "Epgsearch: RemoteTimerModifications failed" msgstr "" msgid "Already running!" msgstr "" msgid "Add to switch list?" msgstr "" msgid "Delete from switch list?" msgstr "" msgid "Button$Details" msgstr "" msgid "Button$Filter" msgstr "" msgid "Button$Show all" msgstr "" msgid "conflicts" msgstr "" msgid "no conflicts!" msgstr "" msgid "no important conflicts!" msgstr "" msgid "C" msgstr "C" msgid "Button$Repeats" msgstr "" msgid "no check" msgstr "" msgid "by channel and time" msgstr "" msgid "by event ID" msgstr "" msgid "Select directory" msgstr "" msgid "Button$Level" msgstr "" msgid "Event" msgstr "" msgid "Favorites" msgstr "" msgid "Search results" msgstr "" msgid "Timer conflict! Show?" msgstr "" msgid "Directory" msgstr "" msgid "Channel" msgstr "" msgid "Childlock" msgstr "" msgid "Record on" msgstr "" msgid "Timer check" msgstr "" msgid "recording with device" msgstr "" msgid "Button$With subtitle" msgstr "" msgid "Button$Without subtitle" msgstr "" msgid "Timer has been deleted" msgstr "" msgid "Button$Extended" msgstr "" msgid "Button$Simple" msgstr "" msgid "Use blacklists" msgstr "" msgid "Edit$Search text too short - use anyway?" msgstr "" msgid "Button$Orphaned" msgstr "" msgid "Button$by name" msgstr "" msgid "Button$by date" msgstr "" msgid "Button$Delete all" msgstr "" msgid "Recordings" msgstr "" msgid "Edit$Delete entry?" msgstr "" msgid "Edit$Delete all entries?" msgstr "" msgid "Summary" msgstr "" msgid "Auxiliary info" msgstr "" msgid "Button$Aux info" msgstr "" msgid "Search actions" msgstr "" msgid "Execute search" msgstr "" msgid "Use as search timer on/off" msgstr "" msgid "Trigger search timer update" msgstr "" msgid "Show recordings done" msgstr "" msgid "Show timers created" msgstr "" msgid "Create a copy" msgstr "" msgid "Use as template" msgstr "" msgid "Show switch list" msgstr "" msgid "Show blacklists" msgstr "" msgid "Delete created timers?" msgstr "" msgid "Timer conflict check" msgstr "" msgid "Disable associated timers too?" msgstr "" msgid "Activate associated timers too?" msgstr "" msgid "Search timers activated in setup." msgstr "" msgid "Run search timer update?" msgstr "" msgid "Copy this entry?" msgstr "" msgid "Copy" msgstr "" msgid "Copy this entry to templates?" msgstr "" msgid "Delete all timers created from this search?" msgstr "" msgid "Button$Actions" msgstr "" msgid "Search entries" msgstr "" msgid "active" msgstr "" msgid "Edit$Delete search?" msgstr "" msgid "Edit search" msgstr "" msgid "Record" msgstr "Posnemi" msgid "Announce by OSD" msgstr "" msgid "Switch only" msgstr "" msgid "Announce and switch" msgstr "" msgid "Announce by mail" msgstr "" msgid "Inactive record" msgstr "" msgid "only globals" msgstr "" msgid "Selection" msgstr "" msgid "all" msgstr "" msgid "count recordings" msgstr "" msgid "count days" msgstr "" msgid "if present" msgstr "" msgid "same day" msgstr "" msgid "same week" msgstr "" msgid "same month" msgstr "" msgid "Template name" msgstr "" msgid "Help$Specify the name of the template." msgstr "" msgid "Help$Specify here the term to search for." msgstr "" msgid "" "Help$The following search modes exist:\n" "\n" "- phrase: searches for sub terms\n" "- all words: all single words must appear\n" "- at least one word: at least one single word must appear\n" "- match exactly: must match exactly\n" "- regular expression: match a regular expression\n" "- fuzzy searching: searches approximately" msgstr "" msgid "Help$This sets the tolerance of fuzzy searching. The value represents the allowed errors." msgstr "" msgid "Help$Set this to 'Yes' if your search should match the case." msgstr "" msgid "Help$Set this to 'Yes' if you like to search in the title of an event." msgstr "" msgid "Help$Set this to 'Yes' if you like to search in the episode of an event." msgstr "" msgid "Help$Set this to 'Yes' if you like to search in the summary of an event." msgstr "" msgid "Use content descriptor" msgstr "" msgid "Help$Set this to 'Yes' if you want to search the contents by a descriptor." msgstr "" msgid "Help$The summary of an event, can contain additional information like 'Genre', 'Category', 'Year',... called 'EPG categories' within EPGSearch. External EPG providers often deliver this information. This allows refining a search and other nice things, like searching for the 'tip of the day'. To use it set this to 'Yes'." msgstr "" msgid "Help$The file epgsearchcats.conf specifies the search mode for this entry. One can search by text or by value. You can also edit a list of predefined values in this file that can be selected here." msgstr "" msgid "Help$If a selected category is not part of the summary of an event this normally excludes this event from the search results. To avoid this, set this option to 'Yes', but please handle this with care to avoid a huge amount of results." msgstr "" msgid "Use in favorites menu" msgstr "" msgid "Result menu layout" msgstr "" msgid "Use as search timer" msgstr "" msgid "Action" msgstr "" msgid "Switch ... minutes before start" msgstr "" msgid "Unmute sound" msgstr "" msgid "Ask ... minutes before start" msgstr "" msgid " Series recording" msgstr "" msgid "Delete recordings after ... days" msgstr "" msgid "Keep ... recordings" msgstr "" msgid "Pause when ... recordings exist" msgstr "" msgid "Avoid repeats" msgstr "" msgid "Allowed repeats" msgstr "" msgid "Only repeats within ... days" msgstr "" msgid "Compare title" msgstr "" msgid "Compare subtitle" msgstr "" msgid "Compare summary" msgstr "" msgid "Min. match in %" msgstr "" msgid "Compare date" msgstr "" msgid "Compare categories" msgstr "" msgid "VPS" msgstr "" msgid "Auto delete" msgstr "" msgid "after ... recordings" msgstr "" msgid "after ... days after first rec." msgstr "" msgid "Edit user-defined days of week" msgstr "" msgid "Compare" msgstr "" msgid "Select blacklists" msgstr "" msgid "Values for EPG category" msgstr "" msgid "Button$Apply" msgstr "" msgid "less" msgstr "" msgid "less or equal" msgstr "" msgid "greater" msgstr "" msgid "greater or equal" msgstr "" msgid "equal" msgstr "" msgid "not equal" msgstr "" msgid "Activation of search timer" msgstr "" msgid "First day" msgstr "" msgid "Last day" msgstr "" msgid "Button$all channels" msgstr "" msgid "Button$only FTA" msgstr "" msgid "Button$Timer preview" msgstr "" msgid "Blacklist results" msgstr "" msgid "found recordings" msgstr "" msgid "Error while accessing recording!" msgstr "" msgid "Button$Default" msgstr "" msgid "Edit$Delete template?" msgstr "" msgid "Overwrite existing entries?" msgstr "" msgid "Edit entry" msgstr "" msgid "Switch" msgstr "" msgid "Announce only" msgstr "" msgid "Announce ... minutes before start" msgstr "" msgid "action at" msgstr "" msgid "Switch list" msgstr "" msgid "Edit template" msgstr "" msgid "Timers" msgstr "" msgid ">>> no info! <<<" msgstr "" msgid "Overview" msgstr "" msgid "Button$Favorites" msgstr "" msgid "Quick search for broadcasts" msgstr "" msgid "Quick search" msgstr "" msgid "Show in main menu" msgstr "" #, c-format msgid "%d new broadcast(s) found! Show them?" msgstr "" msgid "Search timer update done!" msgstr "" #, c-format msgid "small EPG content on:%s" msgstr "" msgid "VDR EPG check warning" msgstr "" #, c-format msgid "Switch to (%d) '%s'?" msgstr "" msgid "Programming timer failed!" msgstr "" vdr-plugin-epgsearch/po/hu_HU.po0000644000175000017500000005747113145412721016434 0ustar tobiastobias# VDR plugin language source file. # Copyright (C) 2007 Klaus Schmidinger # This file is distributed under the same license as the VDR package. # Istvan Koenigsberger , 2002 # Guido Josten , 2002 # msgid "" msgstr "" "Project-Id-Version: VDR 1.5.7\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-06-15 11:15+0200\n" "PO-Revision-Date: 2007-08-14 20:21+0200\n" "Last-Translator: Istvan Koenigsberger , Guido Josten \n" "Language-Team: Hungarian \n" "Language: hu\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "Channel groups" msgstr "" msgid "Button$Select" msgstr "" msgid "Channel group used by:" msgstr "" msgid "Edit$Delete group?" msgstr "" msgid "Edit channel group" msgstr "" msgid "Group name" msgstr "" msgid "Button$Invert selection" msgstr "" msgid "Button$All yes" msgstr "" msgid "Button$All no" msgstr "" msgid "Group name is empty!" msgstr "" msgid "Group name already exists!" msgstr "" msgid "Direct access to epgsearch's conflict check menu" msgstr "" msgid "Timer conflicts" msgstr "" msgid "Conflict info in main menu" msgstr "" msgid "next" msgstr "" #, c-format msgid "timer conflict at %s! Show it?" msgstr "" #, c-format msgid "%d timer conflicts! First at %s. Show them?" msgstr "" msgid "search the EPG for repeats and more" msgstr "" msgid "Program guide" msgstr "" msgid "search timer update running" msgstr "" msgid "Direct access to epgsearch's search menu" msgstr "" msgid "Search" msgstr "" msgid "EpgSearch-Search in main menu" msgstr "" msgid "Button$Help" msgstr "" msgid "Standard" msgstr "" msgid "Button$Commands" msgstr "" msgid "Button$Search" msgstr "" msgid "never" msgstr "" msgid "always" msgstr "" msgid "smart" msgstr "" msgid "before user-def. times" msgstr "" msgid "after user-def. times" msgstr "" msgid "before 'next'" msgstr "" msgid "General" msgstr "" msgid "EPG menus" msgstr "" msgid "User-defined EPG times" msgstr "" msgid "Timer programming" msgstr "" msgid "Search and search timers" msgstr "" msgid "Timer conflict checking" msgstr "" msgid "Email notification" msgstr "" msgid "Hide main menu entry" msgstr "" msgid "Help$Hides the main menu entry and may be useful if this plugin is used to replace the original 'Schedule' entry." msgstr "" msgid "Main menu entry" msgstr "" msgid "Help$The name of the main menu entry which defaults to 'Programm guide'." msgstr "" msgid "Replace original schedule" msgstr "" msgid "Help$When VDR is patched to allow this plugin to replace the original 'Schedule' entry, you can de/activate this replacement here." msgstr "" msgid "Start menu" msgstr "" msgid "Help$Choose between 'Overview - Now' and 'Schedule' as start menu when this plugin is called." msgstr "" msgid "Ok key" msgstr "" msgid "" "Help$Choose here the behaviour of key 'Ok'. You can use it to display the summary or to switch to the corresponding channel.\n" "Note: the functionality of key 'blue' (Switch/Info/Search) depends on this setting." msgstr "" msgid "Red key" msgstr "" msgid "" "Help$Choose which standard function ('Record' or 'Commands') you like to have on the red key.\n" "(Can be toggled with key '0')" msgstr "" msgid "Blue key" msgstr "" msgid "" "Help$Choose which standard function ('Switch'/'Info' or 'Search') you like to have on the blue key.\n" "(Can be toggled with key '0')" msgstr "" msgid "Show progress in 'Now'" msgstr "" msgid "Help$Shows a progressbar in 'Overview - Now' that informs about the remaining time of the current event." msgstr "" msgid "Show channel numbers" msgstr "" msgid "" "Help$Display channel numbers in 'Overview - Now'.\n" "\n" "(To completely define your own menu look please inspect the MANUAL)" msgstr "" msgid "Show channel separators" msgstr "" msgid "Help$Display VDR channel groups as separators between your channels in 'Overview - Now'." msgstr "" msgid "Show day separators" msgstr "" msgid "Help$Display a separator line at day break in 'Schedule'." msgstr "" msgid "Show radio channels" msgstr "" msgid "Help$Show also radio channels." msgstr "" msgid "Limit channels from 1 to" msgstr "" msgid "Help$If you have a large channel set you can speed up things when you limit the displayed channels with this setting. Use '0' to disable the limit." msgstr "" msgid "'One press' timer creation" msgstr "" msgid "Help$When a timer is created with 'Record' you can choose between an immediate creation of the timer or the display of the timer edit menu." msgstr "" msgid "Show channels without EPG" msgstr "" msgid "Help$Choose 'yes' here if you want to display channels without EPG in 'Overview - Now'. 'Ok' on these entries switches the channel." msgstr "" msgid "Time interval for FRew/FFwd [min]" msgstr "" msgid "" "Help$Choose here the time interval which should be used for jumping through the EPG by pressing FRew/FFwd.\n" "\n" "(If you don't have those keys, you can toggle to this functionality pressing '0' and get '<<' and '>>' on the keys green and yellow)" msgstr "" msgid "Toggle Green/Yellow" msgstr "" msgid "Help$Specify if green and yellow shall also be switched when pressing '0'." msgstr "" msgid "Show favorites menu" msgstr "" msgid "" "Help$A favorites menu can display a list of your favorite broadcasts. Enable this if you want an additional menu besides 'Now' and 'Next'\n" "Any search can be used as a favorite. You only have to set the option 'Use in favorites menu' when editing a search." msgstr "" msgid "for the next ... hours" msgstr "" msgid "Help$This value controls the timespan used to display your favorites." msgstr "" msgid "Use user-defined time" msgstr "" msgid "Help$Besides 'Now' and 'Next' you can specify up to 4 other times in the EPG which can be used by repeatedly pressing the green key, e.g. 'prime time', 'late night',..." msgstr "" msgid "Description" msgstr "" msgid "Help$This is the description for your user-defined time as it will appear as label on the green button." msgstr "" msgid "Time" msgstr "" msgid "Help$Specify the user-defined time here in 'HH:MM'." msgstr "" msgid "Use VDR's timer edit menu" msgstr "" msgid "" "Help$This plugin has its own timer edit menu extending the original one with some extra functionality like\n" "- an additional directory entry\n" "- user-defined days of week for repeating timers\n" "- adding an episode name\n" "- support for EPG variables (see MANUAL)" msgstr "" msgid "Default recording dir" msgstr "" msgid "Help$When creating a timer you can specify here a default recording directory." msgstr "" msgid "Add episode to manual timers" msgstr "" msgid "" "Help$If you create a timer for a series, you can automatically add the episode name.\n" "\n" "- never: no addition\n" "- always: always add episode name if present\n" "- smart: add only if event lasts less than 80 mins." msgstr "" msgid "Default timer check method" msgstr "" msgid "" "Help$Manual timers can be checked for EPG changes. Here you can setup the default check method for each channel. Choose between\n" "\n" "- no checking\n" "- by event ID: checks by an event ID supplied by the channel provider.\n" "- by channel and time: check by the duration match." msgstr "" msgid "Button$Setup" msgstr "Beállítások" msgid "Use search timers" msgstr "" msgid "Help$'Search timers' can be used to automatically create timers for events that match your search criterions." msgstr "" msgid " Update interval [min]" msgstr "" msgid "Help$Specify here the time intervall to be used when searching for events in the background." msgstr "" msgid " SVDRP port" msgstr "" msgid "Help$Programming of new timers or timer changes is done with SVDRP. The default value should be correct, so change it only if you know what you are doing." msgstr "" msgid "Help$Specify here the default priority of timers created with this plugin. This value can also be adjusted for each search itself." msgstr "" msgid "Help$Specify here the default lifetime of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "" msgid "Help$Specify here the default start recording margin of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "" msgid "Help$Specify here the default stop recording margin of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "" msgid "No announcements when replaying" msgstr "" msgid "Help$Set this to 'yes' if you don't like to get any announcements of broadcasts if you currently replay anything." msgstr "" msgid "Recreate timers after deletion" msgstr "" msgid "Help$Set this to 'yes' if you want timers to be recreated with the next search timer update after deleting them." msgstr "" msgid "Check if EPG exists for ... [h]" msgstr "" msgid "Help$Specify how many hours of future EPG there should be and get warned else after a search timer update." msgstr "" msgid "Warn by OSD" msgstr "" msgid "Help$Set this to 'yes' if you want get warnings from the EPG check via OSD." msgstr "" msgid "Warn by mail" msgstr "" msgid "Help$Set this to 'yes' if you want get warnings from the EPG check by mail." msgstr "" msgid "Channel group to check" msgstr "" msgid "Help$Specify the channel group to check." msgstr "" msgid "Ignore PayTV channels" msgstr "" msgid "Help$Set this to 'yes' if don't want to see events on PayTV channels when searching for repeats." msgstr "" msgid "Search templates" msgstr "" msgid "Help$Here you can setup templates for your searches." msgstr "" msgid "Blacklists" msgstr "" msgid "Help$Here you can setup blacklists which can be used within a search to exclude events you don't like." msgstr "" msgid "Help$Here you can setup channel groups which can be used within a search. These are different to VDR channel groups and represent a set of arbitrary channels, e.g. 'FreeTV'." msgstr "" msgid "Ignore below priority" msgstr "" msgid "Help$If a timer with priority below the given value will fail it will not be classified as important. Only important conflicts will produce an OSD message about the conflict after an automatic conflict check." msgstr "" msgid "Ignore conflict duration less ... min." msgstr "" msgid "Help$If a conflicts duration is less then the given number of minutes it will not be classified as important. Only important conflicts will produce an OSD message about the conflict after an automatic conflict check." msgstr "" msgid "Only check within next ... days" msgstr "" msgid "Help$This value reduces the conflict check to the given range of days. All other conflicts are classified as 'not yet important'." msgstr "" msgid "Check also remote conflicts" msgstr "" msgid "Help$Set this to 'yes' if the conflict check should be done for timers set on remote hosts. This needs SVDRPPeering to be set in vdr and Plugin epgsearch running on the remote host." msgstr "" msgid "--- Automatic checking ---" msgstr "" msgid "After each timer programming" msgstr "" msgid "Help$Set this to 'yes' if the conflict check should be performed after each manual timer programming. In the case of a conflict you get immediately a message that informs you about it. The message is only displayed if this timer is involved in any conflict." msgstr "" msgid "When a recording starts" msgstr "" msgid "Help$Set this to 'yes' if the conflict check should be performed when a recording starts. In the case of a conflict you get immediately a message that informs you about it. The message is only displayed if the conflict is within the next 2 hours." msgstr "" msgid "After each search timer update" msgstr "" msgid "Help$Set this to 'yes' if the conflict check should be performed after each search timer update." msgstr "" msgid "every ... minutes" msgstr "" msgid "" "Help$Specify here the time intervall to be used for an automatic conflict check in the background.\n" "('0' disables an automatic check)" msgstr "" msgid "if conflicts within next ... minutes" msgstr "" msgid "Help$If the next conflict will appear in the given number of minutes you can specify here a shorter check intervall to get more OSD notifications about it." msgstr "" msgid "Avoid notification when replaying" msgstr "" msgid "Help$Set this to 'yes' if the don't want to get OSD messages about conflicts if you currently replay something. Nevertheless messages will be displayed if the first upcoming conflict is within the next 2 hours." msgstr "" msgid "Search timer notification" msgstr "" msgid "Help$Set this to 'yes' if you want to get an email notification about the search timers that where programmed automatically in the background." msgstr "" msgid "Time between mails [h]" msgstr "" msgid "" "Help$Specifiy how much time in [h] you would\n" "like to have atleast between two mails.\n" "With '0' you get a new mail after each\n" "search timer update with new results." msgstr "" msgid "Timer conflict notification" msgstr "" msgid "Help$Set this to 'yes' if you want to get an email notification about the timer conflicts." msgstr "" msgid "Send to" msgstr "" msgid "Help$Specify the email address where notifications should be sent to." msgstr "" msgid "Mail method" msgstr "" msgid "" "Help$Specify here the method to use when sending mails.\n" "You can choose between\n" " - 'sendmail': requires a properly configured email system\n" " - 'SendEmail.pl': simple script for mail delivery" msgstr "" msgid "--- Email account ---" msgstr "" msgid "Email address" msgstr "" msgid "Help$Specify the email address where notifications should be sent from." msgstr "" msgid "SMTP server" msgstr "" msgid "Help$Specify the SMTP server that should deliver the notifications. If it's using a port different from the default(25) append the port with \":port\"." msgstr "" msgid "Use SMTP authentication" msgstr "" msgid "Help$Set this to 'yes' if your account needs authentication to send mails." msgstr "" msgid "Auth user" msgstr "" msgid "Help$Specify the auth user, if this account needs authentication for SMTP." msgstr "" msgid "Auth password" msgstr "" msgid "Help$Specify the auth password, if this account needs authentication for SMTP." msgstr "" msgid "Mail account check failed!" msgstr "" msgid "Button$Test" msgstr "" msgid "$ abcdefghijklmnopqrstuvwxyz0123456789-.,#~\\^$[]|()*+?{}/:%@&_" msgstr " aábcdeéfghiíjklmnoóöőpqrstuúüűvwxyz0123456789-.,#~\\^$[]|()*+?{}/:%@&_" msgid "Start/Stop time has changed" msgstr "" msgid "Title/episode has changed" msgstr "" msgid "No new timers were added." msgstr "" msgid "No timers were modified." msgstr "" msgid "No timers were deleted." msgstr "" msgid "No new events to announce." msgstr "" msgid "This version of EPGSearch does not support this service!" msgstr "" msgid "EPGSearch does not exist!" msgstr "" #, c-format msgid "%d new broadcast" msgstr "" msgid "Button$by channel" msgstr "" msgid "Button$by time" msgstr "" msgid "Button$Episode" msgstr "" msgid "Button$Title" msgstr "" msgid "announce details" msgstr "" msgid "announce again" msgstr "" msgid "with next update" msgstr "" msgid "again from" msgstr "" msgid "Search timer" msgstr "" msgid "Edit blacklist" msgstr "" msgid "phrase" msgstr "" msgid "all words" msgstr "" msgid "at least one word" msgstr "" msgid "match exactly" msgstr "" msgid "regular expression" msgstr "" msgid "fuzzy" msgstr "" msgid "user-defined" msgstr "" msgid "interval" msgstr "" msgid "channel group" msgstr "" msgid "only FTA" msgstr "" msgid "Search term" msgstr "" msgid "Search mode" msgstr "" msgid "Tolerance" msgstr "" msgid "Match case" msgstr "" msgid "Use title" msgstr "" msgid "Use subtitle" msgstr "" msgid "Use description" msgstr "" msgid "Use extended EPG info" msgstr "" msgid "Ignore missing categories" msgstr "" msgid "Use channel" msgstr "" msgid " from channel" msgstr "" msgid " to channel" msgstr "" msgid "Channel group" msgstr "" msgid "Use time" msgstr "" msgid " Start after" msgstr "" msgid " Start before" msgstr "" msgid "Use duration" msgstr "" msgid " Min. duration" msgstr "" msgid " Max. duration" msgstr "" msgid "Use day of week" msgstr "" msgid "Day of week" msgstr "" msgid "Use global" msgstr "" msgid "Button$Templates" msgstr "" msgid "*** Invalid Channel ***" msgstr "" msgid "Please check channel criteria!" msgstr "" msgid "Edit$Delete blacklist?" msgstr "" msgid "Repeats" msgstr "" msgid "Create search" msgstr "" msgid "Search in recordings" msgstr "" msgid "Mark as 'already recorded'?" msgstr "" msgid "Add/Remove to/from switch list?" msgstr "" msgid "Create blacklist" msgstr "" msgid "EPG Commands" msgstr "" msgid "Epgsearch: RemoteTimerModifications failed" msgstr "" msgid "Already running!" msgstr "" msgid "Add to switch list?" msgstr "" msgid "Delete from switch list?" msgstr "" msgid "Button$Details" msgstr "" msgid "Button$Filter" msgstr "" msgid "Button$Show all" msgstr "" msgid "conflicts" msgstr "" msgid "no conflicts!" msgstr "" msgid "no important conflicts!" msgstr "" msgid "C" msgstr "C" msgid "Button$Repeats" msgstr "" msgid "no check" msgstr "" msgid "by channel and time" msgstr "" msgid "by event ID" msgstr "" msgid "Select directory" msgstr "" msgid "Button$Level" msgstr "" msgid "Event" msgstr "" msgid "Favorites" msgstr "" msgid "Search results" msgstr "" msgid "Timer conflict! Show?" msgstr "" msgid "Directory" msgstr "" msgid "Channel" msgstr "" msgid "Childlock" msgstr "" msgid "Record on" msgstr "" msgid "Timer check" msgstr "" msgid "recording with device" msgstr "" msgid "Button$With subtitle" msgstr "" msgid "Button$Without subtitle" msgstr "" msgid "Timer has been deleted" msgstr "" msgid "Button$Extended" msgstr "" msgid "Button$Simple" msgstr "" msgid "Use blacklists" msgstr "" msgid "Edit$Search text too short - use anyway?" msgstr "" msgid "Button$Orphaned" msgstr "" msgid "Button$by name" msgstr "" msgid "Button$by date" msgstr "" msgid "Button$Delete all" msgstr "" msgid "Recordings" msgstr "" msgid "Edit$Delete entry?" msgstr "" msgid "Edit$Delete all entries?" msgstr "" msgid "Summary" msgstr "" msgid "Auxiliary info" msgstr "" msgid "Button$Aux info" msgstr "" msgid "Search actions" msgstr "" msgid "Execute search" msgstr "" msgid "Use as search timer on/off" msgstr "" msgid "Trigger search timer update" msgstr "" msgid "Show recordings done" msgstr "" msgid "Show timers created" msgstr "" msgid "Create a copy" msgstr "" msgid "Use as template" msgstr "" msgid "Show switch list" msgstr "" msgid "Show blacklists" msgstr "" msgid "Delete created timers?" msgstr "" msgid "Timer conflict check" msgstr "" msgid "Disable associated timers too?" msgstr "" msgid "Activate associated timers too?" msgstr "" msgid "Search timers activated in setup." msgstr "" msgid "Run search timer update?" msgstr "" msgid "Copy this entry?" msgstr "" msgid "Copy" msgstr "" msgid "Copy this entry to templates?" msgstr "" msgid "Delete all timers created from this search?" msgstr "" msgid "Button$Actions" msgstr "" msgid "Search entries" msgstr "" msgid "active" msgstr "" msgid "Edit$Delete search?" msgstr "" msgid "Edit search" msgstr "" msgid "Record" msgstr "Felvenni" msgid "Announce by OSD" msgstr "" msgid "Switch only" msgstr "" msgid "Announce and switch" msgstr "" msgid "Announce by mail" msgstr "" msgid "Inactive record" msgstr "" msgid "only globals" msgstr "" msgid "Selection" msgstr "" msgid "all" msgstr "" msgid "count recordings" msgstr "" msgid "count days" msgstr "" msgid "if present" msgstr "" msgid "same day" msgstr "" msgid "same week" msgstr "" msgid "same month" msgstr "" msgid "Template name" msgstr "" msgid "Help$Specify the name of the template." msgstr "" msgid "Help$Specify here the term to search for." msgstr "" msgid "" "Help$The following search modes exist:\n" "\n" "- phrase: searches for sub terms\n" "- all words: all single words must appear\n" "- at least one word: at least one single word must appear\n" "- match exactly: must match exactly\n" "- regular expression: match a regular expression\n" "- fuzzy searching: searches approximately" msgstr "" msgid "Help$This sets the tolerance of fuzzy searching. The value represents the allowed errors." msgstr "" msgid "Help$Set this to 'Yes' if your search should match the case." msgstr "" msgid "Help$Set this to 'Yes' if you like to search in the title of an event." msgstr "" msgid "Help$Set this to 'Yes' if you like to search in the episode of an event." msgstr "" msgid "Help$Set this to 'Yes' if you like to search in the summary of an event." msgstr "" msgid "Use content descriptor" msgstr "" msgid "Help$Set this to 'Yes' if you want to search the contents by a descriptor." msgstr "" msgid "Help$The summary of an event, can contain additional information like 'Genre', 'Category', 'Year',... called 'EPG categories' within EPGSearch. External EPG providers often deliver this information. This allows refining a search and other nice things, like searching for the 'tip of the day'. To use it set this to 'Yes'." msgstr "" msgid "Help$The file epgsearchcats.conf specifies the search mode for this entry. One can search by text or by value. You can also edit a list of predefined values in this file that can be selected here." msgstr "" msgid "Help$If a selected category is not part of the summary of an event this normally excludes this event from the search results. To avoid this, set this option to 'Yes', but please handle this with care to avoid a huge amount of results." msgstr "" msgid "Use in favorites menu" msgstr "" msgid "Result menu layout" msgstr "" msgid "Use as search timer" msgstr "" msgid "Action" msgstr "" msgid "Switch ... minutes before start" msgstr "" msgid "Unmute sound" msgstr "" msgid "Ask ... minutes before start" msgstr "" msgid " Series recording" msgstr "" msgid "Delete recordings after ... days" msgstr "" msgid "Keep ... recordings" msgstr "" msgid "Pause when ... recordings exist" msgstr "" msgid "Avoid repeats" msgstr "" msgid "Allowed repeats" msgstr "" msgid "Only repeats within ... days" msgstr "" msgid "Compare title" msgstr "" msgid "Compare subtitle" msgstr "" msgid "Compare summary" msgstr "" msgid "Min. match in %" msgstr "" msgid "Compare date" msgstr "" msgid "Compare categories" msgstr "" msgid "VPS" msgstr "" msgid "Auto delete" msgstr "" msgid "after ... recordings" msgstr "" msgid "after ... days after first rec." msgstr "" msgid "Edit user-defined days of week" msgstr "" msgid "Compare" msgstr "" msgid "Select blacklists" msgstr "" msgid "Values for EPG category" msgstr "" msgid "Button$Apply" msgstr "" msgid "less" msgstr "" msgid "less or equal" msgstr "" msgid "greater" msgstr "" msgid "greater or equal" msgstr "" msgid "equal" msgstr "" msgid "not equal" msgstr "" msgid "Activation of search timer" msgstr "" msgid "First day" msgstr "" msgid "Last day" msgstr "" msgid "Button$all channels" msgstr "" msgid "Button$only FTA" msgstr "" msgid "Button$Timer preview" msgstr "" msgid "Blacklist results" msgstr "" msgid "found recordings" msgstr "" msgid "Error while accessing recording!" msgstr "" msgid "Button$Default" msgstr "" msgid "Edit$Delete template?" msgstr "" msgid "Overwrite existing entries?" msgstr "" msgid "Edit entry" msgstr "" msgid "Switch" msgstr "" msgid "Announce only" msgstr "" msgid "Announce ... minutes before start" msgstr "" msgid "action at" msgstr "" msgid "Switch list" msgstr "" msgid "Edit template" msgstr "" msgid "Timers" msgstr "" msgid ">>> no info! <<<" msgstr "" msgid "Overview" msgstr "" msgid "Button$Favorites" msgstr "" msgid "Quick search for broadcasts" msgstr "" msgid "Quick search" msgstr "" msgid "Show in main menu" msgstr "" #, c-format msgid "%d new broadcast(s) found! Show them?" msgstr "" msgid "Search timer update done!" msgstr "" #, c-format msgid "small EPG content on:%s" msgstr "" msgid "VDR EPG check warning" msgstr "" #, c-format msgid "Switch to (%d) '%s'?" msgstr "" msgid "Programming timer failed!" msgstr "" vdr-plugin-epgsearch/po/lt_LT.po0000644000175000017500000012126413145412721016432 0ustar tobiastobias# VDR plugin language source file. # Copyright (C) 2007 Klaus Schmidinger # This file is distributed under the same license as the VDR package. # Valdemaras Pipiras , 2009 # msgid "" msgstr "" "Project-Id-Version: VDR 1.7.10\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-06-15 11:15+0200\n" "PO-Revision-Date: 2007-08-14 20:21+0200\n" "Last-Translator: Valdemaras Pipiras \n" "Language-Team: Lithuanian \n" "Language: lt\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" msgid "Channel groups" msgstr "kanalo grupės" msgid "Button$Select" msgstr "Pasirinkti" msgid "Channel group used by:" msgstr "Kanalo grupė naudojama:" msgid "Edit$Delete group?" msgstr "Ištrinti grupę?" msgid "Edit channel group" msgstr "Koreguoti kanalo grupę" msgid "Group name" msgstr "Grupės pavadinimas" msgid "Button$Invert selection" msgstr "Atvirkštinis pasirinkimas" msgid "Button$All yes" msgstr "Visi taip" msgid "Button$All no" msgstr "Visi ne" msgid "Group name is empty!" msgstr "Grupės pavadinimas tuščias!" msgid "Group name already exists!" msgstr "Toks grupės pavadinimas jau yra!" msgid "Direct access to epgsearch's conflict check menu" msgstr "Tiesioginis priėjimas prie epgsearch įskiepo konflikto pasirinkimo meniu" msgid "Timer conflicts" msgstr "Laikmačio konfliktai" msgid "Conflict info in main menu" msgstr "KOnflikto informacija pagrindiniame meniu" msgid "next" msgstr "sekantis" #, c-format msgid "timer conflict at %s! Show it?" msgstr "Laikmačio konflikas %s! Rodyti?" #, c-format msgid "%d timer conflicts! First at %s. Show them?" msgstr "%d kaikmačio konfliktas(ų)! Pirmasis %s. Rodyti juos?" msgid "search the EPG for repeats and more" msgstr "paieška po EPG ieškant pasikartojimų ir kt." msgid "Program guide" msgstr "Programos gidas" msgid "search timer update running" msgstr "vyksta laikmačio paieškos atnaujinimas" msgid "Direct access to epgsearch's search menu" msgstr "Tiesioginis priėjimas prie epgsearch įskiepo paieškos meniu" msgid "Search" msgstr "Paiška" msgid "EpgSearch-Search in main menu" msgstr "Ieškoti pagrindiniame meniu" msgid "Button$Help" msgstr "Pagalba" msgid "Standard" msgstr "Standartas" msgid "Button$Commands" msgstr "Komandos" msgid "Button$Search" msgstr "Paieška" msgid "never" msgstr "niekada" msgid "always" msgstr "visada" msgid "smart" msgstr "protingas" msgid "before user-def. times" msgstr "prieš vartotojo nustatytus laikus" msgid "after user-def. times" msgstr "po vartotojo nustatytų laikų" msgid "before 'next'" msgstr "prieš 'Sekantis'" msgid "General" msgstr "Pagrindinis" msgid "EPG menus" msgstr "EPG meniu" msgid "User-defined EPG times" msgstr "Vartotojo nustatyti EPG laikai" msgid "Timer programming" msgstr "Laikmačio nustatymai" msgid "Search and search timers" msgstr "Paieška ir paieškos laikmačiai" msgid "Timer conflict checking" msgstr "Ieškoma laikmačių konfliktų" msgid "Email notification" msgstr "El. pašto perspėjimas" msgid "Hide main menu entry" msgstr "Paslėpti pagrindinio meniu antraštę" msgid "Help$Hides the main menu entry and may be useful if this plugin is used to replace the original 'Schedule' entry." msgstr "Paslepia pagrindinio meniu antraštę bei gali būti naudingas jei šis įskiepas naudojamas kaip pakaita įprastai naudojamai 'Programa' antraštei." msgid "Main menu entry" msgstr "Pagrindinio meniu įrašas" msgid "Help$The name of the main menu entry which defaults to 'Programm guide'." msgstr "Pagrindinio meniu antraštės pavadinimas, kuris standartiškai skamba kaip 'Programm guide'." msgid "Replace original schedule" msgstr "Pakeičia įprastai naudojamą programą" msgid "Help$When VDR is patched to allow this plugin to replace the original 'Schedule' entry, you can de/activate this replacement here." msgstr "Kai VDR yra įskiepytas kad leistų pakeisti įprastai naudojamą 'Programa' antraštę, šiuo įšrašu galit įjungti/išjungti tokį pakeitimą." msgid "Start menu" msgstr "Pradinis meniu" msgid "Help$Choose between 'Overview - Now' and 'Schedule' as start menu when this plugin is called." msgstr "Pasirinkit tarp 'Kas rodoma dabar' ir 'Programa' kaip pradinę antraštę šio įskiepo paleidimui." msgid "Ok key" msgstr "Ok mygtukas" msgid "" "Help$Choose here the behaviour of key 'Ok'. You can use it to display the summary or to switch to the corresponding channel.\n" "Note: the functionality of key 'blue' (Switch/Info/Search) depends on this setting." msgstr "" "Čia nustatykite 'Ok' mygtuko elgseną. Jūs galite naudoti jį aprašymo parodymui arba esamo kanalo perjungimui.\n" "Turėkite omenyje: 'mėlyno' mygtuko funkcionalumas (Perjungimas/Informacija/Paieška) tiesiogiai priklauso nuo šio parametro." msgid "Red key" msgstr "Raudonas mygtukas" msgid "" "Help$Choose which standard function ('Record' or 'Commands') you like to have on the red key.\n" "(Can be toggled with key '0')" msgstr "" "Pasirinkite kokią pagrindinę funkciją ('Įrašinėjimas' ar 'Komandos') turėtų atlikinėti raudonas mygtukas.\n" "(Gali būti sukeista naudojant '0' mygtuką)" msgid "Blue key" msgstr "Mėlynas mygtukas" msgid "" "Help$Choose which standard function ('Switch'/'Info' or 'Search') you like to have on the blue key.\n" "(Can be toggled with key '0')" msgstr "" "Pasirinkite kokią pagrindinę funkciją ('Perjungimas/Informacija' ar 'Paieška') turėtų atlikinėti mėlynas mygtukas.\n" "(Pakeiskit spausdami '0')" msgid "Show progress in 'Now'" msgstr "Rodyti praeitą laiką nuo einamos programos pradžios arba kitaip progresą 'Dabar' skiltyje" msgid "Help$Shows a progressbar in 'Overview - Now' that informs about the remaining time of the current event." msgstr "Rodo progreso juostą 'Kas rodoma dabar' dalyje, kas suteikia daugiau informacijos apie tai kiek laiko laida dar tęsis." msgid "Show channel numbers" msgstr "Rodyti kanalų numerius" msgid "" "Help$Display channel numbers in 'Overview - Now'.\n" "\n" "(To completely define your own menu look please inspect the MANUAL)" msgstr "" "Rodyti kanalų numerius 'Kas rodoma dabar' dalyje.\n" "\n" "(Kad visiškai pakeistumėt savo meniu išvaizdą, skaitykit manualą)" msgid "Show channel separators" msgstr "Rodyti kanalų skirtukus" msgid "Help$Display VDR channel groups as separators between your channels in 'Overview - Now'." msgstr "Rodyti VDR kanalų grupes kaip skirtukus tarp kanalų 'Kas rodoma dabar' dalyje." msgid "Show day separators" msgstr "Rodyti dienų skirtukus" msgid "Help$Display a separator line at day break in 'Schedule'." msgstr "Rodyti skiriamąją liniją tarp dienų 'Programa' dalyje." msgid "Show radio channels" msgstr "Rodyti radijo kanalus" msgid "Help$Show also radio channels." msgstr "Taip pat rodyti radijo kanalus." msgid "Limit channels from 1 to" msgstr "Riboti kanalus nuo ą iki" msgid "Help$If you have a large channel set you can speed up things when you limit the displayed channels with this setting. Use '0' to disable the limit." msgstr "Jei turite didelį skaičių kanalų ir norite pagreitinti sistemos darbą, tada reikėtų riboti rodomų kanalų skaičių. Spauskit '0' mygtuką kad athungtumėt šį parametrą." msgid "'One press' timer creation" msgstr "'Vienu paspaudimu' laikmačio sukūrimas" msgid "Help$When a timer is created with 'Record' you can choose between an immediate creation of the timer or the display of the timer edit menu." msgstr "Kai laikmatis sukuriamas iš 'Įrašyti' dalies, galima pasirinkti tarp greito laikmačio sukūrimo arba sukūrimo pasirinkimo per laikmačio meniu." msgid "Show channels without EPG" msgstr "Rodyti kanalus be EPG" msgid "Help$Choose 'yes' here if you want to display channels without EPG in 'Overview - Now'. 'Ok' on these entries switches the channel." msgstr "Čia pasirinkit 'taip' jei norite rodyti kanalus be EPG 'Kas rodoma dabar' dalyje. Spustelėjus 'Ok' ant įrašų perjungs kanalą." msgid "Time interval for FRew/FFwd [min]" msgstr "Laiko intervalas FRew/FFwd [min]" msgid "" "Help$Choose here the time interval which should be used for jumping through the EPG by pressing FRew/FFwd.\n" "\n" "(If you don't have those keys, you can toggle to this functionality pressing '0' and get '<<' and '>>' on the keys green and yellow)" msgstr "" "Čia pasirinkite laiko intervalą kuris bus naudojamas peršokant per EPG įrašus, spaudžiant FRew/FFwd mygtukus.\n" "\n" "\n" "(Jei tokių mygtukų jūsū distancinio valdymo pultas neturi, galite keisti parametro vertes paspaudę '0' bei spustelėję ant pasirodžiusių '<<' bei '>>' su žaliu bei geltonu mygtukais)" msgid "Toggle Green/Yellow" msgstr "Sukeisti Žalią/Geltoną" msgid "Help$Specify if green and yellow shall also be switched when pressing '0'." msgstr "Norodyti ar žalias ir geltonas taip pat turėtų būti sukeičiami vietomis paspaudus '0'." msgid "Show favorites menu" msgstr "Rodyti mėgstamiausių meniu" msgid "" "Help$A favorites menu can display a list of your favorite broadcasts. Enable this if you want an additional menu besides 'Now' and 'Next'\n" "Any search can be used as a favorite. You only have to set the option 'Use in favorites menu' when editing a search." msgstr "" "Mėgstamiasių meniu gali rodyti jūsų mėgstamiasių transliacijų sąrašą. Įgalinkit šią funkciją, jei norite papildomų meniu punktų be 'Dabar' ir 'Sekantis'\n" "Bet kokia vykdyta paieška gali būti panaudota kaip dalis mėgstamiasių sąraše. Tiesiog koreguodami paieškos užklausą turite įgalinti 'Naudokit mėgstamiausiųjų meniu' parametrą." msgid "for the next ... hours" msgstr "sekančiom ... valandom" msgid "Help$This value controls the timespan used to display your favorites." msgstr "Šis parametras nustato laiko " msgid "Use user-defined time" msgstr "Vartotojo nustatytas laikas" msgid "Help$Besides 'Now' and 'Next' you can specify up to 4 other times in the EPG which can be used by repeatedly pressing the green key, e.g. 'prime time', 'late night',..." msgstr "Be 'Dabar' bei 'Sekantis' mygtukų, EPG dar galite nurodyti iki keturių kitų laikų, kurie gali būti naudojami spaudinėjant žalią mygtuką." msgid "Description" msgstr "Aprašymas" msgid "Help$This is the description for your user-defined time as it will appear as label on the green button." msgstr "Tai vartotojo sukurto laiko aprašymas, kuris matysis kaip pavadinimas ant žalio mygtuko." msgid "Time" msgstr "Laikas" msgid "Help$Specify the user-defined time here in 'HH:MM'." msgstr "Nurodykit laiką šitokiu formatu 'HH:MM'." msgid "Use VDR's timer edit menu" msgstr "Naudoti VDR'o laikmačio meniu" msgid "" "Help$This plugin has its own timer edit menu extending the original one with some extra functionality like\n" "- an additional directory entry\n" "- user-defined days of week for repeating timers\n" "- adding an episode name\n" "- support for EPG variables (see MANUAL)" msgstr "" "Šis įskiepas turi savo laikmačio meniu, išplečiantį orginalų meniu papildomom funkcijom, tokiom kaip\n" "\n" "- papildomo katalogo įvestis\n" "- vartotojo užsiduotos savaitės dienos, laikmačių pakartojimams\n" "- laidos serijos pavadinimo uždėjimo galimybė\n" "- EPG kintamųjų palaikymas (daugiau informacijos Manuale)" msgid "Default recording dir" msgstr "Numatytasis įrašų katalogas" msgid "Help$When creating a timer you can specify here a default recording directory." msgstr "Kuriant laikmatį, čia galima nurodyti numatytąjį katalogą įrašams." msgid "Add episode to manual timers" msgstr "Pridėti epizodą nustatytasiems laikmačiams" msgid "" "Help$If you create a timer for a series, you can automatically add the episode name.\n" "\n" "- never: no addition\n" "- always: always add episode name if present\n" "- smart: add only if event lasts less than 80 mins." msgstr "" "Jei kuriate laikmatį serijalui, galite tuo pačiu pridėti tos serijos pavadinimą.\n" "\n" "- niekada: nereikia pridėti\n" "- visada: visada pridėti serijos pavadinimą, jei toks yra\n" "- protingai: pridėti tik tada kai laida tęsiasi mažiau nei 80 minučių." msgid "Default timer check method" msgstr "Numatytasis būdas laikmačio patikrai" msgid "" "Help$Manual timers can be checked for EPG changes. Here you can setup the default check method for each channel. Choose between\n" "\n" "- no checking\n" "- by event ID: checks by an event ID supplied by the channel provider.\n" "- by channel and time: check by the duration match." msgstr "" "Rankiniu būdu nustatyti laikmačiai gali būti pertikrinami ar nebuvo EPG pasikeitimų. Čia kiekvienam kanalui galite nustatyti numatytąjį patikros būdą. Pasirinkite iš\n" "\n" "- netikrinti\n" "- pagal laidos id: tikrina pagal laidos id, kurį pateikia kanalo operatorius.\n" "- pagal kanalą ir laiką: tikrina ar sutampa trukmė." msgid "Button$Setup" msgstr "Nustatymai" msgid "Use search timers" msgstr "Naudoti paieškos laikmačius" msgid "Help$'Search timers' can be used to automatically create timers for events that match your search criterions." msgstr "'Paieškos laikmačiai' gali būti naudojami automatiškam laidų, kurios atitiko paieškos kriterijus, laikmačių sukūrimui." msgid " Update interval [min]" msgstr " Atnaujinimų intervalas [min]" msgid "Help$Specify here the time intervall to be used when searching for events in the background." msgstr "Čia nurodyti laiko intervalą tarp vykdomos laidų pasikeitimų paieškos." msgid " SVDRP port" msgstr " SVDRP portas" msgid "Help$Programming of new timers or timer changes is done with SVDRP. The default value should be correct, so change it only if you know what you are doing." msgstr "Naujų laikmačių kūrimas bei laikmačių pasikeitimai į sistemą įrašomi naudojant SVDRP servisą. Numatytoji reikšmė daugumoj atvejų turėtų tikti, taigi keiskite šį parametrą tik tada kai suprantate ką darote." msgid "Help$Specify here the default priority of timers created with this plugin. This value can also be adjusted for each search itself." msgstr "Čia nurodyti šiuo įskiepu sukurtą numatytąjį laikmačių eiliškumą. Šis parametras taip pat gali būti nustatytas kiekvienai paieškai atskirai." msgid "Help$Specify here the default lifetime of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "Čia nurodyti šiuo įskiepu sukurtą numatytąjį laikmačio/įrašo galiojimo laiką. Šis parametras taip pat gali būti nustatytas kiekvienai paieškai atskirai." msgid "Help$Specify here the default start recording margin of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "Čia nurodyti šiuo įskiepu sukurtą numatytąjį laikmačio/įrašo pradžios uždelsimo laiką nuo įrašymo pradžios. Šis parametras taip pat gali būti nustatytas kiekvienai paieškai atskirai." msgid "Help$Specify here the default stop recording margin of timers/recordings created with this plugin. This value can also be adjusted for each search itself." msgstr "Čia nurodyti šiuo įskiepu sukurtą numatytąjį laikmačio/įrašo pabaigos uždelsimo laiką po įrašymo pabaigos. Šis parametras taip pat gali būti nustatytas kiekvienai paieškai atskirai." msgid "No announcements when replaying" msgstr "Nerodyti pranšimų pakartojimo metu" msgid "Help$Set this to 'yes' if you don't like to get any announcements of broadcasts if you currently replay anything." msgstr "Nustatykite 'taip' jei nenorite gauti jokių transliuotojo pranešimų, tuo atveju jei šiuo metu žiūrite pakartojimą." msgid "Recreate timers after deletion" msgstr "Atkurti laikmačius po ištrynimo" msgid "Help$Set this to 'yes' if you want timers to be recreated with the next search timer update after deleting them." msgstr "Nustatykite 'taip' jei norite kad laikmačiai galėtų būti atkurti po ištrynimo dar kartą panaudojus laikmačio paiešką." msgid "Check if EPG exists for ... [h]" msgstr "" #, fuzzy msgid "Help$Specify how many hours of future EPG there should be and get warned else after a search timer update." msgstr "Nustatyti 'taip' jei konflikto paieška turėtų būti vykdoma po kiekvieno paieškos laikmačio atnaujinimo." #, fuzzy msgid "Warn by OSD" msgstr "Perspėti per ekrano užsklandą" #, fuzzy msgid "Help$Set this to 'yes' if you want get warnings from the EPG check via OSD." msgstr "Nustatyti 'taip' jei norite gauti pranešimus el. paštu apie laikmačio konfliktus." #, fuzzy msgid "Warn by mail" msgstr "Perspėti per emailą" #, fuzzy msgid "Help$Set this to 'yes' if you want get warnings from the EPG check by mail." msgstr "Nustatyti 'taip' jei el.pašto siuntimui reikia autentifikacijos." #, fuzzy msgid "Channel group to check" msgstr "Kanalo grupė" #, fuzzy msgid "Help$Specify the channel group to check." msgstr "Nurodyti šablono pavadinimą." msgid "Ignore PayTV channels" msgstr "Ignoruoti Mokamus kanalus" msgid "Help$Set this to 'yes' if don't want to see events on PayTV channels when searching for repeats." msgstr "Nustatykite 'taip' jei nenorite matyti mokamų kanalų laidų kai ieškote pakartojimų." msgid "Search templates" msgstr "Paieškos šablonai" msgid "Help$Here you can setup templates for your searches." msgstr "Čia galite nustatyti paieškos šablonus savo paieškoms." msgid "Blacklists" msgstr "Juodieji sąrašai" msgid "Help$Here you can setup blacklists which can be used within a search to exclude events you don't like." msgstr "Čia galite nustatyti juoduosius sąrašus, kad poto neroddyti laidų kurios jums nepatinka." msgid "Help$Here you can setup channel groups which can be used within a search. These are different to VDR channel groups and represent a set of arbitrary channels, e.g. 'FreeTV'." msgstr "Čia galite nuststyti kanalo grupes, kurios gali būti naudojamos paieškos metu. Jos skiriasi nuo VDR kanalų grupių." msgid "Ignore below priority" msgstr "Ignoruoti žemesnį prioritetą" msgid "Help$If a timer with priority below the given value will fail it will not be classified as important. Only important conflicts will produce an OSD message about the conflict after an automatic conflict check." msgstr "Jei 'nusimuš' laikmatis, kurio prioritetas žemesnis nei duotoji reikšmė, tai nebus laikoma kaip svarbus faktas. Po automatinės konfliktų paieškos, informacija ekrane pateikiama tik apie svarbius konflikatus." msgid "Ignore conflict duration less ... min." msgstr "Ignoruoti konfliktiškus laidų įrašus, kurių trukmė mažesnė nei ... min." msgid "Help$If a conflicts duration is less then the given number of minutes it will not be classified as important. Only important conflicts will produce an OSD message about the conflict after an automatic conflict check." msgstr "Jei konflikto trukmė bus mažesnė nei duotas minučių skaičius, tai nebus laikoma kaip svarbus faktas. Po automatinės konfliktų paieškos, informacija ekrane pateikiama tik apie svarbius konflikatus." msgid "Only check within next ... days" msgstr "Tikrinti tik kas ... dienas" msgid "Help$This value reduces the conflict check to the given range of days. All other conflicts are classified as 'not yet important'." msgstr "pagal šį parametrą Nustatomas konflikto paieškos periodiškumas dienomis. Visi kiti konfliktai laikomi kaip 'dar ne svarbūs'." msgid "Check also remote conflicts" msgstr "" msgid "Help$Set this to 'yes' if the conflict check should be done for timers set on remote hosts. This needs SVDRPPeering to be set in vdr and Plugin epgsearch running on the remote host." msgstr "" msgid "--- Automatic checking ---" msgstr "--- Automatinė paieška ---" msgid "After each timer programming" msgstr "Po kiekvieno laikmačio nustatymo" msgid "Help$Set this to 'yes' if the conflict check should be performed after each manual timer programming. In the case of a conflict you get immediately a message that informs you about it. The message is only displayed if this timer is involved in any conflict." msgstr "Nustatyti 'taip', jei konflikto paieška turėtų būti atliekama po kiekvieno rankiniu būdu atlikto laikmačio nustatymo. Jei konfliktas aptiktas, jums apie tai ekrane išvedama žinutė. Žinutė rodoma jei laikmatis sukuria kažkokį konfliktą." msgid "When a recording starts" msgstr "Kai įrašas prasideda" msgid "Help$Set this to 'yes' if the conflict check should be performed when a recording starts. In the case of a conflict you get immediately a message that informs you about it. The message is only displayed if the conflict is within the next 2 hours." msgstr "Nustatyti 'taip' jei konfliktų paieška turėtų būti atliekama kai įrašymas prasideda. Jei konfliktas aptiktas, jums apie tai ekrane išvedama žinutė. Žinutė rodoma jei konfliktas vyksta vyksta per artimiausias vdi valandas." msgid "After each search timer update" msgstr "Po kiekvieno paieškos laikmačio atnaujinimo" msgid "Help$Set this to 'yes' if the conflict check should be performed after each search timer update." msgstr "Nustatyti 'taip' jei konflikto paieška turėtų būti vykdoma po kiekvieno paieškos laikmačio atnaujinimo." msgid "every ... minutes" msgstr "kas ... minutes" msgid "" "Help$Specify here the time intervall to be used for an automatic conflict check in the background.\n" "('0' disables an automatic check)" msgstr "" "Čia nurodyti automatinių konfliktų paieškų laiko inetrvalą\n" "('0' išjungia automatinę patikrą)" msgid "if conflicts within next ... minutes" msgstr "jei konfliktai kyla per ... minutes" msgid "Help$If the next conflict will appear in the given number of minutes you can specify here a shorter check intervall to get more OSD notifications about it." msgstr "Jei sekantis konfliktas įvyks per duotą minučių skaičių ir norite daugiau informacijos ekrane apie tai, galite nurodyti trumpesnį patikros intervalą." msgid "Avoid notification when replaying" msgstr "Nerodyti perspėjimų kai kartojama" msgid "Help$Set this to 'yes' if the don't want to get OSD messages about conflicts if you currently replay something. Nevertheless messages will be displayed if the first upcoming conflict is within the next 2 hours." msgstr "Nustatyti 'taip' jei nenorite matyti žinučių ekrane apie konflikus, kai žiūrite pakartojimą. Kitu atveju žinutės bus rodomos jei konfliktas vyksta vyksta per artimiausias vdi valandas" msgid "Search timer notification" msgstr "Paieškos laikmačio perspėjimai" msgid "Help$Set this to 'yes' if you want to get an email notification about the search timers that where programmed automatically in the background." msgstr "Nustatyti 'taip' jei norite perspėjimą apie paieškos laikmačius gauti el. paštu" msgid "Time between mails [h]" msgstr "Laikas tarp el. laiškų išsiuntimų [h]" msgid "" "Help$Specifiy how much time in [h] you would\n" "like to have atleast between two mails.\n" "With '0' you get a new mail after each\n" "search timer update with new results." msgstr "" "Nurodykit kiek laiko [h]\n" "turėtų minimaliai praeiti tarp dviejų el. laiškų siuntimų.\n" "Su '0' mygtuko nuspaudimu gausit el. paštą po kiekvieno\n" "paieškos laikmačio atsinaujinimo naujais rezultatais." msgid "Timer conflict notification" msgstr "Laikmačio konflikto perspėjimas" msgid "Help$Set this to 'yes' if you want to get an email notification about the timer conflicts." msgstr "Nustatyti 'taip' jei norite gauti pranešimus el. paštu apie laikmačio konfliktus." msgid "Send to" msgstr "Siūsti" msgid "Help$Specify the email address where notifications should be sent to." msgstr "Nurodykite el. pašto adresą kuriuo turėtų būti siunčiami perspėjimai." msgid "Mail method" msgstr "El. paštas" msgid "" "Help$Specify here the method to use when sending mails.\n" "You can choose between\n" " - 'sendmail': requires a properly configured email system\n" " - 'SendEmail.pl': simple script for mail delivery" msgstr "" "Čia nustatykite el. pašto siuntimo būdą\n" " - 'sendmail': reikia tinkamai sukonfigūruoti el. pašto sistemą\n" " - 'SendEmail.pl': paprastas pašto siuntimo skriptas" msgid "--- Email account ---" msgstr "--- El. pašto sąskaita ---" msgid "Email address" msgstr "El. pašto adresas" msgid "Help$Specify the email address where notifications should be sent from." msgstr "Nurodyti el. pašto adresą iš kurio turėtų būti siunčiami pranešimai." msgid "SMTP server" msgstr "SMTP serveris" msgid "Help$Specify the SMTP server that should deliver the notifications. If it's using a port different from the default(25) append the port with \":port\"." msgstr "\":port\" ." msgid "Use SMTP authentication" msgstr "Naudoti SMTP autentifikaciją" msgid "Help$Set this to 'yes' if your account needs authentication to send mails." msgstr "Nustatyti 'taip' jei el.pašto siuntimui reikia autentifikacijos." msgid "Auth user" msgstr "Vartotojo vardas" msgid "Help$Specify the auth user, if this account needs authentication for SMTP." msgstr "Nurodykit vartotojo vardą, jei reikalinga SMTP autentifikacija." msgid "Auth password" msgstr "Slapyvardis" msgid "Help$Specify the auth password, if this account needs authentication for SMTP." msgstr "Nurodyki slapyvardį, jei reikalinga SMTP autentifikacija." msgid "Mail account check failed!" msgstr "Pašto prisijungimo patikra!" msgid "Button$Test" msgstr "Testas" msgid "$ abcdefghijklmnopqrstuvwxyz0123456789-.,#~\\^$[]|()*+?{}/:%@&_" msgstr " aąbcčdeęėfghiįjklmnopqrsštuųūvzž0123456789-.,#~\\^$[]|()*+?{}/:%@&_" msgid "Start/Stop time has changed" msgstr "Pasikeitė pradžios/pabaigos laikas" msgid "Title/episode has changed" msgstr "Pasikeitė pavadinimas/epizodas" msgid "No new timers were added." msgstr "Nepridėtas nė vienas laikmatis." msgid "No timers were modified." msgstr "Nė vienas laikmatis nebuvo pakeistas." msgid "No timers were deleted." msgstr "Nė vienas laikmatis nebuvo ištrintas." msgid "No new events to announce." msgstr "Nėra apie ką trimituoti." msgid "This version of EPGSearch does not support this service!" msgstr "Ši EPGSarch įskiepo versija nepalaiko šios funkcijos!" msgid "EPGSearch does not exist!" msgstr "Nerastas EPGSerach įskiepas!" #, c-format msgid "%d new broadcast" msgstr "%d naujas(-i) transliuotojas(-ai)" msgid "Button$by channel" msgstr "pagal kanalą" msgid "Button$by time" msgstr "pagal laiką" msgid "Button$Episode" msgstr "Epizodas" msgid "Button$Title" msgstr "Pavadinimas" msgid "announce details" msgstr "pranešimo detalės" msgid "announce again" msgstr "pranešti dar kartą" msgid "with next update" msgstr "su sekančiu atnaujinimu" msgid "again from" msgstr "dar kartą iš" msgid "Search timer" msgstr "Paieškos laikmatis" msgid "Edit blacklist" msgstr "Koreguoti juoduosius sąrašus" msgid "phrase" msgstr "frazė" msgid "all words" msgstr "visi žodžiai" msgid "at least one word" msgstr "bent vienas žodis" msgid "match exactly" msgstr "tikslus atitikmuo" msgid "regular expression" msgstr "reguliari išraiška" msgid "fuzzy" msgstr "neapibrėžtai" msgid "user-defined" msgstr "vartotojo numastatytas" msgid "interval" msgstr "intervalas" msgid "channel group" msgstr "kanalo grupė" msgid "only FTA" msgstr "tik nekoduoti" msgid "Search term" msgstr "Paiškos frazė" msgid "Search mode" msgstr "Paieškos būdas" msgid "Tolerance" msgstr "Tolerancija" msgid "Match case" msgstr "Atitikti" msgid "Use title" msgstr "Rodyti pavadinimą" msgid "Use subtitle" msgstr "Rodyti aprašą" msgid "Use description" msgstr "Rodyti aprašymą" msgid "Use extended EPG info" msgstr "Rodyti EPG informaciją" msgid "Ignore missing categories" msgstr "Ignoruoti trūkstamas kategorijas" msgid "Use channel" msgstr "Naudoti kanalą" msgid " from channel" msgstr " nuo kanalo" msgid " to channel" msgstr " iki kanalo" msgid "Channel group" msgstr "Kanalo grupė" msgid "Use time" msgstr "Naudoti laiką" msgid " Start after" msgstr " pradėti po" msgid " Start before" msgstr " pradėti prieš" msgid "Use duration" msgstr "Naudoti trukmę" msgid " Min. duration" msgstr " Min. trukmė" msgid " Max. duration" msgstr " Maks. trukmė" msgid "Use day of week" msgstr "Naudoti savaitės dieną" msgid "Day of week" msgstr "Savaitės diena" msgid "Use global" msgstr "" msgid "Button$Templates" msgstr "Šablonai" msgid "*** Invalid Channel ***" msgstr "*** Klaidingas kanalas ***" msgid "Please check channel criteria!" msgstr "Patikrinkit kanalo kriterijų!" msgid "Edit$Delete blacklist?" msgstr "Ištrinti juodajį sąrašą?" msgid "Repeats" msgstr "Pakartojimai" msgid "Create search" msgstr "Sukurti paiešką" msgid "Search in recordings" msgstr "Paieška įrašuose" msgid "Mark as 'already recorded'?" msgstr "Pažymėti kaip 'jau įrašyta'?" msgid "Add/Remove to/from switch list?" msgstr "Įtraukti/Išimti į/iš perjungimo sąrašo?" msgid "Create blacklist" msgstr "Sukurti juodajį sąrašą" msgid "EPG Commands" msgstr "EPG komandos" msgid "Epgsearch: RemoteTimerModifications failed" msgstr "" msgid "Already running!" msgstr "Jau groja!" msgid "Add to switch list?" msgstr "Įtraukti į perjungimo sąrašą?" msgid "Delete from switch list?" msgstr "Ištrinti iš perjungimo sąrašo?" msgid "Button$Details" msgstr "Detalės" msgid "Button$Filter" msgstr "Filtras" msgid "Button$Show all" msgstr "Rodyti visus" msgid "conflicts" msgstr "konfliktai" msgid "no conflicts!" msgstr "nėra konfliktų!" msgid "no important conflicts!" msgstr "nėra svarbių konfliktų!" msgid "C" msgstr "K" msgid "Button$Repeats" msgstr "Pakartojimai" msgid "no check" msgstr "netikrinti" msgid "by channel and time" msgstr "pagal kanalą ir laiką" msgid "by event ID" msgstr "pagal įvykio ID" msgid "Select directory" msgstr "Pasirinkti katalogą" msgid "Button$Level" msgstr "Lygis" msgid "Event" msgstr "Įvykis" msgid "Favorites" msgstr "Mėgstamiausi" msgid "Search results" msgstr "Rezultatų paieška" msgid "Timer conflict! Show?" msgstr "Laikmačio konflikas! Rodyti?" msgid "Directory" msgstr "Katalogas" msgid "Channel" msgstr "Kanalas" msgid "Childlock" msgstr "Paveldėtojo užraktas" msgid "Record on" msgstr "" msgid "Timer check" msgstr "Laikmačio patikra" msgid "recording with device" msgstr "įrašinėjimas su įrenginiu" msgid "Button$With subtitle" msgstr "Su subtitrais" msgid "Button$Without subtitle" msgstr "Be subtitrų" msgid "Timer has been deleted" msgstr "" msgid "Button$Extended" msgstr "Išplėstas" msgid "Button$Simple" msgstr "Paprastas" msgid "Use blacklists" msgstr "Naudoti juoduosius sąrašus" msgid "Edit$Search text too short - use anyway?" msgstr "Ieškomas tekstas per trumpas - vistiek naudoti?" #, fuzzy msgid "Button$Orphaned" msgstr "pagal kanalą" msgid "Button$by name" msgstr "pagal pavadinimą" msgid "Button$by date" msgstr "pagal datą" msgid "Button$Delete all" msgstr "Trinti visus" msgid "Recordings" msgstr "Įrašai" msgid "Edit$Delete entry?" msgstr "Ištrinti įrašą?" msgid "Edit$Delete all entries?" msgstr "Ištrinti visus įrašus?" msgid "Summary" msgstr "Santrauka" msgid "Auxiliary info" msgstr "Papildoma informacija" msgid "Button$Aux info" msgstr "Pap. informacija" msgid "Search actions" msgstr "Veiksmų paieška" msgid "Execute search" msgstr "Įvykdyti paiešką" msgid "Use as search timer on/off" msgstr "Naudoti paieškos laikmačio įjungimui/išjungimui" msgid "Trigger search timer update" msgstr "Įjungti paieškos laikmačio atnaujinimą" msgid "Show recordings done" msgstr "Rodyti padarytus įrašus" msgid "Show timers created" msgstr "Rodyti sukurtus laikmačius" msgid "Create a copy" msgstr "Sukurti kopiją" msgid "Use as template" msgstr "Naudoti šabloną" msgid "Show switch list" msgstr "Rodyti perjungimo sąrašus" msgid "Show blacklists" msgstr "Rodyti juoduosius sąrašus" msgid "Delete created timers?" msgstr "Ištrinti sukurtus laikmačius?" msgid "Timer conflict check" msgstr "Laikmačio konflikto paieška" msgid "Disable associated timers too?" msgstr "Taip pat atjungti ir susijusius laikmačius?" msgid "Activate associated timers too?" msgstr "Taip pat aktyvuoti ir susijusius laikmačius?" msgid "Search timers activated in setup." msgstr "Paieškos laikmačiai aktyvuoti." msgid "Run search timer update?" msgstr "Paleisti paieškos laikmačio atnaujinimą?" msgid "Copy this entry?" msgstr "Kopijuoti šią įvestį?" msgid "Copy" msgstr "Kopijuoti" msgid "Copy this entry to templates?" msgstr "Koreguoti šią įvestį į šabloną?" msgid "Delete all timers created from this search?" msgstr "Ištrinti visus šios paieškos sukurtus laikmačius?" msgid "Button$Actions" msgstr "Veiksmai" msgid "Search entries" msgstr "Įrašų paieška" msgid "active" msgstr "aktyvus" msgid "Edit$Delete search?" msgstr "Ištrinti paiešką?" msgid "Edit search" msgstr "Koreguoti paiešką" msgid "Record" msgstr "Įrašyti" msgid "Announce by OSD" msgstr "Perspėti per ekrano užsklandą" msgid "Switch only" msgstr "Tik perjungti" msgid "Announce and switch" msgstr "Perspėti ir perjungti" msgid "Announce by mail" msgstr "Perspėti per emailą" msgid "Inactive record" msgstr "" msgid "only globals" msgstr "" msgid "Selection" msgstr "Pasirinkimas" msgid "all" msgstr "visi" msgid "count recordings" msgstr "skaičiuoti įrašus" msgid "count days" msgstr "skaičiuoti dienas" msgid "if present" msgstr "jei yra" #, fuzzy msgid "same day" msgstr "Paskutinė diena" #, fuzzy msgid "same week" msgstr "Savaitės diena" msgid "same month" msgstr "" msgid "Template name" msgstr "Šablono pavadinimas" msgid "Help$Specify the name of the template." msgstr "Nurodyti šablono pavadinimą." msgid "Help$Specify here the term to search for." msgstr "Čia nurodykit ko ieškote" msgid "" "Help$The following search modes exist:\n" "\n" "- phrase: searches for sub terms\n" "- all words: all single words must appear\n" "- at least one word: at least one single word must appear\n" "- match exactly: must match exactly\n" "- regular expression: match a regular expression\n" "- fuzzy searching: searches approximately" msgstr "" "Galimi šie paieškos metodai:\n" "\n" "- pagal frazę\n" "- visi žodžiai: visi atskiri žodžiai turi atsispindėti rezultate\n" "- bent vienas žodis: turi būti rastas bent vienas žodis\n" "- tiksli paieška\n" "- reguliarioji išraiška: galima naudoti regexp sintaksę\n" "- neapibrėžta paieška: ieško grubiai naudojant žodžių dalis" msgid "Help$This sets the tolerance of fuzzy searching. The value represents the allowed errors." msgstr "Tai duoda neapibrėžtą paiešką. Ši reikšmė nurodo galimų klaidų skaičių." msgid "Help$Set this to 'Yes' if your search should match the case." msgstr "Pasirinkite 'Taip', jei norite kad paieškos užklausoje paisytumėt raidžių registro." msgid "Help$Set this to 'Yes' if you like to search in the title of an event." msgstr "Pasirinkite 'Taip', jei paiešką norite vykdyti įvykio pavadinime." msgid "Help$Set this to 'Yes' if you like to search in the episode of an event." msgstr "Pasirinkite 'Taip', jei paiešką norite vykdyti vienoje iš įvykio serijos dalių." msgid "Help$Set this to 'Yes' if you like to search in the summary of an event." msgstr "Pasirinkti 'Taip' jei norite ieškoti įvykio santraukoje." #, fuzzy msgid "Use content descriptor" msgstr "Rodyti aprašymą" #, fuzzy msgid "Help$Set this to 'Yes' if you want to search the contents by a descriptor." msgstr "Pasirinkite 'Taip', jei paiešką norite vykdyti įvykio pavadinime." msgid "Help$The summary of an event, can contain additional information like 'Genre', 'Category', 'Year',... called 'EPG categories' within EPGSearch. External EPG providers often deliver this information. This allows refining a search and other nice things, like searching for the 'tip of the day'. To use it set this to 'Yes'." msgstr "Įviokio santrauka gali turėti papildomos informacijos, tokios kaip 'Žanras', 'Kategorija', 'Metai', ... EPGSearch įskiepe vadinamos 'EPG kategorijomis'. Išoriniai EPG tiekėjai dašnai pateikia šitą informaciją. Tai leidžia pagražinti paiešką ir įvesti kitus gražius dalykėlius, tokius kaip 'dienos frazė'. Kad tai panaudotumėt, pasirinkite 'Taip'" msgid "Help$The file epgsearchcats.conf specifies the search mode for this entry. One can search by text or by value. You can also edit a list of predefined values in this file that can be selected here." msgstr "Failas epgsearchcats.conf nusako šio įrašo paieškos būdą, paieška gali būti daroma tiek įvedant tiek pasirenkant reikšmę. Jūs taip pat galite koreguoti jau egzistuojantį reikšmių sąrašą esantį šiame faile." msgid "Help$If a selected category is not part of the summary of an event this normally excludes this event from the search results. To avoid this, set this option to 'Yes', but please handle this with care to avoid a huge amount of results." msgstr "Jei pasirinkta kategorija nėra įvykio santraukos dalis, tai paprastai neįtraukia įvykio į paieškos rezultatus. Kad to išvengtumėte, pasirinkite 'Taip', bet darykite tai apgalvotai, nes kitu atveju galite gauti didžiulį skaičių rezultatų." msgid "Use in favorites menu" msgstr "Naudoti mėgiamiausiųjų sąraše." msgid "Result menu layout" msgstr "Rezultatų meniu išvaizda" msgid "Use as search timer" msgstr "Naudoti kaip paieškos laikmatį" msgid "Action" msgstr "Veiksmas" msgid "Switch ... minutes before start" msgstr "Perjungti likus ... minučių iki pradžios" msgid "Unmute sound" msgstr "Įjungti garsą" msgid "Ask ... minutes before start" msgstr "Klausti ... minučių iki prieš pradžios" msgid " Series recording" msgstr " serijų įrašai" msgid "Delete recordings after ... days" msgstr "Ištrinti įrašus po ... dienų" msgid "Keep ... recordings" msgstr "Laikyti ... įrašus" msgid "Pause when ... recordings exist" msgstr "pristapdyti kai pasiekia ... įrašų ribą." msgid "Avoid repeats" msgstr "Išvengti pakartojimų" msgid "Allowed repeats" msgstr "Leisti pakartojimus" msgid "Only repeats within ... days" msgstr "Kartoji tik kas ... dienas" msgid "Compare title" msgstr "Palyginti pavadinimą" msgid "Compare subtitle" msgstr "Palyginti aprašą" msgid "Compare summary" msgstr "Palyginti santrauką" #, fuzzy msgid "Min. match in %" msgstr " Min. trukmė" #, fuzzy msgid "Compare date" msgstr "Palyginti pavadinimą" msgid "Compare categories" msgstr "Palyginti kategorijas" msgid "VPS" msgstr "VPS" msgid "Auto delete" msgstr "Ištrunti automatiškai" msgid "after ... recordings" msgstr "po ... įrašų" msgid "after ... days after first rec." msgstr "po ... dienų po įrašymo" msgid "Edit user-defined days of week" msgstr "Koreguoti vartotojo pasirinktas savaitės dienas" msgid "Compare" msgstr "Palyginti" msgid "Select blacklists" msgstr "Pasirinkti juoduosius sąrašus" msgid "Values for EPG category" msgstr "EPG kategorijos vertės" msgid "Button$Apply" msgstr "Patvirtinti" msgid "less" msgstr "mažiau" msgid "less or equal" msgstr "mažiau arba lygu" msgid "greater" msgstr "daugiau" msgid "greater or equal" msgstr "daugiau arba lygu" msgid "equal" msgstr "lygu" msgid "not equal" msgstr "nelygu" msgid "Activation of search timer" msgstr "Paieškos laikmačio aktyvavimas" msgid "First day" msgstr "Pirma diena" msgid "Last day" msgstr "Paskutinė diena" msgid "Button$all channels" msgstr "visi kanalai" msgid "Button$only FTA" msgstr "tik nekoduoti" msgid "Button$Timer preview" msgstr "Laikmačio peržiūra." msgid "Blacklist results" msgstr "Rezultatai iš juodųjų sąrašų" msgid "found recordings" msgstr "rasti įrašai" msgid "Error while accessing recording!" msgstr "Klaida bandant paleisti įrašą!" msgid "Button$Default" msgstr "Numatytasis" msgid "Edit$Delete template?" msgstr "Ištrinti šabloną?" msgid "Overwrite existing entries?" msgstr "Perrašyti esamus įrašus?" msgid "Edit entry" msgstr "Koreguoti įrašą" msgid "Switch" msgstr "Pereiti" msgid "Announce only" msgstr "Tik pranešti" msgid "Announce ... minutes before start" msgstr "Pranešti ... minučių prieš prasidedant" msgid "action at" msgstr "veiksmas" msgid "Switch list" msgstr "Sukeisti sąrašus" msgid "Edit template" msgstr "Koreguoti šabloną" msgid "Timers" msgstr "Laikmačiai" msgid ">>> no info! <<<" msgstr ">>> nėra informacijos! <<<" msgid "Overview" msgstr "Peržūra" msgid "Button$Favorites" msgstr "Mėgiamiausi" msgid "Quick search for broadcasts" msgstr "Greita transliacijų paieška" msgid "Quick search" msgstr "Greita paieška" msgid "Show in main menu" msgstr "Rodyti pagriundiniame meniu" #, c-format msgid "%d new broadcast(s) found! Show them?" msgstr "Rasta %d naujas(ų) transliuotojas(ų)! Parodyti juos?" msgid "Search timer update done!" msgstr "Laikmačio atnaujinimo paieška baigta sėkmingai!" #, c-format msgid "small EPG content on:%s" msgstr "" msgid "VDR EPG check warning" msgstr "" #, c-format msgid "Switch to (%d) '%s'?" msgstr "Pereiti į (%d) '%s'?" msgid "Programming timer failed!" msgstr "Nustatyti laikmačio nepavyko!" #~ msgid "in %02ldd" #~ msgstr "per %02ldd" #~ msgid "in %02ldh" #~ msgstr "per %02ldh" #~ msgid "in %02ldm" #~ msgstr "per %02ldm" #, fuzzy #~ msgid "Compare expression" #~ msgstr "reguliari išraiška" vdr-plugin-epgsearch/menu_searchresults.h0000644000175000017500000001177013145412721020522 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #ifndef __EPGSEARCHRES_H #define __EPGSEARCHRES_H #include #include #include "templatefile.h" #include "epgsearchext.h" #include "menu_event.h" typedef enum { showTitleEpisode, showEpisode } ModeYellowSR; typedef enum { showAll, showNoPayTV, showTimerPreview } ModeBlueSR; // --- cMenuSearchResultsItem ------------------------------------------------------ class cMenuSearchResultsItem : public cOsdItem { char *fileName; // for search in recordings bool previewTimer; bool episodeOnly; cMenuTemplate* menuTemplate; public: eTimerMatch timerMatch; bool inSwitchList; bool timerActive; const cEvent *event; const cSearchExt* search; const char *FileName(void) { return fileName; } cMenuSearchResultsItem(const cEvent *EventInfo, bool EpisodeOnly = false, bool PreviewTimer = false, cMenuTemplate* MenuTemplate = NULL, const cSearchExt* Search = NULL); cMenuSearchResultsItem(const cRecording *Recording); bool Update(bool Force = false); void SetMenuItem(cSkinDisplayMenu *DisplayMenu, int Index, bool Current, bool Selectable); }; // --- cMenuSearchResults ------------------------------------------------------ class cMenuSearchResults : public cOsdMenu { friend class cMenuFavorites; protected: int helpKeys; cMenuTemplate* menuTemplate; bool ignoreRunning; cEventObjects eventObjects; virtual bool BuildList()=0; virtual eOSState ProcessKey(eKeys Key); eOSState ShowSummary(void); virtual eOSState OnRed(cSearchExt* searchExt = NULL); virtual eOSState OnGreen(); virtual eOSState OnYellow(); eOSState Record(void); eOSState Switch(void); eOSState Commands(eKeys Key, cSearchExt* SearchExt = NULL); int GetTab(int Tab); virtual void SetHelpKeys(bool Force=false)=0; bool Update(void); void UpdateCurrent(); static const cEvent *scheduleEventInfo; ModeYellowSR modeYellow; ModeBlueSR modeBlue; public: bool m_bSort; cMenuSearchResults(cMenuTemplate* MenuTemplate); }; // --- cMenuSearchResultsForSearch ------------------------------------------------------ class cMenuSearchResultsForSearch : public cMenuSearchResults { protected: cSearchExt* searchExt; virtual bool BuildList(); virtual void SetHelpKeys(bool Force=false); eOSState ProcessKey(eKeys Key); public: cMenuSearchResultsForSearch(cSearchExt*, cMenuTemplate* MenuTemplate); virtual ~cMenuSearchResultsForSearch() {} }; class cBlacklist; // --- cMenuSearchResultsForBlacklist ------------------------------------------------------ class cMenuSearchResultsForBlacklist : public cMenuSearchResults { cBlacklist* blacklist; virtual bool BuildList(); virtual void SetHelpKeys(bool Force=false); eOSState ProcessKey(eKeys Key); public: cMenuSearchResultsForBlacklist(cBlacklist*); }; // --- cMenuSearchResultsForQuery ------------------------------------------------------ class cMenuSearchResultsForQuery : public cMenuSearchResultsForSearch { public: cMenuSearchResultsForQuery(const char *query, bool IgnoreRunning = false); ~cMenuSearchResultsForQuery(); virtual bool BuildList(); }; // --- cMenuSearchResultsForRecs ------------------------------------------------------ class cMenuSearchResultsForRecs : public cMenuSearchResultsForQuery { virtual bool BuildList(); eOSState ProcessKey(eKeys Key); eOSState Play(void); const cRecording *GetRecording(cMenuSearchResultsItem *Item); public: cMenuSearchResultsForRecs(const char *query); }; // --- cMenuSearchResultsForList ------------------------------------------------------ class cMenuSearchResultsForList : public cMenuSearchResults { protected: cSearchResults* searchResults; virtual bool BuildList(); virtual void SetHelpKeys(bool Force=false); virtual eOSState ProcessKey(eKeys Key); public: cMenuSearchResultsForList(cSearchResults& SearchResults, const char* Title, bool IgnoreRunning = false); }; #endif vdr-plugin-epgsearch/menu_blacklists.h0000644000175000017500000000250713145412721017764 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #ifndef __MENU_BLACKLISTS_H #define __MENU_BLACKLISTS_H #include #include "blacklist.h" class cMenuBlacklists : public cOsdMenu { private: eOSState New(void); eOSState Delete(void); protected: virtual eOSState ProcessKey(eKeys Key); public: cMenuBlacklists(); cBlacklist* CurrentBlacklist(void); }; #endif vdr-plugin-epgsearch/menu_recsdone.c0000644000175000017500000001455113145412721017430 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #include "menu_recsdone.h" #include "epgsearchtools.h" int sortModeRecDone = 0; cMenuRecDoneItem::cMenuRecDoneItem(cRecDone* RecDone, bool ShowEpisodeOnly) { recDone = RecDone; showEpisodeOnly = ShowEpisodeOnly; Set(); } void cMenuRecDoneItem::Set() { if (!recDone) return; char *buffer = NULL; char buf[32]; struct tm tm_r; tm *tm = localtime_r(&recDone->startTime, &tm_r); strftime(buf, sizeof(buf), "%d.%m.%y %H:%M", tm); msprintf(&buffer, "%s\t%s~%s", buf, recDone->title && !showEpisodeOnly?recDone->title:"", recDone->shortText?recDone->shortText:""); SetText(buffer, false); } int cMenuRecDoneItem::Compare(const cListObject &ListObject) const { cMenuRecDoneItem *p = (cMenuRecDoneItem *)&ListObject; if (sortModeRecDone == 0) // sort by Date if (recDone->startTime < p->recDone->startTime) return 1; else return -1; else { cString s1 = cString::sprintf("%s~%s", recDone->title?recDone->title:"", recDone->shortText?recDone->shortText:""); cString s2 = cString::sprintf("%s~%s", p->recDone->title?p->recDone->title:"", p->recDone->shortText?p->recDone->shortText:""); int res = strcasecmp(s1, s2); return res; } } // --- cMenuRecsDone ---------------------------------------------------------- #define SHOW_RECDONE_SEARCH 0 #define SHOW_RECDONE_ALL 1 #define SHOW_RECDONE_ORPHANED 2 cMenuRecsDone::cMenuRecsDone(cSearchExt* Search) :cOsdMenu("", 16) { SetMenuCategory(mcUnknown); search = Search; showMode = SHOW_RECDONE_ALL; showEpisodeOnly = false; sortModeRecDone = 0; if (search) showMode = SHOW_RECDONE_SEARCH; Set(); Display(); } const char* cMenuRecsDone::ButtonBlue(cSearchExt* Search) { if (showMode==SHOW_RECDONE_SEARCH && Search) return tr("Button$Show all"); else if (showMode==SHOW_RECDONE_ALL) return tr("Button$Orphaned"); else return Search->search; } void cMenuRecsDone::Set() { Clear(); cMutexLock RecsDoneLock(&RecsDone); cRecDone* recDone = RecsDone.First(); while (recDone) { if (showMode == SHOW_RECDONE_ALL || (showMode == SHOW_RECDONE_SEARCH && search && recDone->searchID == search->ID) || (showMode == SHOW_RECDONE_ORPHANED && recDone->searchID == -1)) Add(new cMenuRecDoneItem(recDone, showEpisodeOnly)); recDone = RecsDone.Next(recDone); } UpdateTitle(); SetHelp(sortModeRecDone==0?tr("Button$by name"):tr("Button$by date"), tr("Button$Delete all"), trVDR("Button$Delete"), ButtonBlue(search)); Sort(); } cRecDone *cMenuRecsDone::CurrentRecDone(void) { cMenuRecDoneItem *item = (cMenuRecDoneItem *)Get(Current()); return item ? item->recDone : NULL; } void cMenuRecsDone::UpdateTitle() { cString buffer = cString::sprintf("%d %s%s%s", Count(), tr("Recordings"), showMode == SHOW_RECDONE_ALL?"":" ", showMode != SHOW_RECDONE_SEARCH ? "":search->search); SetTitle(buffer); Display(); } eOSState cMenuRecsDone::Delete(void) { cRecDone *curRecDone = CurrentRecDone(); if (curRecDone) { if (Interface->Confirm(tr("Edit$Delete entry?"))) { LogFile.Log(1,"deleted recording done: '%s~%s'", curRecDone->title?curRecDone->title:"unknown title", curRecDone->shortText?curRecDone->shortText:"unknown subtitle"); cMutexLock RecsDoneLock(&RecsDone); RecsDone.Del(curRecDone); RecsDone.Save(); cOsdMenu::Del(Current()); Display(); UpdateTitle(); } } return osContinue; } eOSState cMenuRecsDone::DeleteAll(void) { if (Interface->Confirm(tr("Edit$Delete all entries?"))) { cMutexLock RecsDoneLock(&RecsDone); while(Count()>0) { cMenuRecDoneItem *item = (cMenuRecDoneItem *)Get(0); if (!item) break; cRecDone *curRecDone = item->recDone; RecsDone.Del(curRecDone); cOsdMenu::Del(0); } RecsDone.Save(); Display(); UpdateTitle(); } return osContinue; } eOSState cMenuRecsDone::Summary(void) { if (HasSubMenu() || Count() == 0) return osContinue; cRecDone* recDone = CurrentRecDone(); if (recDone && !isempty(recDone->description)) return AddSubMenu(new cMenuTextDone(tr("Summary"), recDone)); return osContinue; } eOSState cMenuRecsDone::ProcessKey(eKeys Key) { eOSState state = cOsdMenu::ProcessKey(Key); if (state == osUnknown) { switch (Key) { case kOk: state = Summary(); break; case kGreen: state = DeleteAll(); break; case kYellow: state = Delete(); break; case kBlue: showMode = (showMode+1)%3; Set(); Display(); break; case k0: showEpisodeOnly = !showEpisodeOnly; Set(); Display(); break; case kRed: sortModeRecDone = 1-sortModeRecDone; Set(); Display(); break; case k8: return osContinue; default: break; } } return state; } eOSState cMenuTextDone::ProcessKey(eKeys Key) { eOSState state = cMenuText::ProcessKey(Key); if (state == osContinue) { switch (Key) { case kBlue: if (recDone->aux) return AddSubMenu(new cMenuText(tr("Auxiliary info"), recDone->aux)); break; case kOk: return osBack; default: state = osContinue; } } return state; } // --- cMenuTextDone ---------------------------------------------------------- cMenuTextDone::cMenuTextDone(const char *Title, cRecDone* RecDone, eDvbFont Font) : cMenuText(Title, RecDone->description, Font), recDone(RecDone) { if (recDone->aux) SetHelp(NULL, NULL, NULL, tr("Button$Aux info")); } vdr-plugin-epgsearch/epgsearch.c0000644000175000017500000006660113145412721016546 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ /* * epgsearch.c: A plugin for the Video Disk Recorder * */ #include #include #include #include #ifdef __FreeBSD__ #include #endif #include #include "menu_event.h" #include "menu_main.h" #include "menu_whatson.h" #include "epgsearchsetup.h" #include "epgsearchcfg.h" #include "epgsearchext.h" #include "epgsearchcats.h" #include "menu_searchresults.h" #include "searchtimer_thread.h" #include "switchtimer_thread.h" #include "menu_myedittimer.h" #include "epgsearchtools.h" #include "rcfile.h" #include "changrp.h" #include "recstatus.h" #include "timerstatus.h" #include "recdone.h" #include "blacklist.h" #include "menu_search.h" #include "templatefile.h" #include "menu_conflictcheck.h" #include "epgsearch.h" #include "conflictcheck_thread.h" #include "uservars.h" #include "mail.h" #include "svdrpclient.h" #include "noannounce.h" #include "menu_deftimercheckmethod.h" #include "timerdone.h" #include "epgsearchservices.h" #include "menu_quicksearch.h" #include "menu_announcelist.h" #include "confdloader.h" #include "pending_notifications.h" #if defined(APIVERSNUM) && APIVERSNUM < 20306 #error "VDR-2.3.6 API version or greater is required!" #endif static const char VERSION[] = "2.3.1"; static const char DESCRIPTION[] = trNOOP("search the EPG for repeats and more"); // globals char *ConfigDir = NULL; bool reloadMenuConf = false; int updateForced = 0; bool isUTF8 = false; // LogFile declaration and statics cLogFile LogFile; char *cLogFile::LogFileName = NULL; int cLogFile::loglevellimit = 0; bool cPluginEpgsearch::VDR_readyafterStartup = false; // external SVDRPCommand const char *epgsSVDRP::cSVDRPClient::SVDRPSendCmd = "svdrpsend"; cPluginEpgsearch::cPluginEpgsearch(void) { showConflicts = false; showAnnounces = false; gl_recStatusMonitor = NULL; gl_timerStatusMonitor = NULL; } cPluginEpgsearch::~cPluginEpgsearch() { delete gl_recStatusMonitor; delete gl_timerStatusMonitor; cSearchTimerThread::Exit(); cSwitchTimerThread::Exit(); cConflictCheckThread::Exit(); if (ConfigDir) free(ConfigDir); } const char* cPluginEpgsearch::Version(void) { return VERSION; } const char* cPluginEpgsearch::Description(void) { return tr(DESCRIPTION); } const char *cPluginEpgsearch::CommandLineHelp(void) { return " -f file, --svdrpsendcmd=file the path to svdrpsend for external\n" " SVDRP communication (default is internal\n" " communication)\n" " -c path, --config=path to specify a specific config dir for epgsearch\n" " -l file, --logfile=file to specify a specific logfile for epgsearch\n" " -v n, --verbose=n verbose level for logfile\n" " -r, --reloadmenuconf reload epgsearchmenu.conf with plugin call\n" " -m file, --mailcmd=file path to an alternative mail script for mail\n" " notification\n"; } const char *cPluginEpgsearch::MainMenuEntry(void) { if (EPGSearchConfig.hidemenu) return NULL; if (isempty(EPGSearchConfig.mainmenuentry)) return tr("Program guide"); else return EPGSearchConfig.mainmenuentry; } bool cPluginEpgsearch::ProcessArgs(int argc, char *argv[]) { // Implement command line argument processing here if applicable. if (argc==5 && !strcmp(argv[0], "timermenu")) { // yes, this is an ugly hack! argv[1] = (char*) new cMenuMyEditTimer((cTimer*) argv[2], (bool) argv[3], (const cEvent*) argv[4]); return true; } if (argc==8 && !strcmp(argv[0], "searchepg")) { cSearchExt* SearchExt = new cSearchExt; strn0cpy(SearchExt->search,argv[2], sizeof(SearchExt->search)); if (atoi(argv[3]) > 0) { LOCK_CHANNELS_READ; SearchExt->useChannel = true; SearchExt->channelMin = Channels->GetByNumber(atoi(argv[3])); SearchExt->channelMax = Channels->GetByNumber(atoi(argv[3])); } SearchExt->mode = atoi(argv[4]); SearchExt->useTitle = atoi(argv[5]); SearchExt->useSubtitle = atoi(argv[6]); SearchExt->useDescription = atoi(argv[7]); argv[1] = (char*) new cMenuSearchResultsForSearch(SearchExt, cTemplFile::GetTemplateByName("MenuSearchResults")); return true; } static const struct option long_options[] = { { "svdrpsendcmd", required_argument, NULL, 'f' }, { "config", required_argument, NULL, 'c' }, { "logfile", required_argument, NULL, 'l' }, { "verbose", required_argument, NULL, 'v' }, { "mailcmd", required_argument, NULL, 'm' }, { "reloadmenuconf", no_argument, NULL, 'r' }, { NULL, no_argument, NULL, 0 } }; int c=0,i=0; while ((c = getopt_long(argc, argv, "f:c:l:v:m:r", long_options, &i)) != -1) { switch (c) { case 'f': epgsSVDRP::cSVDRPClient::SVDRPSendCmd = optarg; EPGSearchConfig.useExternalSVDRP = 1; break; case 'c': ConfigDir = strdup(optarg); break; case 'l': cLogFile::LogFileName = optarg; break; case 'v': cLogFile::loglevellimit = atoi(optarg); break; case 'r': reloadMenuConf = true; break; case 'm': cMailNotifier::MailCmd = optarg; break; default: return false; } } if (EPGSearchConfig.useExternalSVDRP && access(epgsSVDRP::cSVDRPClient::SVDRPSendCmd, F_OK) != 0) { LogFile.eSysLog("ERROR - can't find svdrpsend script: '%s'", epgsSVDRP::cSVDRPClient::SVDRPSendCmd); epgsSVDRP::cSVDRPClient::SVDRPSendCmd = NULL; } return true; } bool cPluginEpgsearch::Service(const char *Id, void *Data) { if (strcmp(Id, "MainMenuHooksPatch-v1.0::osSchedule") == 0 && EPGSearchConfig.ReplaceOrgSchedule!=0) { if (Data == NULL) return true; cOsdMenu **menu = (cOsdMenu**) Data; if (menu) *menu = (cOsdMenu*) MainMenuAction(); return true; } if (strcmp(Id, "Epgsearch-search-v1.0") == 0) { if (Data == NULL) return true; cSearchExt* SearchExt = new cSearchExt; Epgsearch_search_v1_0* searchData = (Epgsearch_search_v1_0*) Data; searchData->pResultMenu = NULL; strn0cpy(SearchExt->search,searchData->query, sizeof(SearchExt->search)); if (searchData->channelNr > 0) { LOCK_CHANNELS_READ; SearchExt->useChannel = true; SearchExt->channelMin = Channels->GetByNumber(searchData->channelNr); SearchExt->channelMax = Channels->GetByNumber(searchData->channelNr); } SearchExt->mode = searchData->mode; SearchExt->useTitle = searchData->useTitle; SearchExt->useSubtitle = searchData->useSubTitle; SearchExt->useDescription = searchData->useDescription; searchData->pResultMenu = new cMenuSearchResultsForSearch(SearchExt, cTemplFile::GetTemplateByName("MenuSearchResults")); return true; } if (strcmp(Id, "Epgsearch-exttimeredit-v1.0") == 0 && !EPGSearchConfig.useVDRTimerEditMenu) { if (Data == NULL) return true; Epgsearch_exttimeredit_v1_0* serviceData = (Epgsearch_exttimeredit_v1_0*) Data; serviceData->pTimerMenu = new cMenuMyEditTimer(serviceData->timer, serviceData->bNew, serviceData->event); return true; } if (strcmp(Id, "Epgsearch-enablesearchtimers-v1.0") == 0) { if (Data == NULL) return true; else { Epgsearch_enablesearchtimers_v1_0* serviceData = (Epgsearch_enablesearchtimers_v1_0*) Data; if (serviceData->enable && cSearchTimerThread::m_Instance == NULL) cSearchTimerThread::Init(this); else if (!serviceData->enable && cSearchTimerThread::m_Instance != NULL) cSearchTimerThread::Exit(); } return true; } if (strcmp(Id, "Epgsearch-updatesearchtimers-v1.0") == 0) { if (Data == NULL) return true; else { Epgsearch_updatesearchtimers_v1_0* serviceData = (Epgsearch_updatesearchtimers_v1_0*) Data; if (!EPGSearchConfig.useSearchTimers) // enable search timer thread if necessary cSearchTimerThread::Init((cPluginEpgsearch*) cPluginManager::GetPlugin("epgsearch"), true); updateForced = serviceData->showMessage?3:1; } return true; } if (strcmp(Id, "Epgsearch-osdmessage-v1.0") == 0) { if (Data == NULL) return true; else { Epgsearch_osdmessage_v1_0* serviceData = (Epgsearch_osdmessage_v1_0*) Data; Skins.Message(serviceData->type, serviceData->message,5); } return true; } if (strcmp(Id, "Epgsearch-searchmenu-v1.0") == 0) { if (Data == NULL) return true; EpgSearchMenu_v1_0* serviceData = (EpgSearchMenu_v1_0*) Data; serviceData->Menu = new cMenuEPGSearchExt(); return true; } if (strcmp(Id, "Epgsearch-conflictmenu-v1.0") == 0) { if (Data == NULL) return true; EpgSearchMenu_v1_0* serviceData = (EpgSearchMenu_v1_0*) Data; serviceData->Menu = new cMenuConflictCheck(); return true; } if (strcmp(Id, "Epgsearch-lastconflictinfo-v1.0") == 0) { if (Data == NULL) return true; Epgsearch_lastconflictinfo_v1_0* serviceData = (Epgsearch_lastconflictinfo_v1_0*) Data; serviceData->nextConflict = cConflictCheckThread::m_cacheNextConflict; serviceData->relevantConflicts = cConflictCheckThread::m_cacheRelevantConflicts; serviceData->totalConflicts = cConflictCheckThread::m_cacheTotalConflicts; return true; } if (strcmp(Id, "Epgsearch-searchresults-v1.0") == 0) { if (Data == NULL) return true; cSearchExt* SearchExt = new cSearchExt; Epgsearch_searchresults_v1_0* searchData = (Epgsearch_searchresults_v1_0*) Data; searchData->pResultList = NULL; strn0cpy(SearchExt->search,searchData->query, sizeof(SearchExt->search)); if (searchData->channelNr > 0) { LOCK_CHANNELS_READ; SearchExt->useChannel = true; SearchExt->channelMin = Channels->GetByNumber(searchData->channelNr); SearchExt->channelMax = Channels->GetByNumber(searchData->channelNr); } SearchExt->mode = searchData->mode; SearchExt->useTitle = searchData->useTitle; SearchExt->useSubtitle = searchData->useSubTitle; SearchExt->useDescription = searchData->useDescription; cSearchResults* results = SearchExt->Run(); // transfer to result list if (results) { results->SortBy(CompareEventTime); searchData->pResultList = new cList; cSearchResult *result = results->First(); while (result) { searchData->pResultList->Add(new Epgsearch_searchresults_v1_0::cServiceSearchResult(result->event)); result = results->Next(result); } } return true; } if (strcmp(Id, "Epgsearch-switchtimer-v1.0") == 0) { if (Data == NULL) return true; else { Epgsearch_switchtimer_v1_0* serviceData = (Epgsearch_switchtimer_v1_0*) Data; if (!serviceData->event) return false; switch(serviceData->mode){ case 0: {// query existence cSwitchTimer *lTimer = SwitchTimers.InSwitchList(serviceData->event); if (lTimer) { serviceData->switchMinsBefore = lTimer->switchMinsBefore; serviceData->announceOnly = lTimer->mode; } // if serviceData->success=lTimer!=NULL; break; } // 0 case 1: { // add/modify cSwitchTimer *lTimer = SwitchTimers.InSwitchList(serviceData->event); if (lTimer) { lTimer->switchMinsBefore = serviceData->switchMinsBefore; lTimer->mode = serviceData->announceOnly; } else { cMutexLock SwitchTimersLock(&SwitchTimers); SwitchTimers.Add(new cSwitchTimer(serviceData->event,serviceData->switchMinsBefore,serviceData->announceOnly)); SwitchTimers.Save(); cSwitchTimerThread::Init(); } // if serviceData->success=true; break; } // 1 case 2: {// delete cSwitchTimer *lTimer = SwitchTimers.InSwitchList(serviceData->event); serviceData->success=lTimer!=NULL; if (lTimer) { cMutexLock SwitchTimersLock(&SwitchTimers); SwitchTimers.Del(lTimer); SwitchTimers.Save(); } // if break; } // 2 default: serviceData->success=false; break; } // switch } // if return true; } // if if (strcmp(Id, "Epgsearch-quicksearch-v1.0") == 0) { if (Data == NULL) return true; EpgSearchMenu_v1_0* serviceData = (EpgSearchMenu_v1_0*) Data; serviceData->Menu = new cMenuQuickSearch(new cSearchExt); return true; } if (strcmp(Id, "Epgsearch-services-v1.0") == 0) { if (Data == NULL) return true; Epgsearch_services_v1_0* serviceData = (Epgsearch_services_v1_0*) Data; std::auto_ptr autoHandler(new cEpgsearchServiceHandler); serviceData->handler = autoHandler; return true; } if (strcmp(Id, "Epgsearch-services-v1.1") == 0) { if (Data == NULL) return true; Epgsearch_services_v1_1* serviceData = (Epgsearch_services_v1_1*) Data; std::auto_ptr autoHandler(new cEpgsearchServiceHandler); serviceData->handler = autoHandler; return true; } return false; } bool cPluginEpgsearch::Initialize(void) { return true; } bool cPluginEpgsearch::Start(void) { if (!ConfigDir) ConfigDir = strdup(cPlugin::ConfigDirectory("epgsearch")); cPlugconfdirVar::dir = cPlugin::ConfigDirectory(); if (cLogFile::LogFileName) LogFile.Open(cLogFile::LogFileName, Version()); else LogFile.Open(AddDirectory(CONFIGDIR, "epgsearch.log"), Version()); gl_recStatusMonitor = new cRecStatusMonitor; gl_timerStatusMonitor = new cTimerStatusMonitor; SearchExtCats.Load(AddDirectory(CONFIGDIR, "epgsearchcats.conf"), true); LoadMenuTemplates(); LoadConfD(); LoadUserVars(); ChannelGroups.Load(AddDirectory(CONFIGDIR, "epgsearchchangrps.conf"), true); Blacklists.Load(AddDirectory(CONFIGDIR, "epgsearchblacklists.conf")); SearchExts.Load(AddDirectory(CONFIGDIR, "epgsearch.conf")); SearchTemplates.Load(AddDirectory(CONFIGDIR, "epgsearchtemplates.conf")); RecsDone.Load(AddDirectory(CONFIGDIR, "epgsearchdone.data")); SwitchTimers.Load(AddDirectory(CONFIGDIR, "epgsearchswitchtimers.conf")); NoAnnounces.Load(AddDirectory(CONFIGDIR, "noannounce.conf")); DefTimerCheckModes.Load(AddDirectory(CONFIGDIR, "deftimerchkmodes.conf")); TimersDone.Load(AddDirectory(CONFIGDIR, "timersdone.conf")); PendingNotifications.Load(AddDirectory(CONFIGDIR, "pendingnotifications.conf")); cSearchTimerThread::Init(this); cSwitchTimerThread::Init(); cConflictCheckThread::Init(this); CheckUTF8(); return true; } void cPluginEpgsearch::CheckUTF8() { std::string CodeSet = GetCodeset(); isUTF8 = EqualsNoCase(CodeSet, "UTF-8"); } void cPluginEpgsearch::Stop(void) { cSearchTimerThread::Exit(); cSwitchTimerThread::Exit(); } void cPluginEpgsearch::MainThreadHook(void) { if (!VDR_readyafterStartup) { // signal VDR is ready, otherwise the search timer thread could use SVDRP before it works LogFile.Log(2, "VDR ready"); VDR_readyafterStartup = true; } } cOsdObject *cPluginEpgsearch::DoInitialSearch(char* rcFilename) { cRCFile rcFile; if (rcFile.Load(rcFilename)) { cSearchExt* SearchExt = new cSearchExt; strn0cpy(SearchExt->search,rcFile.Search, sizeof(SearchExt->search)); if (rcFile.ChannelNr != -1) { LOCK_CHANNELS_READ; SearchExt->useChannel = true; SearchExt->channelMin = Channels->GetByNumber(rcFile.ChannelNr); SearchExt->channelMax = Channels->GetByNumber(rcFile.ChannelNr); } SearchExt->mode = rcFile.SearchMode; SearchExt->useTitle = rcFile.UseTitle; SearchExt->useSubtitle = rcFile.UseSubtitle; SearchExt->useDescription = rcFile.UseDescr; remove(rcFilename); return new cMenuSearchResultsForSearch(SearchExt, cTemplFile::GetTemplateByName("MenuSearchResults")); } else LogFile.eSysLog("could not load '%s'", rcFilename); return NULL; } cOsdObject *cPluginEpgsearch::MainMenuAction(void) { if (reloadMenuConf) LoadMenuTemplates(); if (showConflicts) { showConflicts = false; return new cMenuConflictCheck(); } if (showAnnounces) { showAnnounces = false; return new cMenuAnnounceList(cSearchTimerThread::announceList); } // Perform the action when selected from the main VDR menu. cOsdObject* pMenu = NULL; char* rcFilename = strdup(AddDirectory(CONFIGDIR, ".epgsearchrc")); if (access(rcFilename, F_OK) == 0) pMenu = DoInitialSearch(rcFilename); else pMenu = new cMenuSearchMain(); free(rcFilename); return pMenu; } void cPluginEpgsearch::LoadMenuTemplates() { char* templateFilename = strdup(AddDirectory(CONFIGDIR, "epgsearchmenu.conf")); if (access(templateFilename, F_OK) == 0) { cTemplFile templFile; if (!templFile.Load(templateFilename)) { templFile.Reset(); LogFile.eSysLog("could not load '%s'", templateFilename); } } cTemplFile::PrepareDefaultTemplates(); free(templateFilename); } void cPluginEpgsearch::LoadUserVars() { char* userVarFilename = strdup(AddDirectory(CONFIGDIR, "epgsearchuservars.conf")); if (access(userVarFilename, F_OK) == 0) { LogFile.Log(1, "loading %s", userVarFilename); cUserVarFile userVarFile; if (!userVarFile.Load(userVarFilename)) LogFile.eSysLog("could not load '%s'", userVarFilename); else LogFile.Log(2,"loaded uservars from %s", userVarFilename); } free(userVarFilename); UserVars.InitInternalVars(); UserVars.InitExtEPGVars(); } void cPluginEpgsearch::LoadConfD() { cConfDLoader D; D.Load(); } cMenuSetupPage *cPluginEpgsearch::SetupMenu(void) { // Return a setup menu in case the plugin supports one. return new cMenuEPGSearchSetup; } bool cPluginEpgsearch::SetupParse(const char *Name, const char *Value) { if (!strcasecmp(Name, "IsOrgSchedule")) return (EPGSearchConfig.ReplaceOrgSchedule == false); if (!strcasecmp(Name, "HideMenu")) EPGSearchConfig.hidemenu = atoi(Value); if (!strcasecmp(Name, "MainMenuEntry")) strcpy(EPGSearchConfig.mainmenuentry, Value); if (!strcasecmp(Name, "ReplaceOrgSchedule")) EPGSearchConfig.ReplaceOrgSchedule = atoi(Value); if (!strcasecmp(Name, "StartMenu")) EPGSearchConfig.StartMenu = atoi(Value); if (!strcasecmp(Name, "RedKeyMode")) EPGSearchConfig.redkeymode = atoi(Value); if (!strcasecmp(Name, "BlueKeyMode")) EPGSearchConfig.bluekeymode = atoi(Value); if (!strcasecmp(Name, "ShowProgress")) EPGSearchConfig.showProgress = atoi(Value); if (!strcasecmp(Name, "ShowChannelNr")) EPGSearchConfig.showChannelNr = atoi(Value); if (!strcasecmp(Name, "UseOkForSwitch")) EPGSearchConfig.useOkForSwitch = atoi(Value); if (!strcasecmp(Name, "MaxChannelMenuNow")) EPGSearchConfig.maxChannelMenuNow = atoi(Value); if (!strcasecmp(Name, "ShowRadioChannels")) EPGSearchConfig.showRadioChannels = atoi(Value); if (!strcasecmp(Name, "OnePressTimerCreation")) EPGSearchConfig.onePressTimerCreation = atoi(Value); if (!strcasecmp(Name, "ShowFavoritesMenu")) EPGSearchConfig.showFavoritesMenu = atoi(Value); if (!strcasecmp(Name, "FavoritesMenuTimespan")) EPGSearchConfig.FavoritesMenuTimespan = atoi(Value); if (!strcasecmp(Name, "UserMode1Description")) EPGSearchConfig.ShowModes[showUserMode1].SetDescription(Value); if (!strcasecmp(Name, "UserMode1Time")) EPGSearchConfig.ShowModes[showUserMode1].SetTime(atoi(Value)); if (!strcasecmp(Name, "UserMode1UseIt")) EPGSearchConfig.ShowModes[showUserMode1].SetUsage(atoi(Value)); if (!strcasecmp(Name, "UserMode2Description")) EPGSearchConfig.ShowModes[showUserMode2].SetDescription(Value); if (!strcasecmp(Name, "UserMode2Time")) EPGSearchConfig.ShowModes[showUserMode2].SetTime(atoi(Value)); if (!strcasecmp(Name, "UserMode2UseIt")) EPGSearchConfig.ShowModes[showUserMode2].SetUsage(atoi(Value)); if (!strcasecmp(Name, "UserMode3Description")) EPGSearchConfig.ShowModes[showUserMode3].SetDescription(Value); if (!strcasecmp(Name, "UserMode3Time")) EPGSearchConfig.ShowModes[showUserMode3].SetTime(atoi(Value)); if (!strcasecmp(Name, "UserMode3UseIt")) EPGSearchConfig.ShowModes[showUserMode3].SetUsage(atoi(Value)); if (!strcasecmp(Name, "UserMode4Description")) EPGSearchConfig.ShowModes[showUserMode4].SetDescription(Value); if (!strcasecmp(Name, "UserMode4Time")) EPGSearchConfig.ShowModes[showUserMode4].SetTime(atoi(Value)); if (!strcasecmp(Name, "UserMode4UseIt")) EPGSearchConfig.ShowModes[showUserMode4].SetUsage(atoi(Value)); if (!strcasecmp(Name, "UseSearchTimers")) EPGSearchConfig.useSearchTimers = atoi(Value); if (!strcasecmp(Name, "UpdateIntervall")) EPGSearchConfig.UpdateIntervall = atoi(Value); if (!strcasecmp(Name, "SVDRPPort")) EPGSearchConfig.SVDRPPort = atoi(Value); if (!strcasecmp(Name, "CheckTimerConflicts")) EPGSearchConfig.checkTimerConflictsAfterUpdate = atoi(Value); if (!strcasecmp(Name, "CheckTimerConflictsPriority")) EPGSearchConfig.checkMinPriority = atoi(Value); if (!strcasecmp(Name, "CheckTimerConflictsDays")) EPGSearchConfig.checkMaxDays = atoi(Value); if (!strcasecmp(Name, "RemoteConflictCheck")) EPGSearchConfig.RemoteConflictCheck = atoi(Value); if (!strcasecmp(Name, "CheckConflictsIntervall")) EPGSearchConfig.conflictCheckIntervall = atoi(Value); if (!strcasecmp(Name, "CheckConflictsWithinLimit")) EPGSearchConfig.conflictCheckWithinLimit = atoi(Value); if (!strcasecmp(Name, "CheckConflictsIntervall2")) EPGSearchConfig.conflictCheckIntervall2 = atoi(Value); if (!strcasecmp(Name, "CheckConflictsMinDuration")) EPGSearchConfig.checkMinDuration = atoi(Value); if (!strcasecmp(Name, "CheckConflictsAfterTimerProg")) EPGSearchConfig.checkTimerConflAfterTimerProg = atoi(Value); if (!strcasecmp(Name, "CheckConflictsOnRecording")) EPGSearchConfig.checkTimerConflOnRecording = atoi(Value); if (!strcasecmp(Name, "ConflCheckCmd")) strcpy(EPGSearchConfig.conflCheckCmd, Value); if (!strcasecmp(Name, "NoConflMsgWhileReplay")) EPGSearchConfig.noConflMsgWhileReplay = atoi(Value); if (!strcasecmp(Name, "NoAnnounceWhileReplay")) EPGSearchConfig.noAnnounceWhileReplay = atoi(Value); if (!strcasecmp(Name, "TimerProgRepeat")) EPGSearchConfig.TimerProgRepeat = atoi(Value); if (!strcasecmp(Name, "CheckEPGHours")) EPGSearchConfig.checkEPGHours = atoi(Value); if (!strcasecmp(Name, "CheckEPGWarnByOSD")) EPGSearchConfig.checkEPGWarnByOSD = atoi(Value); if (!strcasecmp(Name, "CheckEPGWarnByMail")) EPGSearchConfig.checkEPGWarnByMail = atoi(Value); if (!strcasecmp(Name, "CheckEPGChannelgroup")) EPGSearchConfig.checkEPGchannelGroupNr = atoi(Value); if (!strcasecmp(Name, "TimeIntervallFRFF")) EPGSearchConfig.timeShiftValue = atoi(Value); if (!strcasecmp(Name, "ToggleGreenYellow")) EPGSearchConfig.toggleGreenYellow = atoi(Value); if (!strcasecmp(Name, "DefPriority")) EPGSearchConfig.DefPriority = atoi(Value); if (!strcasecmp(Name, "DefLifetime")) EPGSearchConfig.DefLifetime = atoi(Value); if (!strcasecmp(Name, "DefMarginStart")) EPGSearchConfig.DefMarginStart = atoi(Value); if (!strcasecmp(Name, "DefMarginStop")) EPGSearchConfig.DefMarginStop = atoi(Value); if (!strcasecmp(Name, "IgnorePayTV")) EPGSearchConfig.ignorePayTV = atoi(Value); if (!strcasecmp(Name, "DefRecordingDir")) strcpy(EPGSearchConfig.defrecdir, Value); if (!strcasecmp(Name, "UseVDRTimerEditMenu")) EPGSearchConfig.useVDRTimerEditMenu = atoi(Value); if (!strcasecmp(Name, "ShowChannelGroups")) EPGSearchConfig.showChannelGroups = atoi(Value); if (!strcasecmp(Name, "ShowDaySeparators")) EPGSearchConfig.showDaySeparators = atoi(Value); if (!strcasecmp(Name, "ShowEmptyChannels")) EPGSearchConfig.showEmptyChannels = atoi(Value); if (!strcasecmp(Name, "DefSearchTemplateID")) EPGSearchConfig.DefSearchTemplateID = atoi(Value); if (!strcasecmp(Name, "AddSubtitleToTimerMode")) EPGSearchConfig.addSubtitleToTimer = (addSubtitleToTimerMode) atoi(Value); if (!strcasecmp(Name, "MailViaScript")) EPGSearchConfig.mailViaScript = atoi(Value); if (!strcasecmp(Name, "MailNotificationSearchtimers")) EPGSearchConfig.sendMailOnSearchtimers = atoi(Value); if (!strcasecmp(Name, "MailNotificationSearchtimersHours")) EPGSearchConfig.sendMailOnSearchtimerHours = atoi(Value); if (!strcasecmp(Name, "MailNotificationSearchtimersLastAt")) EPGSearchConfig.lastMailOnSearchtimerAt = atol(Value); if (!strcasecmp(Name, "MailNotificationConflicts")) EPGSearchConfig.sendMailOnConflicts = atoi(Value); if (!strcasecmp(Name, "MailAddress")) strcpy(EPGSearchConfig.MailAddress, Value); if (!strcasecmp(Name, "MailAddressTo")) strcpy(EPGSearchConfig.MailAddressTo, Value); if (isempty(EPGSearchConfig.MailAddressTo)) strcpy(EPGSearchConfig.MailAddressTo, EPGSearchConfig.MailAddress); if (!strcasecmp(Name, "MailServer")) strcpy(EPGSearchConfig.MailServer, Value); if (!strcasecmp(Name, "MailUseAuth")) EPGSearchConfig.MailUseAuth = atoi(Value); if (!strcasecmp(Name, "MailAuthUser")) strcpy(EPGSearchConfig.MailAuthUser, Value); if (!strcasecmp(Name, "MailAuthPass")) strcpy(EPGSearchConfig.MailAuthPass, Value); if (!strcasecmp(Name, "LastMailConflicts")) strcpy(EPGSearchConfig.LastMailConflicts, Value); return true; } cString cPluginEpgsearch::Active(void) { return cSearchTimerThread::justRunning?tr("search timer update running"):NULL; } VDRPLUGINCREATOR(cPluginEpgsearch); // Don't touch this! vdr-plugin-epgsearch/epgsearchext.c0000644000175000017500000015066413145412721017272 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #include #include "epgsearchext.h" #include "epgsearchcfg.h" #include "epgsearchcats.h" #include "epgsearchtools.h" #include #include "menu_searchresults.h" #include "menu_dirselect.h" #include "changrp.h" #include "menu_search.h" #include "menu_searchedit.h" #include "menu_recsdone.h" #include "searchtimer_thread.h" #include "timer_thread.h" #include "uservars.h" #include "blacklist.h" #include cSearchExts SearchExts; cSearchExts SearchTemplates; #ifndef MAX_SUBTITLE_LENGTH #define MAX_SUBTITLE_LENGTH 40 #endif // -- cSearchExt ----------------------------------------------------------------- char *cSearchExt::buffer = NULL; cSearchExt::cSearchExt(void) { ID = -1; *search = 0; options = 1; useTime = false; startTime = 0000; stopTime = 2359; useChannel = false; { LOCK_CHANNELS_READ; channelMin = Channels->GetByNumber(cDevice::CurrentChannel()); channelMax = Channels->GetByNumber(cDevice::CurrentChannel()); } channelGroup = NULL; useCase = false; mode = 0; useTitle = true; useSubtitle = true; useDescription = true; useDuration = false; minDuration = 0; maxDuration = 2359; useAsSearchTimer = false; useDayOfWeek = false; DayOfWeek = 0; buffer = NULL; *directory = 0; useEpisode = 0; Priority = EPGSearchConfig.DefPriority; Lifetime = EPGSearchConfig.DefLifetime; MarginStart = EPGSearchConfig.DefMarginStart; MarginStop = EPGSearchConfig.DefMarginStop; useVPS = false; action = searchTimerActionRecord; useExtEPGInfo = false; contentsFilter = ""; catvalues = (char**) malloc(SearchExtCats.Count() * sizeof(char*)); cSearchExtCat *SearchExtCat = SearchExtCats.First(); int index = 0; while (SearchExtCat) { catvalues[index] = (char*)malloc(MaxFileName); *catvalues[index] = 0; SearchExtCat = SearchExtCats.Next(SearchExtCat); index++; } avoidRepeats = 0; compareTitle = 1; compareSubtitle = 1; compareSummary = 1; compareSummaryMatchInPercent = 90; compareDate = 0; allowedRepeats = 0; catvaluesAvoidRepeat = 0; repeatsWithinDays = 0; delAfterDays = 0; recordingsKeep = 0; switchMinsBefore = 1; pauseOnNrRecordings = 0; blacklistMode = blacklistsOnlyGlobal; // no blacklists blacklists.Clear(); fuzzyTolerance = 1; useInFavorites = 0; menuTemplate = 0; delMode = 0; delAfterCountRecs = 0; delAfterDaysOfFirstRec = 0; useAsSearchTimerFrom = 0; useAsSearchTimerTil = 0; ignoreMissingEPGCats = 0; unmuteSoundOnSwitch = 0; skipRunningEvents = false; } cSearchExt::~cSearchExt(void) { if (buffer) { free(buffer); buffer = NULL; } if (catvalues) { cSearchExtCat *SearchExtCat = SearchExtCats.First(); int index = 0; while (SearchExtCat) { free(catvalues[index]); SearchExtCat = SearchExtCats.Next(SearchExtCat); index++; } free(catvalues); catvalues = NULL; } } cSearchExt& cSearchExt::operator= (const cSearchExt &SearchExt) { CopyFromTemplate(&SearchExt); ID = SearchExt.ID; strcpy(search, SearchExt.search); cSearchExtCat *SearchExtCat = SearchExtCats.First(); int index = 0; while (SearchExtCat) { *catvalues[index] = 0; strcpy(catvalues[index], SearchExt.catvalues[index]); SearchExtCat = SearchExtCats.Next(SearchExtCat); index++; } return *this; } void cSearchExt::CopyFromTemplate(const cSearchExt* templ, bool ignoreChannelSettings) { options = templ->options; useTime = templ->useTime; startTime = templ->startTime; stopTime = templ->stopTime; if (!ignoreChannelSettings) useChannel = templ->useChannel; useCase = templ->useCase; mode = templ->mode; useTitle = templ->useTitle; useSubtitle = templ->useSubtitle; useDescription = templ->useDescription; useDuration = templ->useDuration; minDuration = templ->minDuration; maxDuration = templ->maxDuration; useAsSearchTimer = templ->useAsSearchTimer; useDayOfWeek = templ->useDayOfWeek; DayOfWeek = templ->DayOfWeek; useEpisode = templ->useEpisode; strcpy(directory, templ->directory); Priority = templ->Priority; Lifetime = templ->Lifetime; MarginStart = templ->MarginStart; MarginStop = templ->MarginStop; useVPS = templ->useVPS; action = templ->action; useExtEPGInfo = templ->useExtEPGInfo; contentsFilter = templ->contentsFilter; switchMinsBefore = templ->switchMinsBefore; pauseOnNrRecordings = templ->pauseOnNrRecordings; cSearchExtCat *SearchExtCat = SearchExtCats.First(); int index = 0; while (SearchExtCat) { strcpy(catvalues[index], templ->catvalues[index]); SearchExtCat = SearchExtCats.Next(SearchExtCat); index++; } if (!ignoreChannelSettings) { channelMin = templ->channelMin; channelMax = templ->channelMax; if (channelGroup) { free(channelGroup); channelGroup = NULL; } if (templ->channelGroup) channelGroup = strdup(templ->channelGroup); } avoidRepeats = templ->avoidRepeats; compareTitle = templ->compareTitle; compareSubtitle = templ->compareSubtitle; compareSummary = templ->compareSummary; compareSummaryMatchInPercent = templ->compareSummaryMatchInPercent; compareDate = templ->compareDate; allowedRepeats = templ->allowedRepeats; catvaluesAvoidRepeat = templ->catvaluesAvoidRepeat; repeatsWithinDays = templ->repeatsWithinDays; delAfterDays = templ->delAfterDays; recordingsKeep = templ->recordingsKeep; blacklistMode = templ->blacklistMode; blacklists.Clear(); const cBlacklistObject* blacklistObj = templ->blacklists.First(); while(blacklistObj) { blacklists.Add(new cBlacklistObject(blacklistObj->blacklist)); blacklistObj = templ->blacklists.Next(blacklistObj); } fuzzyTolerance = templ->fuzzyTolerance; useInFavorites = templ->useInFavorites; menuTemplate = templ->menuTemplate; delMode = templ->delMode; delAfterCountRecs = templ->delAfterCountRecs; delAfterDaysOfFirstRec = templ->delAfterDaysOfFirstRec; useAsSearchTimerFrom = templ->useAsSearchTimerFrom; useAsSearchTimerTil = templ->useAsSearchTimerTil; ignoreMissingEPGCats = templ->ignoreMissingEPGCats; unmuteSoundOnSwitch = templ->unmuteSoundOnSwitch; } bool cSearchExt::operator< (const cListObject &ListObject) { cSearchExt *SE = (cSearchExt *)&ListObject; return strcasecmp(search, SE->search) < 0; } char* replaceSpecialChars(const char* in) { char* tmp_in = strdup(in); while(strstr(tmp_in, "|")) tmp_in = strreplace(tmp_in, "|", "!^pipe^!"); // ugly: replace a pipe with something, strreplace(tmp_in, ':', '|'); return tmp_in; } const char *cSearchExt::ToText() { char tmp_Start[5] = ""; char tmp_Stop[5] = ""; char tmp_minDuration[5] = ""; char tmp_maxDuration[5] = ""; cString tmp_chanSel; char* tmp_catvalues = NULL; char* tmp_blacklists = NULL; free(buffer); char* tmp_search = replaceSpecialChars(search); char* tmp_directory = replaceSpecialChars(directory); char* tmp_contentsFilter = replaceSpecialChars(contentsFilter.c_str()); if (useTime) { sprintf(tmp_Start, "%04d", startTime); sprintf(tmp_Stop, "%04d", stopTime); } if (useDuration) { sprintf(tmp_minDuration, "%04d", minDuration); sprintf(tmp_maxDuration, "%04d", maxDuration); } if (useChannel==1) { if (channelMin->Number() < channelMax->Number()) tmp_chanSel = cString::sprintf("%s|%s", CHANNELSTRING(channelMin), CHANNELSTRING(channelMax)); else tmp_chanSel = cString(CHANNELSTRING(channelMin)); } if (useChannel==2) { int channelGroupNr = ChannelGroups.GetIndex(channelGroup); if (channelGroupNr == -1) { LogFile.eSysLog("channel group '%s' does not exist!", channelGroup); useChannel = 0; } else tmp_chanSel = cString(channelGroup); } if (useExtEPGInfo) { cSearchExtCat *SearchExtCat = SearchExtCats.First(); int index = 0; while (SearchExtCat) { char* catvalue = NULL; if (msprintf(&catvalue, "%s", catvalues[index])==-1) break; while(strstr(catvalue, ":")) catvalue = strreplace(catvalue, ":", "!^colon^!"); // ugly: replace with something, that should not happen to be part ofa category value while(strstr(catvalue, "|")) catvalue = strreplace(catvalue, "|", "!^pipe^!"); // ugly: replace with something, that should not happen to be part of a regular expression if (index == 0) msprintf(&tmp_catvalues, "%d#%s", SearchExtCat->id, catvalue); else { char* temp = tmp_catvalues; msprintf(&tmp_catvalues, "%s|%d#%s", tmp_catvalues, SearchExtCat->id, catvalue); free(temp); } SearchExtCat = SearchExtCats.Next(SearchExtCat); index++; free(catvalue); } } if (blacklistMode == blacklistsSelection && blacklists.Count() > 0) { cBlacklistObject *blacklistObj = blacklists.First(); int index = 0; while (blacklistObj) { if (index == 0) msprintf(&tmp_blacklists, "%d", blacklistObj->blacklist->ID); else { char* temp = tmp_blacklists; msprintf(&tmp_blacklists, "%s|%d", tmp_blacklists, blacklistObj->blacklist->ID); free(temp); } blacklistObj = blacklists.Next(blacklistObj); index++; } } msprintf(&buffer, "%d:%s:%d:%s:%s:%d:%s:%d:%d:%d:%d:%d:%d:%s:%s:%d:%d:%d:%d:%s:%d:%d:%d:%d:%d:%d:%d:%s:%d:%d:%d:%d:%d:%ld:%d:%d:%d:%d:%d:%d:%s:%d:%d:%d:%d:%d:%d:%ld:%ld:%d:%d:%d:%s:%d", ID, tmp_search, useTime, tmp_Start, tmp_Stop, useChannel, (useChannel>0 && useChannel<3)?*tmp_chanSel:"0", useCase, mode, useTitle, useSubtitle, useDescription, useDuration, tmp_minDuration, tmp_maxDuration, useAsSearchTimer, useDayOfWeek, DayOfWeek, useEpisode, tmp_directory, Priority, Lifetime, MarginStart, MarginStop, useVPS, action, useExtEPGInfo, useExtEPGInfo?tmp_catvalues:"", avoidRepeats, allowedRepeats, compareTitle, compareSubtitle, compareSummary, catvaluesAvoidRepeat, repeatsWithinDays, delAfterDays, recordingsKeep, switchMinsBefore, pauseOnNrRecordings, blacklistMode, blacklists.Count()>0?tmp_blacklists:"", fuzzyTolerance, useInFavorites, menuTemplate, delMode, delAfterCountRecs, delAfterDaysOfFirstRec, useAsSearchTimerFrom, useAsSearchTimerTil, ignoreMissingEPGCats, unmuteSoundOnSwitch, compareSummaryMatchInPercent, contentsFilter.c_str(), compareDate); if (tmp_search) free(tmp_search); if (tmp_directory) free(tmp_directory); if (tmp_catvalues) free(tmp_catvalues); if (tmp_blacklists) free(tmp_blacklists); if (tmp_contentsFilter) free(tmp_contentsFilter); return buffer; } bool cSearchExt::Parse(const char *s) { char *line; char *pos; char *pos_next; int parameter = 1; int valuelen; char value[MaxFileName]; bool disableSearchtimer = false; *directory = 0; *search = 0; pos = line = strdup(s); pos_next = pos + strlen(pos); if (*pos_next == '\n') *pos_next = 0; while (*pos) { while (*pos == ' ') pos++; if (*pos) { if (*pos != ':') { pos_next = strchr(pos, ':'); if (!pos_next) pos_next = pos + strlen(pos); valuelen = pos_next - pos + 1; if (valuelen > MaxFileName) valuelen = MaxFileName; strn0cpy(value, pos, valuelen); pos = pos_next; switch (parameter) { case 1: if (!isnumber(value)) return false; ID = atoi(value); break; case 2: strcpy(search, value); break; case 3: useTime = atoi(value); break; case 4: startTime = atoi(value); break; case 5: stopTime = atoi(value); break; case 6: useChannel = atoi(value); break; case 7: if (useChannel == 0) { channelMin = NULL; channelMax = NULL; } else if (useChannel == 1) { int minNum=0, maxNum=0; int fields = sscanf(value, "%d-%d", &minNum, &maxNum); if (fields == 0) // stored with ID { #ifdef __FreeBSD__ char *channelMinbuffer = MALLOC(char, 32); char *channelMaxbuffer = MALLOC(char, 32); int channels = sscanf(value, "%31[^|]|%31[^|]", channelMinbuffer, channelMaxbuffer); #else char *channelMinbuffer = NULL; char *channelMaxbuffer = NULL; int channels = sscanf(value, "%m[^|]|%m[^|]", &channelMinbuffer, &channelMaxbuffer); #endif LOCK_CHANNELS_READ; channelMin = Channels->GetByChannelID(tChannelID::FromString(channelMinbuffer), true, true); if (!channelMin) { LogFile.eSysLog("ERROR: channel '%s' not defined", channelMinbuffer); channelMin = channelMax = NULL; disableSearchtimer = true; useChannel = 0; } if (channels == 1) channelMax = channelMin; else { channelMax = Channels->GetByChannelID(tChannelID::FromString(channelMaxbuffer), true, true); if (!channelMax) { LogFile.eSysLog("ERROR: channel '%s' not defined", channelMaxbuffer); channelMin = channelMax = NULL; disableSearchtimer = true; useChannel = 0; } } free(channelMinbuffer); free(channelMaxbuffer); } } else if (useChannel == 2) channelGroup = strdup(value); break; case 8: useCase = atoi(value); break; case 9: mode = atoi(value); break; case 10: useTitle = atoi(value); break; case 11: useSubtitle = atoi(value); break; case 12: useDescription = atoi(value); break; case 13: useDuration = atoi(value); break; case 14: minDuration = atoi(value); break; case 15: maxDuration = atoi(value); break; case 16: useAsSearchTimer = atoi(value); break; case 17: useDayOfWeek = atoi(value); break; case 18: DayOfWeek = atoi(value); break; case 19: useEpisode = atoi(value); break; case 20: strcpy(directory, value); break; case 21: Priority = atoi(value); break; case 22: Lifetime = atoi(value); break; case 23: MarginStart = atoi(value); break; case 24: MarginStop = atoi(value); break; case 25: useVPS = atoi(value); break; case 26: action = atoi(value); break; case 27: useExtEPGInfo = atoi(value); break; case 28: if (!ParseExtEPGValues(value)) { LogFile.eSysLog("ERROR reading ext. EPG values - 1"); free(line); return false; } break; case 29: avoidRepeats = atoi(value); break; case 30: allowedRepeats = atoi(value); break; case 31: compareTitle = atoi(value); break; case 32: compareSubtitle = atoi(value)>0?1:0; break; case 33: compareSummary = atoi(value); break; case 34: catvaluesAvoidRepeat = atol(value); break; case 35: repeatsWithinDays = atoi(value); break; case 36: delAfterDays = atoi(value); break; case 37: recordingsKeep = atoi(value); break; case 38: switchMinsBefore = atoi(value); break; case 39: pauseOnNrRecordings = atoi(value); break; case 40: blacklistMode = atoi(value); break; case 41: if (blacklistMode == blacklistsSelection && !ParseBlacklistIDs(value)) { LogFile.eSysLog("ERROR parsing blacklist IDs"); free(line); return false; } break; case 42: fuzzyTolerance = atoi(value); break; case 43: useInFavorites = atoi(value); break; case 44: menuTemplate = atoi(value); break; case 45: delMode = atoi(value); break; case 46: delAfterCountRecs = atoi(value); break; case 47: delAfterDaysOfFirstRec = atoi(value); break; case 48: useAsSearchTimerFrom = atol(value); break; case 49: useAsSearchTimerTil = atol(value); break; case 50: ignoreMissingEPGCats = atoi(value); break; case 51: unmuteSoundOnSwitch = atoi(value); break; case 52: compareSummaryMatchInPercent = atoi(value); break; case 53: contentsFilter = value; break; case 54: compareDate = atoi(value); break; default: break; } //switch } parameter++; } if (*pos) pos++; } //while strreplace(directory, '|', ':'); strreplace(search, '|', ':'); strreplace(contentsFilter, "|", ":"); while(strstr(search, "!^pipe^!")) strreplace(search, "!^pipe^!", "|"); while(strstr(directory, "!^pipe^!")) strreplace(directory, "!^pipe^!", "|"); strreplace(contentsFilter, "!^pipe^!", "|"); if (disableSearchtimer && useAsSearchTimer) { useAsSearchTimer = false; LogFile.Log(1, "search timer '%s' disabled", search); } free(line); return (parameter >= 11) ? true : false; } char* cSearchExt::BuildFile(const cEvent* pEvent) const { char* file = NULL; if (!pEvent) return file; const char *Subtitle = pEvent ? pEvent->ShortText() : NULL; char SubtitleBuffer[Utf8BufSize(MAX_SUBTITLE_LENGTH)]; if (isempty(Subtitle)) { time_t Start = pEvent->StartTime(); struct tm tm_r; strftime(SubtitleBuffer, sizeof(SubtitleBuffer), "%Y.%m.%d-%R-%a", localtime_r(&Start, &tm_r)); Subtitle = SubtitleBuffer; } else if (Utf8StrLen(Subtitle) > MAX_SUBTITLE_LENGTH) { Utf8Strn0Cpy(SubtitleBuffer, Subtitle, sizeof(SubtitleBuffer)); SubtitleBuffer[Utf8SymChars(SubtitleBuffer, MAX_SUBTITLE_LENGTH)] = 0; Subtitle = SubtitleBuffer; } if (useEpisode) { cString pFile = cString::sprintf("%s~%s", pEvent->Title(), Subtitle); if (file) free(file); file = strdup(pFile); } else if (pEvent->Title()) file = strdup(pEvent->Title()); if (!isempty(directory)) { char* pFile = NULL; cVarExpr varExprDir(directory); if (!varExprDir.DependsOnVar("%title%", pEvent) && !varExprDir.DependsOnVar("%subtitle%", pEvent)) msprintf(&pFile, "%s~%s", directory, file?file:""); else // ignore existing title and subtitle in file if already used as variables in directory msprintf(&pFile, "%s", directory); // parse the epxression and evaluate it cVarExpr varExprFile(pFile); if (pFile) free(pFile); pFile = strdup(varExprFile.Evaluate(pEvent).c_str()); cVarExpr varExprSearchFile(pFile); if (pFile) free(pFile); pFile = strdup(varExprSearchFile.Evaluate(this).c_str()); if (file) free(file); file = strdup(pFile); free(pFile); } // replace some special chars if (file) { while(strstr(file, "|")) file = strreplace(file, "|", "!^pipe^!"); while(strstr(file, ":")) file = strreplace(file, ':', '|'); while(strstr(file, " ~")) file = strreplace(file, " ~", "~"); while(strstr(file, "~ ")) file = strreplace(file, "~ ", "~"); } return file; } bool cSearchExt::ParseBlacklistIDs(const char *s) { char *line; char *pos; char *pos_next; int valuelen; char value[MaxFileName]; cMutexLock BlacklistLock(&Blacklists); blacklists.Clear(); pos = line = strdup(s); pos_next = pos + strlen(pos); if (*pos_next == '\n') *pos_next = 0; while (*pos) { while (*pos == ' ') pos++; if (*pos) { if (*pos != '|') { pos_next = strchr(pos, '|'); if (!pos_next) pos_next = pos + strlen(pos); valuelen = pos_next - pos + 1; if (valuelen > MaxFileName) valuelen = MaxFileName; strn0cpy(value, pos, valuelen); pos = pos_next; cBlacklist* blacklist = Blacklists.GetBlacklistFromID(atoi(value)); if (!blacklist) LogFile.eSysLog("blacklist ID %s missing, will be skipped", value); else blacklists.Add(new cBlacklistObject(blacklist)); } } if (*pos) pos++; } //while free(line); return true; } bool cSearchExt::ParseExtEPGValues(const char *s) { char *line; char *pos; char *pos_next; int valuelen; char value[MaxFileName]; pos = line = strdup(s); pos_next = pos + strlen(pos); if (*pos_next == '\n') *pos_next = 0; while (*pos) { while (*pos == ' ') pos++; if (*pos) { if (*pos != '|') { pos_next = strchr(pos, '|'); if (!pos_next) pos_next = pos + strlen(pos); valuelen = pos_next - pos + 1; if (valuelen > MaxFileName) valuelen = MaxFileName; strn0cpy(value, pos, valuelen); pos = pos_next; if (!ParseExtEPGEntry(value)) { LogFile.eSysLog("ERROR reading ext. EPG value: %s", value); free(line); return false; } } } if (*pos) pos++; } //while free(line); return true; } bool cSearchExt::ParseExtEPGEntry(const char *s) { char *line; char *pos; char *pos_next; int parameter = 1; int valuelen; char value[MaxFileName]; int currentid = -1; pos = line = strdup(s); pos_next = pos + strlen(pos); if (*pos_next == '\n') *pos_next = 0; while (*pos) { while (*pos == ' ') pos++; if (*pos) { if (*pos != '#') { pos_next = strchr(pos, '#'); if (!pos_next) pos_next = pos + strlen(pos); valuelen = pos_next - pos + 1; if (valuelen > MaxFileName) valuelen = MaxFileName; strn0cpy(value, pos, valuelen); pos = pos_next; switch (parameter) { case 1: { currentid = atoi(value); int index = SearchExtCats.GetIndexFromID(currentid); if (index > -1 && index < SearchExtCats.Count()) strcpy(catvalues[index], ""); } break; case 2: if (currentid > -1) { int index = SearchExtCats.GetIndexFromID(currentid); if (index > -1 && index < SearchExtCats.Count()) { while(strstr(value, "!^colon^!")) strreplace(value, "!^colon^!", ":"); while(strstr(value, "!^pipe^!")) strreplace(value, "!^pipe^!", "|"); strcpy(catvalues[index], value); } } break; default: break; } //switch } parameter++; } if (*pos) pos++; } //while free(line); return (parameter >= 2) ? true : false; } bool cSearchExt::Save(FILE *f) { return fprintf(f, "%s\n", ToText()) > 0; } const cEvent * cSearchExt::GetEventBySearchExt(const cSchedule *schedules, const cEvent *Start, bool inspectTimerMargin) { if (!schedules) return NULL; const cEvent *pe = NULL; const cEvent *p1 = NULL; const cList* Events = schedules->Events(); if (Start) p1 = Events->Next(Start); else p1 = Events->First(); time_t tNow=time(NULL); char* searchText = strdup(search); int searchStart = 0, searchStop = 0; if (useTime) { searchStart = startTime; searchStop = stopTime; if (searchStop < searchStart) searchStop += 2400; } int minSearchDuration = 0; int maxSearchDuration = 0; if (useDuration) { minSearchDuration = minDuration/100*60 + minDuration%100; maxSearchDuration = maxDuration/100*60 + maxDuration%100; } if (!useCase) ToLower(searchText); for (const cEvent *p = p1; p; p = Events->Next(p)) { if(!p) { break; } if (skipRunningEvents && tNow > p->StartTime()) continue; // ignore events without title if (!p->Title() || !*p->Title()) continue; if (tNow < p->EndTime() + (inspectTimerMargin?(MarginStop * 60):0)) { if (useTime) { time_t tEvent = p->StartTime(); struct tm tmEvent; localtime_r(&tEvent, &tmEvent); int eventStart = tmEvent.tm_hour*100 + tmEvent.tm_min; int eventStart2 = eventStart + 2400; if ((eventStart < searchStart || eventStart > searchStop) && (eventStart2 < searchStart || eventStart2 > searchStop)) continue; if (useDayOfWeek) { if (DayOfWeek >= 0) { if (( DayOfWeek != tmEvent.tm_wday || (DayOfWeek == tmEvent.tm_wday && eventStart < searchStart)) && (!((DayOfWeek+1)%7 == tmEvent.tm_wday && eventStart2 < searchStop))) continue; } else { int iFound = 0; for(int i=0; i<7; i++) { if ((abs(DayOfWeek) & (int)pow(2,i)) && ((i == tmEvent.tm_wday && eventStart >= searchStart) || ((i+1)%7 == tmEvent.tm_wday && eventStart2 < searchStop))) { iFound = 1; break; } } if (!iFound) continue; } } } if (useDuration) { int duration = p->Duration()/60; if (minSearchDuration > duration || maxSearchDuration < duration) continue; } if (!useTime && useDayOfWeek) { time_t tEvent = p->StartTime(); struct tm tmEvent; localtime_r(&tEvent, &tmEvent); if (DayOfWeek >= 0 && DayOfWeek != tmEvent.tm_wday) continue; if (DayOfWeek < 0) { int iFound = 0; for(int i=0; i<7; i++) if (abs(DayOfWeek) & (int)pow(2,i) && i == tmEvent.tm_wday) { iFound = 1; break; } if (!iFound) continue; } } char* szTest = NULL; msprintf(&szTest, "%s%s%s%s%s", (useTitle?(p->Title()?p->Title():""):""), (useSubtitle||useDescription)?"~":"", (useSubtitle?(p->ShortText()?p->ShortText():""):""),useDescription?"~":"", (useDescription?(p->Description()?p->Description():""):"")); if (!useCase) ToLower(szTest); if (szTest && *szTest) { if (!MatchesSearchMode(szTest, searchText, mode," ,;|~", fuzzyTolerance)) { free(szTest); continue; } } if (szTest) free(szTest); if (contentsFilter.size() > 0 && !MatchesContentsFilter(p)) continue; if (useExtEPGInfo && !MatchesExtEPGInfo(p)) continue; pe=p; break; } } free(searchText); return pe; } // returns a pointer array to the matching search results cSearchResults* cSearchExt::Run(int PayTVMode, bool inspectTimerMargin, int evalLimitMins, cSearchResults* pPrevResults, bool suppressRepeatCheck) { LogFile.Log(3,"start search for search timer '%s'", search); bool noPayTV = false; if (PayTVMode == -1) // use search's setting noPayTV = (useChannel == 3); else noPayTV = (PayTVMode == 1); time_t tNow=time(NULL); cSearchResults* pSearchResults = pPrevResults; cSearchResults* pBlacklistResults = GetBlacklistEvents(inspectTimerMargin?MarginStop:0); { LOCK_CHANNELS_READ; LOCK_SCHEDULES_READ; int counter = 0; const cSchedule *Schedule = Schedules->First(); while (Schedule) { const cChannel* channel = Channels->GetByChannelID(Schedule->ChannelID(),true,true); if (!channel) { Schedule = (const cSchedule *)Schedules->Next(Schedule); continue; } if (useChannel == 1 && channelMin && channelMax) { if (channelMin->Number() > channel->Number() || channelMax->Number() < channel->Number()) { Schedule = (const cSchedule *)Schedules->Next(Schedule); continue; } } if (useChannel == 2 && channelGroup) { cChannelGroup* group = ChannelGroups.GetGroupByName(channelGroup); if (!group || !group->ChannelInGroup(channel)) { Schedule = (const cSchedule *)Schedules->Next(Schedule); continue; } } if (useChannel == 3 && noPayTV) { if (channel->Ca() >= CA_ENCRYPTED_MIN) { Schedule = (const cSchedule *)Schedules->Next(Schedule); continue; } } if (noPayTV) // no paytv { if (channel->Ca() >= CA_ENCRYPTED_MIN) { Schedule = (const cSchedule *)Schedules->Next(Schedule); continue; } } const cEvent *pPrevEvent = NULL; do { const cEvent* event = GetEventBySearchExt(Schedule, pPrevEvent,inspectTimerMargin); pPrevEvent = event; if (evalLimitMins && event) // limit evaluation to now + limit { if (tNow + evalLimitMins*60 <= event->EndTime()) break; } if (event && Channels->GetByChannelID(event->ChannelID(),true,true)) { if (pBlacklistResults && pBlacklistResults->Lookup(event)) { LogFile.Log(3,"skip '%s~%s' (%s - %s, channel %d): matches blacklist", event->Title()?event->Title():"no title", event->ShortText()?event->ShortText():"no subtitle", GETDATESTRING(event), GETTIMESTRING(event), ChannelNrFromEvent(event)); continue; } if (!pSearchResults) pSearchResults = new cSearchResults; pSearchResults->Add(new cSearchResult(event, this)); counter++; } } while(pPrevEvent); Schedule = (const cSchedule *)Schedules->Next(Schedule); } LogFile.Log(3,"found %d event(s) for search timer '%s'", counter, search); } // Give up locks if (pBlacklistResults) delete pBlacklistResults; if (useAsSearchTimer && avoidRepeats && pSearchResults && !suppressRepeatCheck) { pSearchResults->SortBy(CompareEventTime); // sort before checking repeats to make sure the first event is selected CheckRepeatTimers(pSearchResults); } skipRunningEvents = false; return pSearchResults; } cSearchResults* cSearchExt::GetBlacklistEvents(int MarginStop) { if (blacklistMode == blacklistsNone) return NULL; cMutexLock BlacklistLock(&Blacklists); cSearchResults* blacklistEvents = NULL; if (blacklistMode == blacklistsOnlyGlobal) { cBlacklist* tmpblacklist = Blacklists.First(); while(tmpblacklist) { if (tmpblacklist->isGlobal) blacklistEvents = tmpblacklist->Run(blacklistEvents, MarginStop); tmpblacklist = Blacklists.Next(tmpblacklist); } } if (blacklistMode == blacklistsAll) { cBlacklist* tmpblacklist = Blacklists.First(); while(tmpblacklist) { blacklistEvents = tmpblacklist->Run(blacklistEvents, MarginStop); tmpblacklist = Blacklists.Next(tmpblacklist); } } if (blacklistMode == blacklistsSelection) { cBlacklistObject* tmpblacklistObj = blacklists.First(); while(tmpblacklistObj) { blacklistEvents = tmpblacklistObj->blacklist->Run(blacklistEvents, MarginStop); tmpblacklistObj = blacklists.Next(tmpblacklistObj); } } return blacklistEvents; } void cSearchExt::CheckRepeatTimers(cSearchResults* pResults) { if (!pResults) return; if (avoidRepeats == 0) return; LogFile.Log(2,"analysing repeats for search timer '%s'...", search); if ((action != searchTimerActionRecord) && (action != searchTimerActionInactiveRecord)) { LogFile.Log(3,"search timer not set to 'record', so skip all"); return; } cSearchResult* pResultObj = NULL; for (pResultObj = pResults->First(); pResultObj; pResultObj = pResults->Next(pResultObj)) { if ((action != searchTimerActionRecord) && (action != searchTimerActionInactiveRecord)) // only announce if there is no timer for the event { pResultObj->needsTimer = false; continue; } const cEvent* pEvent = pResultObj->event; // check if this event was already recorded int records = 0; cRecDone* firstRec = NULL; LogFile.Log(3,"get count recordings with %d%% match", compareSummaryMatchInPercent); records = RecsDone.GetCountRecordings(pEvent, this, &firstRec, compareSummaryMatchInPercent); LogFile.Log(3,"recordings: %d", records); if (records > allowedRepeats) // already recorded { LogFile.Log(3,"skip '%s~%s' (%s - %s, channel %d): already recorded %d equal event(s)", pEvent->Title()?pEvent->Title():"no title", pEvent->ShortText()?pEvent->ShortText():"no subtitle", GETDATESTRING(pEvent), GETTIMESTRING(pEvent), ChannelNrFromEvent(pEvent), records); pResultObj->needsTimer = false; // first assume we need no timer continue; } int plannedTimers = 0; LogFile.Log(3,"get planned recordings"); cSearchResult* pFirstResultMatching = NULL; // check other results, if they are already planned for equal events for (cSearchResult* pResultObjP = pResults->First(); pResultObjP; pResultObjP = pResults->Next(pResultObjP)) { if (pResultObj == pResultObjP) break; const cEvent* pEventP = pResultObjP->event; if (!pEventP) continue; if (!pResultObjP->needsTimer) continue; if (EventsMatch(pEvent, pEventP, compareTitle, compareSubtitle, compareSummary, compareDate, catvaluesAvoidRepeat, compareSummaryMatchInPercent)) { if (!pFirstResultMatching) pFirstResultMatching = pResultObjP; plannedTimers++; } } LogFile.Log(3,"planned: %d", plannedTimers); if (plannedTimers + records > allowedRepeats) { LogFile.Log(3,"skip '%s~%s' (%s - %s, channel %d): events planned(%d), recorded(%d), allowed(%d)", pEvent->Title()?pEvent->Title():"no title", pEvent->ShortText()?pEvent->ShortText():"no subtitle", GETDATESTRING(pEvent), GETTIMESTRING(pEvent), ChannelNrFromEvent(pEvent), plannedTimers, records, allowedRepeats); pResultObj->needsTimer = false; continue; } else if (allowedRepeats > 0 && repeatsWithinDays > 0) // if we only allow repeats with in a given range { if (firstRec) // already recorded, check for allowed repeat within days { if (firstRec->startTime > pEvent->StartTime() - pEvent->Duration()) // no repeat { LogFile.Log(3,"skip '%s~%s' (%s - %s, channel %d); no repeat for event already recorded at %s, channel %d", pEvent->Title()?pEvent->Title():"no title", pEvent->ShortText()?pEvent->ShortText():"no subtitle", GETDATESTRING(pEvent), GETTIMESTRING(pEvent), ChannelNrFromEvent(pEvent), DAYDATETIME(firstRec->startTime), firstRec->ChannelNr()); pResultObj->needsTimer = false; continue; } int daysFromFirstRec = int(double((pEvent->StartTime() - firstRec->startTime)) / (60*60*24) + 0.5); if (daysFromFirstRec > repeatsWithinDays) { LogFile.Log(3,"skip '%s~%s' (%s - %s, channel %d); first recording at %s is %d days before, limit is %d days", pEvent->Title()?pEvent->Title():"no title", pEvent->ShortText()?pEvent->ShortText():"no subtitle", GETDATESTRING(pEvent), GETTIMESTRING(pEvent), ChannelNrFromEvent(pEvent), DAYDATETIME(firstRec->startTime),daysFromFirstRec, repeatsWithinDays); pResultObj->needsTimer = false; continue; } } if (plannedTimers > 0 && pFirstResultMatching) { const cEvent* pFirst = pFirstResultMatching->event; if (pFirst->StartTime() > pEvent->StartTime() - pEvent->Duration()) // no repeat { LogFile.Log(3,"skip '%s~%s' (%s - %s, channel %d); no repeat for event already recorded at %s - %s, channel %d", pEvent->Title()?pEvent->Title():"no title", pEvent->ShortText()?pEvent->ShortText():"no subtitle", GETDATESTRING(pEvent), GETTIMESTRING(pEvent), ChannelNrFromEvent(pEvent), GETDATESTRING(pFirst), GETTIMESTRING(pFirst), ChannelNrFromEvent(pFirst)); pResultObj->needsTimer = false; continue; } int daysBetween = int(double((pEvent->StartTime() - pFirst->StartTime())) / (60*60*24) + 0.5); if (daysBetween > repeatsWithinDays) { LogFile.Log(3,"skip '%s~%s' (%s - %s, channel %d); first event '%s~%s' (%s - %s) is %d days before, limit is %d days", pEvent->Title()?pEvent->Title():"no title", pEvent->ShortText()?pEvent->ShortText():"no subtitle", GETDATESTRING(pEvent), GETTIMESTRING(pEvent), ChannelNrFromEvent(pEvent), GETDATESTRING(pFirst), GETTIMESTRING(pFirst),daysBetween, repeatsWithinDays); pResultObj->needsTimer = false; continue; } } } bool dummy; const cTimer* timer = cSearchTimerThread::GetTimer(this, pEvent, dummy); if (timer && !timer->HasFlags(tfActive)) { LogFile.Log(3,"skip '%s~%s' (%s - %s, channel %d), existing timer disabled", pEvent->Title()?pEvent->Title():"no title", pEvent->ShortText()?pEvent->ShortText():"no subtitle", GETDATESTRING(pEvent), GETTIMESTRING(pEvent), ChannelNrFromEvent(pEvent)); pResultObj->needsTimer = false; continue; } else LogFile.Log(3,"*** planning event '%s~%s' (%s - %s, channel %d) for recording", pEvent->Title()?pEvent->Title():"no title", pEvent->ShortText()?pEvent->ShortText():"no subtitle", GETDATESTRING(pEvent), GETTIMESTRING(pEvent), ChannelNrFromEvent(pEvent)); } int needsTimer = 0; for (pResultObj = pResults->First(); pResultObj; pResultObj = pResults->Next(pResultObj)) if (pResultObj->needsTimer) needsTimer++; LogFile.Log(2,"%d/%d events need a timer for search timer '%s'", needsTimer, pResults->Count(), search); } void cSearchExt::CheckExistingRecordings(cSearchResults* pResults) { if (!pResults) return; LogFile.Log(3,"analysing existing recordings for search timer '%s'...", search); // how many recordings do we already have? int num = GetCountRecordings(); cSearchResult* pResultObj = NULL; int remain = pauseOnNrRecordings - num; for (pResultObj = pResults->First(); pResultObj; pResultObj = pResults->Next(pResultObj), remain--) { if (!pResultObj->needsTimer) { remain++; continue; // maybe already disabled because of done feature } pResultObj->needsTimer = (remain > 0); if (remain <= 0) { const cEvent* pEvent = pResultObj->event; LogFile.Log(3,"skip '%s~%s' (%s - %s, channel %d): only %d recordings are allowed", pEvent->Title()?pEvent->Title():"no title", pEvent->ShortText()?pEvent->ShortText():"no subtitle", GETDATESTRING(pEvent), GETTIMESTRING(pEvent), ChannelNrFromEvent(pEvent), pauseOnNrRecordings); } } } bool cSearchExt::MatchesExtEPGInfo(const cEvent* e) { if (!e || !e->Description()) return false; cSearchExtCat* SearchExtCat = SearchExtCats.First(); while (SearchExtCat) { char* value = NULL; int index = SearchExtCats.GetIndexFromID(SearchExtCat->id); if (index > -1) value = catvalues[index]; if (value && SearchExtCat->searchmode >= 10 && atol(value) == 0) // numerical value != 0 ? value = NULL; if (value && *value) { char* testvalue = GetExtEPGValue(e, SearchExtCat); if (!testvalue) return (ignoreMissingEPGCats?true:false); // compare not case sensitive char* valueLower = strdup(value); ToLower(valueLower); ToLower(testvalue); if (!MatchesSearchMode(testvalue, valueLower, SearchExtCat->searchmode, ",;|~", fuzzyTolerance)) { free(testvalue); free(valueLower); return false; } free(testvalue); free(valueLower); } SearchExtCat = SearchExtCats.Next(SearchExtCat); } return true; } void cSearchExt::OnOffTimers(bool bOn) { LOCK_TIMERS_WRITE; for (cTimer *ti = Timers->First(); ti; ti = Timers->Next(ti)) { if (((!bOn && ti->HasFlags(tfActive)) || (bOn && !ti->HasFlags(tfActive))) && TriggeredFromSearchTimerID(ti) == ID) ti->OnOff(); } } void cSearchExt::DeleteAllTimers() { cList DelTimers; LOCK_TIMERS_WRITE; Timers->SetExplicitModify(); cTimer *ti = Timers->First(); while(ti) { if (!ti->Recording() && TriggeredFromSearchTimerID(ti) == ID) { cTimer* tiNext = Timers->Next(ti); LogFile.iSysLog("deleting timer %s", *ti->ToDescr()); Timers->Del(ti); Timers->SetModified(); ti = tiNext; } else ti = Timers->Next(ti); }; } cTimerObjList* cSearchExt::GetTimerList(cTimerObjList* timerList) { if (!timerList) timerList = new cTimerObjList; LOCK_TIMERS_READ; for (const cTimer *ti = Timers->First(); ti; ti = Timers->Next(ti)) { if (TriggeredFromSearchTimerID(ti) == ID) { // check if already in list bool found = false; for (cTimerObj *tObj = timerList->First(); tObj; tObj = timerList->Next(tObj)) { if (tObj->timer == ti) { found = true; break; } } if (!found) timerList->Add(new cTimerObj(ti)); } } return timerList; } // counts the currently existent recordings triggered by this search timer int cSearchExt::GetCountRecordings() { int countRecs = 0; LOCK_RECORDINGS_READ; for (const cRecording *recording = Recordings->First(); recording; recording = Recordings->Next(recording)) { if (recording->IsEdited()) continue; // ignore recordings edited if (!recording->Info()) continue; char* searchID = GetAuxValue(recording, "s-id"); if (!searchID) continue; if (ID == atoi(searchID)) countRecs++; free(searchID); } LogFile.Log(3, "found %d recordings for search '%s'", countRecs, search); return countRecs; } bool cSearchExt::IsActiveAt(time_t t) { if (useAsSearchTimer == 0) return false; if (useAsSearchTimer == 2) { if (useAsSearchTimerFrom > 0 && t < useAsSearchTimerFrom) return false; if (useAsSearchTimerTil > 0 && t > useAsSearchTimerTil) return false; } return true; } bool cSearchExt::HasContent(int contentID) { for(unsigned int i=0; i>std::noshowbase>>std::hex>>tmpContentID)) return false; if (contentID == tmpContentID) return true; } return false; } void cSearchExt::SetContentFilter(int* contentStringsFlags) { // create the hex array of content descriptor IDs string tmp; contentsFilter = ""; for(unsigned int i=0; contentStringsFlags && i<=CONTENT_DESCRIPTOR_MAX; i++) { if (contentStringsFlags[i]) { std::ostringstream oss; oss<>std::hex>>searchContentID)) return false; int c=0, eventContentID=0; bool found = false; while((eventContentID=e->Contents(c++)) > 0) if (eventContentID == searchContentID) { found = true; break; } if (!found) return false; } return true; } // -- cSearchExts ---------------------------------------------------------------- bool cSearchExts::Load(const char *FileName) { cMutexLock SearchExtsLock(this); Clear(); if (FileName) { free(fileName); fileName = strdup(FileName); } bool result = true; if (fileName && access(fileName, F_OK) == 0) { LogFile.iSysLog("loading %s", fileName); FILE *f = fopen(fileName, "r"); if (f) { int line = 0; char buffer[MAXPARSEBUFFER]; result = true; while (fgets(buffer, sizeof(buffer), f) > 0) { line++; char *p = strchr(buffer, '#'); if (p == buffer) *p = 0; stripspace(buffer); if (!isempty(buffer)) { cSearchExt* search = new cSearchExt; if (search->Parse(buffer)) Add(search); else { LogFile.eSysLog("error in '%s', line %d\n", fileName, line); delete search; result = false; break; } } } fclose(f); } else { LOG_ERROR_STR(fileName); result = false; } } if (!result) fprintf(stderr, "vdr: error while reading '%s'\n", fileName); LogFile.Log(2,"loaded searches from %s (count: %d)", fileName, Count()); return result; } int cSearchExts::GetNewID() { cMutexLock SearchExtsLock(this); int newID = -1; cSearchExt *l = (cSearchExt *)First(); while (l) { newID = std::max(newID, l->ID); l = (cSearchExt *)l->Next(); } return newID+1; } void cSearchExts::Update(void) { cMutexLock SearchExtsLock(this); cSearchExt *l = (cSearchExt *)First(); while (l) { // check if ID is set if (l->ID == -1) l->ID = GetNewID(); l = (cSearchExt *)l->Next(); } } bool cSearchExts::Save(void) { cMutexLock SearchExtsLock(this); bool result = true; cSearchExt *l = (cSearchExt *)this->First(); cSafeFile f(fileName); if (f.Open()) { while (l) { if (!l->Save(f)) { result = false; break; } l = (cSearchExt *)l->Next(); } if (!f.Close()) result = false; } else result = false; return result; } cSearchExt* cSearchExts::GetSearchFromID(int ID) { if (ID == -1) return NULL; cMutexLock SearchExtsLock(this); cSearchExt *l = (cSearchExt *)First(); while (l) { if (l->ID == ID) return l; l = (cSearchExt *)l->Next(); } return NULL; } void cSearchExts::RemoveBlacklistID(int ID) { bool changed = false; cMutexLock SearchExtsLock(this); cSearchExt *l = (cSearchExt *)First(); while (l) { cBlacklistObject* blacklistObj = l->blacklists.First(); while(blacklistObj) { cBlacklistObject* blacklistObjNext = l->blacklists.Next(blacklistObj); if (blacklistObj->blacklist->ID == ID) { l->blacklists.Del(blacklistObj); changed = true; } blacklistObj = blacklistObjNext; } l = (cSearchExt *)l->Next(); } if (changed) Save(); } bool cSearchExts::Exists(const cSearchExt* SearchExt) { cMutexLock SearchExtsLock(this); cSearchExt *l = (cSearchExt *)First(); while (l) { if (l == SearchExt) return true; l = (cSearchExt *)l->Next(); } return false; } cSearchExts* cSearchExts::Clone() { cSearchExts* clonedList = new cSearchExts(); cMutexLock SearchExtsLock(this); cSearchExt *l = (cSearchExt *)First(); while (l) { cSearchExt* clone = new cSearchExt(); *clone = *l; clonedList->Add(clone); l = (cSearchExt *)l->Next(); } return clonedList; } bool cSearchExts::CheckForAutoDelete(cSearchExt* SearchExt) { if (!SearchExt || SearchExt->delMode == 0) return false; cRecDone* firstRec = NULL; bool delSearch = false; int recs = RecsDone.GetTotalCountRecordings(SearchExt, &firstRec); if (SearchExt->delMode == 1 && SearchExt->delAfterCountRecs > 0) delSearch = recs >= SearchExt->delAfterCountRecs; if (SearchExt->delMode == 2 && SearchExt->delAfterDaysOfFirstRec && firstRec) delSearch = (time(NULL) - firstRec->startTime) > SearchExt->delAfterDaysOfFirstRec * 24 * 60 * 60; if (delSearch) { int DelID = SearchExt->ID; LogFile.Log(1,"auto deleting search '%s' (ID: %d)", SearchExt->search, DelID); cMutexLock SearchExtsLock(&SearchExts); SearchExts.Del(SearchExt); SearchExts.Save(); RecsDone.RemoveSearchID(DelID); } return delSearch; } void cSearchExts::SortBy(int(*compar)(const void *, const void *)) { int n = Count(); cListObject *a[n]; cListObject *object = objects; int i = 0; while (object && i < n) { a[i++] = object; object = object->Next(); } qsort(a, n, sizeof(cListObject *), compar); objects = lastObject = NULL; for (i = 0; i < n; i++) { a[i]->Unlink(); count--; Add(a[i]); } } cSearchResult::cSearchResult(const cEvent* Event, int searchID) : event(Event), blacklist(NULL), needsTimer(true) { search = SearchExts.GetSearchFromID(searchID); } vdr-plugin-epgsearch/recdone_thread.h0000644000175000017500000000262213145412721017551 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger 2017 Johann Friedrichs This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ #ifndef VDR_RECDONE_THREAD_H #define VDR_RECDONE_THREAD_H #include #include "recstatus.h" class cRecdoneThread: public cThread { private: char * m_filename; public: virtual void Action(void); cRecdoneThread(void); virtual ~cRecdoneThread(); void SetFilename(const char *FileName) { m_filename = strdup(FileName); }; int RecLengthInSecs(const cRecording *pRecording); bool IsPesRecording(const cRecording *pRecording); }; #endif vdr-plugin-epgsearch/menu_recsdone.h0000644000175000017500000000437013145412721017433 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #ifndef __MENU_RECSDONE_H #define __MENU_RECSDONE_H #include "epgsearchext.h" #include "recdone.h" #include #include // --- cMenuRecDoneItem ---------------------------------------------------------- class cMenuRecDoneItem : public cOsdItem { public: cRecDone* recDone; bool showEpisodeOnly; cMenuRecDoneItem(cRecDone* RecDone, bool ShowEpisodeOnly = false); void Set(); int Compare(const cListObject &ListObject) const; }; // --- cMenuRecDone ---------------------------------------------------------- class cMenuRecsDone : public cOsdMenu { private: cSearchExt* search; eOSState Delete(void); eOSState DeleteAll(void); const char* ButtonBlue(cSearchExt* Search); int showMode; bool showEpisodeOnly; protected: void Set(); virtual eOSState ProcessKey(eKeys Key); void UpdateTitle(); eOSState Summary(void); cRecDone* CurrentRecDone(void); public: cMenuRecsDone(cSearchExt* search = NULL); }; // --- cMenuTextDone ---------------------------------------------------------- class cMenuTextDone : public cMenuText { cRecDone* recDone; public: cMenuTextDone(const char *Title, cRecDone* RecDone, eDvbFont Font = fontOsd); virtual eOSState ProcessKey(eKeys Key); }; #endif vdr-plugin-epgsearch/timerstatus.h0000644000175000017500000000253213145412721017167 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #include class cTimerStatusMonitor : public cStatus { bool conflictCheckAdvised; protected: virtual void TimerChange(const cTimer *Timer, eTimerChange Change); public: cTimerStatusMonitor(); void SetConflictCheckAdvised(bool ConflictCheckAdvised = true); bool ConflictCheckAdvised(); }; extern cTimerStatusMonitor* gl_timerStatusMonitor; vdr-plugin-epgsearch/pending_notifications.c0000644000175000017500000001140013145412721021145 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #include #include "pending_notifications.h" #include "epgsearchtools.h" cPendingNotifications PendingNotifications; char *cPendingNotification::buffer = NULL; // -- cPendingNotifications ----------------------------------------------------------------- cPendingNotification::~cPendingNotification(void) { if (buffer) { free(buffer); buffer = NULL; } } bool cPendingNotification::Parse(const char *s) { char *t = skipspace(s + 1); switch (*s) { case 'F': strreplace(t, '|', '\n'); formatted = strdup(t); break; default: LogFile.eSysLog("ERROR: unexpected tag while reading epgsearch pending notifications data: %s", s); return false; } return true; } bool cPendingNotification::Read(FILE *f) { cPendingNotification *p = NULL; char *s; cReadLine ReadLine; while ((s = ReadLine.Read(f)) != NULL) { char *t = skipspace(s + 1); switch (*s) { case 'N': if (!p) { tEventID EventID; int Type, TimerMod, SearchID; time_t Start; int n = sscanf(t, "%d %u %d %d %ld", &Type, &EventID, &TimerMod, &SearchID, &Start); if (n == 5) { p = new cPendingNotification; if (p) { p->type = Type; p->eventID = EventID; p->timerMod = TimerMod; p->searchID = SearchID; p->start = Start; PendingNotifications.Add(p); } } } break; case 'C': { s = skipspace(s + 1); char *pC = strchr(s, ' '); if (pC) *pC = 0; // strips optional channel name if (*s) { tChannelID channelID = tChannelID::FromString(s); if (channelID.Valid()) { if (p) p->channelID = channelID; } else { LogFile.Log(3, "ERROR: illegal channel ID: %s", s); return false; } } } break; case 'n': p = NULL; break; default: if (p && !p->Parse(s)) { LogFile.Log(1,"ERROR: parsing %s", s); return false; } } } return true; } const char *cPendingNotification::ToText(void) const { char* tmpFormatted = formatted!=""?strdup(formatted.c_str()):NULL; if (tmpFormatted) strreplace(tmpFormatted, '\n', '|'); if (buffer) free(buffer); buffer = NULL; LOCK_CHANNELS_READ; const cChannel *channel = Channels->GetByChannelID(channelID, true, true); if (!channel) LogFile.Log(3,"invalid channel in pending notifications!"); msprintf(&buffer, "N %d %u %d %d %ld\nC %s\n%s%s%sn", type, eventID, timerMod, searchID, start, channel?CHANNELSTRING(channel):"", tmpFormatted?"F ":"",tmpFormatted?tmpFormatted:"", tmpFormatted?"\n":""); if (tmpFormatted) free(tmpFormatted); return buffer; } bool cPendingNotification::Save(FILE *f) { return fprintf(f, "%s\n", ToText()) > 0; } bool cPendingNotifications::Load(const char *FileName) { Clear(); if (FileName) { free(fileName); fileName = strdup(FileName); } if (fileName && access(fileName, F_OK) == 0) { LogFile.iSysLog("loading %s", fileName); FILE *f = fopen(fileName, "r"); bool result = false; if (f) { result = cPendingNotification::Read(f); fclose(f); } if (result) LogFile.Log(2,"loaded pending notifications from %s (count: %d)", fileName, Count()); else LogFile.Log(1,"error loading pending notifications from %s (count: %d)", fileName, Count()); return result; } return false; } bool cPendingNotifications::Save(void) { bool result = true; cPendingNotification* l = (cPendingNotification*)this->First(); cSafeFile f(fileName); if (f.Open()) { while (l) { if (!l->Save(f)) { result = false; break; } l = (cPendingNotification*)l->Next(); } if (!f.Close()) result = false; } else result = false; LogFile.Log(2,"saved pending notifications (count: %d)", Count()); return result; } vdr-plugin-epgsearch/timerdone.h0000644000175000017500000000417313145412721016574 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #ifndef __TIMERDONE_H #define __TIMERDONE_H #include #include using std::string; // --- cTimerDone -------------------------------------------------------- class cTimerDone : public cListObject { public: time_t start; // Start time of the timer time_t stop; // Stop time of the timer tChannelID channelID; int searchID; string title; string shorttext; cTimerDone(); cTimerDone(const time_t Start, const time_t Stop, const cEvent* pEvent, const int SearchID); bool operator== (const cTimerDone &arg) const; static bool Read(FILE *f); bool Parse(const char *s); cString ToText(void) const; bool Save(FILE *f); const cEvent* GetEvent() const; }; class cTimersDone : public cConfig, public cMutex { public: cTimerDone* InList(const time_t Start, const time_t Stop, const cEvent* pEvent, const int SearchID); void Update(const time_t Start, const time_t Stop, const cEvent* pEvent, const int SearchID, cTimerDone* timerdone); void ClearOutdated(void); void RemoveEntriesOfSearch(const int SearchID); }; extern cTimersDone TimersDone; #endif vdr-plugin-epgsearch/source/0000755000175000017500000000000013145412721015730 5ustar tobiastobiasvdr-plugin-epgsearch/source/vdr-epgsearchclient-0.0.2.tgz0000644000175000017500000002433413145412721023050 0ustar tobiastobiasO\wFϯyĔz v`iξ=94Hvi^o tyvisY3% ?5G477ϓfFi57#Kƞܹ;O'ӧ|y:`>{㽟?ط>ۚkЋgϦd\]GU7l(@:BP=z .Qv.;GGn3;lܱ(`Rp{NCyY7w{.>]bGoy%,ȵ"fa GA)+K'yϺΰw56siI L yB哹lu?%2uS0j5f_ ?Nu4XǕ*ba]Ǎ]{S3!u[C6 |^ |5GU`%ش\JELEPX-]A/gVrSJ4(GRGS73Xqx88`*U>j2#FGs}b޹~\t2 ."pf׵؁\r%y OYeGRbB-`Vt6H˓MڦbBL4 //5m؍AigP؋ˉ` "$@~pkvo@r"ž֖M6i8uw۳ç9.ǵ˪̝#W1/ +6[ bCRR'(,auT*/M__\T lOv4C3q :ܗIj583.jz3y[=̂zn ͡dpi" "o,YA s ~1tCn]@",P \Usa$Uyr3I*.C6̗Kz%"\J+r PɍȲ܎'Ng0L!4 HO4J5&`DNsPL8)v2.C%)y&S~i2 /O5˧Rvд 5^wݸQWJL& b~A@F:_mGx"Y),dRzRT֓HW: -?O SdWT0>{VwP7IQ:$!!꧈ҍ*GӶbe"3f&0\ v3iA ǡXJJ8Y cF϶4? {n)؂.~1pM=߼."sA澝F SS s"ȔfS,'3[toa,!0l!hK>nMcb fi 9BID.k k+i0" הDusFtB*92*  ;/^ /քm -ns9/( A@[# 5b%n]eC>¸Gri @L[ъF^x6BWOTq(J%YQ|!:5e6;ɍيC(}P|A]1d^^l=[e?w٨wengXhCv5]wH W( (WfOp!Sj)hƶE r&!>^}y}1qc`‰ ȋ`T/@""Q>9\X= gPBqj10؇ӝLM  P5L1Hq `$7'j čO"f#&+q~vXLX^iF! X1`Ս".W,/*؇6F7f֣a> QEp}W}bN#(0tp-`% 86IKat͖=R^OX1]NR 8S O5T0._a= UN(,gn˸+7yg'Qq==~vFk _ -tHll[VtlXp{1TTwC:B2u<@68kGrߌ.uWo:B! Zf ko=|x&?!/9>_[_dɇx`ao tPz2=0c5M_΅k"rC`^^Bj% p'Sx dsCaX@M@" [i4PZ$\ZW#0zJ zzvj.@ՙ!۾1_5=譥m?ݰhU3aj`,u_f{oGrH̢d򋎪>eoW#^koP .Y;`%>4>jg?< Az b]`]ֺz_^G"P`R;_ຉc0e`eՒ{eͱB1> *@4۞!$bfyd1 VDfpά0bC+y pd{" 9II#}{Uʝ_Yx<J+•JN%6Y)YӕYWq'5~ %=5jw~j[GBn|Wi,fS :6TgܦS|!}%G7c޽_ .|"/zo{T^2bِP?JqE=0.p;tS=h?mkg  H-1؟fJK.?uϺWėh./Wy_w2C,$N-VneCRȾ @S~`/4k,L'CpkAA8(H:9[O%8 "7ayaVb\_W9}Q_s a@&&0@E΋ FufkߑJ=j6Y=`!opvq O@VB|p5ql&~lPm}/e{`x\?vZuyFvxb@!]k& ?Ty$ӣQs6PW~wؾ`W//zwpā?f%rJM\ F4å9PyT"nmo;6xQۢF1.юU2(/یAh6kM cףź"[ ܅\<| t=A F,O56Ufx崫/p\[ nBWP-&PՂfXJ6U 9S-ݙ%E#,9)͆QI“\TgHrJOBB8E 4,ĉ,wsr+lk5ȬJWQ_{L7RVuF@ֺh,NB>fٷkXL,6xgNZd0|J&Vt(+=} RyatM9w |Hܜ(U$S^8O.Lo$V0APGԼ77h j"IP")BJf*bo4|. 5f}hْ֨;rFPݹj^@[>N |q 80 PcFc D"M~A)]^O8459ѽXY. GDڢVf-YENds|A7Q%'&pv|\}Mvl:}ce+Cֵ 8Ð%9X5Z^jetTE`.  ` "0tl%S>,P,9DZܬd:ºV{"zf`TZtƣW0<4DӘGR={AOF6 *I`3|,0n[JgItxML 3'5IxKԉ9-2&ߒyR4rW1QZ|$D6KG6S^\hq CqRlI}=rR(״6^B :һ_\+\'kx&e[M^('ԥ¤/"z~7Hhl#1bikh :FneS(AUVj#څ4~5<x9}NiIX;:i`t'>Fնv13Z,nȐ+kO'd/ eSH^cs(KI(Ub E)k hN{܄>kP19}ǃhR J" pNCv 9Ƒ74[Ab{ZlcxY5NB|ugxxDc1VγϣSHwMk7AЬ|MCSU&[njN}Z(鮀py  ;B ndnh-4"?ӪǼcWi A&H_iDc`Tu5q@w.=qh{8B˽9PU-pnhS^( sZ]iUfy`U5$$rj!q,Y Rv~}[-4]ESIz ÅTcS(#|y \voYS߰h&S?q?r ?DQ@(LiHCVO+"a73^ҽYN w0 ؙSt Ӛ.E7j0:e ,牐{R5[v^3yDMV Q!l AJzFrOȰphuB#ߜ>L=Xbg%>5 RC20 gRƲR}f0Ҷx`p$ M)nN0zZg㋱^7XђHRo"^Z\/4E^(Z d Z)@kw5F-,Bza:Pf]GPLD*^ 1+`uýC"2\QX1= + I\5f4;Z 7g.uK 6.kzpfeY<nw |Y|DPғ[PنSđ|an*Bzl A릟P <ܽIr^5T_Ch;b\*[M1^ؽO5+hu;{&EGo{:0=Ǩ:< .1=3^Ǥ2ᇋUZd2EwcQ%htvq  SOX\ZI!ߦ4j rm{bԞ@K)Eydq԰3R| #cy R"TsΉ QX_z5fKZZhNI$\G d/ŕ2pqVSOڐ~wFnӳ sћZx[\ 1x֎WS>orL MiClȣV'q&b GD@og̤w7gRrDӺڊ}GJAt#཈S[SXXrհ}D2"5 |BdTsY$g Dv͡ QaB8+>;EeK iu[, /:YbPkVq5ѠS(-cr"":^655؞3>b4-~խEs4pP J7ϻ?`v=gLLFl+jRDj7`iXTZJN^k:Mp_¯ogH}Ne> وϫ*N \?: %{IZ܋'Ty Ҽwa>V ~"~JbYbJJ^[#88e(JjQt"̓k8ziH89\;?߶OW‘."]3]7=pgR/O̠w^Įi..QE2Pjf~)pΊ Y\]U:(aWZj]#], IC QιH-8wX/># + J!:[R7Jbص^,ӛbnq<<L%;n:x)k=Z uFDlI#vA$kea_E^F& حo3@omRUF:oAԪ7֋Ty@j'yUt qؙ{t-ao zImTG&CKr9 V័ 7f6VIcXo؇8'm0X|C%sC$!Ƴiq~v,?Vgb@TF}§S7-UUQ܆{Q0fF'O۶f~N&ÛWgEv98~JGSgžO?L,H/M2lVٯffOLZoou^jf^fUvg:Me2(4"dj^guaz;F4q| 27j|7 p_F7i6bCٯl*O'q& Hn3Y's6޺ FO>eYbt=.0HuwCv<J#/pnՕ6> o.Qtӯ;X { X,}g^yS}lq,uz]x4|]bIv;MRr'2Q6O$ l=6EڰѾ'_F9v~kP1Ux0s+"t/X ψÒ`AE BL>H#ѓUSWܭ+Fҡl'9-ݸHsyݓ?x aNfÔ#^dx{z8 //&rL䰍n) 6M?ڙ Ƥb')I ; &uQ)hH{+<$^rmQ :r0]&0L~sLM|ϗjr |+LkƤ)<1B`~b7|F?L>NtIV7®" g'w@oB4mz.C*&?W2QN) +-L_'IA//Ҩ硺ˊ~0eP=U즃[0Pj );nal˒>g NŚV9NstqhܸC ?*dxwIƠS:h̴jU:\DOpFҘZßY*?]ϟ$(Jd -Z.@ULH㪾=;t=uѫJrc7U ُS%+ѩ>a).wqQz!/k_c|N0iH[￱tY{*5=h`T!xym<3s|9>s|9>s|8Ovdr-plugin-epgsearch/README.Translators0000644000175000017500000000177013145412721017630 0ustar tobiastobias--------------------------------------------------- Building and maintaining translations for EPGSearch --------------------------------------------------- If your language is not yet supported in EPGSearch or any updates are needed it would be great if you could give your support for this. To do so please follow these steps: 1. Check if there is a current beta version of EPGSearch at http://winni.vdr-developer.org/epgsearch/downloads/beta If not please use the latest known release. 2. Copy the original po file for your language to any backup destination. Now edit the original po file for your language in the po subdirectory. All entries with 'msgstr ""' should be filled with your translation. 3. To test your translations, simply recompile EPGSearch and check your changes. 4. When done please send me your po file or even better a patch for it, created like cd po diff -Nru /path-to-backup-po-file/x.po x.po > epgsearch_x.diff Many thanks for your support Christian vdr-plugin-epgsearch/README.git0000644000175000017500000000051513145412721016073 0ustar tobiastobiasNote: This is a dummy README needed by some maintainers that use the git repository to fetch epgsearch. In the official or beta tar balls it is replaced by a symbolic link to ./doc/en/epgsearch.1.txt which is not part of the git repository since it is built from the sources (via 'make docs'). If its in the way, just remove it. vdr-plugin-epgsearch/menu_searchtemplate.h0000644000175000017500000000303213145412721020624 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #ifndef __MENU_SEARCHTEMPLATE_H #define __MENU_SEARCHTEMPLATE_H #include #include "epgsearchext.h" #include "blacklist.h" class cMenuEPGSearchTemplate : public cOsdMenu { private: bool newSearch; eOSState New(void); eOSState Delete(void); eOSState DefaultTemplate(void); cSearchExt* search; cBlacklist* blacklist; protected: virtual eOSState ProcessKey(eKeys Key); public: cMenuEPGSearchTemplate(cSearchExt* Search, cBlacklist* Blacklist, bool New); cSearchExt* CurrentSearchTemplate(void); }; #endif vdr-plugin-epgsearch/.gitignore0000644000175000017500000000022213145412721016414 0ustar tobiastobias/createcats /.dependencies /.dependencies_doc /.doc_stmp /MANUAL /README.DE /doc/ /html/ /man/ /po/epgsearch.pot /po/*.mo *.o *.so *.tgz *.tmp *~ vdr-plugin-epgsearch/epgsearchtools.c0000644000175000017500000006573713145412721017640 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #include #include #include #include #include #include #include #ifdef __FreeBSD__ #include #endif #include "uservars.h" #include "epgsearchtools.h" #include "epgsearchext.h" #include "epgsearchcats.h" #include "epgsearchcfg.h" #include "svdrpclient.h" #include "distance.h" #include "md5.h" #include "afuzzy.h" #include "timerstatus.h" #include #ifdef HAVE_PCREPOSIX #include #elif defined(HAVE_LIBTRE) #include #else #include #endif const char AllowedChars[] = trNOOP("$ abcdefghijklmnopqrstuvwxyz0123456789-.,#~\\^$[]|()*+?{}/:%@&_"); extern bool isUTF8; int CompareEventTime(const void *p1, const void *p2) { time_t time1 = (*(cSearchResult **)p1)->event->StartTime(); time_t time2 = (*(cSearchResult **)p2)->event->StartTime(); if (time1 == time2) return (int)(ChannelNrFromEvent((*(cSearchResult **)p1)->event) - ChannelNrFromEvent((*(cSearchResult **)p2)->event)); else return (int)(time1 - time2); } int CompareEventChannel(const void *p1, const void *p2) { int ch1 = ChannelNrFromEvent((*(cSearchResult **)p1)->event); int ch2 = ChannelNrFromEvent((*(cSearchResult **)p2)->event); if (ch1 == ch2) return (int)((*(cSearchResult **)p1)->event->StartTime() - (*(cSearchResult **)p2)->event->StartTime()); else return ch1 - ch2; } int CompareSearchExtPrioDescTerm(const void *p1, const void *p2) { int prio1 = (*(cSearchExt **)p1)->Priority; int prio2 = (*(cSearchExt **)p2)->Priority; if (prio2 != prio1) return prio2 - prio1; else return strcmp((*(cSearchExt **)p1)->search, (*(cSearchExt **)p2)->search); } cString IndentMenuItem(const char* szString, int indentions) { char* szIndented = NULL; msprintf(&szIndented, "%*s", strlen(szString)+indentions*2, szString); cString szIndentedStr(szIndented, true /*take pointer*/); return szIndentedStr; } bool MatchesSearchMode(const char* szTest, const char* searchText, int mode, const char* delim, int tolerance) { if (szTest && *szTest) { if (mode == 0) // substring return (strstr(szTest, searchText) != NULL); else if (mode == 1 || mode == 2) // AND or OR { bool bTesting = false; char *pstrSearchToken, *pptr; bool bFirst=true; char *pstrSearch=strdup(searchText); pstrSearchToken=strtok_r(pstrSearch, delim, &pptr); while(pstrSearchToken) { if(szTest && strstr(szTest, skipspace(pstrSearchToken))) { if(mode==1) { // means AND if(bFirst) { bTesting=true; bFirst=false; } else bTesting&=true; } else bTesting|=true; } else {// not found!! if(mode==1) { // means AND bTesting=false; bFirst=false; } } pstrSearchToken=strtok_r(NULL, delim, &pptr); } free(pstrSearch); return bTesting; } else if (mode == 3) // match exactly { if (strcmp(szTest, searchText) == 0) return true; else return false; } else if (mode == 4) // regexp { regex_t re; if ( 0 == regcomp(&re, searchText, REG_EXTENDED | REG_NOSUB) ) { int status = regexec( &re, szTest, 0, NULL, 0); regfree(&re); return (status == 0); } return false; } else if (mode == 5) // fuzzy { AFUZZY af = { NULL, NULL, NULL, NULL, NULL, NULL, { 0 }, { 0 }, 0, 0, 0, 0, 0, 0 }; string query = searchText?searchText:""; if (query.size() > 32) query = query.substr(0, 32); afuzzy_init(query.c_str(), tolerance, 0, &af); /* Checking substring */ int res = afuzzy_checkSUB(szTest, &af); afuzzy_free(&af); return (res > 0); } else if (mode >= 10 && mode <= 15) { int testvalue = atoi(szTest); int value = atoi(searchText); if (value == 0) return true; if (mode == 10) // less return testvalue < value; else if (mode == 11) // less or equal return testvalue <= value; else if (mode == 12) // greater return testvalue > value; else if (mode == 13) // greater or equal return testvalue >= value; else if (mode == 14) // equal return testvalue == value; else if (mode == 15) // not equal return testvalue != value; } } return false; } void ToLower(char* szText) { if (!szText) return; if (!isUTF8) { for (int loop = 0; szText[loop] !=0; loop++) szText[loop] = tolower(szText[loop]); return; } else { int length = strlen(szText)+1; uint* valueUtf8 = new uint[length]; int lengthUtf8 = Utf8ToArray(szText, valueUtf8, length); for(int i=0; iDescription(), SearchExtCat->name, SearchExtCat->format); } char* GetExtEPGValue(const char* description, const char* catname, const char *format) { if (isempty(description)) return NULL; char* tmp1 = NULL; char* tmp2 = NULL; // search the category, must be the first line or at the beginning of a line if (msprintf(&tmp1, "\n%s: ", catname)==-1 || msprintf(&tmp2, "%s: ", catname)==-1) return NULL; char* descr = strdup(description); char* cat = NULL; int valueOffset = 0; if ((cat = strstr(descr, tmp1)) != NULL) { cat++; // skip linefeed valueOffset = strlen(tmp1); } else if (strstr(descr, tmp2) == descr) // in first line { cat = descr; valueOffset = strlen(tmp2)+1; } else { free(descr); free(tmp1); free(tmp2); return NULL; } // search the value to appear before the next line feed or end char* end = strchr(cat, '\n'); int endpos = strlen(cat); if (end) endpos = end - cat; cat[endpos] = 0; char* value = NULL; msprintf(&value, "%s", cat + valueOffset - 1); if (format) { int ivalue; if (sscanf(value,"%8i",&ivalue)==1) { free(value); value = NULL; msprintf(&value, format, ivalue); } } free(descr); free(tmp1); free(tmp2); return value; } char* GetAuxValue(const char* aux, const char* name) { if (isempty(aux)) return NULL; char* descr = strdup(aux); char* beginaux = strstr(descr, ""); char* endaux = strstr(descr, ""); if (!beginaux || !endaux) { free(descr); return NULL; } beginaux += 11; // strlen(""); endaux[0] = 0; memmove(descr, beginaux, endaux - beginaux + 1); if (strcmp(name, "epgsearch") == 0) return descr; // full aux int namelen = strlen(name); char catname[100] = ""; catname[0] = '<'; memcpy(catname + 1, name, namelen); catname[1 + namelen] = '>'; catname[2 + namelen] = 0; char* cat = strcasestr(descr, catname); if (!cat) { free(descr); return NULL; } cat += namelen + 2; char* end = strstr(cat, "Info()) return NULL; return GetAuxValue(recording->Info()->Aux(), name); } char* GetAuxValue(const cTimer *timer, const char* name) { if (!timer || !timer->Aux()) return NULL; return GetAuxValue(timer->Aux(), name); } string UpdateAuxValue(string aux, string section, long num) { return UpdateAuxValue(aux, section, NumToString(num)); } string UpdateAuxValue(string aux, string section, string value) { string secStart = "<" + section + ">"; string secEnd = ""; int valueStartPos = aux.find(secStart); int valueEndPos = aux.find(secEnd); if (valueStartPos >= 0 && valueEndPos >= 0) aux.replace(valueStartPos + secStart.size(), valueEndPos - valueStartPos - secStart.size(), value); else aux += secStart + value + secEnd; return aux; } // replace s1 with s2 in s ignoring the case of s1 char *strreplacei(char *s, const char *s1, const char *s2) { char *p = strcasestr(s, s1); if (p) { int of = p - s; int l = strlen(s); int l1 = strlen(s1); int l2 = 0; if (s2) l2 = strlen(s2); if (l2 > l1) s = (char *)realloc(s, l + l2 - l1 + 1); if (l2 != l1) memmove(s + of + l2, s + of + l1, l - of - l1 + 1); memcpy(s + of, s2, l2); } return s; } std::string strreplace( std::string& result, const std::string& replaceWhat, const std::string& replaceWithWhat) { while(1) { const int pos = result.find(replaceWhat); if (pos==-1) break; result.replace(pos,replaceWhat.size(),replaceWithWhat); } return result; } void sleepMSec(long ms) { cCondWait::SleepMs(ms); } void sleepSec(long s) { sleepMSec(s * 1000); } bool SendViaSVDRP(cString SVDRPcmd) { bool bSuccess = true; cString cmdbuf; if (EPGSearchConfig.useExternalSVDRP) { cmdbuf = cString::sprintf("%s -p %d \"%s\"", epgsSVDRP::cSVDRPClient::SVDRPSendCmd, EPGSearchConfig.SVDRPPort, *SVDRPcmd); FILE *p = popen(cmdbuf, "r"); if (p) pclose(p); else { LogFile.eSysLog("can't open pipe for command '%s'", *cmdbuf); bSuccess = false; } } else { cmdbuf = SVDRPcmd; epgsSVDRP::cSVDRPClient client; if (!client.SendCmd(*cmdbuf)) { LogFile.eSysLog("command '%s' failed", *cmdbuf); bSuccess = false; } } return bSuccess; } int SendMsg(cString Message, bool confirm, int seconds, eMessageType messageType) { int Keys = Skins.QueueMessage(messageType, Message, seconds, confirm?seconds+2:0); return Keys; } bool InEditMode(const char* ItemText, const char* ItemName, const char* ItemValue) { bool bEditMode = true; // ugly solution to detect, if in edit mode char* value = strdup(ItemText); strreplace(value, ItemName, ""); strreplace(value, ":\t", ""); // for bigpatch strreplace(value, "\t", ""); if (strlen(value) == strlen(ItemValue)) bEditMode = false; free(value); return bEditMode; } // checks if the timer was triggered from a search timer and return a pointer to the search cSearchExt* TriggeredFromSearchTimer(const cTimer* timer) { char* searchID = GetAuxValue(timer, "s-id"); if (!searchID) return NULL; cSearchExt* search = SearchExts.GetSearchFromID(atoi(searchID)); free(searchID); return search; } int TriggeredFromSearchTimerID(const cTimer* timer) { cSearchExt* trigger = TriggeredFromSearchTimer(timer); if (trigger) return trigger->ID; else return -1; } double FuzzyMatch(const char* s1, const char* s2, int maxLength) { Distance D; int dist = D.LD (s1, s2, maxLength); double fMaxLength = std::max(strlen(s1), strlen(s2)); return (fMaxLength - dist)/fMaxLength; } bool DescriptionMatches(const char* eDescr, const char* rDescr, int matchLimit) { if (eDescr == NULL && rDescr == NULL) return true; if (eDescr == NULL && rDescr != NULL) return false; if (eDescr != NULL && rDescr == NULL) return false; int l_eDescr = strlen(eDescr); int l_rDescr = strlen(rDescr); if (l_eDescr == l_rDescr && strcmp(eDescr, rDescr) == 0) return true; // partial match: // first check the length, should only be different at match limit int minLength = std::min(l_eDescr, l_rDescr); int maxLength = std::max(l_eDescr, l_rDescr); if (100*double(minLength)/double(maxLength) < matchLimit) return false; // last try with Levenshtein Distance, only compare the first 1000 chars double fMatch = FuzzyMatch(eDescr, rDescr, 1000); double tmp_matchlimit = matchLimit/100.0; if(maxLength - minLength < 5 && matchLimit < 95) { tmp_matchlimit = 0.95; LogFile.Log(2,"difference between both descriptions is < 5 setting matchlimit to: %.2f %%", tmp_matchlimit*100); } if (fMatch > tmp_matchlimit) { LogFile.Log(2,"match is: %.2f %%", fMatch*100); return true; } return false; } const cEvent* GetEvent(const cTimer* timer) { const cEvent* event = NULL; const cChannel *channel = timer->Channel(); time_t Time = timer->StartTime() + (timer->StopTime() - timer->StartTime()) / 2; for (int seconds = 0; seconds <= 3; seconds++) { { LOCK_SCHEDULES_READ; if (Schedules) { const cSchedule *Schedule = Schedules->GetSchedule(channel->GetChannelID()); if (Schedule) { event = Schedule->GetEventAround(Time); if (event) return event; } } } if (seconds == 0) LogFile.Log(2,"waiting for EPG info..."); sleepSec(1); } LogFile.Log(1,"no EPG info available"); return NULL; } // this extracts the real description from a given epg entry cutting all that looks like a category line // we assume that a category has a name not longer than MAXCATNAMELENGTH and a value not longer than // MAXCATVALUELENGTH (so in most cases e.g. the 'cast' category will stay part of the description). name and // value are separated with ': ' #define MAXCATNAMELENGTH 40 #define MAXCATVALUELENGTH 60 char* GetRawDescription(const char* descr) { if (!descr || !*descr) return NULL; char* rawDescr = (char*) calloc(strlen(descr)+1, sizeof(char)); const char* tmp = descr; while(tmp) { // extract a single line const char* lf = strchr(tmp, '\n'); char* line = NULL; if (lf) line = strndup(tmp, lf-tmp); else line = strdup(tmp); // if (lf) *lf = 0; // check for category char* delim = strstr(line, ": "); if (!delim || (delim && (delim - line > MAXCATNAMELENGTH || strlen(line) - (delim - line) + 2 > MAXCATVALUELENGTH))) if (*line) strcat(rawDescr, line); if (lf) tmp += strlen(line)+1; else tmp = NULL; free(line); } return rawDescr; } void PrepareTimerFile(const cEvent* event, cTimer* timer) { if (!event) return; if (EPGSearchConfig.addSubtitleToTimer == addSubtitleNever && strlen(EPGSearchConfig.defrecdir) == 0) // nothing to do return; if (!isempty(event->ShortText())) // add subtitle if present { bool addSubtitle = (EPGSearchConfig.addSubtitleToTimer != addSubtitleNever); if (EPGSearchConfig.addSubtitleToTimer == addSubtitleSmart) if (event->Duration() > 80*60) addSubtitle = false; if (addSubtitle) { char tmp[MaxFileName] = ""; snprintf(tmp, MaxFileName, "%s~%s", event->Title(), event->ShortText()); timer->SetFile(tmp); } } if (strlen(EPGSearchConfig.defrecdir) > 0) { char directory[MaxFileName] = ""; strn0cpy(directory, EPGSearchConfig.defrecdir,sizeof(directory)); cVarExpr varExprDir(directory); if (!varExprDir.DependsOnVar("%title%", event)) { strcat(directory, "~"); strcat(directory, timer->File()); } // parse the epxression and evaluate it cVarExpr varExpr(directory); strcpy(directory, varExpr.Evaluate(event).c_str()); if (strchr(directory, '%') == NULL) // only set directory to new value if all categories could have been replaced timer->SetFile(directory); } } bool EventsMatch(const cEvent* event1, const cEvent* event2, bool compareTitle, int compareSubtitle, bool compareSummary, int compareDate, unsigned long catvaluesAvoidRepeat, int matchLimit) { if (!event1 || !event2) return false; if (event1 == event2) return true; // only compare the alphanumeric portions string Title1 = ""; string Title2 = ""; if (compareTitle) { string s1 = event1->Title()?event1->Title():""; string s2 = event2->Title()?event2->Title():""; Title1 = GetAlNum(s1); Title2 = GetAlNum(s2); std::transform(Title1.begin(), Title1.end(), Title1.begin(), tolower); std::transform(Title2.begin(), Title2.end(), Title2.begin(), tolower); } string Subtitle1 = ""; string Subtitle2 = ""; if (compareSubtitle) { string s1 = event1->ShortText()?event1->ShortText():""; string s2 = event2->ShortText()?event2->ShortText():""; Subtitle1 = GetAlNum(s1); Subtitle2 = GetAlNum(s2); std::transform(Subtitle1.begin(), Subtitle1.end(), Subtitle1.begin(), tolower); std::transform(Subtitle2.begin(), Subtitle2.end(), Subtitle2.begin(), tolower); } string compareExpression = ""; if (compareDate == 1) compareExpression = "%date%"; if (compareDate == 2) compareExpression = "%year%-%week%"; if (compareDate == 3) compareExpression = "%year%-%month%"; bool match = false; if ((!compareTitle || Title1 == Title2) && (!compareSubtitle || (Subtitle1 == Subtitle2 && Subtitle1!=""))) { const char* Descr1 = event1->Description(); const char* Descr2 = event2->Description(); if (compareSummary) { char* rawDescr1 = GetRawDescription(Descr1); char* rawDescr2 = GetRawDescription(Descr2); match = DescriptionMatches(rawDescr1, rawDescr2, matchLimit); free(rawDescr1); free(rawDescr2); if (!match) return false; } if (compareExpression.size() > 0) { cVarExpr varExpr(compareExpression); string resEvent1 = varExpr.Evaluate(event1); string resEvent2 = varExpr.Evaluate(event2); if (resEvent1 != resEvent2) return false; } if (catvaluesAvoidRepeat != 0) // check categories { bool bCatMatch = ((Descr1 && Descr2) || (!Descr1 && !Descr2)); cSearchExtCat *SearchExtCat = SearchExtCats.First(); int index = 0; while (catvaluesAvoidRepeat > 0 && SearchExtCat && bCatMatch) { if (catvaluesAvoidRepeat & (1<name, SearchExtCat->format); char* CatValue2 = GetExtEPGValue(Descr2, SearchExtCat->name, SearchExtCat->format); if ((!CatValue1 && CatValue2) || (!CatValue2 && CatValue1) || (CatValue1 && CatValue2 && strcmp(CatValue1, CatValue2) != 0)) bCatMatch = false; free(CatValue1); free(CatValue2); } SearchExtCat = SearchExtCats.Next(SearchExtCat); index++; } if (bCatMatch) match = true; } else match = true; } return match; } int ChannelNrFromEvent(const cEvent* pEvent) { if (!pEvent) return -1; LOCK_CHANNELS_READ; const cChannel* channel = Channels->GetByChannelID(pEvent->ChannelID(), true, true); if (!channel) return -1; else return channel->Number(); } void DelTimer(int index) { cString cmdbuf = cString::sprintf("DELT %d", index); LogFile.Log(2, "delete timer %d", index); SendViaSVDRP(cmdbuf); gl_timerStatusMonitor->SetConflictCheckAdvised(); } char* FixSeparators(char* buffer, char sep) { int l = strlen(buffer); char *dest = buffer; for (int i = 0; i < l; i ++) { char c = buffer[i]; int j = i; if (c == sep) { for (j = i + 1; (j < l) & (buffer[j] == ' '); j++) ; if ((j <= l) | (i + 1 < j)) { switch (buffer[j]) { case '\t': i = j; c = '\t'; break; case 0: i = j; c = 0; break; default: break; } } } if (c == '\t') { for (; (j < l) & (buffer[j] == ' '); j++) ; if (j < l && buffer[j] == sep) { buffer[j] = '\t'; i = j - 1; continue; } } *dest++ = c; } *dest = 0; return buffer; } cString DateTime(time_t t) { char buffer[32]; if (t == 0) time(&t); struct tm tm_r; tm *tm = localtime_r(&t, &tm_r); snprintf(buffer, sizeof(buffer), "%02d.%02d. %02d:%02d", tm->tm_mday, tm->tm_mon + 1, tm->tm_hour, tm->tm_min); return buffer; } string NumToString(long num) { ostringstream os; os << num; return os.str(); } int FindIgnoreCase(const string& expr, const string& query) { const char *p = expr.c_str(); const char *r = strcasestr(p, query.c_str()); if (!r) return -1; return r - p; } bool EqualsNoCase(const string& a, const string& b) { return strcasecmp(a.c_str(), b.c_str()) == 0; } string Strip(const string& input) { string str = input; string::size_type pos = str.find_last_not_of(' '); if(pos != string::npos) { str.erase(pos + 1); pos = str.find_first_not_of(' '); if(pos != string::npos) str.erase(0, pos); } else str.erase(str.begin(), str.end()); return str; } string GetAlNum(const string& s) { string res; for(unsigned int i=0; i= 0) result.replace(pos, what.size(), with); return result; } string EscapeString(const string& S) { string tmp = S; int apostrophPos = 0; int apostrophTempPos = 0; while((apostrophPos = tmp.find("'", apostrophTempPos)) >= apostrophTempPos) { tmp.replace(apostrophPos, 1, "'\"'\"'"); apostrophTempPos = apostrophPos + 5; } return tmp; } string QuoteApostroph(const string& S) { string tmp = S; int apostrophPos = 0; int apostrophTempPos = 0; while((apostrophPos = tmp.find("\"", apostrophTempPos)) >= apostrophTempPos) { tmp.replace(apostrophPos, 1, "\\\""); apostrophTempPos = apostrophPos + 2; } return tmp; } string MD5(const string& input) { char* szInput = strdup(input.c_str()); if (!szInput) return ""; char* szRes = MD5String(szInput); string res = szRes; free(szRes); return res; } void SetAux(cTimer* timer, string aux) { if (!timer) return; string timerText = *timer->ToText(); string::size_type auxPos = string::npos; for(int i=0; i<=7; i++) // get aux value auxPos = timerText.find(":", auxPos == string::npos?0:auxPos+1); if (auxPos == string::npos) return; timerText.replace(auxPos+1, timerText.size()-auxPos+1, aux); timer->Parse(timerText.c_str()); } int msprintf(char **strp, const char *fmt, ...) { va_list ap; va_start (ap, fmt); int res=vasprintf (strp, fmt, ap); va_end (ap); return res; } std::string GetCodeset() { // Taken from VDR's vdr.c char *CodeSet = NULL; if (setlocale(LC_CTYPE, "")) CodeSet = nl_langinfo(CODESET); else { char *LangEnv = getenv("LANG"); // last resort in case locale stuff isn't installed if (LangEnv) { CodeSet = strchr(LangEnv, '.'); if (CodeSet) CodeSet++; // skip the dot } } if (CodeSet) return std::string(CodeSet); else return "ISO-8859-15"; } /* Read a line from a socket */ ssize_t Readline(int sockd, char *vptr, size_t maxlen) { size_t n, rc; char c, *buffer; buffer = vptr; for ( n = 1; n < maxlen; n++ ) { if ( (rc = read(sockd, &c, 1)) == 1 ) { if ( c == '\n' ) break; *buffer++ = c; } else if ( rc == 0 ) { if ( n == 1 ) return 0; else break; } else { if ( errno == EINTR ) continue; return -1; } } *buffer = 0; return n; } /* Write a line to a socket */ ssize_t Writeline(int sockd, const char *vptr, ssize_t n) { ssize_t nleft; ssize_t nwritten; const char *buffer; buffer = vptr; nleft = n; while ( nleft > 0 ) { if ( (nwritten = write(sockd, buffer, nleft)) <= 0 ) { if ( errno == EINTR ) nwritten = 0; else return -1; } nleft -= nwritten; buffer += nwritten; } return n; } long getAddrFromString(const char* hostnameOrIp, struct sockaddr_in* addr) { unsigned long ip; struct hostent * he; if(hostnameOrIp==NULL || addr==NULL) return -1; ip=inet_addr(hostnameOrIp); if(ip!=INADDR_NONE) { addr->sin_addr.s_addr=ip; return 0; } else { he=gethostbyname(hostnameOrIp); if(he==NULL) return -1; else memcpy(&(addr->sin_addr),he->h_addr_list[0],4); return 0; } } char *cCommand::result = NULL; cCommand::cCommand(void) { title = command = NULL; confirm = false; } cCommand::~cCommand() { free(title); free(command); } bool cCommand::Parse(const char *s) { const char *p = strchr(s, ':'); if (p) { int l = p - s; if (l > 0) { title = MALLOC(char, l + 1); stripspace(strn0cpy(title, s, l + 1)); if (!isempty(title)) { int l = strlen(title); if (l > 1 && title[l - 1] == '?') { confirm = true; title[l - 1] = 0; } command = stripspace(strdup(skipspace(p + 1))); return !isempty(command); } } } return false; } const char *cCommand::Execute(const char *Parameters) { free(result); result = NULL; cString cmdbuf; if (Parameters) cmdbuf = cString::sprintf("%s %s", command, Parameters); const char *cmd = *cmdbuf ? *cmdbuf : command; dsyslog("executing command '%s'", cmd); cPipe p; if (p.Open(cmd, "r")) { int l = 0; int c; while ((c = fgetc(p)) != EOF) { if (l % 20 == 0) result = (char *)realloc(result, l + 21); result[l++] = char(c); } if (result) result[l] = 0; p.Close(); } else esyslog("ERROR: can't open pipe for command '%s'", cmd); return result; } vdr-plugin-epgsearch/menu_event.h0000644000175000017500000000665613145412721016763 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #ifndef __EPGSEARCH_MENUEVENT_H #define __EPGSEARCH_MENUEVENT_H #include typedef enum { SurfModeUnknown, SurfModeTime, SurfModeChannel } MenuEventSurfMode; class cEventObj { const cEvent *event; bool selected; public: cEventObj(const cEvent* Event, bool Selected = false) : event(Event), selected(Selected) {} const cEvent* Event() { return event; } bool Selected() { return selected; } void Select(bool Selected) { selected = Selected; } }; class cEventObjects { public: typedef std::list< cEventObj* > EventObjectList; typedef EventObjectList::size_type size_type; typedef EventObjectList::iterator iterator; typedef EventObjectList::const_iterator const_iterator; cEventObjects() {} ~cEventObjects() { for(EventObjectList::iterator i = m_list.begin(); i != m_list.end(); ++i) delete (*i); } size_type size() const { return m_list.size(); } iterator begin() { return m_list.begin(); } const_iterator begin() const { return m_list.begin(); } iterator end() { return m_list.end(); } const_iterator end() const { return m_list.end(); } void Add(const cEvent* Event) { m_list.push_back(new cEventObj(Event)); } void Clear() { m_list.clear(); } void SetCurrent(const cEvent* Event) { for(EventObjectList::iterator i = m_list.begin(); i != m_list.end(); ++i) (*i)->Select((*i)->Event() == Event); } cEventObj* GetCurrent() { for(EventObjectList::iterator i = m_list.begin(); i != m_list.end(); ++i) if ((*i)->Selected()) return (*i); return NULL; } private: EventObjectList m_list; }; class cMenuEventSearch : public cOsdMenu { protected: const cEvent *event; char* szGreen; char* szYellow; cEventObjects& eventObjects; MenuEventSurfMode surfMode; virtual void Set(); cEventObj* GetPrev(const cEvent* Event); cEventObj* GetNext(const cEvent* Event); virtual void Display(void); virtual eOSState ProcessKey(eKeys Key); eOSState Commands(eKeys Key); public: cMenuEventSearch(const cEvent* Event, cEventObjects& EventObjects, MenuEventSurfMode SurfMode = SurfModeUnknown); ~cMenuEventSearch(); #ifdef USE_GRAPHTFT const char* MenuKind() { return "MenuEvent"; } #endif }; class cMenuEventSearchSimple : public cMenuEventSearch { private: virtual void Set(); public: cMenuEventSearchSimple(const cEvent* Event, cEventObjects& EventObjects); }; #endif vdr-plugin-epgsearch/epgsearchcats.h0000644000175000017500000000443413145412721017422 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #ifndef __EPGSEARCHCATS_H #define __EPGSEARCHCATS_H #include #include #include // --- cSearchExtCat -------------------------------------------------------- class cSearchExtCat : public cListObject { public: int id; char* name; char* format; char* menuname; int searchmode; // text comarison: // 0 - substring, // 1 - substring-and, // 2 - substring or, // 3 - equal, // 4 - regular expression, // 5 - fuzzy (not available for categories) // numerical comparison: // 10 - less // 11 - less or equal // 12 - greater // 13 - greater or equal // 14 - equal // 15 - not equal char** values; int nvalues; public: cSearchExtCat(void); virtual ~cSearchExtCat(void); bool Parse(const char *s); const char* ToText(void); }; class cSearchExtCats : public cConfig { private: public: cSearchExtCats(void) {} int GetIndexFromID(int id); }; extern cSearchExtCats SearchExtCats; #endif vdr-plugin-epgsearch/conflictcheck_thread.h0000644000175000017500000000340613145412721020732 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #ifndef VDR_CONFLICTCHECK_THREAD_H #define VDR_CONFLICTCHECK_THREAD_H #include #include "conflictcheck.h" #include "epgsearch.h" class cConflictCheckThread: public cThread { private: bool m_Active; time_t m_lastUpdate; cPluginEpgsearch* m_plugin; static bool m_runOnce; static bool m_forceUpdate; cCondWait Wait; protected: virtual void Action(void); void Stop(void); public: static cConflictCheckThread *m_Instance; static time_t m_cacheNextConflict; static int m_cacheRelevantConflicts; static int m_cacheTotalConflicts; cConflictCheckThread(cPluginEpgsearch* thePlugin); virtual ~cConflictCheckThread(); static void Init(cPluginEpgsearch* thePlugin, bool runOnce = false); static void Exit(void); }; #endif vdr-plugin-epgsearch/blacklist.c0000644000175000017500000004561113145412721016553 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #include #include "epgsearchtools.h" #include "blacklist.h" #include "epgsearchcats.h" #include #include "menu_dirselect.h" #include "changrp.h" #include "menu_search.h" #include "menu_searchedit.h" #include "menu_searchresults.h" #include cBlacklists Blacklists; // -- cBlacklist ----------------------------------------------------------------- char *cBlacklist::buffer = NULL; cBlacklist::cBlacklist(void) { ID = -1; *search = 0; options = 1; useTime = false; startTime = 0000; stopTime = 2359; useChannel = false; { LOCK_CHANNELS_READ; channelMin = Channels->GetByNumber(cDevice::CurrentChannel()); channelMax = channelMin; } channelGroup = NULL; useCase = false; mode = 0; useTitle = true; useSubtitle = true; useDescription = true; useDuration = false; minDuration = 0; maxDuration = 130; useDayOfWeek = false; DayOfWeek = 0; buffer = NULL; isGlobal = 0; useExtEPGInfo = false; catvalues = (char**) malloc(SearchExtCats.Count() * sizeof(char*)); cSearchExtCat *SearchExtCat = SearchExtCats.First(); int index = 0; while (SearchExtCat) { catvalues[index] = (char*)malloc(MaxFileName); *catvalues[index] = 0; SearchExtCat = SearchExtCats.Next(SearchExtCat); index++; } ignoreMissingEPGCats = 0; fuzzyTolerance = 1; } cBlacklist::~cBlacklist(void) { if (buffer) { free(buffer); buffer = NULL; } if (catvalues) { cSearchExtCat *SearchExtCat = SearchExtCats.First(); int index = 0; while (SearchExtCat) { free(catvalues[index]); SearchExtCat = SearchExtCats.Next(SearchExtCat); index++; } free(catvalues); catvalues = NULL; } } cBlacklist& cBlacklist::operator= (const cBlacklist &Blacklist) { char** catvaluesTemp = this->catvalues; memcpy(this, &Blacklist, sizeof(*this)); this->catvalues = catvaluesTemp; cSearchExtCat *SearchExtCat = SearchExtCats.First(); int index = 0; while (SearchExtCat) { *catvalues[index] = 0; strcpy(catvalues[index], Blacklist.catvalues[index]); SearchExtCat = SearchExtCats.Next(SearchExtCat); index++; } return *this; } void cBlacklist::CopyFromTemplate(const cSearchExt* templ) { options = templ->options; useTime = templ->useTime; startTime = templ->startTime; stopTime = templ->stopTime; useChannel = templ->useChannel; useCase = templ->useCase; mode = templ->mode; useTitle = templ->useTitle; useSubtitle = templ->useSubtitle; useDescription = templ->useDescription; useDuration = templ->useDuration; minDuration = templ->minDuration; maxDuration = templ->maxDuration; useDayOfWeek = templ->useDayOfWeek; DayOfWeek = templ->DayOfWeek; useExtEPGInfo = templ->useExtEPGInfo; isGlobal = 0; cSearchExtCat *SearchExtCat = SearchExtCats.First(); int index = 0; while (SearchExtCat) { strcpy(catvalues[index], templ->catvalues[index]); SearchExtCat = SearchExtCats.Next(SearchExtCat); index++; } channelMin = templ->channelMin; channelMax = templ->channelMax; if (channelGroup) free(channelGroup); if (templ->channelGroup) channelGroup = strdup(templ->channelGroup); fuzzyTolerance = templ->fuzzyTolerance; ignoreMissingEPGCats = templ->ignoreMissingEPGCats; } bool cBlacklist::operator< (const cListObject &ListObject) { cBlacklist *BL = (cBlacklist *)&ListObject; return strcasecmp(search, BL->search) < 0; } const char *cBlacklist::ToText(void) { char tmp_Start[5] = ""; char tmp_Stop[5] = ""; char tmp_minDuration[5] = ""; char tmp_maxDuration[5] = ""; char* tmp_chanSel = NULL; char* tmp_search = NULL; char* tmp_catvalues = NULL; free(buffer); tmp_search = strdup(search); while(strstr(tmp_search, "|")) tmp_search = strreplace(tmp_search, "|", "!^pipe^!"); // ugly: replace a pipe with something, that should not happen to be part of a regular expression strreplace(tmp_search, ':', '|'); if (useTime) { sprintf(tmp_Start, "%04d", startTime); sprintf(tmp_Stop, "%04d", stopTime); } if (useDuration) { sprintf(tmp_minDuration, "%04d", minDuration); sprintf(tmp_maxDuration, "%04d", maxDuration); } if (useChannel==1) { if (channelMin->Number() < channelMax->Number()) msprintf(&tmp_chanSel, "%s|%s", CHANNELSTRING(channelMin), CHANNELSTRING(channelMax)); else msprintf(&tmp_chanSel, "%s", CHANNELSTRING(channelMin)); } if (useChannel==2) { int channelGroupNr = ChannelGroups.GetIndex(channelGroup); if (channelGroupNr == -1) { LogFile.eSysLog("channel group %s does not exist!", channelGroup); useChannel = 0; } else tmp_chanSel = strdup(channelGroup); } if (useExtEPGInfo) { cSearchExtCat *SearchExtCat = SearchExtCats.First(); int index = 0; while (SearchExtCat) { char* catvalue = NULL; if (msprintf(&catvalue, "%s", catvalues[index])!=-1) { while(strstr(catvalue, ":")) catvalue = strreplace(catvalue, ":", "!^colon^!"); // ugly: replace with something, that should not happen to be part ofa category value while(strstr(catvalue, "|")) catvalue = strreplace(catvalue, "|", "!^pipe^!"); // ugly: replace with something, that should not happen to be part of a regular expression if (index == 0) msprintf(&tmp_catvalues, "%d#%s", SearchExtCat->id, catvalue); else { char* temp = tmp_catvalues; msprintf(&tmp_catvalues, "%s|%d#%s", tmp_catvalues, SearchExtCat->id, catvalue); free(temp); } } SearchExtCat = SearchExtCats.Next(SearchExtCat); index++; free(catvalue); } } msprintf(&buffer, "%d:%s:%d:%s:%s:%d:%s:%d:%d:%d:%d:%d:%d:%s:%s:%d:%d:%d:%s:%d:%d:%d", ID, tmp_search, useTime, tmp_Start, tmp_Stop, useChannel, (useChannel>0 && useChannel<3)?tmp_chanSel:"0", useCase, mode, useTitle, useSubtitle, useDescription, useDuration, tmp_minDuration, tmp_maxDuration, useDayOfWeek, DayOfWeek, useExtEPGInfo, useExtEPGInfo?tmp_catvalues:"", fuzzyTolerance, ignoreMissingEPGCats, isGlobal); if (tmp_chanSel) free(tmp_chanSel); if (tmp_search) free(tmp_search); if (tmp_catvalues) free(tmp_catvalues); return buffer; } bool cBlacklist::Parse(const char *s) { char *line; char *pos; char *pos_next; int parameter = 1; int valuelen; char value[MaxFileName]; pos = line = strdup(s); pos_next = pos + strlen(pos); if (*pos_next == '\n') *pos_next = 0; while (*pos) { while (*pos == ' ') pos++; if (*pos) { if (*pos != ':') { pos_next = strchr(pos, ':'); if (!pos_next) pos_next = pos + strlen(pos); valuelen = pos_next - pos + 1; if (valuelen > MaxFileName) valuelen = MaxFileName; strn0cpy(value, pos, valuelen); pos = pos_next; switch (parameter) { case 1: ID = atoi(value); break; case 2: strcpy(search, value); break; case 3: useTime = atoi(value); break; case 4: startTime = atoi(value); break; case 5: stopTime = atoi(value); break; case 6: useChannel = atoi(value); break; case 7: if (useChannel == 0) { channelMin = NULL; channelMax = NULL; } else if (useChannel == 1) { int minNum=0, maxNum=0; int fields = sscanf(value, "%d-%d", &minNum, &maxNum); if (fields == 0) // stored with ID { #ifdef __FreeBSD__ char *channelMinbuffer = MALLOC(char, 32); char *channelMaxbuffer = MALLOC(char, 32); int channels = sscanf(value, "%31[^|]|%31[^|]", channelMinbuffer, channelMaxbuffer); #else char *channelMinbuffer = NULL; char *channelMaxbuffer = NULL; int channels = sscanf(value, "%m[^|]|%m[^|]", &channelMinbuffer, &channelMaxbuffer); #endif LOCK_CHANNELS_READ; channelMin = Channels->GetByChannelID(tChannelID::FromString(channelMinbuffer), true, true); if (!channelMin) { LogFile.eSysLog("ERROR: channel %s not defined", channelMinbuffer); channelMin = channelMax = NULL; useChannel = 0; } if (channels == 1) channelMax = channelMin; else { channelMax = Channels->GetByChannelID(tChannelID::FromString(channelMaxbuffer), true, true); if (!channelMax) { LogFile.eSysLog("ERROR: channel %s not defined", channelMaxbuffer); channelMin = channelMax = NULL; useChannel = 0; } } free(channelMinbuffer); free(channelMaxbuffer); } } else if (useChannel == 2) channelGroup = strdup(value); break; case 8: useCase = atoi(value); break; case 9: mode = atoi(value); break; case 10: useTitle = atoi(value); break; case 11: useSubtitle = atoi(value); break; case 12: useDescription = atoi(value); break; case 13: useDuration = atoi(value); break; case 14: minDuration = atoi(value); break; case 15: maxDuration = atoi(value); break; case 16: useDayOfWeek = atoi(value); break; case 17: DayOfWeek = atoi(value); break; case 18: useExtEPGInfo = atoi(value); break; case 19: if (!ParseExtEPGValues(value)) { LogFile.eSysLog("ERROR reading ext. EPG values - 1"); free(line); return false; } break; case 20: fuzzyTolerance = atoi(value); break; case 21: ignoreMissingEPGCats = atoi(value); break; case 22: isGlobal = atoi(value); break; default: break; } //switch } parameter++; } if (*pos) pos++; } //while strreplace(search, '|', ':'); while(strstr(search, "!^pipe^!")) strreplace(search, "!^pipe^!", "|"); free(line); return (parameter >= 19) ? true : false; } bool cBlacklist::ParseExtEPGValues(const char *s) { char *line; char *pos; char *pos_next; int valuelen; char value[MaxFileName]; pos = line = strdup(s); pos_next = pos + strlen(pos); if (*pos_next == '\n') *pos_next = 0; while (*pos) { while (*pos == ' ') pos++; if (*pos) { if (*pos != '|') { pos_next = strchr(pos, '|'); if (!pos_next) pos_next = pos + strlen(pos); valuelen = pos_next - pos + 1; if (valuelen > MaxFileName) valuelen = MaxFileName; strn0cpy(value, pos, valuelen); pos = pos_next; if (!ParseExtEPGEntry(value)) { LogFile.eSysLog("ERROR reading ext. EPG value: %s", value); free(line); return false; } } } if (*pos) pos++; } //while free(line); return true; } bool cBlacklist::ParseExtEPGEntry(const char *s) { char *line; char *pos; char *pos_next; int parameter = 1; int valuelen; char value[MaxFileName]; int currentid = -1; pos = line = strdup(s); pos_next = pos + strlen(pos); if (*pos_next == '\n') *pos_next = 0; while (*pos) { while (*pos == ' ') pos++; if (*pos) { if (*pos != '#') { pos_next = strchr(pos, '#'); if (!pos_next) pos_next = pos + strlen(pos); valuelen = pos_next - pos + 1; if (valuelen > MaxFileName) valuelen = MaxFileName; strn0cpy(value, pos, valuelen); pos = pos_next; switch (parameter) { case 1: { currentid = atoi(value); int index = SearchExtCats.GetIndexFromID(currentid); if (index > -1) strcpy(catvalues[index], ""); } break; case 2: if (currentid > -1) { int index = SearchExtCats.GetIndexFromID(currentid); if (index > -1) { while(strstr(value, "!^colon^!")) strreplace(value, "!^colon^!", ":"); while(strstr(value, "!^pipe^!")) strreplace(value, "!^pipe^!", "|"); strcpy(catvalues[index], value); } } break; default: break; } //switch } parameter++; } if (*pos) pos++; } //while free(line); return (parameter >= 2) ? true : false; } bool cBlacklist::Save(FILE *f) { return fprintf(f, "%s\n", ToText()) > 0; } const cEvent * cBlacklist::GetEventByBlacklist(const cSchedule *schedule, const cEvent *Start, int MarginStop) { const cEvent *pe = NULL; const cEvent *p1 = NULL; if (Start) p1 = schedule->Events()->Next(Start); else p1 = schedule->Events()->First(); time_t tNow=time(NULL); char* szTest = NULL; char* searchText = strdup(search); if (!useCase) ToLower(searchText); int searchStart = 0, searchStop = 0; if (useTime) { searchStart = startTime; searchStop = stopTime; if (searchStop < searchStart) searchStop += 2400; } int minSearchDuration = 0; int maxSearchDuration = 0; if (useDuration) { minSearchDuration = minDuration/100*60 + minDuration%100; maxSearchDuration = maxDuration/100*60 + maxDuration%100; } for (const cEvent *p = p1; p; p = schedule->Events()->Next(p)) { if(!p) { break; } if (szTest) { free(szTest); szTest = NULL; } // ignore events without title if (!p->Title() || strlen(p->Title()) == 0) continue; msprintf(&szTest, "%s%s%s%s%s", (useTitle?p->Title():""), (useSubtitle||useDescription)?"~":"", (useSubtitle?p->ShortText():""),useDescription?"~":"", (useDescription?p->Description():"")); if (tNow < p->EndTime() + MarginStop * 60) { if (!useCase) ToLower(szTest); if (useTime) { time_t tEvent = p->StartTime(); struct tm tmEvent; localtime_r(&tEvent, &tmEvent); int eventStart = tmEvent.tm_hour*100 + tmEvent.tm_min; int eventStart2 = tmEvent.tm_hour*100 + tmEvent.tm_min + 2400; if ((eventStart < searchStart || eventStart > searchStop) && (eventStart2 < searchStart || eventStart2 > searchStop)) continue; } if (useDuration) { int duration = p->Duration()/60; if (minSearchDuration > duration || maxSearchDuration < duration) continue; } if (useDayOfWeek) { time_t tEvent = p->StartTime(); struct tm tmEvent; localtime_r(&tEvent, &tmEvent); if (DayOfWeek >= 0 && DayOfWeek != tmEvent.tm_wday) continue; if (DayOfWeek < 0) { int iFound = 0; for(int i=0; i<7; i++) if (abs(DayOfWeek) & (int)pow(2,i) && i == tmEvent.tm_wday) { iFound = 1; break; } if (!iFound) continue; } } if (strlen(szTest) > 0) { if (!MatchesSearchMode(szTest, searchText, mode," ,;|~", fuzzyTolerance)) continue; } if (useExtEPGInfo && !MatchesExtEPGInfo(p)) continue; pe=p; break; } } if (szTest) free(szTest); free(searchText); return pe; } // returns a pointer array to the matching search results cSearchResults* cBlacklist::Run(cSearchResults* pSearchResults, int MarginStop) { LogFile.Log(3,"start search for blacklist '%s'", search); LOCK_CHANNELS_READ; LOCK_SCHEDULES_READ; const cSchedule *Schedule = Schedules->First(); while (Schedule) { const cChannel* channel = Channels->GetByChannelID(Schedule->ChannelID(),true,true); if (!channel) { Schedule = (const cSchedule *)Schedules->Next(Schedule); continue; } if (useChannel == 1 && channelMin && channelMax) { if (channelMin->Number() > channel->Number() || channelMax->Number() < channel->Number()) { Schedule = (const cSchedule *)Schedules->Next(Schedule); continue; } } if (useChannel == 2 && channelGroup) { cChannelGroup* group = ChannelGroups.GetGroupByName(channelGroup); if (!group || !group->ChannelInGroup(channel)) { Schedule = (const cSchedule *)Schedules->Next(Schedule); continue; } } if (useChannel == 3) { if (channel->Ca() >= CA_ENCRYPTED_MIN) { Schedule = (const cSchedule *)Schedules->Next(Schedule); continue; } } const cEvent *pPrevEvent = NULL; do { const cEvent* event = GetEventByBlacklist(Schedule, pPrevEvent, MarginStop); pPrevEvent = event; if (event && Channels->GetByChannelID(event->ChannelID(),true,true)) { if (!pSearchResults) pSearchResults = new cSearchResults; pSearchResults->Add(new cSearchResult(event, this)); } } while(pPrevEvent); Schedule = (const cSchedule *)Schedules->Next(Schedule); } LogFile.Log(3,"found %d event(s) for blacklist '%s'", pSearchResults?pSearchResults->Count():0, search); return pSearchResults; } bool cBlacklist::MatchesExtEPGInfo(const cEvent* e) { if (!e || !e->Description()) return false; cSearchExtCat* SearchExtCat = SearchExtCats.First(); while (SearchExtCat) { char* value = NULL; int index = SearchExtCats.GetIndexFromID(SearchExtCat->id); if (index > -1) value = catvalues[index]; if (value && strlen(value) > 0) { char* testvalue = GetExtEPGValue(e, SearchExtCat); if (!testvalue) return false; // compare not case sensitive char* valueLower = strdup(value); ToLower(valueLower); ToLower(testvalue); if (!MatchesSearchMode(testvalue, valueLower, SearchExtCat->searchmode, ",;|~", fuzzyTolerance)) { free(testvalue); free(valueLower); return false; } free(testvalue); free(valueLower); } SearchExtCat = SearchExtCats.Next(SearchExtCat); } return true; } // -- cBlacklists ---------------------------------------------------------------- int cBlacklists::GetNewID() { int newID = -1; cMutexLock BlacklistLock(this); cBlacklist *l = (cBlacklist *)First(); while (l) { newID = std::max(newID, l->ID); l = (cBlacklist *)l->Next(); } return newID+1; } cBlacklist* cBlacklists::GetBlacklistFromID(int ID) { if (ID == -1) return NULL; cMutexLock BlacklistLock(this); cBlacklist *l = (cBlacklist *)First(); while (l) { if (l->ID == ID) return l; l = (cBlacklist *)l->Next(); } return NULL; } bool cBlacklists::Exists(const cBlacklist* Blacklist) { cMutexLock BlacklistLock(this); cBlacklist *l = (cBlacklist*)First(); while (l) { if (l == Blacklist) return true; l = (cBlacklist*)l->Next(); } return false; } vdr-plugin-epgsearch/switchtimer.h0000644000175000017500000000353513145412721017151 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #ifndef __SWITCHTIMER_H #define __SWITCHTIMER_H #include class cSwitchTimer : public cListObject { public: tEventID eventID; time_t startTime; tChannelID channelID; int switchMinsBefore; int mode; // 0 = switch, 1 = announce only, 2 = ask for switch int unmute; cSwitchTimer(void); cSwitchTimer(const cEvent* Event, int SwitchMinsBefore=1, int mode=0, int unmute=0); cSwitchTimer& operator= (const cSwitchTimer &SwitchTimer); const cEvent* Event(); bool Parse(const char *s); cString ToText(bool& ignore); bool Save(FILE *f); }; class cSwitchTimers : public cConfig, public cMutex { public: cSwitchTimers(void) {} ~cSwitchTimers(void) {} cSwitchTimer* InSwitchList(const cEvent* event); bool Exists(const cSwitchTimer* SwitchTimer); }; extern cSwitchTimers SwitchTimers; #endif vdr-plugin-epgsearch/confdloader.h0000644000175000017500000000225313145412721017063 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #ifndef VDR_EPGSEARCH_CONFDLOADER_INC #define VDR_EPGSEARCH_CONFDLOADER_INC class cConfDLoader { public: cConfDLoader() {} bool Load(); bool LoadFile(const char *FileName); }; #endif vdr-plugin-epgsearch/templatefile.h0000644000175000017500000000511013145412721017251 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #ifndef __EPGSEARCHTEMPLFILE_H #define __EPGSEARCHTEMPLFILE_H #include #include #include using std::set; #define MAXTEMPLLEN 2000 class cMenuTemplate { private: char name[MAXTEMPLLEN]; char* menuTemplate; int menuTabs[cSkinDisplayMenu::MaxTabs]; public: cMenuTemplate(const char* Name) { strcpy(name, Name); menuTemplate = 0; for(int i=0; i { public: static set menuTemplates; // the set of all templates static char** SearchTemplates; // an array thats stores the name of all search results templates cTemplFile(); static bool Parse(const char *Name, const char *Value); bool Load(const char *FileName); static void PrepareDefaultTemplates(); static void Reset(); static cMenuTemplate* GetTemplateByName(const char* Name); static int CountSearchResultsTemplates(); static cMenuTemplate* GetSearchTemplateByPos(int iPos); }; #endif vdr-plugin-epgsearch/menu_blacklistedit.h0000644000175000017500000000332213145412721020443 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #ifndef __MENU_BLACKLISTEDIT_H #define __MENU_BLACKLISTEDIT_H #include "blacklist.h" // --- cMenuBlacklistEdit -------------------------------------------------------- class cMenuBlacklistEdit: public cOsdMenu { protected: cBlacklist *blacklist; cBlacklist data; int channelMin; int channelMax; bool addIfConfirmed; int UserDefDayOfWeek; int channelGroupNr; char* channelGroupName; char** menuitemsChGr; int* catvaluesNumeric; char *SearchModes[6]; char *DaysOfWeek[8]; char *UseChannelSel[4]; public: cMenuBlacklistEdit(cBlacklist *Blacklist, bool New = false); virtual eOSState ProcessKey(eKeys Key); virtual ~cMenuBlacklistEdit(); virtual void Set(); void CreateMenuitemsChannelGroups(); }; #endif vdr-plugin-epgsearch/blacklist.h0000644000175000017500000000611013145412721016547 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #ifndef __EPGSEARCHBL_H #define __EPGSEARCHBL_H #include class cSearchExt; class cSearchResults; class cBlacklist : public cListObject { friend class cMenuEditSearchExt; public: int ID; char search[MaxFileName]; int options; int useTime; int startTime; int stopTime; int useChannel; const cChannel *channelMin; const cChannel *channelMax; char* channelGroup; int useCase; int mode; int useTitle; int useSubtitle; int useDescription; int useDuration; int minDuration; int maxDuration; int useDayOfWeek; int DayOfWeek; int useExtEPGInfo; int ignoreMissingEPGCats; char** catvalues; int fuzzyTolerance; int isGlobal; static char *buffer; public: cBlacklist(void); virtual ~cBlacklist(void); cBlacklist& operator= (const cBlacklist&); virtual bool operator< (const cListObject &ListObject); const char *Search(void) { return search; } int Options(void) { return options; } int StartTime(void) { return startTime; } int StopTime(void) { return stopTime; } int UseChannel(void) { return useChannel; } const cChannel *ChannelMin(void) { return channelMin; } const cChannel *ChannelMax(void) { return channelMax; } const cEvent * GetEventByBlacklist(const cSchedule *schedules, const cEvent *Start, int MarginStop = 0); bool MatchesExtEPGInfo(const cEvent* e); const char *ToText(void); bool Parse(const char *s); bool ParseExtEPGValues(const char *s); bool ParseExtEPGEntry(const char *s); bool Save(FILE *f); cSearchResults* Run(cSearchResults* pSearchResults = NULL, int MarginStop = 0); void CopyFromTemplate(const cSearchExt* templ); }; class cBlacklists : public cConfig, public cMutex { public: int GetNewID(void); cBlacklist* GetBlacklistFromID(int ID); bool Exists(const cBlacklist* Blacklist); }; class cBlacklistObject: public cListObject { public: cBlacklist* blacklist; cBlacklistObject(cBlacklist* Blacklist) : blacklist(Blacklist) {} }; extern cBlacklists Blacklists; #endif vdr-plugin-epgsearch/recstatus.h0000644000175000017500000000362113145412721016620 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #ifndef __RECSTATUS_H #define __RECSTATUS_H #include #include "recdone.h" #include "epgsearchtools.h" // --- cRecDoneTimerObj -------------------------------------------------------- class cRecDoneTimerObj : public cTimerObj { public: int deviceNr; cRecDone* recDone; time_t lastBreak; public: cRecDoneTimerObj(const cTimer* Timer, int DeviceNr) : cTimerObj(Timer), deviceNr(DeviceNr), recDone(NULL), lastBreak(0) {} ~cRecDoneTimerObj() { timer = NULL; recDone = NULL; } // do not delete anything! }; class cTimersRecording: public cList, public cMutex { }; extern cTimersRecording TimersRecording; class cRecStatusMonitor : public cStatus { protected: virtual void Recording(const cDevice *Device, const char *Name, const char*, bool On); public: cRecStatusMonitor(); int TimerRecDevice(const cTimer*); }; extern cRecStatusMonitor* gl_recStatusMonitor; #endif vdr-plugin-epgsearch/distance.h0000644000175000017500000000314313145412721016374 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ //--------------------------------------------------- // Levenshtein Distance // by Michael Gilleland, Merriam Park Software // // source: // http://www.merriampark.com/ld.htm#CPLUSPLUS // //--------------------------------------------------- #ifndef _DISTANCE_INC_ #define _DISTANCE_INC_ class Distance { public: int LD (char const *s, char const *t, int maxLength); private: int Minimum (int a, int b, int c); int *GetCellPointer (int *pOrigin, int col, int row, int nCols); int GetAt (int *pOrigin, int col, int row, int nCols); void PutAt (int *pOrigin, int col, int row, int nCols, int x); }; #endif vdr-plugin-epgsearch/md5.c0000644000175000017500000002251313145412721015264 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ ///////////////////////////////////////////////////////////////////////// // MD5.cpp // Implementation file for MD5 class // // This C++ Class implementation of the original RSA Data Security, Inc. // MD5 Message-Digest Algorithm is copyright (c) 2002, Gary McNickle. // All rights reserved. This software is a derivative of the "RSA Data // Security, Inc. MD5 Message-Digest Algorithm" // // You may use this software free of any charge, but without any // warranty or implied warranty, provided that you follow the terms // of the original RSA copyright, listed below. // // Original RSA Data Security, Inc. Copyright notice ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All // rights reserved. // // License to copy and use this software is granted provided that it // is identified as the "RSA Data Security, Inc. MD5 Message-Digest // Algorithm" in all material mentioning or referencing this software // or this function. // License is also granted to make and use derivative works provided // that such works are identified as "derived from the RSA Data // Security, Inc. MD5 Message-Digest Algorithm" in all material // mentioning or referencing the derived work. // RSA Data Security, Inc. makes no representations concerning either // the merchantability of this software or the suitability of this // software for any particular purpose. It is provided "as is" // without express or implied warranty of any kind. // These notices must be retained in any copies of any part of this // documentation and/or software. ///////////////////////////////////////////////////////////////////////// #include #include #include #include #include "md5.h" static unsigned char PADDING[64] = { 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; #define S11 7 #define S12 12 #define S13 17 #define S14 22 #define S21 5 #define S22 9 #define S23 14 #define S24 20 #define S31 4 #define S32 11 #define S33 16 #define S34 23 #define S41 6 #define S42 10 #define S43 15 #define S44 21 // PrintMD5: Converts a completed md5 digest into a char* string. char* PrintMD5(uchar md5Digest[16]) { char chBuffer[256]; char chEach[10]; int nCount; memset(chBuffer,0,256); memset(chEach, 0, 10); for (nCount = 0; nCount < 16; nCount++) { sprintf(chEach, "%02x", md5Digest[nCount]); strncat(chBuffer, chEach, sizeof(chEach)); } return strdup(chBuffer); } // MD5String: Performs the MD5 algorithm on a char* string, returning // the results as a char*. char* MD5String(char* szString) { int nLen = strlen(szString); md5 alg; alg.Update((unsigned char*)szString, (unsigned int)nLen); alg.Finalize(); return PrintMD5(alg.Digest()); } // md5::Init // Initializes a new context. void md5::Init() { memset(m_Count, 0, 2 * sizeof(uint4)); m_State[0] = 0x67452301; m_State[1] = 0xefcdab89; m_State[2] = 0x98badcfe; m_State[3] = 0x10325476; } // md5::Update // MD5 block update operation. Continues an MD5 message-digest // operation, processing another message block, and updating the // context. void md5::Update(uchar* chInput, uint4 nInputLen) { uint4 i, index, partLen; // Compute number of bytes mod 64 index = (unsigned int)((m_Count[0] >> 3) & 0x3F); // Update number of bits if ((m_Count[0] += (nInputLen << 3)) < (nInputLen << 3)) m_Count[1]++; m_Count[1] += (nInputLen >> 29); partLen = 64 - index; // Transform as many times as possible. if (nInputLen >= partLen) { memcpy( &m_Buffer[index], chInput, partLen ); Transform(m_Buffer); for (i = partLen; i + 63 < nInputLen; i += 64) Transform(&chInput[i]); index = 0; } else i = 0; // Buffer remaining input memcpy( &m_Buffer[index], &chInput[i], nInputLen-i ); } // md5::Finalize // MD5 finalization. Ends an MD5 message-digest operation, writing // the message digest and zeroizing the context. void md5::Finalize() { uchar bits[8]; uint4 index, padLen; // Save number of bits Encode (bits, m_Count, 8); // Pad out to 56 mod 64 index = (unsigned int)((m_Count[0] >> 3) & 0x3f); padLen = (index < 56) ? (56 - index) : (120 - index); Update(PADDING, padLen); // Append length (before padding) Update (bits, 8); // Store state in digest Encode (m_Digest, m_State, 16); memset(m_Count, 0, 2 * sizeof(uint4)); memset(m_State, 0, 4 * sizeof(uint4)); memset(m_Buffer,0, 64 * sizeof(uchar)); } // md5::Transform // MD5 basic transformation. Transforms state based on block. void md5::Transform (uchar* block) { uint4 a = m_State[0], b = m_State[1], c = m_State[2], d = m_State[3], x[16]; Decode (x, block, 64); // Round 1 FF (a, b, c, d, x[ 0], S11, 0xd76aa478); FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); FF (c, d, a, b, x[ 2], S13, 0x242070db); FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); FF (d, a, b, c, x[ 5], S12, 0x4787c62a); FF (c, d, a, b, x[ 6], S13, 0xa8304613); FF (b, c, d, a, x[ 7], S14, 0xfd469501); FF (a, b, c, d, x[ 8], S11, 0x698098d8); FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); FF (c, d, a, b, x[10], S13, 0xffff5bb1); FF (b, c, d, a, x[11], S14, 0x895cd7be); FF (a, b, c, d, x[12], S11, 0x6b901122); FF (d, a, b, c, x[13], S12, 0xfd987193); FF (c, d, a, b, x[14], S13, 0xa679438e); FF (b, c, d, a, x[15], S14, 0x49b40821); // Round 2 GG (a, b, c, d, x[ 1], S21, 0xf61e2562); GG (d, a, b, c, x[ 6], S22, 0xc040b340); GG (c, d, a, b, x[11], S23, 0x265e5a51); GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); GG (a, b, c, d, x[ 5], S21, 0xd62f105d); GG (d, a, b, c, x[10], S22, 0x2441453); GG (c, d, a, b, x[15], S23, 0xd8a1e681); GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); GG (d, a, b, c, x[14], S22, 0xc33707d6); GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); GG (b, c, d, a, x[ 8], S24, 0x455a14ed); GG (a, b, c, d, x[13], S21, 0xa9e3e905); GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); GG (c, d, a, b, x[ 7], S23, 0x676f02d9); GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); // Round 3 HH (a, b, c, d, x[ 5], S31, 0xfffa3942); HH (d, a, b, c, x[ 8], S32, 0x8771f681); HH (c, d, a, b, x[11], S33, 0x6d9d6122); HH (b, c, d, a, x[14], S34, 0xfde5380c); HH (a, b, c, d, x[ 1], S31, 0xa4beea44); HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); HH (b, c, d, a, x[10], S34, 0xbebfbc70); HH (a, b, c, d, x[13], S31, 0x289b7ec6); HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); HH (b, c, d, a, x[ 6], S34, 0x4881d05); HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); HH (d, a, b, c, x[12], S32, 0xe6db99e5); HH (c, d, a, b, x[15], S33, 0x1fa27cf8); HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); // Round 4 II (a, b, c, d, x[ 0], S41, 0xf4292244); II (d, a, b, c, x[ 7], S42, 0x432aff97); II (c, d, a, b, x[14], S43, 0xab9423a7); II (b, c, d, a, x[ 5], S44, 0xfc93a039); II (a, b, c, d, x[12], S41, 0x655b59c3); II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); II (c, d, a, b, x[10], S43, 0xffeff47d); II (b, c, d, a, x[ 1], S44, 0x85845dd1); II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); II (d, a, b, c, x[15], S42, 0xfe2ce6e0); II (c, d, a, b, x[ 6], S43, 0xa3014314); II (b, c, d, a, x[13], S44, 0x4e0811a1); II (a, b, c, d, x[ 4], S41, 0xf7537e82); II (d, a, b, c, x[11], S42, 0xbd3af235); II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); II (b, c, d, a, x[ 9], S44, 0xeb86d391); m_State[0] += a; m_State[1] += b; m_State[2] += c; m_State[3] += d; memset(x, 0, sizeof(x)); } // md5::Encode // Encodes input (uint4) into output (uchar). Assumes nLength is // a multiple of 4. void md5::Encode(uchar* dest, uint4* src, uint4 nLength) { uint4 i, j; assert(nLength % 4 == 0); for (i = 0, j = 0; j < nLength; i++, j += 4) { dest[j] = (uchar)(src[i] & 0xff); dest[j+1] = (uchar)((src[i] >> 8) & 0xff); dest[j+2] = (uchar)((src[i] >> 16) & 0xff); dest[j+3] = (uchar)((src[i] >> 24) & 0xff); } } // md5::Decode // Decodes input (uchar) into output (uint4). Assumes nLength is // a multiple of 4. void md5::Decode(uint4* dest, uchar* src, uint4 nLength) { uint4 i, j; assert(nLength % 4 == 0); for (i = 0, j = 0; j < nLength; i++, j += 4) { dest[i] = ((uint4)src[j]) | (((uint4)src[j+1])<<8) | (((uint4)src[j+2])<<16) | (((uint4)src[j+3])<<24); } } vdr-plugin-epgsearch/menu_search.h0000644000175000017500000000256413145412721017101 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #ifndef __MENU_SEARCH_H #define __MENU_SEARCH_H #include #include "epgsearchext.h" class cMenuEPGSearchExt : public cOsdMenu { private: eOSState New(void); eOSState Delete(void); eOSState Actions(eKeys Key); protected: virtual eOSState ProcessKey(eKeys Key); public: cMenuEPGSearchExt(); cSearchExt* CurrentSearchExt(void); void UpdateTitle(); }; #endif vdr-plugin-epgsearch/mail.c0000644000175000017500000004740113145412721015524 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #include #include #include #include "mail.h" #include "epgsearchcfg.h" #include "log.h" #include "epgsearchtools.h" #include "uservars.h" #include "noannounce.h" #include "pending_notifications.h" #ifndef SENDMAIL #define SENDMAIL "/usr/sbin/sendmail" #endif extern bool isUTF8; using namespace std; string cMailNotifier::MailCmd = "sendEmail.pl"; // ---------------------- // cMailTimerNotification string cMailTimerNotification::Format(const string& templ) const { const cEvent* pEvent = GetEvent(); if (!pEvent) return ""; eTimerMatch TimerMatch = tmNone; LOCK_TIMERS_READ; const cTimer* pTimer = Timers->GetMatch(pEvent, &TimerMatch); if (!pTimer) return ""; string result = templ; cVarExpr varExprEvent(result); result = varExprEvent.Evaluate(pEvent); cVarExpr varExprTimer(result); result = varExprTimer.Evaluate(pTimer); if (timerMod == tmStartStop) result = ReplaceAll(result, "%timer.modreason%", tr("Start/Stop time has changed")); if (timerMod == tmFile) result = ReplaceAll(result, "%timer.modreason%", tr("Title/episode has changed")); else result = ReplaceAll(result, "%timer.modreason%", ""); return result; } const cEvent* cMailTimerNotification::GetEvent() const { LOCK_SCHEDULES_READ; if (!Schedules) return NULL; const cSchedule *schedule = Schedules->GetSchedule(channelID); if (!schedule) return NULL; return schedule->GetEvent(eventID); } bool cMailTimerNotification::operator< (const cMailTimerNotification &N) const { LOCK_CHANNELS_READ; const cChannel* channel = Channels->GetByChannelID(channelID,true,true); const cChannel* channelOther = Channels->GetByChannelID(N.channelID,true,true); if (!channel || !channelOther) return false; const cEvent* event = GetEvent(); const cEvent* eventOther = N.GetEvent(); if (event && eventOther) // sort event by start time and channel { if (event->StartTime() == eventOther->StartTime()) return channel->Number() < channelOther->Number(); else return event->StartTime() < eventOther->StartTime(); } return false; } // ------------------------- // cMailDelTimerNotification cMailDelTimerNotification::cMailDelTimerNotification(const cTimer* pTimer, const cEvent* pEvent, const string& templ) { if (!pTimer || !pTimer->Channel()) return; channelID = pTimer->Channel()->GetChannelID(); start = pTimer->StartTime(); string result = templ; cVarExpr varExprEvent(result); result = varExprEvent.Evaluate(pEvent); cVarExpr varExprTimer(result); formatted = varExprTimer.Evaluate(pTimer); } cMailDelTimerNotification::cMailDelTimerNotification(const string& Formatted, tChannelID ChannelID, time_t Start) { formatted = Formatted; channelID = ChannelID; start = Start; } bool cMailDelTimerNotification::operator< (const cMailDelTimerNotification &N) const { LOCK_CHANNELS_READ; const cChannel* channel = Channels->GetByChannelID(channelID,true,true); const cChannel* channelOther = Channels->GetByChannelID(N.channelID,true,true); if (!channel || !channelOther) return false; if (channel != channelOther) return channel->Number() < channelOther->Number(); else return (start < N.start); } // ---------------------- // cMailAnnounceEventNotification string cMailAnnounceEventNotification::Format(const string& templ) const { const cEvent* pEvent = GetEvent(); if (!pEvent) return ""; string result = templ; cVarExpr varExprEvent(result); result = varExprEvent.Evaluate(pEvent); result = ReplaceAll(result, "%searchid%", NumToString(searchextID)); cSearchExt* search = SearchExts.GetSearchFromID(searchextID); if (search) result = ReplaceAll(result, "%search%", search->search); return result; } // ------------- // cMailNotifier cMailNotifier::cMailNotifier(string Subject, string Body) : subject(Subject), body(Body) { if (subject.size() > 0) SendMail(true); } bool cMailNotifier::SendMailViaSendmail() { char mailcmd[256]; const char* mailargs = "%s -i -FVDR -oem %s"; const char* mailproc = SENDMAIL; FILE* mail; string to = EPGSearchConfig.MailAddressTo; snprintf(mailcmd, sizeof(mailcmd), mailargs, mailproc, to.c_str()); if (!(mail = popen(mailcmd, "w"))) { return false; } fprintf(mail, "From: VDR\n"); fprintf(mail, "To: %s\n", to.c_str()); fprintf(mail, "Subject: %s\n", subject.c_str()); if (FindIgnoreCase(body, "") >= 0) fprintf(mail, "Content-Type: text/html; charset=%s\n", GetCodeset().c_str()); else fprintf(mail, "Content-Type: text/plain; charset=%s\n", GetCodeset().c_str()); fprintf(mail, "\n"); fprintf(mail, "%s", body.c_str()); pclose(mail); return true; } bool cMailNotifier::SendMailViaScript() { // create a temporary file for the message body string filename = *AddDirectory(CONFIGDIR, "epgsearchmail.temp"); std::ofstream bodyfile(filename.c_str()); if (!bodyfile) { LogFile.eSysLog("error opening file %s", filename.c_str()); return false; } bodyfile << body; bodyfile.close(); string AuthUser = EPGSearchConfig.MailAuthUser; string AuthPass = EPGSearchConfig.MailAuthPass; string cmdArgs = string(" -f \"VDR <") + EPGSearchConfig.MailAddress + ">\"" + " -t " + EPGSearchConfig.MailAddressTo + " -s " + EPGSearchConfig.MailServer + " -u \"" + subject + "\""+ (EPGSearchConfig.MailUseAuth? (AuthUser != "" ?(" -xu " + AuthUser):"") + (AuthPass != "" ?(" -xp " + AuthPass):"") :"") + " -o message-charset=" + GetCodeset() + " -o message-file=" + filename; bool success = ExecuteMailScript(cmdArgs); if (remove(filename.c_str()) != 0) LogFile.eSysLog("error deleting file %s", filename.c_str()); return success; } bool cMailNotifier::SendMail(bool force) { time_t nextMailDelivery = EPGSearchConfig.lastMailOnSearchtimerAt + EPGSearchConfig.sendMailOnSearchtimerHours*60*60; if (time(NULL) > nextMailDelivery || force) { if (!EPGSearchConfig.mailViaScript) return SendMailViaSendmail(); else return SendMailViaScript(); } else { LogFile.Log(2, "mail delivery delayed until %s", DAYDATETIME(nextMailDelivery)); return false; } } bool cMailNotifier::ExecuteMailScript(string ScriptArgs) { string mailCmd = MailCmd; LogFile.Log(3, "starting mail script: %s with parameters: %s", mailCmd.c_str(), ScriptArgs.c_str()); if (mailCmd == "sendEmail.pl") // beautify output for standard script ScriptArgs += " | cut -d\" \" -f 6-"; cCommand cmd; string fullcmd = "mailcmd: " + mailCmd; if (!cmd.Parse(fullcmd.c_str())) { LogFile.eSysLog("error parsing cmd: %s", MailCmd.c_str()); return false; } const char* res = cmd.Execute(ScriptArgs.c_str()); scriptReply = res?res:""; if (scriptReply != "") LogFile.iSysLog("mail cmd result: %s", scriptReply.c_str()); return true; } bool cMailNotifier::TestMailAccount(string MailAddressTo, string MailAddress, string MailServer, string AuthUser, string AuthPass) { string cmdArgs = string("-v -f \"VDR <") + MailAddress + ">\"" + " -t " + MailAddressTo + " -s " + MailServer + " -u \"VDR-Testmail\"" + (AuthUser != "" ?(" -xu " + AuthUser):"") + (AuthPass != "" ?(" -xp " + AuthPass):"") + " -m \"Success! ;-)\""; return ExecuteMailScript(cmdArgs); } string cMailNotifier::LoadTemplate(const string& templtype) { string filename = *AddDirectory(CONFIGDIR, templtype.c_str()); string templ = ""; if (filename != "" && access(filename.c_str(), F_OK) == 0) { LogFile.iSysLog("loading %s", filename.c_str()); FILE *f = fopen(filename.c_str(), "r"); if (f) { templ = ""; char *s; cReadLine ReadLine; while ((s = ReadLine.Read(f)) != NULL) { if (strlen(s) > 0 && s[0] == '#') continue; templ += string(s) + "\n"; } fclose(f); } } return templ; } string cMailNotifier::GetTemplValue(const string& templ, const string& entry) { if (templ == "" || entry == "") return ""; string start = "<" + entry + ">"; string end = ""; int eBegin = FindIgnoreCase(templ, start); int eEnd = FindIgnoreCase(templ, end); if (eBegin < 0 || eEnd < 0) return ""; string value(templ.begin() + eBegin + start.length(), templ.begin() + eEnd); return value; } // ------------------- // cMailUpdateNotifier cMailUpdateNotifier::cMailUpdateNotifier() { mailTemplate = LoadTemplate("epgsearchupdmail.templ"); } void cMailUpdateNotifier::AddNewTimerNotification(tEventID EventID, tChannelID ChannelID) { cMailTimerNotification N(EventID, ChannelID); newTimers.insert(N); } void cMailUpdateNotifier::AddModTimerNotification(tEventID EventID, tChannelID ChannelID, uint timerMod) { if (timerMod == tmNoChange || timerMod == tmAuxEventID) // if anything but the eventID has changed return; cMailTimerNotification N(EventID, ChannelID, timerMod); modTimers.insert(N); } void cMailUpdateNotifier::AddRemoveTimerNotification(const cTimer* t, const cEvent* e) { string templTimer = GetTemplValue(mailTemplate, "timer"); cMailDelTimerNotification N(t, e, templTimer); delTimers.insert(N); } void cMailUpdateNotifier::AddRemoveTimerNotification(const string& Formatted, tChannelID ChannelID, time_t Start) { cMailDelTimerNotification N(Formatted, ChannelID, Start); delTimers.insert(N); } void cMailUpdateNotifier::AddAnnounceEventNotification(tEventID EventID, tChannelID ChannelID, int SearchExtID) { cMailAnnounceEventNotification N(EventID, ChannelID, SearchExtID); announceEvents.insert(N); } void cMailUpdateNotifier::SendUpdateNotifications() { // insert pending notifications cPendingNotification* p = PendingNotifications.First(); while (p) { if (p->type == 0) AddNewTimerNotification(p->eventID, p->channelID); else if (p->type == 1) AddModTimerNotification(p->eventID, p->channelID, p->timerMod); else if (p->type == 2) AddRemoveTimerNotification(p->formatted, p->channelID, p->start); else if (p->type == 3) AddAnnounceEventNotification(p->eventID, p->channelID, p->searchID); p = PendingNotifications.Next(p); } if (newTimers.empty() && modTimers.empty() && delTimers.empty() && announceEvents.empty()) return; // extract single templates if (mailTemplate == "") { LogFile.eSysLog("error loading %s", *AddDirectory(CONFIGDIR, "epgsearchupdmail.templ")); return; } string templSubject = GetTemplValue(mailTemplate, "subject"); string templBody = GetTemplValue(mailTemplate, "mailbody"); string templTimer = GetTemplValue(mailTemplate, "timer"); string templEvent = GetTemplValue(mailTemplate, "event"); // create the timer list for new timers string newtimers; if (newTimers.empty()) newtimers = tr("No new timers were added."); std::set::iterator itnt; for (itnt = newTimers.begin(); itnt != newTimers.end(); ++itnt) { string message = (*itnt).Format(templTimer); if (message != "") newtimers += message; } // create the timer list for modified timers string modtimers; if (modTimers.empty()) modtimers = tr("No timers were modified."); std::set::iterator itmt; for (itmt = modTimers.begin(); itmt != modTimers.end(); ++itmt) { string message = (*itmt).Format(templTimer); if (message != "") modtimers += message; } // create the timer list for removed timers string deltimers; if (delTimers.empty()) deltimers = tr("No timers were deleted."); std::set::iterator itdt; for (itdt = delTimers.begin(); itdt != delTimers.end(); ++itdt) { string message = (*itdt).Format(""); if (message != "") deltimers += message; } // create the list of events to announce string announceevents; if (announceEvents.empty()) announceevents = tr("No new events to announce."); std::set::iterator itae; for (itae = announceEvents.begin(); itae != announceEvents.end(); ++itae) { string message = (*itae).Format(templEvent); if (message != "") announceevents += message; } // evaluate variables cVarExpr varExprSubj(templSubject); subject = varExprSubj.Evaluate(); subject = ReplaceAll(subject, "%update.countnewtimers%", NumToString((long)newTimers.size())); subject = ReplaceAll(subject, "%update.countmodtimers%", NumToString((long)modTimers.size())); subject = ReplaceAll(subject, "%update.countdeltimers%", NumToString((long)delTimers.size())); subject = ReplaceAll(subject, "%update.countnewevents%", NumToString((long)announceEvents.size())); newtimers = ReplaceAll(newtimers, "%update.countnewtimers%", NumToString((long)newTimers.size())); modtimers = ReplaceAll(modtimers, "%update.countmodtimers%", NumToString((long)modTimers.size())); deltimers = ReplaceAll(deltimers, "%update.countdeltimers%", NumToString((long)delTimers.size())); announceevents = ReplaceAll(announceevents, "%update.countnewevents%", NumToString((long)announceEvents.size())); cVarExpr varExprBody(templBody); body = varExprBody.Evaluate(); body = ReplaceAll(body, "%update.countnewtimers%", NumToString((long)newTimers.size())); body = ReplaceAll(body, "%update.countmodtimers%", NumToString((long)modTimers.size())); body = ReplaceAll(body, "%update.countdeltimers%", NumToString((long)delTimers.size())); body = ReplaceAll(body, "%update.countnewevents%", NumToString((long)announceEvents.size())); body = ReplaceAll(body, "%update.newtimers%", newtimers); body = ReplaceAll(body, "%update.modtimers%", modtimers); body = ReplaceAll(body, "%update.deltimers%", deltimers); body = ReplaceAll(body, "%update.newevents%", announceevents); if (SendMail()) { EPGSearchConfig.lastMailOnSearchtimerAt = time(NULL); cPluginManager::GetPlugin("epgsearch")->SetupStore("MailNotificationSearchtimersLastAt", EPGSearchConfig.lastMailOnSearchtimerAt); // remove pending notifications while((p = PendingNotifications.First()) != NULL) PendingNotifications.Del(p); } else { // add current notifications to pending ones for (itnt = newTimers.begin(); itnt != newTimers.end(); ++itnt) PendingNotifications.Add(new cPendingNotification(0, itnt->eventID, itnt->channelID, -1)); for (itmt = modTimers.begin(); itmt != modTimers.end(); ++itmt) PendingNotifications.Add(new cPendingNotification(1, itmt->eventID, itmt->channelID, -1, itmt->timerMod)); for (itdt = delTimers.begin(); itdt != delTimers.end(); ++itdt) PendingNotifications.Add(new cPendingNotification(2, -1, itdt->channelID, itdt->start, -1, -1, itdt->formatted)); for (itae = announceEvents.begin(); itae != announceEvents.end(); ++itae) PendingNotifications.Add(new cPendingNotification(3, itae->eventID, itae->channelID, -1, -1, itae->searchextID)); } PendingNotifications.Save(); newTimers.clear(); modTimers.clear(); delTimers.clear(); // Add announced events to the "no announce" list for (itae = announceEvents.begin(); itae != announceEvents.end(); ++itae) { cNoAnnounce* noAnnounce = new cNoAnnounce(itae->GetEvent()); if (noAnnounce && noAnnounce->Valid()) NoAnnounces.Add(noAnnounce); } if (!announceEvents.empty()) { NoAnnounces.ClearOutdated(); NoAnnounces.Save(); } announceEvents.clear(); } // --------------------- // cMailConflictNotifier void cMailConflictNotifier::SendConflictNotifications(cConflictCheck& conflictCheck) { if (conflictCheck.relevantConflicts == 0) return; // check if anything has changed since last mail ostringstream newMailConflicts; cList* failedList = conflictCheck.GetFailed(); if (!failedList) return; for(cConflictCheckTime* ct = failedList->First(); ct; ct = failedList->Next(ct)) { if (!ct || ct->ignore) continue; std::set::iterator it; for (it = ct->failedTimers.begin(); it != ct->failedTimers.end(); ++it) if ((*it) && !(*it)->ignore && (*it)->Event()) { std::string channelID = *(*it)->Event()->ChannelID().ToString(); newMailConflicts << (*it)->Event()->EventID() << "|" << channelID; } } string newMailConflictsMD5 = MD5(newMailConflicts.str()); if (newMailConflictsMD5 == EPGSearchConfig.LastMailConflicts) { LogFile.Log(3, "conflicts unchanged - no new notification needed."); return; } // open the template string templ = LoadTemplate("epgsearchconflmail.templ"); if (templ == "") { LogFile.eSysLog("error loading %s", *AddDirectory(CONFIGDIR, "epgsearchconflmail.templ")); return; } // extract single templates LogFile.Log(3, "extracting templates"); string templSubject = GetTemplValue(templ, "subject"); string templBody = GetTemplValue(templ, "mailbody"); string templConflictsAt = GetTemplValue(templ, "conflictsat"); string templConflictTimer = GetTemplValue(templ, "conflicttimer"); LogFile.Log(3, "extracting templates - done"); // create the conflict list string conflicts; for(cConflictCheckTime* ct = failedList->First(); ct; ct = failedList->Next(ct)) { if (ct->ignore) continue; // format conflict time string conflictsAt = templConflictsAt; conflictsAt = ReplaceAll(conflictsAt, "%conflict.time%", TIMESTRING(ct->evaltime)); conflictsAt = ReplaceAll(conflictsAt, "%conflict.date%", DATESTRING(ct->evaltime)); string conflicttimers; std::set::iterator it; for (it = ct->failedTimers.begin(); it != ct->failedTimers.end(); ++it) if (!(*it)->ignore && (*it)->Event()) { cMailTimerNotification M((*it)->Event()->EventID(), (*it)->Event()->ChannelID()); string message = M.Format(templConflictTimer); if (message != "") { message = ReplaceAll(message, "%device%", NumToString((*it)->device)); conflicttimers += message; } } conflictsAt = ReplaceAll(conflictsAt, "%conflict.confltimers%", conflicttimers); conflicts += conflictsAt; } // evaluate variables cVarExpr varExprSubj(templSubject); subject = varExprSubj.Evaluate(); subject = ReplaceAll(subject, "%conflict.count%", NumToString(conflictCheck.relevantConflicts)); conflicts = ReplaceAll(conflicts, "%conflict.count%", NumToString(conflictCheck.relevantConflicts)); cVarExpr varExprBody(templBody); body = varExprBody.Evaluate(); body = ReplaceAll(body, "%conflict.count%", NumToString(conflictCheck.relevantConflicts)); body = ReplaceAll(body, "%conflict.conflicts%", conflicts); SendMail(); // store conflicts strcpy(EPGSearchConfig.LastMailConflicts, newMailConflictsMD5.c_str()); cPluginManager::GetPlugin("epgsearch")->SetupStore("LastMailConflicts", EPGSearchConfig.LastMailConflicts); } vdr-plugin-epgsearch/menu_searchtemplate.c0000644000175000017500000001677513145412721020641 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #include #include #include #include #include "menu_searchtemplate.h" #include "epgsearchtools.h" #include "epgsearchcfg.h" #include "recdone.h" #include "menu_templateedit.h" #include "menu_searchactions.h" using namespace std; // --- cMenuSearchTemplateItem ---------------------------------------------------------- class cMenuSearchTemplateItem : public cOsdItem { private: public: cSearchExt* searchExt; cMenuSearchTemplateItem(cSearchExt* SearchExt); int Compare(const cListObject &ListObject) const; void Set(void); }; cMenuSearchTemplateItem::cMenuSearchTemplateItem(cSearchExt* SearchExt) { searchExt = SearchExt; Set(); } void cMenuSearchTemplateItem::Set(void) { ostringstream line; if (searchExt->ID == EPGSearchConfig.DefSearchTemplateID) line << "*"; else if (searchExt->useAsSearchTimer) { if (searchExt->IsActiveAt(time(NULL))) line << ">"; else line << "!"; } line << "\t"; if (searchExt->search && strlen(searchExt->search) > 0) line << setiosflags(ios::left) << string(searchExt->search); else line << setiosflags(ios::left) << "*"; line << "\t"; if (searchExt->useChannel == 1) { if (searchExt->channelMin != searchExt->channelMax) line << setiosflags(ios::left) << searchExt->channelMin->Number() << " - " << searchExt->channelMax->Number(); else line << setiosflags(ios::left) << setw(11) << (searchExt->useChannel?CHANNELNAME(searchExt->channelMin):""); } else if (searchExt->useChannel == 2) line << setiosflags(ios::left) << setw(11) << searchExt->channelGroup; line << "\t"; if (searchExt->useTime) { ostringstream timeline; timeline << setfill('0') << setw(2) << searchExt->startTime / 100 << ":" << setw(2) << searchExt->startTime % 100; timeline << "\t"; timeline << setfill('0') << setw(2) << searchExt->stopTime / 100 << ":" << setw(2) << searchExt->stopTime % 100; line << timeline.str(); } else line << "--:--\t--:--"; SetText(strdup(line.str().c_str()), false); } int cMenuSearchTemplateItem::Compare(const cListObject &ListObject) const { cMenuSearchTemplateItem *p = (cMenuSearchTemplateItem *)&ListObject; return strcasecmp(searchExt->search, p->searchExt->search); } // --- cMenuEPGSearchTemplate ---------------------------------------------------------- cMenuEPGSearchTemplate::cMenuEPGSearchTemplate(cSearchExt* Search, cBlacklist* Blacklist, bool New) :cOsdMenu(tr("Search templates"), 2, 20, 11, 6, 5) { SetMenuCategory(mcPlugin); search = Search; blacklist = Blacklist; newSearch = New; cMutexLock SearchTemplatesLock(&SearchTemplates); cSearchExt *SearchExt = SearchTemplates.First(); while (SearchExt) { Add(new cMenuSearchTemplateItem(SearchExt)); SearchExt = SearchTemplates.Next(SearchExt); } SetHelp(trVDR("Button$Edit"), trVDR("Button$New"), trVDR("Button$Delete"), tr("Button$Default")); Sort(); Display(); } cSearchExt *cMenuEPGSearchTemplate::CurrentSearchTemplate(void) { cMenuSearchTemplateItem *item = (cMenuSearchTemplateItem *)Get(Current()); return item ? item->searchExt : NULL; } eOSState cMenuEPGSearchTemplate::New(void) { if (HasSubMenu()) return osContinue; return AddSubMenu(new cMenuEditTemplate(new cSearchExt, true)); } eOSState cMenuEPGSearchTemplate::Delete(void) { cSearchExt *curSearchExt = CurrentSearchTemplate(); if (curSearchExt) { if (Interface->Confirm(tr("Edit$Delete template?"))) { cMutexLock SearchTemplatesLock(&SearchTemplates); SearchTemplates.Del(curSearchExt); SearchTemplates.Save(); cOsdMenu::Del(Current()); Display(); } } return osContinue; } eOSState cMenuEPGSearchTemplate::DefaultTemplate(void) { if (HasSubMenu()) return osContinue; cSearchExt *curSearchExt = CurrentSearchTemplate(); int current = Current(); cMenuSearchTemplateItem *oldDefaultTemplateItem = NULL; for(int i=0; isearchExt && item->searchExt->ID == EPGSearchConfig.DefSearchTemplateID) oldDefaultTemplateItem = item; } if (curSearchExt) { if (EPGSearchConfig.DefSearchTemplateID == curSearchExt->ID) EPGSearchConfig.DefSearchTemplateID = -1; else EPGSearchConfig.DefSearchTemplateID = curSearchExt->ID; cPluginManager::GetPlugin("epgsearch")->SetupStore("DefSearchTemplateID", EPGSearchConfig.DefSearchTemplateID); SetCurrent(oldDefaultTemplateItem); RefreshCurrent(); DisplayCurrent(true); SetCurrent(Get(current)); RefreshCurrent(); DisplayCurrent(true); Display(); } return osContinue; } eOSState cMenuEPGSearchTemplate::ProcessKey(eKeys Key) { int SearchNumber = HasSubMenu() ? Count() : -1; eOSState state = cOsdMenu::ProcessKey(Key); if (state == osUnknown) { if (HasSubMenu()) return osContinue; switch (Key) { case kOk: { if (search) { if (!newSearch && !Interface->Confirm(tr("Overwrite existing entries?"))) return osBack; // duplicate template cSearchExt* t =CurrentSearchTemplate(); if (!t) return osContinue; // copy all except the name and id search->CopyFromTemplate(t); } if (blacklist) { if (!newSearch && !Interface->Confirm(tr("Overwrite existing entries?"))) return osBack; // duplicate template cSearchExt* t =CurrentSearchTemplate(); if (!t) return osContinue; // copy all except the name and id blacklist->CopyFromTemplate(t); } return osBack; } case kRed: if (CurrentSearchTemplate()) state = AddSubMenu(new cMenuEditTemplate(CurrentSearchTemplate())); else state = osContinue; break; case kGreen: state = New(); break; case kYellow: state = Delete(); break; case kBlue: state = DefaultTemplate(); break; default: break; } } if (SearchNumber >= 0 && !HasSubMenu()) { cSearchExt* search = SearchTemplates.Get(SearchNumber); if (search) // a newly created template was confirmed with Ok Add(new cMenuSearchTemplateItem(search)); else search = CurrentSearchTemplate(); // always update all entries, since channel group names may have changed and affect other searches Sort(); for(int i=0; iSet(); if (item->searchExt == search) SetCurrent(item); } } Display(); } return state; } vdr-plugin-epgsearch/menu_searchactions.h0000644000175000017500000000300313145412721020447 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #ifndef __EPGSEARCHACTIONS_H #define __EPGSEARCHACTIONS_H #include #include "epgsearchext.h" // --- cMenuSearchActions --------------------------------------------------------- class cMenuSearchActions : public cOsdMenu { private: cSearchExt* search; bool directCall; eOSState Search(void); eOSState OnOffSearchtimer(void); eOSState Execute(); public: cMenuSearchActions(cSearchExt* Search, bool DirectCall = false); virtual ~cMenuSearchActions(); virtual eOSState ProcessKey(eKeys Key); }; #endif vdr-plugin-epgsearch/epgsearchtools.h0000644000175000017500000002170213145412721017625 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #ifndef __EPGSEARCH_TOOLS_INC__ #define __EPGSEARCH_TOOLS_INC__ #include #include // For VDRVERSNUM only #include "epgsearchext.h" #include "recdone.h" using std::string; #define MAXPARSEBUFFER KILOBYTE(10) #undef CHANNELNAME #define CHANNELNAME(x) (x ? x->ShortName(true) : "") #undef TIMESTRING #define TIMESTRING(x) *(TimeString(x)) #undef DATESTRING #define DATESTRING(x) *(DateString(x)) #undef GETDATESTRING #define GETDATESTRING(x) *(x->GetDateString()) #undef GETTIMESTRING #define GETTIMESTRING(x) *(x->GetTimeString()) #undef PRINTDAY #define PRINTDAY *cTimer::PrintDay #undef DAYDATETIME #define DAYDATETIME(x) *DayDateTime(x) #undef CHANNELSTRING #define CHANNELSTRING(x) (*x->GetChannelID().ToString()) #undef WEEKDAYNAME #define WEEKDAYNAME(x) (*WeekDayName(x)) #undef ADDDIR #define ADDDIR *AddDirectory #undef CONFIGDIR #define CONFIGDIR (!ConfigDir?cPlugin::ConfigDirectory():ConfigDir) #define CHNUMWIDTH (numdigits(Channels->MaxNumber()) + 2) #define SHORTTEXT(EVENT) \ (EVENT && EPGSearchConfig.showShortText && !isempty((EVENT)->ShortText()))?" ~ ":"", \ (EVENT && EPGSearchConfig.showShortText && !isempty((EVENT)->ShortText()))?(EVENT)->ShortText():"" #define ISRADIO(x) ((x)->Vpid()==0||(x)->Vpid()==1||(x)->Vpid()==0x1fff) #ifndef MENU_SEPARATOR_ITEMS #define MENU_SEPARATOR_ITEMS "----------------------------------------" #endif #define UPDS_WITH_OSD (1<<1) #define UPDS_WITH_EPGSCAN (1<<2) // Icons used in VDRSymbols-Font #define ICON_REC 0x8B #define ICON_RUNNING 0x92 #define ICON_CLOCK 0x8C #define ICON_CLOCK_HALF 0x94 #define ICON_BAR_OPEN 0x87 #define ICON_BAR_FULL 0x88 #define ICON_BAR_EMPTY 0x89 #define ICON_BAR_CLOSE 0x8A #define ICON_VPS 0x93 #define ICON_TIMER_INACT 0x95 // UTF-8 Icons #define ICON_BAR_OPEN_UTF8 "\uE007" #define ICON_BAR_FULL_UTF8 "\uE008" #define ICON_BAR_EMPTY_UTF8 "\uE009" #define ICON_BAR_CLOSE_UTF8 "\uE00A" #define ICON_REC_UTF8 "\uE00B" #define ICON_CLOCK_UTF8 "\uE00C" #define ICON_CLOCK_HALF_UTF8 "\uE014" #define ICON_RUNNING_UTF8 "\uE012" #define ICON_VPS_UTF8 "\uE013" #define ICON_TIMER_INACT_UTF8 "\uE015" #define CONTENT_DESCRIPTOR_MAX 255 #define ERROR(T) Skins.Message(mtError, T) #define INFO(I) Skins.Message(mtInfo, I) extern const char AllowedChars[]; extern char* ConfigDir; // Helper functions class cSearchExt; class cSearchExtCat; class cEvent; cString IndentMenuItem(const char*, int indentions=1); bool MatchesSearchMode(const char* test, const char* values, int searchmode, const char* delim, int tolerance); char* GetExtEPGValue(const cEvent* e, cSearchExtCat* SearchExtCat); char* GetExtEPGValue(const char* description, const char* catname, const char *format); char* GetAuxValue(const char* aux, const char* name); char* GetAuxValue(const cRecording *recording, const char* name); char* GetAuxValue(const cTimer* timer, const char* name); string UpdateAuxValue(string aux, string section, string value); string UpdateAuxValue(string aux, string section, long num); void ToLower(char* szText); char *strreplacei(char *s, const char *s1, const char *s2); std::string strreplace(std::string& result, const std::string& replaceWhat, const std::string& replaceWithWhat); // replace s1 with s2 in s ignoring the case of s1 inline char *strreplacei(char *s, const char *s1, const char s2) { char *p = strcasestr(s, s1); if (p) { int offset = p - s; int l = strlen(s); int l1 = strlen(s1); memmove(s + offset + 1, s + offset + l1, l - offset - l1 + 1); s[offset] = s2; } return s; } void sleepMSec(long ms); void sleepSec(long s); bool SendViaSVDRP(cString SVDRPcmd); int SendMsg(cString Message, bool confirm = false, int seconds = 0, eMessageType messageType = mtInfo); bool InEditMode(const char* ItemText, const char* ItemName, const char* ItemValue); cSearchExt* TriggeredFromSearchTimer(const cTimer* timer); int TriggeredFromSearchTimerID(const cTimer* timer); double FuzzyMatch(const char* s1, const char* s2, int maxLength); bool DescriptionMatches(const char* eDescr, const char* rDescr, int matchLimit = 90); const cEvent* GetEvent(const cTimer* timer); char* GetRawDescription(const char* descr); void PrepareTimerFile(const cEvent* event, cTimer* timer); int CompareEventTime(const void *p1, const void *p2); int CompareEventChannel(const void *p1, const void *p2); int CompareSearchExtPrioDescTerm(const void *p1, const void *p2); bool EventsMatch(const cEvent* event1, const cEvent* event2, bool compareTitle, int compareSubtitle, bool compareSummary, int compareDate, unsigned long catvaluesAvoidRepeat, int matchLimit=90); int ChannelNrFromEvent(const cEvent* pEvent); void DelTimer(int index); char* FixSeparators(char* buffer, char sep); cString DateTime(time_t t); string NumToString(long l); int FindIgnoreCase(const string& expr, const string& query); bool EqualsNoCase(const string& a, const string& b); string Strip(const string& input); string ReplaceAll(const string& input, const string& what, const string& with); string GetAlNum(const string& s); string EscapeString(const string& S); string QuoteApostroph(const string& S); string MD5(const string& input); time_t GetDateTime(time_t day, int start); void SetAux(cTimer* timer, string aux); int msprintf(char **strp, const char *fmt, ...); std::string GetCodeset(); ssize_t Readline(int sockd, char *vptr, size_t maxlen); ssize_t Writeline(int sockd, const char *vptr, ssize_t n); long getAddrFromString(const char* hostnameOrIp, struct sockaddr_in* addr); // --- cTimerObj -------------------------------------------------------- class cTimerObj : public cListObject { public: const cTimer* timer; cTimerObj(const cTimer* Timer) : timer(Timer) {} virtual ~cTimerObj() { timer = NULL; } // do not delete anything! }; // --- cTimerObjList -------------------------------------------------------- class cTimerObjList : public cList { public: void DelTimer(const cTimer* t) { for (cTimerObj* pTObj = First(); pTObj; pTObj = Next(pTObj)) if (pTObj->timer == t) { Del(pTObj); return; } } }; // --- icstring ------------------------------------------ // a case-insensitive string class struct ignorecase_traits : public std:: #if defined(__GNUC__) && __GNUC__ < 3 && __GNUC_MINOR__ < 96 string_char_traits #else char_traits #endif { // return whether c1 and c2 are equal static bool eq(const char& c1, const char& c2) { return (c1==c2 || std::toupper(c1)==std::toupper(c2)); } // return whether c1 is less than c2 static bool lt(const char& c1, const char& c2) { return std::toupper(c1) icstring; // --- eTimerMod ------------------------------------------------------------- enum eTimerMod { tmNoChange=0, tmStartStop=1, tmFile=2, tmAuxEventID=4 }; // --- cCommands ------------------------------------------------------------------- class cCommand : public cListObject { private: char *title; char *command; bool confirm; static char *result; public: cCommand(void); virtual ~cCommand(); bool Parse(const char *s); const char *Title(void) { return title; } bool Confirm(void) { return confirm; } const char *Execute(const char *Parameters = NULL); }; class cCommands : public cConfig {}; #endif vdr-plugin-epgsearch/menu_whatson.h0000644000175000017500000000740513145412721017316 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #ifndef __EPGSEARCH_MENUWHATSON_H #define __EPGSEARCH_MENUWHATSON_H #include #include "epgsearchcfg.h" #include "templatefile.h" #include "menu_event.h" // --- cMenuMyScheduleItem ------------------------------------------------------ class cMenuMyScheduleItem : public cOsdItem { public: const cEvent *event; const cChannel *channel; showMode mode; eTimerMatch timerMatch; bool isRemote; bool inSwitchList; bool timerActive; cMenuTemplate* menuTemplate; cMenuMyScheduleItem(const cTimers *Timers, const cEvent *Event, const cChannel *Channel = NULL, showMode ShowMode = showNow, cMenuTemplate* menuTemplate = NULL); virtual bool Update(const cTimers *Timers, bool Force = false); virtual void SetMenuItem(cSkinDisplayMenu *DisplayMenu, int Index, bool Current, bool Selectable); }; // --- cMenuMyScheduleSepItem ------------------------------------------------------ class cMenuMyScheduleSepItem : public cMenuMyScheduleItem { cEvent *dummyEvent; // this event is used to store the text of the separator in its title // to pass it in SetMenuItem via the event argument. Would be nice // if VDR had a SetItemSeparator function for this public: cMenuMyScheduleSepItem(const cTimers *Timers = NULL, const cEvent *Event = NULL, const cChannel *Channel = NULL); ~cMenuMyScheduleSepItem(); virtual bool Update(const cTimers *Timers = NULL,bool Force = false); virtual void SetMenuItem(cSkinDisplayMenu *DisplayMenu, int Index, bool Current, bool Selectable); }; // --- cMenuWhatsOnSearch ---------------------------------------------------------- class cMenuWhatsOnSearch : public cOsdMenu { private: int helpKeys; eOSState Record(void); eOSState ExtendedSearch(void); static int currentChannel; cEventObjects eventObjects; public: static const cChannel *scheduleChannel; static cList showModes; static showMode currentShowMode; static int shiftTime; static time_t seekTime; time_t GetTimeT(int iTime); static showMode GetNextMode(); cMenuWhatsOnSearch(int CurrentChannelNr); ~cMenuWhatsOnSearch(); void LoadSchedules(); static int CurrentChannel(void) { return currentChannel; } static void SetCurrentChannel(int ChannelNr) { currentChannel = ChannelNr; } static const cChannel *ScheduleChannel(const cChannel* forceChannel = NULL); virtual eOSState ProcessKey(eKeys Key); virtual eOSState Switch(void); virtual eOSState Shift(int); virtual eOSState Commands(eKeys Key); virtual eOSState ShowSummary(); void SetHelpKeys(bool Force = false); int GetTab(int Tab); bool Update(void); void CreateShowModes(); static cShowMode* GetShowMode(showMode mode); void UpdateCurrent(); #ifdef USE_GRAPHTFT virtual const char* MenuKind(); virtual void Display(void); #endif }; #endif vdr-plugin-epgsearch/menu_searchedit.h0000644000175000017500000000754613145412721017754 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #ifndef __MENU_SEARCHEDIT_H #define __MENU_SEARCHEDIT_H #include #include #include "epgsearchext.h" // --- cMenuEditSearchExt -------------------------------------------------------- class cMenuEditSearchExt : public cOsdMenu { protected: cSearchExt *searchExt; cSearchExt data; int channelMin; int channelMax; bool addIfConfirmed; int UserDefDayOfWeek; int channelGroupNr; char* channelGroupName; char** menuitemsChGr; int* catarrayAvoidRepeats; int* catvaluesNumeric; cList blacklists; char *SearchModes[6]; char *DaysOfWeek[8]; char *UseChannelSel[4]; char *SearchTimerModes[6]; char *BlacklistModes[4]; char *DelModes[3]; char *SearchActiveModes[3]; char *CompareSubtitleModes[2]; char *CompareDateModes[4]; std::vector contentStringIDs; int useContentDescriptors; int *contentStringsFlags; bool templateMode; std::vector helpTexts; void AddHelp(const char* helpText); public: cMenuEditSearchExt(cSearchExt *SearchExt, bool New = false, bool Template = false, bool FromEPG = false); virtual ~cMenuEditSearchExt(); virtual void Set(); virtual eOSState ProcessKey(eKeys Key); eOSState Help(); }; // --- cMenuEditDaysOfWeek -------------------------------------------------------- class cMenuEditDaysOfWeek : public cOsdMenu { private: int* pDaysOfWeek; int Days[7]; int offset; bool negate; public: cMenuEditDaysOfWeek(int* DaysOfWeek, int Offset=0, bool Negate = true); virtual eOSState ProcessKey(eKeys Key); }; // --- cMenuSearchEditCompCats -------------------------------------------------------- class cMenuSearchEditCompCats : public cOsdMenu { private: int* search_catarrayAvoidRepeats; int* edit_catarrayAvoidRepeats; public: cMenuSearchEditCompCats(int* catarrayAvoidRepeats); ~cMenuSearchEditCompCats(); eOSState ProcessKey(eKeys Key); }; // --- cMenuBlacklistsSelection -------------------------------------------------------- class cMenuBlacklistsSelection : public cOsdMenu { private: int* blacklistsSel; cList* blacklists; public: cMenuBlacklistsSelection(cList* pBlacklists); ~cMenuBlacklistsSelection(); void Set(); eOSState ProcessKey(eKeys Key); }; // --- cMenuCatValuesSelect -------------------------------------------------------- class cMenuCatValuesSelect : public cOsdMenu { private: char* catValues; int catIndex; int searchMode; std::vector sel_cats; public: cMenuCatValuesSelect(char* CatValues, int CatIndex, int SearchMode); void Set(); eOSState ProcessKey(eKeys Key); }; // --- cMenuSearchActivSettings -------------------------------------------------------- class cMenuSearchActivSettings : public cOsdMenu { private: cSearchExt *searchExt; public: cMenuSearchActivSettings(cSearchExt *SearchExt); eOSState ProcessKey(eKeys Key); }; #endif vdr-plugin-epgsearch/menu_whatson.c0000644000175000017500000007303413145412721017312 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #include #include #include #include #include "uservars.h" #include "menu_whatson.h" #include "epgsearchext.h" #include "menu_event.h" #include "menu_myedittimer.h" #include "menu_searchresults.h" #include "menu_search.h" #include "menu_commands.h" #include "epgsearchcfg.h" #include "switchtimer.h" #include "epgsearchcats.h" #include "conflictcheck.h" #include #include #include "menu_conflictcheck.h" #include "templatefile.h" #include "menu_deftimercheckmethod.h" #include "timerstatus.h" #define HOURS(x) ((x)/100) #define MINUTES(x) ((x)%100) #define SKIPHOURS 20 #define HOURS2SECS(x) (x*60*60) extern int exitToMainMenu; extern bool isUTF8; int gl_InfoConflict = 0; // --- cMenuMyScheduleItem ------------------------------------------------------ cMenuMyScheduleItem::cMenuMyScheduleItem(const cTimers *Timers, const cEvent *Event, const cChannel *Channel, showMode Mode, cMenuTemplate* MenuTemplate) { event = Event; channel = Channel; mode = Mode; timerMatch = tmNone; isRemote = false; inSwitchList = false; timerActive = false; menuTemplate = MenuTemplate; Update(Timers, true); } bool cMenuMyScheduleItem::Update(const cTimers* Timers, bool Force) { if (!menuTemplate) return false; const char* menutemplate = menuTemplate->MenuTemplate(); if (!menutemplate || strlen(menutemplate) == 0) return false; bool result = false; eTimerMatch OldTimerMatch = timerMatch; bool OldIsRemote = isRemote; bool OldInSwitchList = inSwitchList; bool OldtimerActive = timerActive; bool hasMatch = false; const cTimer* timer = NULL; if (event) timer = Timers->GetMatch(event, &timerMatch); if (event) inSwitchList = (SwitchTimers.InSwitchList(event)!=NULL); if (timer) hasMatch = true; if (timer) timerActive = timer->HasFlags(tfActive); if (timer) isRemote = timer->Remote(); if (Force || timerMatch != OldTimerMatch || inSwitchList != OldInSwitchList || isRemote != OldIsRemote || timerActive != OldtimerActive) { char szProgressPart[Utf8BufSize(12)] = ""; char szProgressPartT2S[12] = ""; time_t now = time(NULL); if (channel) { if (event) { time_t startTime = event->StartTime(); if ((now - event->StartTime()) >= 0 || strstr(menutemplate, "%time%") != NULL) { int frac = 0; if (mode == showNow) { int dur = event->Duration(); if (dur != 0) frac = ((now - startTime) * 8 + (dur >> 1)) / dur; } if (mode == showNext) frac = ( ( 30*60 - std::min((time_t)30*60, startTime - now) ) * 8 + 15*60 ) / (30*60); frac = std::min(8,std::max(0, frac)); szProgressPartT2S[0] = '['; memset(szProgressPartT2S + 1,'|',frac); memset(szProgressPartT2S + 1 + frac ,' ', 8 - frac); szProgressPartT2S[9] = ']'; szProgressPartT2S[10] = 0; if (!isUTF8) { szProgressPart[0] = ICON_BAR_OPEN; memset(szProgressPart + 1, ICON_BAR_EMPTY, 6); szProgressPart[7] = ICON_BAR_CLOSE; szProgressPart[8] = 0; memset(szProgressPart, ICON_BAR_FULL, frac?frac:sizeof(szProgressPart)); } else { #if defined(__GNUC__) && __GNUC__ < 3 && __GNUC_MINOR__ < 96 #else std::stringstream buffer; buffer << ICON_BAR_OPEN_UTF8; for(int i=0;i<8;i++) buffer << (iGetTimeString(), 12); szProgressPart[11] = 0; memcpy(szProgressPartT2S, szProgressPart, 12); } } } char t[Utf8BufSize(2)],v[Utf8BufSize(2)],r[Utf8BufSize(2)]; char szStatus[Utf8BufSize(4)]; szStatus[3] = 0; t[1]=v[1]=r[1] = 0; if (EPGSearchConfig.WarEagle) { if (!isUTF8) { t[0] = event && hasMatch ? (timerMatch == tmFull) ? ((timer && timer->Recording()) ? ICON_REC : (timerActive ? ICON_CLOCK : ICON_TIMER_INACT)) : (timerActive ? ICON_CLOCK_HALF : ' ' ): ' '; v[0] = event && event->Vps() && (event->Vps() - event->StartTime()) ? ICON_VPS : ' '; r[0] = event && event->IsRunning() ? ICON_RUNNING : ' '; } else { #if defined(__GNUC__) && __GNUC__ < 3 && __GNUC_MINOR__ < 96 #else sprintf(t, "%s", (event && hasMatch ? (timerMatch == tmFull) ? ((timer && timer->Recording()) ? ICON_REC_UTF8 : (timerActive ? ICON_CLOCK_UTF8 : ICON_TIMER_INACT_UTF8)) : (timerActive ? ICON_CLOCK_HALF_UTF8 : " ") : " ")); sprintf(v, "%s", event && event->Vps() && (event->Vps() - event->StartTime()) ? ICON_VPS_UTF8 : " "); sprintf(r, "%s", (event && event->IsRunning() ? ICON_RUNNING_UTF8 : " ")); #endif } } else { t[0] = event && hasMatch ? (timerMatch == tmFull) ? ((timer && timer->Recording()) ? 'R' : (timerActive ? 'T' : 'i')) : (timerActive ? 't' : ' ') : ' '; v[0] = event && event->Vps() && (event->Vps() - event->StartTime()) ? 'V' : ' '; r[0] = event && event->IsRunning() ? '*' : ' '; } if (event && inSwitchList) { cSwitchTimer* s = SwitchTimers.InSwitchList(event); t[0] = (s && s->mode==1)?'s':'S'; } if (EPGSearchConfig.WarEagle && isUTF8) { std::stringstream buffer; buffer << t << v << r; char* temp = strdup(buffer.str().c_str()); sprintf(szStatus, "%s", temp); free(temp); } else { szStatus[0] = t[0]; szStatus[1] = v[0]; szStatus[2] = r[0]; } char* buffer = strdup(menutemplate); strreplace(buffer, '|', '\t'); char* title = NULL; title = strdup(event?event->Title():tr(">>> no info! <<<")); title = strreplacei(title, ":", "%colon%"); // assume a title has the form "a?b:c", // we need to replace the colon to avoid misinterpretation of the expression as a condition buffer = strreplacei(buffer, "%title%", title); free(title); if (channel) { char szChannelNr[6] = ""; snprintf(szChannelNr, 6, "%d", channel->Number()); buffer = strreplacei(buffer, "%chnr%", szChannelNr); buffer = strreplacei(buffer, "%chsh%", channel->ShortName(true)); buffer = strreplacei(buffer, "%chlng%", channel->Name()); buffer = strreplacei(buffer, "%progr%", szProgressPart); buffer = strreplacei(buffer, "%progrT2S%", szProgressPartT2S); } // parse the epxression and evaluate it cVarExpr varExpr(buffer); char* tmp = strdup(varExpr.Evaluate(event).c_str()); free(buffer); buffer = tmp; buffer = strreplacei(buffer, "$status$", szStatus); buffer = strreplacei(buffer, "$t_status$", t); buffer = strreplacei(buffer, "$v_status$", v); buffer = strreplacei(buffer, "$r_status$", r); buffer = FixSeparators(buffer, '~'); buffer = FixSeparators(buffer, ':'); buffer = FixSeparators(buffer, '-'); SetText(buffer, false); if (gl_InfoConflict == 0 && EPGSearchConfig.checkTimerConflAfterTimerProg && !Force && timer && ((timerMatch && timerMatch != OldTimerMatch) || (isRemote != OldIsRemote))) { cConflictCheck C; C.Check(); if (C.TimerInConflict(timer)) gl_InfoConflict = 1; } return true; } return result; } void cMenuMyScheduleItem::SetMenuItem(cSkinDisplayMenu *DisplayMenu, int Index, bool Current, bool Selectable) { bool withDate = (channel == NULL); // search for a better way to determine this if (!DisplayMenu->SetItemEvent(event, Index, Current, Selectable, channel, withDate, timerMatch)) DisplayMenu->SetItem(Text(), Index, Current, Selectable); } // --- cMenuMyScheduleSepItem ------------------------------------------------------ cMenuMyScheduleSepItem::cMenuMyScheduleSepItem(const cTimers *Timers, const cEvent *Event, const cChannel *Channel) : cMenuMyScheduleItem(Timers, Event, Channel, showNow, NULL) { event = Event; channel = Channel; dummyEvent = NULL; SetSelectable(false); Update(Timers, true); } cMenuMyScheduleSepItem::~cMenuMyScheduleSepItem() { if (dummyEvent) delete dummyEvent; } bool cMenuMyScheduleSepItem::Update(const cTimers *Timers, bool Force) { if (channel) SetText(cString::sprintf("%s\t %s %s", MENU_SEPARATOR_ITEMS, channel->Name(), MENU_SEPARATOR_ITEMS)); else if (event) { dummyEvent = new cEvent(0); dummyEvent->SetTitle(cString::sprintf("%s\t %s %s", MENU_SEPARATOR_ITEMS, GETDATESTRING(event), MENU_SEPARATOR_ITEMS)); SetText(dummyEvent->Title()); } return true; } void cMenuMyScheduleSepItem::SetMenuItem(cSkinDisplayMenu *DisplayMenu, int Index, bool Current, bool Selectable) { bool withDate = (channel == NULL); // search for a better way to determine this if (!DisplayMenu->SetItemEvent(dummyEvent, Index, Current, Selectable, channel, withDate, timerMatch)) DisplayMenu->SetItem(Text(), Index, Current, Selectable); } // --- cMenuWhatsOnSearch ---------------------------------------------------------- int cMenuWhatsOnSearch::currentChannel = 0; showMode cMenuWhatsOnSearch::currentShowMode = showNow; const cChannel *cMenuWhatsOnSearch::scheduleChannel = NULL; extern const char *ShowModes[]; cList cMenuWhatsOnSearch::showModes; time_t cMenuWhatsOnSearch::seekTime = 0; int cMenuWhatsOnSearch::shiftTime = 0; cMenuWhatsOnSearch::cMenuWhatsOnSearch(int CurrentChannelNr) :cOsdMenu("", GetTab(1), GetTab(2), GetTab(3), GetTab(4), GetTab(5)) { if (currentShowMode == showNow) SetMenuCategory(mcScheduleNow); else if (currentShowMode == showNext) SetMenuCategory(mcScheduleNext); else SetMenuCategory(mcSchedule); helpKeys = -1; shiftTime = 0; CreateShowModes(); LoadSchedules(); currentChannel = CurrentChannelNr; SetHelpKeys(); } cMenuWhatsOnSearch::~cMenuWhatsOnSearch() { } #ifdef USE_GRAPHTFT const char* cMenuWhatsOnSearch::MenuKind() { if (currentShowMode == showNow) return "MenuEpgsWhatsOnNow"; if (currentShowMode == showNext) return "MenuEpgsWhatsOnNext"; if (currentShowMode > showNext) return "MenuEpgsWhatsOnElse"; else return "MenuWhatsOnElse"; } void cMenuWhatsOnSearch::Display(void) { cOsdMenu::Display(); if (Count() > 0) { int i = 0; for (cOsdItem *item = First(); item; item = Next(item)) cStatus::MsgOsdEventItem(!item->Selectable() ? 0 : ((cMenuMyScheduleItem*)item)->event, item->Text(), i++, Count()); } } #endif /* GRAPHTFT */ int cMenuWhatsOnSearch::GetTab(int Tab) { if (currentShowMode == showNow) return cTemplFile::GetTemplateByName("MenuWhatsOnNow")->Tab(Tab-1); if (currentShowMode == showNext) return cTemplFile::GetTemplateByName("MenuWhatsOnNext")->Tab(Tab-1); if (currentShowMode > showNext) return cTemplFile::GetTemplateByName("MenuWhatsOnElse")->Tab(Tab-1); else return 0; } void cMenuWhatsOnSearch::LoadSchedules() { Clear(); eventObjects.Clear(); // time_t SeekTime; cString szTitle; cShowMode* mode = GetShowMode(currentShowMode); if (!mode) return; if (shiftTime != 0) { if (currentShowMode == showNow || currentShowMode == showNext) seekTime = time(NULL); else { if (mode) seekTime = GetTimeT(mode->GetTime()); if (seekTime < time(NULL)) seekTime += HOURS2SECS(24); } seekTime += shiftTime*60; struct tm tm_r; time_t now = time(NULL); tm tm_seek = *localtime_r(&seekTime, &tm_r); tm tm_now = *localtime_r(&now, &tm_r); if (tm_seek.tm_mday != tm_now.tm_mday) szTitle = cString::sprintf("%s - %s", tr("Overview"), DAYDATETIME(seekTime)); else szTitle = cString::sprintf("%s - %02d:%02d", tr("Overview"), tm_seek.tm_hour, tm_seek.tm_min); } else { seekTime = GetTimeT(mode->GetTime()); if (seekTime < time(NULL) && currentShowMode != showNow && currentShowMode != showNext) { seekTime += HOURS2SECS(24); szTitle = cString::sprintf("%s - %s (%s)", tr("Overview"), mode->GetDescription(), *WeekDayName(seekTime)); } else szTitle = cString::sprintf("%s - %s", tr("Overview"), mode->GetDescription()); } SetTitle(szTitle); cMenuTemplate* currentTemplate = NULL; if (currentShowMode == showNow) currentTemplate = cTemplFile::GetTemplateByName("MenuWhatsOnNow"); if (currentShowMode == showNext) currentTemplate = cTemplFile::GetTemplateByName("MenuWhatsOnNext"); if (currentShowMode > showNext) currentTemplate = cTemplFile::GetTemplateByName("MenuWhatsOnElse"); int maxChannel = EPGSearchConfig.maxChannelMenuNow; if (currentChannel > maxChannel) maxChannel = 0; LOCK_TIMERS_READ; // needed in MyScheduleItem LOCK_CHANNELS_READ; for (const cChannel *Channel = Channels->First(); Channel; Channel = Channels->Next(Channel)) { if (!Channel->GroupSep()) { if (maxChannel && Channel->Number() > maxChannel) break; if (EPGSearchConfig.showRadioChannels == 0 && ISRADIO(Channel)) continue; const cSchedule *Schedule; { LOCK_SCHEDULES_READ; Schedule = Schedules->GetSchedule(Channel); } const cEvent *Event = NULL; if (Schedule) { if (shiftTime != 0) Event = Schedule->GetEventAround(seekTime); else { switch(currentShowMode) { default: case showNow: Event = Schedule->GetPresentEvent(); break; case showNext: Event = Schedule->GetFollowingEvent(); break; case showUserMode1: case showUserMode2: case showUserMode3: case showUserMode4: Event = Schedule->GetEventAround(seekTime); break; } } } if (!EPGSearchConfig.showEmptyChannels && !Event) continue; Add(new cMenuMyScheduleItem(Timers, Event, Channel, currentShowMode, currentTemplate), Channel->Number() == currentChannel); if (Event) eventObjects.Add(Event); } else { if (EPGSearchConfig.showChannelGroups && strlen(Channel->Name())) Add(new cMenuMyScheduleSepItem(NULL, NULL, Channel)); } } } time_t cMenuWhatsOnSearch::GetTimeT(int iTime) { struct tm tm_r; time_t t = time(NULL); tm* tmnow = localtime_r(&t, &tm_r); tmnow->tm_hour = HOURS(iTime); tmnow->tm_min = MINUTES(iTime); return mktime(tmnow); } showMode cMenuWhatsOnSearch::GetNextMode() { showMode nextShowMode = currentShowMode; cShowMode* Mode = GetShowMode(currentShowMode); if (Mode) { cShowMode* ModeNext = showModes.Next(Mode); if (ModeNext == NULL) nextShowMode = showNow; else nextShowMode = ModeNext->GetMode(); } else // no mode found? fall back to 'now' nextShowMode = showNow; return nextShowMode; } void cMenuWhatsOnSearch::CreateShowModes() { showModes.Clear(); cShowMode* ModeNow = new cShowMode(showNow, trVDR("Button$Now")); showModes.Add(ModeNow); cShowMode* ModeNext = new cShowMode(showNext, trVDR("Button$Next")); showModes.Add(ModeNext); time_t now = time(NULL); for(int i=showUserMode1; i HOURS2SECS(SKIPHOURS)) continue; cShowMode* Mode = new cShowMode((showMode)i, EPGSearchConfig.ShowModes[i].GetDescription(), 1, EPGSearchConfig.ShowModes[i].GetTime(), SeekTime); showModes.Add(Mode); } if (EPGSearchConfig.showFavoritesMenu) { cShowMode* ModeFav = new cShowMode(showFavorites, tr("Button$Favorites")); showModes.Add(ModeFav); } showModes.Sort(); } cShowMode* cMenuWhatsOnSearch::GetShowMode(showMode mode) { for (cShowMode *showMode = showModes.First(); showMode; showMode = showModes.Next(showMode)) if (mode == showMode->GetMode()) return showMode; return NULL; } const cChannel *cMenuWhatsOnSearch::ScheduleChannel(const cChannel *force_channel) { const cChannel *ch = force_channel?force_channel:scheduleChannel; scheduleChannel = NULL; return ch; } eOSState cMenuWhatsOnSearch::Switch(void) { cMenuMyScheduleItem *item = (cMenuMyScheduleItem *)Get(Current()); if (item && item->channel) { if (cDevice::PrimaryDevice()->SwitchChannel(item->channel, true)) return osEnd; } INFO(trVDR("Can't switch channel!")); return osContinue; } eOSState cMenuWhatsOnSearch::Record(void) { cMenuMyScheduleItem *item = (cMenuMyScheduleItem *)Get(Current()); if (item) { LOCK_TIMERS_WRITE; Timers->SetExplicitModify(); if (item->timerMatch == tmFull) { eTimerMatch tm = tmNone; cTimer *timer = Timers->GetMatch(item->event, &tm); if (timer) { if (EPGSearchConfig.useVDRTimerEditMenu) return AddSubMenu(new cMenuEditTimer(timer)); else return AddSubMenu(new cMenuMyEditTimer(timer, false, item->event, item->channel)); } } cTimer *timer = NULL; if (item->event) { timer = new cTimer(item->event); PrepareTimerFile(item->event, timer); } else timer = new cTimer(false, false, item->channel); cTimer *t = Timers->GetTimer(timer); if (EPGSearchConfig.onePressTimerCreation == 0 || t || !item->event || (!t && item->event && item->event->StartTime() - (Setup.MarginStart+2) * 60 < time(NULL))) { if (t) { delete timer; timer = t; } timer->SetFlags(tfActive); if (EPGSearchConfig.useVDRTimerEditMenu) return AddSubMenu(new cMenuEditTimer(timer, !t)); else return AddSubMenu(new cMenuMyEditTimer(timer, !t, item->event, item->channel)); } else { string fullaux = ""; string aux = ""; if (item->event) { const cEvent* event = item->event; int bstart = event->StartTime() - timer->StartTime(); int bstop = timer->StopTime() - event->EndTime(); int checkmode = DefTimerCheckModes.GetMode(timer->Channel()); aux = UpdateAuxValue(aux, "channel", NumToString(timer->Channel()->Number()) + " - " + CHANNELNAME(timer->Channel())); aux = UpdateAuxValue(aux, "update", checkmode); aux = UpdateAuxValue(aux, "eventid", event->EventID()); aux = UpdateAuxValue(aux, "bstart", bstart); aux = UpdateAuxValue(aux, "bstop", bstop); fullaux = UpdateAuxValue(fullaux, "epgsearch", aux); } #ifdef USE_PINPLUGIN aux = ""; aux = UpdateAuxValue(aux, "protected", timer->FskProtection() ? "yes" : "no"); fullaux = UpdateAuxValue(fullaux, "pin-plugin", aux); #endif SetAux(timer, fullaux); if (Setup.SVDRPPeering && *Setup.SVDRPDefaultHost) timer->SetRemote(Setup.SVDRPDefaultHost); Timers->Add(timer); if (!HandleRemoteTimerModifications(timer)) { Timers->Del(timer); ERROR(tr("Epgsearch: RemoteTimerModifications failed")); } else { gl_timerStatusMonitor->SetConflictCheckAdvised(); timer->Matches(); Timers->SetModified(); LogFile.iSysLog("timer %s added (active)", *timer->ToDescr()); } if (HasSubMenu()) CloseSubMenu(); if (Update()) Display(); SetHelpKeys(); } } return osContinue; } bool cMenuWhatsOnSearch::Update(void) { bool result = false; LOCK_TIMERS_READ; for (cOsdItem *item = First(); item; item = Next(item)) { if (item->Selectable() && ((cMenuMyScheduleItem *)item)->Update(Timers)) result = true; } return result; } eOSState cMenuWhatsOnSearch::Commands(eKeys Key) { if (HasSubMenu() || Count() == 0) return osContinue; cMenuMyScheduleItem *mi = (cMenuMyScheduleItem *)Get(Current()); if (mi) { if (!mi->event) { if (Key == k3) return Switch(); else if (Key == k2) return Record(); else return osContinue; } cMenuSearchCommands *menu; eOSState state = AddSubMenu(menu = new cMenuSearchCommands(tr("EPG Commands"), mi->event, true)); if (Key != kNone) state = menu->ProcessKey(Key); return state; } return osContinue; } eOSState cMenuWhatsOnSearch::ExtendedSearch(void) { return AddSubMenu(new cMenuEPGSearchExt()); } void cMenuWhatsOnSearch::SetHelpKeys(bool Force) { cMenuMyScheduleItem *item = (cMenuMyScheduleItem *)Get(Current()); int NewHelpKeys = 0; if (item) { if (item->Selectable() && item->timerMatch == tmFull) NewHelpKeys = 2; else NewHelpKeys = 1; } bool hasTimer = (NewHelpKeys == 2); if (NewHelpKeys != helpKeys || Force) { showMode nextShowMode = GetNextMode(); cShowMode* mode = GetShowMode(nextShowMode); const char* szButtonGreen = NULL; if (mode) szButtonGreen = mode->GetDescription(); if (toggleKeys==0) SetHelp((EPGSearchConfig.redkeymode==0?(hasTimer?trVDR("Button$Timer"):trVDR("Button$Record")):tr("Button$Commands")), szButtonGreen, trVDR("Button$Schedule"), EPGSearchConfig.bluekeymode==0?(EPGSearchConfig.useOkForSwitch?trVDR("Button$Info"):trVDR("Button$Switch")):tr("Button$Search")); else SetHelp((EPGSearchConfig.redkeymode==1?(hasTimer?trVDR("Button$Timer"):trVDR("Button$Record")):tr("Button$Commands")), (EPGSearchConfig.toggleGreenYellow==0?szButtonGreen:"<<"), (EPGSearchConfig.toggleGreenYellow==0?trVDR("Button$Schedule"):">>"), EPGSearchConfig.bluekeymode==1?(EPGSearchConfig.useOkForSwitch?trVDR("Button$Info"):trVDR("Button$Switch")):tr("Button$Search")); helpKeys = NewHelpKeys; } } eOSState cMenuWhatsOnSearch::Shift(int iMinutes) { shiftTime += iMinutes; cMenuMyScheduleItem *mi = (cMenuMyScheduleItem *)Get(Current()); int TempChannel = currentChannel; if (mi) { currentChannel = mi->channel->Number(); LOCK_CHANNELS_READ; scheduleChannel = Channels->GetByNumber(currentChannel); } LoadSchedules(); Display(); currentChannel = TempChannel; SetHelpKeys(); return osContinue; } eOSState cMenuWhatsOnSearch::ShowSummary() { if (Count()) { const cEvent *ei = ((cMenuMyScheduleItem *)Get(Current()))->event; if (ei) { const cChannel *channel; { LOCK_CHANNELS_READ; channel = Channels->GetByChannelID(ei->ChannelID(), true, true); } if (channel) return AddSubMenu(new cMenuEventSearch(ei, eventObjects, SurfModeChannel)); } } return osContinue; } void cMenuWhatsOnSearch::UpdateCurrent() { // navigation in summary could have changed current item, so update it cEventObj* cureventObj = eventObjects.GetCurrent(); if (cureventObj && cureventObj->Event()) for (cMenuMyScheduleItem *item = (cMenuMyScheduleItem *)First(); item; item = (cMenuMyScheduleItem *)Next(item)) if (item->Selectable() && item->event == cureventObj->Event()) { cureventObj->Select(false); SetCurrent(item); Display(); break; } } eOSState cMenuWhatsOnSearch::ProcessKey(eKeys Key) { exitToMainMenu = 0; if (!HasSubMenu() && Key == kBack) { exitToMainMenu = 1; return osBack; } bool HadSubMenu = HasSubMenu(); eOSState state = cOsdMenu::ProcessKey(Key); if (!HasSubMenu() && HadSubMenu) // navigation in summary could have changed current item, so update it UpdateCurrent(); if (state == osUnknown) { switch (Key) { case kFastRew: if(!HasSubMenu()) return Shift(-EPGSearchConfig.timeShiftValue); break; case kFastFwd: if(!HasSubMenu()) return Shift(EPGSearchConfig.timeShiftValue); break; case kRecord: case kRed: if(HasSubMenu()) { UpdateCurrent(); state = Record(); break; } if (Count()) { if (EPGSearchConfig.redkeymode==toggleKeys) state = Record(); else { cMenuMyScheduleItem *mi = (cMenuMyScheduleItem *)Get(Current()); if (mi && mi->Selectable()) { if (mi->event) return AddSubMenu(new cMenuSearchCommands(tr("EPG Commands"),mi->event)); else return osContinue; } } } break; case k0: if(!HasSubMenu()) { toggleKeys = 1 - toggleKeys; SetHelpKeys(true); } state = osContinue; break; case k1...k9: return Commands(Key); case kYellow: if(!HasSubMenu()) { if (toggleKeys == 0 || (toggleKeys == 1 && EPGSearchConfig.toggleGreenYellow == 0)) { cMenuMyScheduleItem *mi = (cMenuMyScheduleItem *)Get(Current()); if (mi && mi->Selectable() && mi->channel) { LOCK_SCHEDULES_READ; const cSchedule *Schedule = Schedules->GetSchedule(mi->channel); if (Schedule) { time_t now = time(NULL); bool hasFutureEvents = false; for (const cEvent *e = Schedule->Events()->First(); e; e = Schedule->Events()->Next(e)) if (e->StartTime() > now) { hasFutureEvents = true; break; } if (!hasFutureEvents) return osContinue; } else return osContinue; } state = osBack; // continue with kGreen } else return Shift(EPGSearchConfig.timeShiftValue); } case kGreen: if(!HasSubMenu()) { if (toggleKeys == 0 || (toggleKeys == 1 && EPGSearchConfig.toggleGreenYellow == 0)) { if (Key == kYellow) currentShowMode = showNow; else currentShowMode = GetNextMode(); cMenuMyScheduleItem *mi = (cMenuMyScheduleItem *)Get(Current()); if (mi && mi->Selectable()) { currentChannel = mi->channel->Number(); LOCK_CHANNELS_READ; scheduleChannel = Channels->GetByNumber(currentChannel); } } else return Shift(-EPGSearchConfig.timeShiftValue); } break; case kBlue: if (HasSubMenu()) { UpdateCurrent(); return Switch(); } if (EPGSearchConfig.bluekeymode==toggleKeys) return EPGSearchConfig.useOkForSwitch?ShowSummary():Switch(); else return ExtendedSearch(); break; case kOk: { cMenuMyScheduleItem *mi = (cMenuMyScheduleItem *)Get(Current()); if (mi && mi->Selectable()) { if (!mi->event) // no EPG, so simply switch to channel return Switch(); else return EPGSearchConfig.useOkForSwitch?Switch():ShowSummary(); } } break; case kInfo: return ShowSummary(); break; default: break; } } if (!HasSubMenu()) { if ((HadSubMenu || gl_TimerProgged) && Update()) { if (gl_TimerProgged) // when using epgsearch's timer edit menu, update is delayed because of SVDRP { gl_TimerProgged = 0; SetHelpKeys(); } Display(); } if (Key != kNone) SetHelpKeys(); if (gl_InfoConflict) { gl_InfoConflict = 0; if (Interface->Confirm(tr("Timer conflict! Show?"))) return AddSubMenu(new cMenuConflictCheck()); } } return state; } vdr-plugin-epgsearch/menu_dirselect.c0000644000175000017500000001622113145412721017600 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #include "menu_dirselect.h" #include "epgsearchext.h" #include "epgsearchcats.h" #include "epgsearchtools.h" set cMenuDirSelect::directorySet; cDirExts DirExts; cConfDDirExts ConfDDirExts; // --- cMenuDirItem --------------------------------------------------------- class cMenuDirItem : public cOsdItem { private: char* directory; public: cMenuDirItem(const char* text) : cOsdItem(text) { directory = strdup(text);} ~cMenuDirItem(){ if (directory) free(directory);} virtual int Compare(const cListObject &ListObject) const; }; int cMenuDirItem::Compare(const cListObject &ListObject) const { const cMenuDirItem *p = (cMenuDirItem *)&ListObject; int hasVars1 = (strchr(directory,'%') != NULL?1:0); int hasVars2 = (strchr(p->directory,'%') != NULL?1:0); if (hasVars1 || hasVars2) { if (hasVars1 != hasVars2) return hasVars2-hasVars1; else return strcasecmp(directory, p->directory); } else return strcasecmp(directory, p->directory); } // --- cMenuDirSelect --------------------------------------------------------- cMenuDirSelect::cMenuDirSelect(char* szDirectory) :cOsdMenu(tr("Select directory")) { SetMenuCategory(mcTimerEdit); Directory = szDirectory; yellow=NULL; MaxLevel = 1; CurLevel = 1; Load(); } cMenuDirSelect::~cMenuDirSelect() { if (yellow) free(yellow); } int cMenuDirSelect::Level(const char* szDir) { int iLevel = 1; if (strchr(szDir, '%')) // dirs with vars always have level 1 return 1; do { const char* pos = strchr(szDir, '~'); if (pos) { iLevel++; szDir = pos+1; } else return iLevel; } while(true); return 1; } void cMenuDirSelect::AddDistinct(const char* szText) { int iLevel = Level(szText); MaxLevel = std::max(MaxLevel, iLevel); if (iLevel > CurLevel) // only show Items of the specified level, except those with vars return; for(int i=0; iText(); char* itemtext = strdup(ItemText); char* sztext = strdup(szText); ToLower(itemtext); ToLower(sztext); if (itemtext && strlen(itemtext) > 0 && strcmp(sztext, itemtext) == 0) { free(itemtext); free(sztext); return; } free(itemtext); free(sztext); } Add(new cMenuDirItem(hk(szText))); } void cMenuDirSelect::CreateDirSet(bool extraDirs) { directorySet.clear(); // add distinct directories from current recordings { LOCK_RECORDINGS_READ; for (const cRecording *recording = Recordings->First(); recording; recording = Recordings->Next(recording)) { if (recording->HierarchyLevels() > 0) { char* dir = strdup(recording->Name()); // strip the trailing rec dir char* pos = strrchr(dir, '~'); if (pos) { *pos=0; for(int iLevel = 0; iLevel < recording->HierarchyLevels(); iLevel++) { directorySet.insert(dir); char* pos = strrchr(dir, '~'); if (pos) *pos=0; } } free(dir); } } } // give up Recordings Lock // add distinct directories from current timers { LOCK_TIMERS_READ; for (const cTimer *timer = Timers->First(); timer; timer = Timers->Next(timer)) { char* dir = strdup(timer->File()); // strip the trailing name dir char* pos = strrchr(dir, '~'); if (pos) { *pos=0; do { directorySet.insert(dir); char* pos = strrchr(dir, '~'); if (pos) *pos=0; else break; } while(true); } free(dir); } } // add distinct directories from folders.conf for(cNestedItem* item = Folders.First(); item; item = Folders.Next(item)) AddVDRFolders(item); if (extraDirs) { cMutexLock SearchExtsLock(&SearchExts); cSearchExt *searchExt = SearchExts.First(); // add distinct directories from existing search timers while (searchExt) { if (strlen(searchExt->directory) > 0) directorySet.insert(searchExt->directory); searchExt = SearchExts.Next(searchExt); } // add distinct directories from epgsearchdirs.conf DirExts.Load(AddDirectory(CONFIGDIR, "epgsearchdirs.conf"), true); cDirExt* DirExt = DirExts.First(); while (DirExt) { directorySet.insert(DirExt->Name()); DirExt = DirExts.Next(DirExt); } // add distinct directories from conf.d files DirExt = ConfDDirExts.First(); while (DirExt) { directorySet.insert(DirExt->Name()); DirExt = ConfDDirExts.Next(DirExt); } } } void cMenuDirSelect::AddVDRFolders(cNestedItem* folder, string parentDirectory) { if (folder == NULL) return; string folderDirectory = string((parentDirectory.size() == 0)?"":parentDirectory + "~") + folder->Text(); directorySet.insert(folderDirectory); if (folder->SubItems() == NULL) return; for(cNestedItem* subfolder = folder->SubItems()->First(); subfolder; subfolder = folder->SubItems()->Next(subfolder)) AddVDRFolders(subfolder, folderDirectory); } void cMenuDirSelect::Load() { int current = Current(); char* oldSelection = NULL; // save old selection for reselection if (current>-1) oldSelection = strdup(Get(current)->Text()); Clear(); CreateDirSet(); std::set::iterator it; for (it = directorySet.begin(); it != directorySet.end(); ++it) AddDistinct((*it).c_str()); Sort(); for(int i=0; iText(); if (oldSelection && strchr(text, '%') == NULL && strstr(text, oldSelection) == text) // skip entries with variables { SetCurrent(Get(i)); break; } } if (oldSelection) free(oldSelection); if (yellow) { free(yellow); yellow = NULL; } msprintf(&yellow, "%s %d", tr("Button$Level"), (CurLevel==MaxLevel?1:CurLevel+1)); SetHelp(NULL, NULL, MaxLevel==1?NULL:yellow, tr("Button$Select")); Display(); } eOSState cMenuDirSelect::ProcessKey(eKeys Key) { eOSState state = cOsdMenu::ProcessKey(Key); if (state == osUnknown) { switch ((int)Key) { case kBlue|k_Repeat: case kYellow: if (++CurLevel>MaxLevel) CurLevel=1; Load(); return osContinue; case kGreen: case kRed: return osContinue; case kBlue: case kOk: if (Count() > 0) strn0cpy(Directory,Get(Current())->Text(), MaxFileName); return osBack; default: break; } } return state; } vdr-plugin-epgsearch/menu_timersdone.c0000644000175000017500000001463013145412721017775 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #include #include "menu_timersdone.h" #include "epgsearchtools.h" int sortModeTimerDone = 0; cMenuTimerDoneItem::cMenuTimerDoneItem(cTimerDone* TimerDone) { timerDone = TimerDone; Set(); } void cMenuTimerDoneItem::Set(void) { if (!timerDone) return; char *buffer = NULL; char buf[32]; struct tm tm_r; tm *tm = localtime_r(&timerDone->start, &tm_r); strftime(buf, sizeof(buf), "%d.%m.%y %H:%M", tm); LOCK_CHANNELS_READ; const cChannel* ch = Channels->GetByChannelID(timerDone->channelID, true, true); msprintf(&buffer, "%d\t%s\t%s~%s", ch?ch->Number():0, buf, timerDone->title.c_str(), timerDone->shorttext.c_str()); SetText(buffer, false); } int cMenuTimerDoneItem::Compare(const cListObject &ListObject) const { cMenuTimerDoneItem *p = (cMenuTimerDoneItem *)&ListObject; if (sortModeTimerDone == 0) // sort by Date if (timerDone->start > p->timerDone->start) return 1; else return -1; else { cString s1 = cString::sprintf("%s~%s", timerDone->title.c_str(), timerDone->shorttext.c_str()); cString s2 = cString::sprintf("%s~%s", p->timerDone->title.c_str(), p->timerDone->shorttext.c_str()); int res = strcasecmp(s1, s2); return res; } } // --- cMenuTimersDone ---------------------------------------------------------- cMenuTimersDone::cMenuTimersDone(cSearchExt* Search) :cOsdMenu("", 4, 15) { SetMenuCategory(mcTimer); search = Search; showAll = true; sortModeTimerDone = 0; if (search) showAll = false; Set(); Display(); } void cMenuTimersDone::Set() { Clear(); eventObjects.Clear(); cMutexLock TimersDoneLock(&TimersDone); cTimerDone* timerDone = TimersDone.First(); while (timerDone) { if (showAll || (!showAll && search && timerDone->searchID == search->ID)) Add(new cMenuTimerDoneItem(timerDone)); timerDone = TimersDone.Next(timerDone); } UpdateTitle(); SetHelp(sortModeTimerDone==0?tr("Button$by name"):tr("Button$by date"), tr("Button$Delete all"), trVDR("Button$Delete"), showAll?search->search:tr("Button$Show all")); Sort(); cMenuTimerDoneItem* item = (cMenuTimerDoneItem*)First(); while(item) { if (item->timerDone) { const cEvent* Event = item->timerDone->GetEvent(); if (Event) eventObjects.Add(Event); } item = (cMenuTimerDoneItem*)Next(item); } } void cMenuTimersDone::UpdateCurrent() { // navigation in summary could have changed current item, so update it cEventObj* cureventObj = eventObjects.GetCurrent(); if (cureventObj && cureventObj->Event()) for (cMenuTimerDoneItem *item = (cMenuTimerDoneItem *)First(); item; item = (cMenuTimerDoneItem *)Next(item)) if (item->Selectable() && item->timerDone->GetEvent() == cureventObj->Event()) { cureventObj->Select(false); SetCurrent(item); Display(); break; } } cTimerDone *cMenuTimersDone::CurrentTimerDone(void) { cMenuTimerDoneItem *item = (cMenuTimerDoneItem *)Get(Current()); return item ? item->timerDone : NULL; } void cMenuTimersDone::UpdateTitle() { cString buffer = cString::sprintf("%d %s%s%s", Count(), tr("Timers"), showAll?"":" ", showAll?"":search->search); SetTitle(buffer); Display(); } eOSState cMenuTimersDone::Delete(void) { cTimerDone *curTimerDone = CurrentTimerDone(); if (curTimerDone) { if (Interface->Confirm(tr("Edit$Delete entry?"))) { LogFile.Log(1,"deleted timer done: '%s~%s'", curTimerDone->title!=""?curTimerDone->title.c_str():"unknown title", curTimerDone->shorttext!=""?curTimerDone->shorttext.c_str():"unknown subtitle"); cMutexLock TimersDoneLock(&TimersDone); TimersDone.Del(curTimerDone); TimersDone.Save(); cOsdMenu::Del(Current()); Display(); UpdateTitle(); } } return osContinue; } eOSState cMenuTimersDone::DeleteAll(void) { if (Interface->Confirm(tr("Edit$Delete all entries?"))) { cMutexLock TimersDoneLock(&TimersDone); while(Count()>0) { cMenuTimerDoneItem *item = (cMenuTimerDoneItem *)Get(0); if (!item) break; cTimerDone *curTimerDone = item->timerDone; TimersDone.Del(curTimerDone); cOsdMenu::Del(0); } TimersDone.Save(); Display(); UpdateTitle(); } return osContinue; } eOSState cMenuTimersDone::ProcessKey(eKeys Key) { bool HadSubMenu = HasSubMenu(); eOSState state = cOsdMenu::ProcessKey(Key); if (!HasSubMenu() && HadSubMenu) UpdateCurrent(); if (state == osUnknown) { switch (Key) { case kGreen: state = DeleteAll(); break; case kYellow: state = Delete(); break; case kBlue: if(!HasSubMenu()) { showAll = !showAll; Set(); Display(); } break; case k0: case kRed: if(!HasSubMenu()) { sortModeTimerDone = 1-sortModeTimerDone; Set(); Display(); } break; case k8: return osContinue; case kOk: { cTimerDone *TimerDone = CurrentTimerDone(); if (TimerDone) { const cEvent* Event = TimerDone->GetEvent(); if (!Event) break; return AddSubMenu(new cMenuEventSearchSimple(Event, eventObjects)); } } default: break; } } return state; } vdr-plugin-epgsearch/epgsearchcfg.c0000644000175000017500000001010713145412721017214 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #include "epgsearchcfg.h" #include "epgsearchtools.h" cEPGSearchConfig EPGSearchConfig; cEPGSearchConfig::cEPGSearchConfig(void) { hidemenu = 0; redkeymode = 0; bluekeymode = 1; showProgress = 1; showChannelNr = 0; useSearchTimers = 0; UpdateIntervall = 30; SVDRPPort = 6419; timeShiftValue = 30; toggleGreenYellow = 1; StartMenu = 0; DefPriority = Setup.DefaultPriority; DefLifetime = Setup.DefaultLifetime; DefMarginStart = Setup.MarginStart; DefMarginStop = Setup.MarginStop; checkTimerConflictsAfterUpdate = 0; checkMinPriority = 0; checkMinDuration = 0; checkMaxDays = 14; ignorePayTV = 0; useExternalSVDRP = 0; ignorePrimary = 0; strcpy(defrecdir,""); useVDRTimerEditMenu = 0; showChannelGroups = 0; showDaySeparators = 0; showEmptyChannels = 0; DefSearchTemplateID = -1; addSubtitleToTimer = addSubtitleSmart; strcpy(mainmenuentry, ""); WarEagle = 0; showRadioChannels = 1; onePressTimerCreation = 1; conflictCheckIntervall = 30; conflictCheckWithinLimit = 60; conflictCheckIntervall2 = 15; checkTimerConflAfterTimerProg = 0; checkTimerConflOnRecording = 0; showFavoritesMenu = 0; FavoritesMenuTimespan = 24; useOkForSwitch = 0; strcpy(MailAddress, ""); strcpy(MailAddressTo, ""); strcpy(MailServer, ""); MailUseAuth = 0; strcpy(MailAuthUser, ""); strcpy(MailAuthPass, ""); strcpy(LastMailConflicts, ""); mailViaScript = 1; manualTimerCheckDefault = 0; noAnnounceWhileReplay = 0; TimerProgRepeat = 0; maxChannelMenuNow = 0; noConflMsgWhileReplay = 0; sendMailOnSearchtimerHours = 0; lastMailOnSearchtimerAt = 0; checkEPGHours = 6; checkEPGWarnByOSD = 1; checkEPGWarnByMail = 0; checkEPGchannelGroupNr = -1; strcpy(conflCheckCmd, ""); ReplaceOrgSchedule = 0; sendMailOnSearchtimers = 0; sendMailOnConflicts = 0; RemoteConflictCheck = 0; } cShowMode& cShowMode::operator= (const cShowMode &ShowMode) { this->mode = ShowMode.mode; this->seekTime = ShowMode.seekTime; memcpy(this->description, ShowMode.description, sizeof(ShowMode.description)); this->useIt = ShowMode.useIt; this->itime = ShowMode.itime; return *this; } int cShowMode::Compare(const cListObject &ListObject) const { cShowMode *p = (cShowMode *)&ListObject; if (EPGSearchConfig.showFavoritesMenu == 1) { if (mode == showFavorites) { if (p->mode <= showNext) return 1; else return -1; } if (p->mode == showFavorites) { if (mode <= showNext) return -1; else return 1; } } if (EPGSearchConfig.showFavoritesMenu == 2) { if (mode == showFavorites && p->mode != showFavorites) return 1; if (p->mode == showFavorites && mode != showFavorites) return -1; } if (EPGSearchConfig.showFavoritesMenu == 3) { if (mode == showFavorites) { if (p->mode < showNext) return 1; else return -1; } if (p->mode == showFavorites) { if (mode < showNext) return -1; else return 1; } } if (mode > showNext && p->mode > showNext) return seekTime - p->seekTime; else return mode - p->mode; } vdr-plugin-epgsearch/recdone_thread.c0000644000175000017500000001476613145412721017560 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger 2017 Johann Friedrichs This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ #include #include #ifdef __FreeBSD__ #include #endif #include "recdone_thread.h" #include "recdone.h" #include #include #define ALLOWED_BREAK_INSECS 2 extern int updateForced; cRecdoneThread::cRecdoneThread() : cThread("EPGSearch: recdone") { } cRecdoneThread::~cRecdoneThread() { } bool cRecdoneThread::IsPesRecording(const cRecording *pRecording) { return pRecording && pRecording->IsPesRecording(); } #define LOC_INDEXFILESUFFIX "/index" struct tIndexTs { uint64_t offset:40; // up to 1TB per file (not using off_t here - must definitely be exactly 64 bit!) int reserved:7; // reserved for future use int independent:1; // marks frames that can be displayed by themselves (for trick modes) uint16_t number:16; // up to 64K files per recording tIndexTs(off_t Offset, bool Independent, uint16_t Number) { offset = Offset; reserved = 0; independent = Independent; number = Number; } }; int cRecdoneThread::RecLengthInSecs(const cRecording *pRecording) { struct stat buf; cString fullname = cString::sprintf("%s%s", pRecording->FileName(), IsPesRecording(pRecording) ? LOC_INDEXFILESUFFIX ".vdr" : LOC_INDEXFILESUFFIX); if (pRecording->FileName() && *fullname && access(fullname, R_OK) == 0 && stat(fullname, &buf) == 0) { double frames = buf.st_size ? (buf.st_size - 1) / sizeof(tIndexTs) + 1 : 0; double Seconds = 0; modf((frames + 0.5) / pRecording->FramesPerSecond(), &Seconds); return Seconds; } return -1; } void cRecdoneThread::Action(void) { LogFile.Log(1,"started recdone_thread with %s",m_filename); cMutexLock RecsDoneLock(&RecsDone); time_t now = time(NULL); // remove timers that finished recording from TimersRecording // incomplete recordings are kept for a while, perhaps they will be resumed LOCK_TIMERS_READ; cMutexLock TimersRecordingLock(&TimersRecording); cRecDoneTimerObj *tiR = TimersRecording.First(); while(tiR) { // check if timer still exists bool found = false; for (const cTimer *ti = Timers->First(); ti; ti = Timers->Next(ti)) if (ti == tiR->timer) { found = true; break; } if (found && !tiR->timer->Recording()) { if (tiR->recDone) { cSearchExt* search = SearchExts.GetSearchFromID(tiR->recDone->searchID); if (!search) return; // check if recording has ended before timer end bool complete = true; const cRecording *pRecording; { LOCK_RECORDINGS_READ; pRecording = Recordings->GetByName(m_filename); } long timerLengthSecs = tiR->timer->StopTime()-tiR->timer->StartTime(); int recFraction = 100; if (pRecording && timerLengthSecs) { int recLen = RecLengthInSecs(pRecording); recFraction = double(recLen) * 100 / timerLengthSecs; } bool vpsUsed = tiR->timer->HasFlags(tfVps) && tiR->timer->Event() && tiR->timer->Event()->Vps(); if ((!vpsUsed && now < tiR->timer->StopTime()) || recFraction < (vpsUsed ? 90: 98)) // assure timer has reached its end or at least 98% were recorded { complete = false; LogFile.Log(1,"finished: '%s' (not complete! - recorded only %d%%); search timer: '%s'; VPS used: %s", tiR->timer->File(), recFraction, search->search, vpsUsed ? "Yes": "No"); } else { LogFile.Log(1,"finished: '%s'; search timer: '%s'; VPS used: %s", tiR->timer->File(), search->search, vpsUsed ? "Yes": "No"); if (recFraction < 100) LogFile.Log(2,"recorded %d%%'", recFraction); } if (complete) { RecsDone.Add(tiR->recDone); LogFile.Log(1,"added rec done for '%s~%s';%s", tiR->recDone->title?tiR->recDone->title:"unknown title", tiR->recDone->shortText?tiR->recDone->shortText:"unknown subtitle", search->search); RecsDone.Save(); tiR->recDone = NULL; // prevent deletion tiR->lastBreak = 0; // check for search timers to delete automatically SearchExts.CheckForAutoDelete(search); // trigger a search timer update (skip running events) search->skipRunningEvents = true; updateForced = 1; } else if (tiR->lastBreak == 0) // store first break tiR->lastBreak = now; } if (tiR->lastBreak == 0 || (now - tiR->lastBreak) > ALLOWED_BREAK_INSECS) { // remove finished recordings or those with an unallowed break if (tiR->recDone) delete tiR->recDone; // clean up cRecDoneTimerObj *tiRNext = TimersRecording.Next(tiR); TimersRecording.Del(tiR); tiR = tiRNext; continue; } break; } if (!found) { if (tiR->recDone) delete tiR->recDone; // clean up cRecDoneTimerObj *tiRNext = TimersRecording.Next(tiR); TimersRecording.Del(tiR); tiR = tiRNext; continue; } tiR = TimersRecording.Next(tiR); } if (m_filename) free(m_filename); LogFile.Log(1,"recdone_thread ended"); } vdr-plugin-epgsearch/log.h0000644000175000017500000000574013145412721015370 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #ifndef _LOG_INC_ #define _LOG_INC_ #include #include #include class cLogFile: public cFile { public: static int loglevellimit; void Open(const char* filename, const char* version) { if (loglevellimit == 0) return; if (!cFile::Open(filename, O_CREAT|O_APPEND|O_WRONLY)) esyslog("EPGSEARCH: could not open log file: %s", filename); Log(1, "---------------------------------------", loglevellimit); Log(1, "EPGSearch log started (verbose level %d, version %s)", loglevellimit, version); } void Log(int LogLevel, const char *text, ...) { if (LogLevel > loglevellimit) return; if(IsOpen()) { char* buffer = NULL; va_list Arg; va_start(Arg,text); if (vasprintf(&buffer, text, Arg) < 0) esyslog("EPGSearch: vasprintf error"); va_end(Arg); time_t now = time(NULL); char datebuf[32]; struct tm tm_r; tm *tm = localtime_r(&now, &tm_r); char *p = stpcpy(datebuf, WeekDayName(tm->tm_wday)); *p++ = ' '; strftime(p, sizeof(datebuf) - (p - datebuf), "%d.%m.%Y", tm); char timebuf[25]; strftime(timebuf, sizeof(timebuf), "%T", localtime_r(&now, &tm_r)); cString log = cString::sprintf("%s %s: %s\n", datebuf, timebuf, buffer); free(buffer); safe_write(*this, log, strlen(log)); } } void eSysLog(const char *text, ...) { char* buffer = NULL; va_list Arg; va_start(Arg,text); if (vasprintf(&buffer, text, Arg) < 0) esyslog("EPGSearch: vasprintf error"); va_end(Arg); esyslog("EPGSearch: %s", buffer); Log(1, "%s", buffer); free(buffer); } void iSysLog(const char *text, ...) { char* buffer = NULL; va_list Arg; va_start(Arg,text); if (vasprintf(&buffer, text, Arg) < 0) esyslog("EPGSearch: vasprintf error"); va_end(Arg); isyslog("EPGSearch: %s", buffer); Log(1, "%s", buffer); free(buffer); } int Level() { return loglevellimit; } static char *LogFileName; }; extern cLogFile LogFile; #endif vdr-plugin-epgsearch/menu_timersdone.h0000644000175000017500000000357613145412721020011 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #ifndef __MENU_TIMERSDONE_H #define __MENU_TIMERSDONE_H #include "epgsearchext.h" #include "timerdone.h" #include "menu_event.h" #include #include // --- cMenuTimerDoneItem ---------------------------------------------------------- class cMenuTimerDoneItem : public cOsdItem { public: cTimerDone* timerDone; cMenuTimerDoneItem(cTimerDone* TimerDone); void Set(void); int Compare(const cListObject &ListObject) const; }; class cMenuTimersDone : public cOsdMenu { private: cSearchExt* search; eOSState Delete(void); eOSState DeleteAll(void); bool showAll; cEventObjects eventObjects; protected: void Set(); virtual eOSState ProcessKey(eKeys Key); void UpdateTitle(); eOSState Summary(void); cTimerDone* CurrentTimerDone(void); void UpdateCurrent(); public: cMenuTimersDone(cSearchExt* search = NULL); }; #endif vdr-plugin-epgsearch/services.c0000644000175000017500000002577113145412721016433 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #include #include #include #include #include "epgsearchservices.h" #include "epgsearchext.h" #include "epgsearchcfg.h" #include "searchtimer_thread.h" #include "epgsearchcats.h" #include "changrp.h" #include "blacklist.h" #include "menu_dirselect.h" #include "epgsearchtools.h" #include "conflictcheck.h" #include "timerstatus.h" #include "uservars.h" std::list cEpgsearchServiceHandler::SearchTimerList() { std::list list; cMutexLock SearchExtsLock(&SearchExts); for (int i = 0; i < SearchExts.Count(); i++) { cSearchExt* search = SearchExts.Get(i); if (search) list.push_back(search->ToText()); } return list; } int cEpgsearchServiceHandler::AddSearchTimer(const std::string& settings) { cSearchExt* search = new cSearchExt; if (search->Parse(settings.c_str())) { search->ID = SearchExts.GetNewID(); LogFile.Log(1,"added search '%s' (%d) via service interface", search->search, search->ID); cMutexLock SearchExtsLock(&SearchExts); SearchExts.Add(search); SearchExts.Save(); if (search->useAsSearchTimer && !EPGSearchConfig.useSearchTimers) // enable search timer thread if necessary cSearchTimerThread::Init((cPluginEpgsearch*) cPluginManager::GetPlugin("epgsearch"), true); return search->ID; } else { LogFile.Log(1,"error adding '%s' via service interface", search->search); delete search; return -1; } } bool cEpgsearchServiceHandler::ModSearchTimer(const std::string& settings) { cSearchExt Search; if (Search.Parse(settings.c_str())) { cSearchExt *searchTemp = SearchExts.GetSearchFromID(Search.ID); if (searchTemp) { searchTemp->Parse(settings.c_str()); LogFile.Log(1,"modified search '%s' (%d) via service interface", searchTemp->search, searchTemp->ID); SearchExts.Save(); if (searchTemp->useAsSearchTimer && !EPGSearchConfig.useSearchTimers) // enable search timer thread if necessary cSearchTimerThread::Init((cPluginEpgsearch*) cPluginManager::GetPlugin("epgsearch"), true); return true; } } else { LogFile.Log(1,"error modifying '%s' via service interface", settings.c_str()); } return false; } bool cEpgsearchServiceHandler::DelSearchTimer(int ID) { cSearchExt *search = SearchExts.GetSearchFromID(ID); if (search) { LogFile.Log(1,"search '%s' deleted via service interface", search->search); cMutexLock SearchExtsLock(&SearchExts); SearchExts.Del(search); SearchExts.Save(); RecsDone.RemoveSearchID(ID); return true; } else LogFile.Log(1,"error deleting search with id '%d' via service interface", ID); return false; } std::list cEpgsearchServiceHandler::TranslateResults(cSearchResults* pCompleteSearchResults) { std::list list; if (pCompleteSearchResults) { // transfer to result list pCompleteSearchResults->SortBy(CompareEventTime); cSearchResult *result = pCompleteSearchResults->First(); while (result && result->search) { const cEvent* pEvent = result->event; cTimer* Timer = new cTimer(pEvent); static char bufStart[25]; static char bufEnd[25]; struct tm tm_r; time_t eStart = pEvent->StartTime(); time_t eStop = pEvent->EndTime(); time_t start = eStart - (result->search->MarginStart * 60); time_t stop = eStop + (result->search->MarginStop * 60); if (result->search->useVPS && pEvent->Vps() && Setup.UseVps) { start = pEvent->Vps(); stop = start + pEvent->Duration(); } strftime(bufStart, sizeof(bufStart), "%H%M", localtime_r(&start, &tm_r)); strftime(bufEnd, sizeof(bufEnd), "%H%M", localtime_r(&stop, &tm_r)); eTimerMatch timerMatch; bool hasTimer = false; LOCK_TIMERS_READ; if (Timers->GetMatch(pEvent, &timerMatch)) hasTimer = (timerMatch == tmFull); if (!result->search->useAsSearchTimer) result->needsTimer = false; LOCK_CHANNELS_READ; const cChannel *channel = Channels->GetByChannelID(pEvent->ChannelID(), true, true); int timerMode = hasTimer?1:(result->needsTimer?2:0); std::string title = pEvent->Title()?ReplaceAll(pEvent->Title(), "|", "!^pipe!^"):""; title = ReplaceAll(title, ":", "|"); std::string shorttext = pEvent->ShortText()?ReplaceAll(pEvent->ShortText(), "|", "!^pipe!^"):""; shorttext = ReplaceAll(shorttext, ":", "|"); std::string description = pEvent->Description()?ReplaceAll(pEvent->Description(), "|", "!^pipe!^"):""; description = ReplaceAll(description, ":", "|"); cString cmdbuf = cString::sprintf("%d:%u:%s:%s:%s:%ld:%ld:%s:%ld:%ld:%s:%d", result->search->ID, pEvent->EventID(), title.c_str(), shorttext.c_str(), description.c_str(), pEvent->StartTime(), pEvent->EndTime(), CHANNELSTRING(channel), timerMode>0?start:-1, timerMode>0?stop:-1, timerMode>0?result->search->BuildFile(pEvent):"", timerMode); list.push_back(*cmdbuf); delete(Timer); result = pCompleteSearchResults->Next(result); } } return list; } std::list cEpgsearchServiceHandler::QuerySearchTimer(int ID) { std::list list; cSearchResults* pCompleteSearchResults = NULL; cSearchExt* search = SearchExts.GetSearchFromID(ID); if (!search) return list; pCompleteSearchResults = search->Run(); list = TranslateResults(pCompleteSearchResults); if (pCompleteSearchResults) delete pCompleteSearchResults; return list; } std::list cEpgsearchServiceHandler::QuerySearch(std::string query) { std::list list; cSearchExt* temp_SearchExt = new cSearchExt; if (temp_SearchExt->Parse(query.c_str())) { cSearchResults* pCompleteSearchResults = temp_SearchExt->Run(); list = TranslateResults(pCompleteSearchResults); if (pCompleteSearchResults) delete pCompleteSearchResults; } delete temp_SearchExt; return list; } std::list cEpgsearchServiceHandler::ExtEPGInfoList() { std::list list; for (int i = 0; i < SearchExtCats.Count(); i++) { cSearchExtCat *SearchExtCat = SearchExtCats.Get(i); if (SearchExtCat) list.push_back(SearchExtCat->ToText()); } return list; } std::list cEpgsearchServiceHandler::ChanGrpList() { std::list list; for (int i = 0; i < ChannelGroups.Count(); i++) { cChannelGroup *changrp = ChannelGroups.Get(i); if (changrp) list.push_back(changrp->ToText()); } return list; } std::list cEpgsearchServiceHandler::BlackList() { std::list list; cMutexLock BlacklistLock(&Blacklists); for (int i = 0; i < Blacklists.Count(); i++) { cBlacklist* blacklist = Blacklists.Get(i); if (blacklist) list.push_back(blacklist->ToText()); } return list; } std::set cEpgsearchServiceHandler::DirectoryList() { cMenuDirSelect::CreateDirSet(); return cMenuDirSelect::directorySet; } std::string cEpgsearchServiceHandler::ReadSetupValue(const std::string& entry) { if (entry == "DefPriority") return NumToString(EPGSearchConfig.DefPriority); if (entry == "DefLifetime") return NumToString(EPGSearchConfig.DefLifetime); if (entry == "DefMarginStart") return NumToString(EPGSearchConfig.DefMarginStart); if (entry == "DefMarginStop") return NumToString(EPGSearchConfig.DefMarginStop); return ""; } bool cEpgsearchServiceHandler::WriteSetupValue(const std::string& entry, const std::string& value) { return true; } std::list cEpgsearchServiceHandler::TimerConflictList(bool relOnly) { std::list list; cConflictCheck conflictCheck; conflictCheck.Check(); if ((relOnly && conflictCheck.numConflicts > 0) || conflictCheck.relevantConflicts > 0) { string sBuffer; cList* failedList = conflictCheck.GetFailed(); for(cConflictCheckTime* ct = failedList->First(); ct; ct = failedList->Next(ct)) { if (relOnly && ct->ignore) continue; std::ostringstream conflline; conflline << ct->evaltime << ":"; std::set::iterator it; std::ostringstream timerparts; for (it = ct->failedTimers.begin(); it != ct->failedTimers.end(); ++it) { if (relOnly && (*it)->ignore) continue; std::ostringstream timerpart; int recPart = (*it)->recDuration * 100 / ((*it)->stop - (*it)->start); timerpart << (*it)->timer->Id() << "|" << recPart << "|"; std::set::iterator itcc; if ((*it)->concurrentTimers) { std::ostringstream cctimers; for (itcc = (*it)->concurrentTimers->begin(); itcc != (*it)->concurrentTimers->end(); ++itcc) cctimers << (cctimers.str().empty()?"":"#") << (*itcc)->timer->Id(); timerpart << cctimers.str(); } timerparts << (timerparts.str().empty()?"":":") << timerpart.str(); } conflline << timerparts.str(); list.push_back(conflline.str()); } } // set advised to false after an external conflict check if (gl_timerStatusMonitor) gl_timerStatusMonitor->SetConflictCheckAdvised(false); return list; } bool cEpgsearchServiceHandler::IsConflictCheckAdvised() { return gl_timerStatusMonitor?gl_timerStatusMonitor->ConflictCheckAdvised():false; } std::set cEpgsearchServiceHandler::ShortDirectoryList() { cMenuDirSelect::CreateDirSet(false); return cMenuDirSelect::directorySet; } std::string cEpgsearchServiceHandler::Evaluate(const std::string& expr, const cEvent* event) { if (!event) return expr; cVarExpr varExpr(expr); return varExpr.Evaluate(event); } vdr-plugin-epgsearch/menu_searchedit.c0000644000175000017500000012551113145412721017740 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #include #include #include #include "menu_searchedit.h" #include "changrp.h" #include "epgsearchcats.h" #include "epgsearchtools.h" #include "menu_dirselect.h" #include "menu_recsdone.h" #include "menu_searchtemplate.h" #include "epgsearchcfg.h" #include "blacklist.h" #include "menu_blacklists.h" #include "epgsearch.h" #include "searchtimer_thread.h" #include #include "templatefile.h" using namespace std; cChannelGroups ChannelGroups; cSearchExtCats SearchExtCats; // --- cMenuEditSearchExt -------------------------------------------------------- cMenuEditSearchExt::cMenuEditSearchExt(cSearchExt *SearchExt, bool New, bool Template, bool FromEPG) :cOsdMenu(tr("Edit search"),32) { SetMenuCategory(mcPlugin); templateMode = Template; SearchModes[0] = strdup(tr("phrase")); SearchModes[1] = strdup(tr("all words")); SearchModes[2] = strdup(tr("at least one word")); SearchModes[3] = strdup(tr("match exactly")); SearchModes[4] = strdup(tr("regular expression")); SearchModes[5] = strdup(tr("fuzzy")); DaysOfWeek[0] = strdup(WeekDayName(0)); DaysOfWeek[1] = strdup(WeekDayName(1)); DaysOfWeek[2] = strdup(WeekDayName(2)); DaysOfWeek[3] = strdup(WeekDayName(3)); DaysOfWeek[4] = strdup(WeekDayName(4)); DaysOfWeek[5] = strdup(WeekDayName(5)); DaysOfWeek[6] = strdup(WeekDayName(6)); DaysOfWeek[7] = strdup(tr("user-defined")); UseChannelSel[0] = strdup(trVDR("no")); UseChannelSel[1] = strdup(tr("interval")); UseChannelSel[2] = strdup(tr("channel group")); UseChannelSel[3] = strdup(tr("only FTA")); SearchTimerModes[0] = strdup(tr("Record")); SearchTimerModes[1] = strdup(tr("Announce by OSD")); SearchTimerModes[2] = strdup(tr("Switch only")); SearchTimerModes[3] = strdup(tr("Announce and switch")); SearchTimerModes[4] = strdup(tr("Announce by mail")); SearchTimerModes[5] = strdup(tr("Inactive record")); BlacklistModes[0] = strdup(tr("only globals")); BlacklistModes[1] = strdup(tr("Selection")); BlacklistModes[2] = strdup(tr("all")); BlacklistModes[3] = strdup(trVDR("none")); DelModes[0] = strdup(trVDR("no")); DelModes[1] = strdup(tr("count recordings")); DelModes[2] = strdup(tr("count days")); SearchActiveModes[0] = strdup(trVDR("no")); SearchActiveModes[1] = strdup(trVDR("yes")); SearchActiveModes[2] = strdup(tr("user-defined")); CompareSubtitleModes[0] = strdup(trVDR("no")); CompareSubtitleModes[1] = strdup(tr("if present")); CompareDateModes[0] = strdup(trVDR("no")); CompareDateModes[1] = strdup(tr("same day")); CompareDateModes[2] = strdup(tr("same week")); CompareDateModes[3] = strdup(tr("same month")); // collect content string IDs std::set contentStrings; for(unsigned int i=0; iID == EPGSearchConfig.DefSearchTemplateID) SearchTempl = SearchExtTempl; SearchExtTempl = SearchTemplates.Next(SearchExtTempl); } if (SearchTempl) SearchExt->CopyFromTemplate(SearchTempl, FromEPG); } searchExt = SearchExt; addIfConfirmed = New; if (!templateMode) SetHelp(NULL, NULL, tr("Button$Help"), tr("Button$Templates")); if (searchExt) { data = *searchExt; UserDefDayOfWeek = 0; if (searchExt->DayOfWeek < 0) { UserDefDayOfWeek = searchExt->DayOfWeek; data.DayOfWeek = 7; } menuitemsChGr = NULL; channelGroupName = NULL; channelMin = channelMax = cDevice::CurrentChannel(); channelGroupNr = 0; if (data.channelMin) channelMin = data.channelMin->Number(); if (data.channelMax) channelMax = data.channelMax->Number(); if (data.useChannel==2) { channelGroupNr = ChannelGroups.GetIndex(data.channelGroup); if (channelGroupNr == -1) { free(data.channelGroup); data.channelGroup = NULL; channelGroupNr = 0; // no selection } else { channelGroupName = strdup(data.channelGroup); channelGroupNr++; } } contentStringsFlags = NULL; // set the flags for the content descriptors contentStringsFlags = (int*) malloc((CONTENT_DESCRIPTOR_MAX+1) * sizeof(int)); for(unsigned int i=0; i<=CONTENT_DESCRIPTOR_MAX;i++) contentStringsFlags[i] = data.HasContent(i); useContentDescriptors = (data.contentsFilter.size() > 0); catarrayAvoidRepeats = NULL; catvaluesNumeric = NULL; if (SearchExtCats.Count() > 0) { // fill an array, that stores yes/no for using categories in avoid repeats catarrayAvoidRepeats = (int*) malloc(SearchExtCats.Count() * sizeof(int)); catvaluesNumeric = (int*) malloc(SearchExtCats.Count() * sizeof(int)); cSearchExtCat *SearchExtCat = SearchExtCats.First(); int index = 0; while (SearchExtCat) { catarrayAvoidRepeats[index] = (SearchExt->catvaluesAvoidRepeat & (1<catvalues[index]); SearchExtCat = SearchExtCats.Next(SearchExtCat); index++; } } blacklists.Clear(); if (data.blacklistMode == blacklistsSelection) { cBlacklistObject* blacklistObj = searchExt->blacklists.First(); while(blacklistObj) { blacklists.Add(new cBlacklistObject(blacklistObj->blacklist)); blacklistObj = searchExt->blacklists.Next(blacklistObj); } } Set(); } } void cMenuEditSearchExt::AddHelp(const char* helpText) { helpTexts.push_back(helpText); } void cMenuEditSearchExt::Set() { int current = Current(); Clear(); helpTexts.clear(); if (templateMode) { Add(new cMenuEditStrItem( tr("Template name"), data.search, sizeof(data.search), tr(AllowedChars))); AddHelp(tr("Help$Specify the name of the template.")); } else { Add(new cMenuEditStrItem( tr("Search term"), data.search, sizeof(data.search), tr(AllowedChars))); AddHelp(tr("Help$Specify here the term to search for.")); } Add(new cMenuEditStraItem(tr("Search mode"), &data.mode, 6, SearchModes)); AddHelp(tr("Help$The following search modes exist:\n\n- phrase: searches for sub terms\n- all words: all single words must appear\n- at least one word: at least one single word must appear\n- match exactly: must match exactly\n- regular expression: match a regular expression\n- fuzzy searching: searches approximately")); if (data.mode == 5) // fuzzy { Add(new cMenuEditIntItem(IndentMenuItem(tr("Tolerance")), &data.fuzzyTolerance, 1, 9)); AddHelp(tr("Help$This sets the tolerance of fuzzy searching. The value represents the allowed errors.")); } Add(new cMenuEditBoolItem( tr("Match case"), &data.useCase, trVDR("no"), trVDR("yes"))); AddHelp(tr("Help$Set this to 'Yes' if your search should match the case.")); Add(new cMenuEditBoolItem( tr("Use title"), &data.useTitle, trVDR("no"), trVDR("yes"))); AddHelp(tr("Help$Set this to 'Yes' if you like to search in the title of an event.")); Add(new cMenuEditBoolItem( tr("Use subtitle"), &data.useSubtitle, trVDR("no"), trVDR("yes"))); AddHelp(tr("Help$Set this to 'Yes' if you like to search in the episode of an event.")); Add(new cMenuEditBoolItem( tr("Use description"), &data.useDescription, trVDR("no"), trVDR("yes"))); AddHelp(tr("Help$Set this to 'Yes' if you like to search in the summary of an event.")); Add(new cMenuEditBoolItem( tr("Use content descriptor"), &useContentDescriptors, trVDR("no"), trVDR("yes"))); AddHelp(tr("Help$Set this to 'Yes' if you want to search the contents by a descriptor.")); if (useContentDescriptors) { vector::const_iterator it; for(unsigned int i=0; i< contentStringIDs.size(); i++) { int level = (contentStringIDs[i] % 0x10==0?1:2); Add(new cMenuEditBoolItem(IndentMenuItem(tr(cEvent::ContentToString(contentStringIDs[i])), level), &contentStringsFlags[contentStringIDs[i]], trVDR("no"), trVDR("yes"))); } } // show Categories only if we have them if (SearchExtCats.Count() > 0) { Add(new cMenuEditBoolItem( tr("Use extended EPG info"), &data.useExtEPGInfo, trVDR("no"), trVDR("yes"))); AddHelp(tr("Help$The summary of an event, can contain additional information like 'Genre', 'Category', 'Year',... called 'EPG categories' within EPGSearch. External EPG providers often deliver this information. This allows refining a search and other nice things, like searching for the 'tip of the day'. To use it set this to 'Yes'.")); if (data.useExtEPGInfo) { cSearchExtCat *SearchExtCat = SearchExtCats.First(); int index = 0; while (SearchExtCat) { if (SearchExtCat->searchmode >= 10) Add(new cMenuEditIntItem(IndentMenuItem(SearchExtCat->menuname), &catvaluesNumeric[index], 0, 999999, "")); else Add(new cMenuEditStrItem( IndentMenuItem(SearchExtCat->menuname), data.catvalues[index], MaxFileName, tr(AllowedChars))); AddHelp(tr("Help$The file epgsearchcats.conf specifies the search mode for this entry. One can search by text or by value. You can also edit a list of predefined values in this file that can be selected here.")); SearchExtCat = SearchExtCats.Next(SearchExtCat); index++; } Add(new cMenuEditBoolItem(IndentMenuItem(tr("Ignore missing categories")), &data.ignoreMissingEPGCats, trVDR("no"), trVDR("yes"))); AddHelp(tr("Help$If a selected category is not part of the summary of an event this normally excludes this event from the search results. To avoid this, set this option to 'Yes', but please handle this with care to avoid a huge amount of results.")); } } Add(new cMenuEditStraItem(tr("Use channel"), &data.useChannel, 4, UseChannelSel)); if (data.useChannel==1) { Add(new cMenuEditChanItem(tr(" from channel"), &channelMin)); Add(new cMenuEditChanItem(tr(" to channel"), &channelMax)); } if (data.useChannel==2) { // create the char array for the menu display if (menuitemsChGr) delete [] menuitemsChGr; menuitemsChGr = ChannelGroups.CreateMenuitemsList(); int oldchannelGroupNr = channelGroupNr; channelGroupNr = ChannelGroups.GetIndex(channelGroupName); if (channelGroupNr == -1) { if (oldchannelGroupNr > 0 && oldchannelGroupNr <= ChannelGroups.Count()) // perhaps its name was changed channelGroupNr = oldchannelGroupNr; else channelGroupNr = 0; // no selection } else channelGroupNr++; Add(new cMenuEditStraItem(IndentMenuItem(tr("Channel group")), &channelGroupNr, ChannelGroups.Count()+1, menuitemsChGr)); } Add(new cMenuEditBoolItem( tr("Use time"), &data.useTime, trVDR("no"), trVDR("yes"))); if (data.useTime == true) { Add(new cMenuEditTimeItem(tr(" Start after"), &data.startTime)); Add(new cMenuEditTimeItem(tr(" Start before"), &data.stopTime)); } Add(new cMenuEditBoolItem( tr("Use duration"), &data.useDuration, trVDR("no"), trVDR("yes"))); if (data.useDuration == true) { Add(new cMenuEditTimeItem(tr(" Min. duration"), &data.minDuration)); Add(new cMenuEditTimeItem(tr(" Max. duration"), &data.maxDuration)); } Add(new cMenuEditBoolItem( tr("Use day of week"), &data.useDayOfWeek, trVDR("no"), trVDR("yes"))); if (data.useDayOfWeek) { if (data.DayOfWeek < 0) { UserDefDayOfWeek = data.DayOfWeek; data.DayOfWeek = 7; } Add(new cMenuEditStraItem(IndentMenuItem(tr("Day of week")), &data.DayOfWeek, 8, DaysOfWeek)); } Add(new cMenuEditStraItem(tr("Use blacklists"), &data.blacklistMode, 4, BlacklistModes)); if (EPGSearchConfig.showFavoritesMenu) Add(new cMenuEditBoolItem( tr("Use in favorites menu"), &data.useInFavorites, trVDR("no"), trVDR("yes"))); int countSearchTemplates = 0; if ((countSearchTemplates = cTemplFile::CountSearchResultsTemplates()) > 1) { Add(new cMenuEditStraItem(tr("Result menu layout"), &data.menuTemplate, countSearchTemplates, cTemplFile::SearchTemplates)); } Add(new cMenuEditStraItem( tr("Use as search timer"), &data.useAsSearchTimer, 3, SearchActiveModes)); if (data.useAsSearchTimer) { Add(new cMenuEditStraItem(IndentMenuItem(tr("Action")), &data.action, 6, SearchTimerModes)); if (data.action == searchTimerActionSwitchOnly) { Add(new cMenuEditIntItem(IndentMenuItem(tr("Switch ... minutes before start")), &data.switchMinsBefore, 0, 99)); Add(new cMenuEditBoolItem(IndentMenuItem(tr("Unmute sound")), &data.unmuteSoundOnSwitch, trVDR("no"), trVDR("yes"))); } if (data.action == searchTimerActionAnnounceAndSwitch) { Add(new cMenuEditIntItem(IndentMenuItem(tr("Ask ... minutes before start")), &data.switchMinsBefore, 0, 99)); Add(new cMenuEditBoolItem(IndentMenuItem(tr("Unmute sound")), &data.unmuteSoundOnSwitch, trVDR("no"), trVDR("yes"))); } if ((data.action == searchTimerActionRecord) || (data.action == searchTimerActionInactiveRecord)) { Add(new cMenuEditBoolItem( tr(" Series recording"), &data.useEpisode, trVDR("no"), trVDR("yes"))); Add(new cMenuEditStrItem(IndentMenuItem(tr("Directory")), data.directory, sizeof(data.directory), tr(AllowedChars))); Add(new cMenuEditIntItem(IndentMenuItem(tr("Delete recordings after ... days")), &data.delAfterDays, 0, 999)); if (data.delAfterDays > 0) Add(new cMenuEditIntItem(IndentMenuItem(IndentMenuItem(tr("Keep ... recordings"))), &data.recordingsKeep, 0, 999)); Add(new cMenuEditIntItem(IndentMenuItem(tr("Pause when ... recordings exist")), &data.pauseOnNrRecordings, 0, 999)); Add(new cMenuEditBoolItem(IndentMenuItem(tr("Avoid repeats")), &data.avoidRepeats, trVDR("no"), trVDR("yes"))); if (data.avoidRepeats) { Add(new cMenuEditIntItem(IndentMenuItem(tr("Allowed repeats"),2), &data.allowedRepeats, 0, 99)); if (data.allowedRepeats > 0) Add(new cMenuEditIntItem(IndentMenuItem(tr("Only repeats within ... days"),2), &data.repeatsWithinDays, 0, 999)); Add(new cMenuEditBoolItem(IndentMenuItem(tr("Compare title"),2), &data.compareTitle, trVDR("no"), trVDR("yes"))); Add(new cMenuEditStraItem(IndentMenuItem(tr("Compare subtitle"),2), &data.compareSubtitle, 2, CompareSubtitleModes)); Add(new cMenuEditBoolItem(IndentMenuItem(tr("Compare summary"),2), &data.compareSummary, trVDR("no"), trVDR("yes"))); if (data.compareSummary) Add(new cMenuEditIntItem(IndentMenuItem(tr("Min. match in %"),3), &data.compareSummaryMatchInPercent, 1, 100)); Add(new cMenuEditStraItem(IndentMenuItem(tr("Compare date"),2), &data.compareDate, 4, CompareDateModes)); // show 'Compare categories' only if we have them if (SearchExtCats.Count() > 0) { cSearchExtCat *SearchExtCat = SearchExtCats.First(); int iUsed = 0; int index = 0; while (SearchExtCat) { if (catarrayAvoidRepeats[index]) iUsed++; SearchExtCat = SearchExtCats.Next(SearchExtCat); index++; } cString itemtext = cString::sprintf("%s (%d/%d)", tr("Compare categories"), iUsed, SearchExtCats.Count()); Add(new cOsdItem(IndentMenuItem(IndentMenuItem(itemtext)))); } } Add(new cMenuEditIntItem(IndentMenuItem(trVDR("Priority")), &data.Priority, 0, MAXPRIORITY)); Add(new cMenuEditIntItem(IndentMenuItem(trVDR("Lifetime")), &data.Lifetime, 0, MAXLIFETIME)); Add(new cMenuEditIntItem(IndentMenuItem(trVDR("Setup.Recording$Margin at start (min)")), &data.MarginStart, -INT_MAX, INT_MAX)); Add(new cMenuEditIntItem(IndentMenuItem(trVDR("Setup.Recording$Margin at stop (min)")), &data.MarginStop, -INT_MAX, INT_MAX)); Add(new cMenuEditBoolItem(IndentMenuItem(tr("VPS")), &data.useVPS, trVDR("no"), trVDR("yes"))); } if ((data.action == searchTimerActionRecord) || (data.action == searchTimerActionInactiveRecord)) { Add(new cMenuEditStraItem(IndentMenuItem(tr("Auto delete")), &data.delMode, 3, DelModes)); if (data.delMode == 1) Add(new cMenuEditIntItem(IndentMenuItem(IndentMenuItem(tr("after ... recordings"))), &data.delAfterCountRecs, 0, 999)); else if (data.delMode == 2) Add(new cMenuEditIntItem(IndentMenuItem(IndentMenuItem(tr("after ... days after first rec."))), &data.delAfterDaysOfFirstRec, 0, 999)); } } SetCurrent(Get(current)); } cMenuEditSearchExt::~cMenuEditSearchExt() { if (searchExt && addIfConfirmed) delete searchExt; // apparently it wasn't confirmed if (menuitemsChGr) free(menuitemsChGr); if (channelGroupName) free(channelGroupName); if (catarrayAvoidRepeats) free(catarrayAvoidRepeats); if (catvaluesNumeric) free(catvaluesNumeric); if (contentStringsFlags) free(contentStringsFlags); int i; for(i=0; i<=5; i++) free(SearchModes[i]); for(i=0; i<=7; i++) free(DaysOfWeek[i]); for(i=0; i<=3; i++) free(UseChannelSel[i]); for(i=0; i<=5; i++) free(SearchTimerModes[i]); for(i=0; i<=3; i++) free(BlacklistModes[i]); for(i=0; i<=2; i++) free(DelModes[i]); for(i=0; i<=2; i++) free(SearchActiveModes[i]); for(i=0; i<=1; i++) free(CompareSubtitleModes[i]); for(i=0; i<=3; i++) free(CompareDateModes[i]); } eOSState cMenuEditSearchExt::Help() { const char* ItemText = Get(Current())->Text(); eOSState state = osContinue; if(Current() < (int) helpTexts.size()) { char* title = NULL; if (msprintf(&title, "%s - %s", tr("Button$Help"), ItemText)!=-1) { if (strchr(title, ':')) *strchr(title, ':') = 0; state = AddSubMenu(new cMenuText(title, helpTexts[Current()])); free(title); } } return state; } eOSState cMenuEditSearchExt::ProcessKey(eKeys Key) { bool bHadSubMenu = HasSubMenu(); int iTemp_mode = data.mode; int iTemp_useTime = data.useTime; int iTemp_useChannel = data.useChannel; int iTemp_useDuration = data.useDuration; int iTemp_useDayOfWeek = data.useDayOfWeek; int iTemp_useAsSearchTimer = data.useAsSearchTimer; int iTemp_useExtEPGInfo = data.useExtEPGInfo; int iTemp_useContentDescriptor = useContentDescriptors; int iTemp_avoidRepeats = data.avoidRepeats; int iTemp_allowedRepeats = data.allowedRepeats; int iTemp_delAfterDays = data.delAfterDays; int iTemp_action = data.action; int iTemp_delMode = data.delMode; int iTemp_compareSummary = data.compareSummary; eOSState state = cOsdMenu::ProcessKey(Key); if (iTemp_mode != data.mode || iTemp_useTime != data.useTime || iTemp_useChannel != data.useChannel || iTemp_useDuration != data.useDuration || iTemp_useDayOfWeek != data.useDayOfWeek || iTemp_useAsSearchTimer != data.useAsSearchTimer || iTemp_useExtEPGInfo != data.useExtEPGInfo || iTemp_useContentDescriptor != useContentDescriptors || iTemp_avoidRepeats != data.avoidRepeats || iTemp_allowedRepeats != data.allowedRepeats || iTemp_delAfterDays != data.delAfterDays || iTemp_action != data.action || iTemp_delMode != data.delMode || iTemp_compareSummary != data.compareSummary) { Set(); Display(); if ((iTemp_useAsSearchTimer != data.useAsSearchTimer || iTemp_action != data.action) && data.useAsSearchTimer) // if search timer menu is dropped then scroll down to display all contents { int cur = Current(); PageDown(); SetCurrent(Get(cur)); Display(); } } const char* ItemText = Get(Current())->Text(); if (!HasSubMenu()) { if (strlen(ItemText)>0 && strstr(ItemText, tr(" from channel")) == ItemText && ((Key >= k0 && Key <= k9) || Key == kLeft || Key == kRight)) { channelMax = channelMin; Set(); Display(); } } int iOnUserDefDayItem = 0; int iOnDirectoryItem = 0; int iOnUseChannelGroups = 0; int iOnChannelGroup = 0; int iOnAvoidRepeats = 0; int iOnCompareCats = 0; int iOnTerm = 0; int iOnUseBlacklistsSelection = 0; int iOnExtCatItemBrowsable = 0; int iOnUseAsSearchTimer = 0; int iCatIndex = -1; char* catname = NULL; if (!HasSubMenu() && strlen(ItemText)>0) { // check, if on an item of ext. EPG info int iOnExtCatItem = 0; cSearchExtCat *SearchExtCat = SearchExtCats.First(); int index = 0; while (SearchExtCat) { if (strstr(ItemText, IndentMenuItem(SearchExtCat->menuname)) == ItemText) { iOnExtCatItem = 1; if (SearchExtCat->nvalues > 0) iOnExtCatItemBrowsable = 1; iCatIndex = index; catname = SearchExtCat->menuname; break; } index++; SearchExtCat = SearchExtCats.Next(SearchExtCat); } if (strstr(ItemText, tr("Search term")) == ItemText) { if (!InEditMode(ItemText, tr("Search term"), data.search)) // show template for a new search { SetHelp(NULL, NULL, tr("Button$Help"), tr("Button$Templates")); iOnTerm = 1; } } else if (strstr(ItemText, IndentMenuItem(tr("Day of week"))) == ItemText) { if (data.DayOfWeek == 7) { SetHelp(trVDR("Button$Edit")); iOnUserDefDayItem = 1; } else SetHelp(NULL, NULL, tr("Button$Help")); } else if (strstr(ItemText, tr("Use as search timer")) == ItemText) { if (data.useAsSearchTimer == 2) { SetHelp(NULL, NULL, tr("Button$Help"), tr("Button$Setup")); iOnUseAsSearchTimer = 1; } else SetHelp(NULL, NULL, tr("Button$Help")); } else if (strstr(ItemText, IndentMenuItem(tr("Directory"))) == ItemText) { if (!InEditMode(ItemText, IndentMenuItem(tr("Directory")), data.directory)) SetHelp(NULL, NULL, tr("Button$Help"), tr("Button$Select")); iOnDirectoryItem = 1; } else if (strstr(ItemText, tr("Use channel")) == ItemText && data.useChannel == 2) { SetHelp(NULL, NULL, tr("Button$Help"), tr("Button$Setup")); iOnUseChannelGroups = 1; } else if (strstr(ItemText, IndentMenuItem(tr("Channel group"))) == ItemText) { SetHelp(NULL, NULL, tr("Button$Help"), tr("Button$Setup")); iOnChannelGroup = 1; } else if (strstr(ItemText, tr("Use blacklists")) == ItemText && data.blacklistMode == blacklistsSelection) { SetHelp(NULL, NULL, tr("Button$Help"), tr("Button$Setup")); iOnUseBlacklistsSelection = 1; } else if (strstr(ItemText, IndentMenuItem(tr("Avoid repeats"))) == ItemText) { SetHelp(NULL, NULL, tr("Button$Help"), tr("Button$Setup")); iOnAvoidRepeats = 1; } else if (strstr(ItemText, IndentMenuItem(IndentMenuItem(tr("Compare categories")))) == ItemText) { SetHelp(NULL, NULL, tr("Button$Help"), tr("Button$Setup")); iOnCompareCats = 1; } else if (iOnExtCatItem) { if (!InEditMode(ItemText, IndentMenuItem(catname), data.catvalues[iCatIndex]) || SearchExtCats.Get(iCatIndex)->searchmode >= 10) SetHelp(NULL, NULL, tr("Button$Help"), iOnExtCatItemBrowsable?tr("Button$Select"):NULL); } else if (strstr(ItemText, tr("Search term")) != ItemText) SetHelp(NULL, NULL, tr("Button$Help"), NULL); } if (state == osUnknown) { if (HasSubMenu()) return osContinue; switch (Key) { case kOk: if (data.useChannel==1) { LOCK_CHANNELS_READ; const cChannel *ch = Channels->GetByNumber(channelMin); if (ch) data.channelMin = ch; else { ERROR(tr("*** Invalid Channel ***")); break; } ch = Channels->GetByNumber(channelMax); if (ch) data.channelMax = ch; else { ERROR(tr("*** Invalid Channel ***")); break; } if (channelMin > channelMax) { ERROR(tr("Please check channel criteria!")); return osContinue; } } if (data.useChannel==2) data.channelGroup = strdup(menuitemsChGr[channelGroupNr]); if ((data.useTitle || data.useSubtitle || data.useDescription) && (int(strlen(data.search)) < 3) && !Interface->Confirm(tr("Edit$Search text too short - use anyway?"))) break; if (searchExt) { *searchExt = data; if (data.DayOfWeek == 7) searchExt->DayOfWeek = UserDefDayOfWeek; // transfer cat selection for 'avoid repeats' back to search cSearchExtCat *SearchExtCat = SearchExtCats.First(); int index = 0; searchExt->catvaluesAvoidRepeat = 0; while (SearchExtCat) { if (catarrayAvoidRepeats[index]) searchExt->catvaluesAvoidRepeat += (1<searchmode >= 10) { if (searchExt->catvalues[index]) free(searchExt->catvalues[index]); msprintf(&searchExt->catvalues[index], "%d", catvaluesNumeric[index]); } SearchExtCat = SearchExtCats.Next(SearchExtCat); index++; } searchExt->SetContentFilter(useContentDescriptors?contentStringsFlags:NULL); if (data.blacklistMode == blacklistsSelection) { searchExt->blacklists.Clear(); cBlacklistObject* blacklistObj = blacklists.First(); while(blacklistObj) { searchExt->blacklists.Add(new cBlacklistObject(blacklistObj->blacklist)); blacklistObj = blacklists.Next(blacklistObj); } } else searchExt->blacklists.Clear(); if (addIfConfirmed) { cMutexLock SearchExtsLock(&SearchExts); searchExt->ID = SearchExts.GetNewID(); SearchExts.Add(searchExt); } if (searchExt->useAsSearchTimer && !EPGSearchConfig.useSearchTimers) // enable search timer thread if necessary { cSearchTimerThread::Init((cPluginEpgsearch*) cPluginManager::GetPlugin("epgsearch"), true); INFO(tr("Search timers activated in setup.")); } SearchExts.Save(); addIfConfirmed = false; } return osBack; case kRed: if (iOnUserDefDayItem) state = AddSubMenu(new cMenuEditDaysOfWeek(&UserDefDayOfWeek)); break; case kBlue: if (iOnDirectoryItem && !InEditMode(ItemText, IndentMenuItem(tr("Directory")), data.directory)) state = AddSubMenu(new cMenuDirSelect(data.directory)); if (iOnUseChannelGroups || iOnChannelGroup) { if (channelGroupName) free(channelGroupName); channelGroupName = strdup(menuitemsChGr[channelGroupNr]); state = AddSubMenu(new cMenuChannelGroups(&channelGroupName)); } if (iOnAvoidRepeats) state = AddSubMenu(new cMenuRecsDone(searchExt)); if (iOnCompareCats) state = AddSubMenu(new cMenuSearchEditCompCats(catarrayAvoidRepeats)); if (iOnTerm) state = AddSubMenu(new cMenuEPGSearchTemplate(&data, NULL, addIfConfirmed)); if (iOnUseBlacklistsSelection) state = AddSubMenu(new cMenuBlacklistsSelection(&blacklists)); if (iOnExtCatItemBrowsable) state = AddSubMenu(new cMenuCatValuesSelect(data.catvalues[iCatIndex], iCatIndex, SearchExtCats.Get(iCatIndex)->searchmode)); if (iOnUseAsSearchTimer) state = AddSubMenu(new cMenuSearchActivSettings(&data)); break; case kGreen: state = osContinue; break; case kYellow: case kInfo: state = Help(); break; default: break; } } if ((iOnUseChannelGroups || iOnChannelGroup || iOnCompareCats || iOnTerm || iOnExtCatItemBrowsable) && bHadSubMenu && !HasSubMenu()) // return form submenu { if (iOnTerm) { if (data.DayOfWeek < 0) { UserDefDayOfWeek = data.DayOfWeek; data.DayOfWeek = 7; } if (data.useChannel == 1) { channelMin = data.channelMin->Number(); channelMax = data.channelMax->Number(); } if (data.useChannel == 2) { channelGroupNr = ChannelGroups.GetIndex(data.channelGroup); channelGroupName = strdup(data.channelGroup); } if (SearchExtCats.Count() > 0) { cSearchExtCat *SearchExtCat = SearchExtCats.First(); int index = 0; while (SearchExtCat) { catarrayAvoidRepeats[index] = (data.catvaluesAvoidRepeat & (1< 0) { cSearchExtCat *SearchExtCat = SearchExtCats.First(); int index = 0; while (SearchExtCat) { if (SearchExtCat->searchmode >= 10) catvaluesNumeric[index] = atoi(data.catvalues[index]); SearchExtCat = SearchExtCats.Next(SearchExtCat); index++; } } Set(); Display(); } return state; } // --- cMenuEditDaysOfWeek -------------------------------------------------------- cMenuEditDaysOfWeek::cMenuEditDaysOfWeek(int* DaysOfWeek, int Offset, bool Negate) :cOsdMenu(tr("Edit user-defined days of week"),30) { SetMenuCategory(mcPlugin); int i=0; offset = Offset; negate = Negate; pDaysOfWeek = DaysOfWeek; if (negate) *pDaysOfWeek = -*pDaysOfWeek; for(i=0; i<7; i++) Days[(i+offset)%7]=((*pDaysOfWeek) & (int)pow(2,i))?1:0; for(i=0; i<7; i++) Add(new cMenuEditBoolItem( WeekDayName((i+1)%7), &Days[(i+1)%7], trVDR("no"), trVDR("yes"))); SetHelp(NULL); } eOSState cMenuEditDaysOfWeek::ProcessKey(eKeys Key) { if (Key == kBack && negate) *pDaysOfWeek = -*pDaysOfWeek; eOSState state = cOsdMenu::ProcessKey(Key); if (state == osUnknown) { switch (Key) { case kOk: *pDaysOfWeek = 0; for(int i=0; i<7; i++) *pDaysOfWeek += Days[i]?(int)pow(2,(i+7-offset)%7):0; if (negate) *pDaysOfWeek = -*pDaysOfWeek; state = osBack; break; default: break; } } return state; } // --- cMenuSearchEditCompCats -------------------------------------------------------- cMenuSearchEditCompCats::cMenuSearchEditCompCats(int* catarrayAvoidRepeats) :cOsdMenu(tr("Compare categories"),30) { SetMenuCategory(mcPlugin); search_catarrayAvoidRepeats = catarrayAvoidRepeats; edit_catarrayAvoidRepeats = (int*) malloc(SearchExtCats.Count() * sizeof(int)); cSearchExtCat *SearchExtCat = SearchExtCats.First(); int index = 0; while (SearchExtCat) { edit_catarrayAvoidRepeats[index] = catarrayAvoidRepeats[index]; cString menutext = cString::sprintf("%s %s", tr("Compare"), SearchExtCat->menuname); Add(new cMenuEditBoolItem(menutext, &edit_catarrayAvoidRepeats[index], trVDR("no"), trVDR("yes"))); SearchExtCat = SearchExtCats.Next(SearchExtCat); index++; } } cMenuSearchEditCompCats::~cMenuSearchEditCompCats() { free(edit_catarrayAvoidRepeats); } eOSState cMenuSearchEditCompCats::ProcessKey(eKeys Key) { eOSState state = cOsdMenu::ProcessKey(Key); if (state == osUnknown) { switch (Key) { case kOk: { cSearchExtCat *SearchExtCat = SearchExtCats.First(); int index = 0; while (SearchExtCat) { search_catarrayAvoidRepeats[index] = edit_catarrayAvoidRepeats[index]; SearchExtCat = SearchExtCats.Next(SearchExtCat); index++; } } state = osBack; break; default: break; } } return state; } // --- cMenuBlacklistsSelection -------------------------------------------------------- cMenuBlacklistsSelection::cMenuBlacklistsSelection(cList* pBlacklists) :cOsdMenu(tr("Select blacklists"),30) { SetMenuCategory(mcPlugin); blacklists = pBlacklists; blacklistsSel = new int[Blacklists.Count()]; cMutexLock BlacklistLock(&Blacklists); cBlacklist* blacklist = Blacklists.First(); int index = 0; while(blacklist) { blacklistsSel[index] = false; cBlacklistObject* blacklistObjSel = blacklists->First(); while(blacklistObjSel) { if (blacklistObjSel->blacklist->ID == blacklist->ID) { blacklistsSel[index] = true; break; } blacklistObjSel = blacklists->Next(blacklistObjSel); } blacklist = Blacklists.Next(blacklist); index++; } SetHelp(tr("Button$Invert selection"), tr("Button$All yes"), tr("Button$All no"), tr("Button$Setup")); Set(); } cMenuBlacklistsSelection::~cMenuBlacklistsSelection() { if (blacklistsSel) delete [] blacklistsSel; } // --- cMenuBlacklistsSelectionItem ---------------------------------------------------------- class cMenuBlacklistsSelectionItem : public cMenuEditBoolItem { const char* name; public: cMenuBlacklistsSelectionItem(const char *Name, int *Value, const char *FalseString = NULL, const char *TrueString = NULL): cMenuEditBoolItem(Name, Value, FalseString, TrueString) { name = Name; } int Compare(const cListObject &ListObject) const { cMenuBlacklistsSelectionItem *p = (cMenuBlacklistsSelectionItem*)&ListObject; return strcasecmp(name, p->name); } }; void cMenuBlacklistsSelection::Set() { int current = Current(); Clear(); cMutexLock BlacklistLock(&Blacklists); cBlacklist* blacklist = Blacklists.First(); int index = 0; while(blacklist) { Add(new cMenuBlacklistsSelectionItem(blacklist->search, &blacklistsSel[index], trVDR("no"), trVDR("yes"))); blacklist = Blacklists.Next(blacklist); index++; } SetCurrent(Get(current)); Sort(); } eOSState cMenuBlacklistsSelection::ProcessKey(eKeys Key) { bool bHadSubMenu = HasSubMenu(); eOSState state = cOsdMenu::ProcessKey(Key); if (state == osUnknown) { switch (Key) { case kOk: { cMutexLock BlacklistLock(&Blacklists); blacklists->Clear(); cBlacklist* blacklist = Blacklists.First(); int index = 0; while(blacklist) { if (blacklistsSel[index++]) blacklists->Add(new cBlacklistObject(blacklist)); blacklist = Blacklists.Next(blacklist); } } state = osBack; break; case kRed: case kGreen: case kYellow: { cMutexLock BlacklistLock(&Blacklists); cBlacklist* blacklist = Blacklists.First(); int index = 0; while(blacklist) { blacklistsSel[index] = (Key == kGreen?1:(Key == kRed?1-blacklistsSel[index]:0)); blacklist = Blacklists.Next(blacklist); index++; } Set(); Display(); return osContinue; } break; case kBlue: state = AddSubMenu(new cMenuBlacklists); break; default: break; } } if (bHadSubMenu && !HasSubMenu()) // return form submenu { Clear(); delete [] blacklistsSel; blacklistsSel = new int[Blacklists.Count()]; cMutexLock BlacklistLock(&Blacklists); cBlacklist* blacklist = Blacklists.First(); int index = 0; while(blacklist) { blacklistsSel[index] = false; cBlacklistObject* blacklistObjSel = blacklists->First(); while(blacklistObjSel) { if (blacklistObjSel->blacklist->ID == blacklist->ID) { blacklistsSel[index] = true; break; } blacklistObjSel = blacklists->Next(blacklistObjSel); } blacklist = Blacklists.Next(blacklist); index++; } Set(); Display(); } return state; } // --- cMenuCatValuesSelect -------------------------------------------------------- cMenuCatValuesSelect::cMenuCatValuesSelect(char* CatValues, int CatIndex, int SearchMode) :cOsdMenu(tr("Values for EPG category"), 1, 40) { SetMenuCategory(mcPlugin); catValues = CatValues; catIndex = CatIndex; searchMode = SearchMode; cSearchExtCat* SearchExtCat = SearchExtCats.Get(catIndex); if (SearchExtCat) { sel_cats.assign(SearchExtCat->nvalues, false); for(int i=0; invalues; i++) { char *pstrSearchToken, *pptr; char *pstrSearch=strdup(catValues); pstrSearchToken=strtok_r(pstrSearch, ",;|~", &pptr); while(pstrSearchToken) { if(SearchExtCat->values[i] && strcmp(SearchExtCat->values[i], skipspace(pstrSearchToken))==0) sel_cats[i] = true; pstrSearchToken=strtok_r(NULL, ",;|~", &pptr); } free(pstrSearch); } } Set(); SetHelp(trVDR("Button$On/Off"), NULL, NULL, tr("Button$Apply")); } void cMenuCatValuesSelect::Set() { int current = Current(); int selCount = 0; Clear(); string SearchMode = string(tr("Search mode")) + ": "; if (searchMode == 0) SearchMode += tr("phrase"); else if (searchMode == 1) SearchMode += tr("all words"); else if (searchMode == 2) SearchMode += tr("at least one word"); else if (searchMode == 3) SearchMode += tr("match exactly"); else if (searchMode == 4) SearchMode += tr("regular expression"); else if (searchMode == 10) SearchMode += tr("less"); else if (searchMode == 11) SearchMode += tr("less or equal"); else if (searchMode == 12) SearchMode += tr("greater"); else if (searchMode == 13) SearchMode += tr("greater or equal"); else if (searchMode == 14) SearchMode += tr("equal"); else if (searchMode == 15) SearchMode += tr("not equal"); cOsdItem* sItem = new cOsdItem(SearchMode.c_str()); Add(sItem); sItem->SetSelectable(false); cSearchExtCat* SearchExtCat = SearchExtCats.Get(catIndex); if (SearchExtCat) { for(int i=0; invalues; i++) { cString entry = cString::sprintf("%c\t%s", sel_cats[i]?'*':' ', SearchExtCat->values[i]); if (sel_cats[i]) selCount++; Add(new cOsdItem(entry)); } } SetCurrent(Get(current)); if (SearchExtCat) { cString title = cString::sprintf("%s (%d/%d)", tr("Values for EPG category"), selCount, SearchExtCat->nvalues); if (*title) SetTitle(title); } Display(); } eOSState cMenuCatValuesSelect::ProcessKey(eKeys Key) { eOSState state = cOsdMenu::ProcessKey(Key); if (state == osUnknown) { switch (Key) { case kOk: case kRed: if (Current()>0) { cSearchExtCat* SearchExtCat = SearchExtCats.Get(catIndex); if (SearchExtCat && SearchExtCat->searchmode >= 10 && catValues) // only one numeric value, so jump back { strcpy(catValues, SearchExtCat->values[Current()-1]); state = osBack; } else { sel_cats[Current()-1] = !sel_cats[Current()-1]; Set(); Display(); } } break; case kBlue: { *catValues = 0; cSearchExtCat* SearchExtCat = SearchExtCats.Get(catIndex); if (SearchExtCat) { for(int i=0; invalues; i++) { if (sel_cats[i]) { if (*catValues) strcat(catValues, ", "); strcat(catValues, SearchExtCat->values[i]); } } } state = osBack; break; } default: break; } } return state; } // --- cMenuSearchActivSettings -------------------------------------------------------- cMenuSearchActivSettings::cMenuSearchActivSettings(cSearchExt *SearchExt) :cOsdMenu(tr("Activation of search timer"), 25) { SetMenuCategory(mcPlugin); searchExt = SearchExt; if (searchExt) { Add(new cMenuEditDateItem(tr("First day"), &searchExt->useAsSearchTimerFrom, NULL)); Add(new cMenuEditDateItem(tr("Last day"), &searchExt->useAsSearchTimerTil, NULL)); } } eOSState cMenuSearchActivSettings::ProcessKey(eKeys Key) { eOSState state = cOsdMenu::ProcessKey(Key); if (state == osUnknown) { switch (Key) { case kOk: state = osBack; break; default: break; } } return state; } vdr-plugin-epgsearch/switchtimer_thread.c0000644000175000017500000001167613145412721020500 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #include "switchtimer_thread.h" #include "epgsearchcfg.h" #include "epgsearchtools.h" #include "epgsearch.h" #include #include #define MSG_DELAY 7 cSwitchTimerThread *cSwitchTimerThread::m_Instance = NULL; cSwitchTimerThread::cSwitchTimerThread(void) : cThread("EPGSearch: switchtimer") { m_Active = false; m_lastUpdate = time(NULL); } cSwitchTimerThread::~cSwitchTimerThread() { if (m_Active) Stop(); } void cSwitchTimerThread::Init(void) { if (m_Instance == NULL && SwitchTimers.Count() > 0) { m_Instance = new cSwitchTimerThread; m_Instance->Start(); } } void cSwitchTimerThread::Exit(void) { if (m_Instance != NULL) { m_Instance->Stop(); DELETENULL(m_Instance); } } void cSwitchTimerThread::Stop(void) { m_Active = false; Wait.Signal(); Cancel(6); } void cSwitchTimerThread::Action(void) { m_Active = true; // let VDR do its startup if (!cPluginEpgsearch::VDR_readyafterStartup) LogFile.Log(2, "SwitchTimerThread: waiting for VDR to become ready..."); while(m_Active && !cPluginEpgsearch::VDR_readyafterStartup) Wait.Wait(1000); time_t nextUpdate = time(NULL); while (m_Active) { time_t now = time(NULL); if (now >= nextUpdate) { LogFile.Log(3,"locking switch timers"); SwitchTimers.cMutex::Lock(); LogFile.Log(3,"switch timer check started"); cSwitchTimer* switchTimer = SwitchTimers.First(); while (switchTimer && m_Active && Running()) { if (switchTimer->startTime - now < switchTimer->switchMinsBefore*60 + MSG_DELAY + 1) { LOCK_CHANNELS_READ; const cChannel *channel = Channels->GetByChannelID(switchTimer->channelID, true, true); bool doSwitch = (switchTimer->mode == 0); bool doAsk = (switchTimer->mode == 2); bool doUnmute = switchTimer->unmute; SwitchTimers.Del(switchTimer); const cEvent* event = switchTimer->Event(); if (event && channel && (event->EndTime() >= now)) { cString Message = cString::sprintf("%s: %s - %s", event->Title(), CHANNELNAME(channel), GETTIMESTRING(event)); cString SwitchCmd = cString::sprintf("CHAN %d", channel->Number()); // switch if (doSwitch) { LogFile.Log(1,"switching to channel %d", channel->Number()); if (cDevice::CurrentChannel() != channel->Number()) SendViaSVDRP(SwitchCmd); if (doUnmute && cDevice::PrimaryDevice()->IsMute()) cDevice::PrimaryDevice()->ToggleMute(); } if (!doAsk) SendMsg(Message); if (doAsk) { cString Message = cString::sprintf(tr("Switch to (%d) '%s'?"), channel->Number(), event->Title()); if(SendMsg(Message, true, MSG_DELAY) == kOk) { LogFile.Log(1,"switching to channel %d", channel->Number()); if (cDevice::CurrentChannel() != channel->Number()) SendViaSVDRP(SwitchCmd); if (doUnmute && cDevice::PrimaryDevice()->IsMute()) cDevice::PrimaryDevice()->ToggleMute(); } } if (m_Active && Running()) Wait.Wait(1000 * MSG_DELAY); } SwitchTimers.Save(); break; } switchTimer = SwitchTimers.Next(switchTimer); } SwitchTimers.Unlock(); LogFile.Log(3,"switch timer check finished"); if (m_Active && Running()) Wait.Wait(1000 * MSG_DELAY); m_lastUpdate = time(NULL); nextUpdate = long(m_lastUpdate/60)*60+ 60 - MSG_DELAY ; // check at each full minute minus 5sec if (SwitchTimers.Count() == 0) m_Active = false; if (!Running()) m_Active = false; } while (m_Active && time(NULL)%MSG_DELAY != 0) // sync heart beat to MSG_DELAY Wait.Wait(1000); Wait.Wait(1000); }; m_Instance = NULL; } vdr-plugin-epgsearch/menu_main.h0000644000175000017500000000371413145412721016556 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #ifndef __EPGSEARCH_MENUMAIN_H #define __EPGSEARCH_MENUMAIN_H #include #include "menu_event.h" // --- cMenuSearchMain --------------------------------------------------------- class cMenuSearchMain : public cOsdMenu { private: int helpKeys; int otherChannel; int currentChannel; eOSState Record(void); eOSState ExtendedSearch(void); void PrepareSchedule(const cChannel *Channel); eOSState Commands(eKeys Key); void SetHelpKeys(bool Force = false); int GetTab(int Tab); int shiftTime; bool InWhatsOnMenu; bool InFavoritesMenu; cEventObjects eventObjects; public: cMenuSearchMain(void); virtual ~cMenuSearchMain(); virtual eOSState ProcessKey(eKeys Key); eOSState Switch(void); eOSState Shift(int iMinutes); eOSState ShowSummary(); bool Update(void); void UpdateCurrent(); #ifdef USE_GRAPHTFT virtual const char* MenuKind() { return "MenuEpgsSchedule"; } virtual void Display(void); #endif static int forceMenu; }; #endif vdr-plugin-epgsearch/epgsearchonly.c0000644000175000017500000000403713145412721017443 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #include #include #include #include "services.h" #include "mainmenushortcut.h" static const char *VERSION = "0.0.1"; static const char *DESCRIPTION = trNOOP("Direct access to epgsearch's search menu"); static const char *MAINMENUENTRY = trNOOP("Search"); static const char *SETUPTEXT = trNOOP("EpgSearch-Search in main menu"); class cPluginEpgsearchonly:public cMainMenuShortcut { public: virtual const char *Version() { return VERSION; } virtual const char *Description() { return I18nTranslate(DESCRIPTION, I18nEpgsearch); } virtual bool Initialize(); virtual cOsdObject *MainMenuAction() { return GetEpgSearchMenu("Epgsearch-searchmenu-v1.0"); }; protected: virtual const char *SetupText() { return I18nTranslate(SETUPTEXT, I18nEpgsearch); } virtual const char *MainMenuText() { return I18nTranslate(MAINMENUENTRY, I18nEpgsearch); } }; bool cPluginEpgsearchonly::Initialize() { return cMainMenuShortcut::Initialize(); } VDRPLUGINCREATOR(cPluginEpgsearchonly); // Don't touch this! vdr-plugin-epgsearch/mail.h0000644000175000017500000001002713145412721015523 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #ifndef __EPGSEARCH_MAIL_H #define __EPGSEARCH_MAIL_H #include #include #include #include #include "conflictcheck.h" using std::string; using std::set; // --- cMailNotifier -------------------------------------------------------- class cMailNotifier { protected: string subject; string body; bool SendMailViaSendmail(); bool SendMailViaScript(); bool SendMail(bool force=false); bool ExecuteMailScript(string ScriptArgs); public: string scriptReply; cMailNotifier() {} cMailNotifier(string Subject, string Body); bool TestMailAccount(string MailAddressTo, string MailAddress, string MailServer, string AuthUser, string AuthPass); static string LoadTemplate(const string& templtype); static string GetTemplValue(const string& templ, const string& entry); static string MailCmd; }; class cMailTimerNotification { friend class cMailUpdateNotifier; tEventID eventID; tChannelID channelID; uint timerMod; protected: virtual const cEvent* GetEvent() const; public: cMailTimerNotification(tEventID EventID, tChannelID ChannelID, uint TimerMod = tmNoChange) : eventID(EventID), channelID(ChannelID), timerMod(TimerMod) {} virtual bool operator< (const cMailTimerNotification &N) const; virtual string Format(const string& templ) const; }; class cMailDelTimerNotification { friend class cMailUpdateNotifier; time_t start; tChannelID channelID; public: string formatted; cMailDelTimerNotification(const cTimer* t, const cEvent* pEvent, const string& templ); cMailDelTimerNotification(const string& Formatted, tChannelID ChannelID, time_t Start); bool operator< (const cMailDelTimerNotification &N) const; string Format(const string& templ) const { return formatted; } }; class cMailAnnounceEventNotification : public cMailTimerNotification { friend class cMailUpdateNotifier; int searchextID; public: cMailAnnounceEventNotification(tEventID EventID, tChannelID ChannelID, int SearchExtID) : cMailTimerNotification(EventID, ChannelID), searchextID(SearchExtID) {} string Format(const string& templ) const; }; class cMailUpdateNotifier : public cMailNotifier { set newTimers; set modTimers; set delTimers; set announceEvents; string mailTemplate; public: cMailUpdateNotifier(); void AddNewTimerNotification(tEventID EventID, tChannelID ChannelID); void AddModTimerNotification(tEventID EventID, tChannelID ChannelID, uint timerMod = tmNoChange); void AddRemoveTimerNotification(const cTimer* t, const cEvent* e = NULL); void AddRemoveTimerNotification(const string& Formatted, tChannelID ChannelID, time_t Start); void AddAnnounceEventNotification(tEventID EventID, tChannelID ChannelID, int SearchExtID); void SendUpdateNotifications(); }; class cMailConflictNotifier : public cMailNotifier { public: void SendConflictNotifications(cConflictCheck& conflictcheck); }; #endif vdr-plugin-epgsearch/uservars.h0000644000175000017500000006375613145412721016474 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #ifndef __USERVARS_INC__ #define __USERVARS_INC__ #include #include #include #include #include #include #include #include "varparser.h" #include "epgsearchtools.h" #include "epgsearchcats.h" using std::string; using std::set; using std::map; using std::ostringstream; class cUserVar : public cListObject { const cEvent* oldEvent; // cache bool oldescapeStrings; string oldResult; string EvaluateCondExpr(const cEvent* e, bool escapeStrings = false); string EvaluateCompExpr(const cEvent* e, bool escapeStrings = false); string EvaluateShellCmd(const cEvent* e); string EvaluateConnectCmd(const cEvent* e); string EvaluateLengthCmd(const cEvent* e); public: cUserVar(); cVarParser varparser; set usedVars; virtual string Evaluate(const cEvent* e, bool escapeStrings = false); string EvaluateInternalVars(const string& Expr, const cEvent* e, bool escapeStrings = false); string EvaluateInternalTimerVars(const string& Expr, const cTimer* t); string EvaluateInternalSearchVars(const string& Expr, const cSearchExt* s); string EvaluateExtEPGVars(const string& Expr, const cEvent* e, bool escapeStrings = false); string EvaluateUserVars(const string& Expr, const cEvent* e, bool escapeStrings = false); virtual string Name(bool = false) { return varparser.varName; } virtual bool IsCondExpr() { return varparser.IsCondExpr(); } virtual bool IsShellCmd() { return varparser.IsShellCmd(); } virtual bool IsConnectCmd() { return varparser.IsConnectCmd(); } virtual bool IsLengthCmd() { return varparser.IsLengthCmd(); } bool DependsOnVar(const string& varName); bool DependsOnVar(cUserVar* var); bool AddDepVar(cUserVar* var); void ResetCache(); }; class cExtEPGVar : public cUserVar { const string name; static string nameSpace; public: cExtEPGVar(const string& Name) : name(Name) {} string Name(bool withNamespace = false) { return "%" + (withNamespace?nameSpace + ".":"") + name + "%"; } bool IsCondExpr() { return false; } bool IsShellCmd() { return false; } string Evaluate(const cEvent* e, bool escapeStrings = false) { if (!e) return ""; cSearchExtCat* SearchExtCat = SearchExtCats.First(); while (SearchExtCat) { string varName = string("%") + SearchExtCat->name + string("%"); int varPos = FindIgnoreCase(varName, Name()); if (varPos == 0) { char* value = GetExtEPGValue(e, SearchExtCat); string res = value?value:""; if (escapeStrings) return "'" + EscapeString(res) + "'"; else return res; } SearchExtCat = SearchExtCats.Next(SearchExtCat); } return ""; } }; class cInternalVar : public cUserVar { const string name; public: cInternalVar(const string& Name) : name(Name) {} string Name(bool = false) { return "%" + name + "%"; } bool IsCondExpr() { return false; } bool IsShellCmd() { return false; } }; class cTitleVar : public cInternalVar { public: cTitleVar() : cInternalVar("title") {} string Evaluate(const cEvent* e, bool escapeStrings = false) { string res = (e && !isempty(e->Title()))? e->Title() : ""; if (escapeStrings) return "'" + EscapeString(res) + "'"; else return res; } }; class cSubtitleVar : public cInternalVar { public: cSubtitleVar() : cInternalVar("subtitle") {} string Evaluate(const cEvent* e, bool escapeStrings = false) { string res = (e && !isempty(e->ShortText()))? e->ShortText() : ""; if (escapeStrings) return "'" + EscapeString(res) + "'"; else return res; } }; class cSummaryVar : public cInternalVar { public: cSummaryVar() : cInternalVar("summary") {} string Evaluate(const cEvent* e, bool escapeStrings = false) { string res = (e && !isempty(e->Description()))? e->Description() : ""; if (escapeStrings) return "'" + EscapeString(res) + "'"; else return res; } }; class cHTMLSummaryVar : public cInternalVar { public: cHTMLSummaryVar() : cInternalVar("htmlsummary") {} string Evaluate(const cEvent* e, bool escapeStrings = false) { if (e && !isempty(e->Description())) { string res = ReplaceAll(e->Description(), "\n", "
"); if (escapeStrings) return "'" + EscapeString(res) + "'"; else return res; } else return ""; } }; class cEventIDVar : public cInternalVar { public: cEventIDVar() : cInternalVar("eventid") {} string Evaluate(const cEvent* e, bool escapeStrings = false) { if (e) { ostringstream os; os << e->EventID(); return os.str(); } else return ""; } }; class cLiveEventIDVar : public cInternalVar { public: cLiveEventIDVar() : cInternalVar("liveeventid") {} string Evaluate(const cEvent* e, bool escapeStrings = false) { if (!e) return ""; LOCK_CHANNELS_READ; const cChannel *channel = Channels->GetByChannelID(e->ChannelID(), true); if (!channel) return ""; string res(channel->GetChannelID().ToString()); res = "event_" + res; res = ReplaceAll(res, ".", "p"); res = ReplaceAll(res, "-", "m"); res += "_" + NumToString(e->EventID()); if (escapeStrings) return "'" + EscapeString(res) + "'"; else return res; } }; class cTimeVar : public cInternalVar { public: cTimeVar() : cInternalVar("time") {} string Evaluate(const cEvent* e, bool escapeStrings = false) { string res = (e? *(e->GetTimeString()) : ""); if (escapeStrings) return "'" + EscapeString(res) + "'"; else return res; } }; class cTimeEndVar : public cInternalVar { public: cTimeEndVar() : cInternalVar("timeend") {} string Evaluate(const cEvent* e, bool escapeStrings = false) { string res = (e? *(e->GetEndTimeString()) : ""); if (escapeStrings) return "'" + EscapeString(res) + "'"; else return res; } }; class cTime_wVar : public cInternalVar { public: cTime_wVar() : cInternalVar("time_w") {} string Evaluate(const cEvent* e, bool escapeStrings = false) { string res = (e? WEEKDAYNAME(e->StartTime()) : ""); if (escapeStrings) return "'" + EscapeString(res) + "'"; else return res; } }; class cTime_dVar : public cInternalVar { public: cTime_dVar() : cInternalVar("time_d") {} string Evaluate(const cEvent* e, bool escapeStrings = false) { if (!e) return ""; char day[3] = ""; struct tm tm_r; const time_t t = e->StartTime(); tm *tm = localtime_r(&t, &tm_r); strftime(day, sizeof(day), "%d", tm); if (escapeStrings) return "'" + EscapeString(day) + "'"; else return day; } }; class cTime_lngVar : public cInternalVar { public: cTime_lngVar() : cInternalVar("time_lng") {} string Evaluate(const cEvent* e, bool escapeStrings = false) { if (!e) return ""; ostringstream os; os << e->StartTime(); if (escapeStrings) return "'" + EscapeString(os.str()) + "'"; else return os.str(); } }; class cTimeSpanVar : public cInternalVar { public: cTimeSpanVar() : cInternalVar("timespan") {} string Evaluate(const cEvent* e, bool escapeStrings = false) { if (!e) return ""; time_t diff = e->StartTime() - time(NULL); string res; if (labs(diff) >= SECSINDAY) { cString buffer; if (diff > 0) buffer = cString::sprintf(tr("in %02ldd"), long(diff / SECSINDAY)); else buffer = cString::sprintf("%02ldd", long(-diff / SECSINDAY)); res = buffer; } else if (labs(diff) >= (60 * 60)) { cString buffer; if (diff > 0) buffer = cString::sprintf(tr("in %02ldh"), long(diff / (60*60))); else buffer = cString::sprintf("%02ldh", long(-diff / (60*60))); res = buffer; } else { cString buffer; if (diff > 0) buffer = cString::sprintf(tr("in %02ldm"), long(diff / 60)); else buffer = cString::sprintf("%02ldm", long(-diff / 60)); res = buffer; } if (escapeStrings) return "'" + EscapeString(res) + "'"; else return res; } }; class cLength_Var : public cInternalVar { public: cLength_Var() : cInternalVar("length") {} string Evaluate(const cEvent* e, bool escapeStrings = false) { return (e? NumToString(e->Duration()) : ""); } }; class cDateVar : public cInternalVar { public: cDateVar() : cInternalVar("date") {} string Evaluate(const cEvent* e, bool escapeStrings = false) { if (!e) return ""; char date[9] = ""; struct tm tm_r; const time_t t = e->StartTime(); tm *tm = localtime_r(&t, &tm_r); strftime(date, sizeof(date), "%d.%m.%y", tm); if (escapeStrings) return "'" + EscapeString(date) + "'"; else return date; } }; class cDateShortVar : public cInternalVar { public: cDateShortVar() : cInternalVar("datesh") {} string Evaluate(const cEvent* e, bool escapeStrings = false) { if (!e) return ""; char dateshort[7] = ""; struct tm tm_r; const time_t t = e->StartTime(); tm *tm = localtime_r(&t, &tm_r); strftime(dateshort, sizeof(dateshort), "%d.%m.", tm); if (escapeStrings) return "'" + EscapeString(dateshort) + "'"; else return dateshort; } }; class cDateISOVar : public cInternalVar { public: cDateISOVar() : cInternalVar("date_iso") {} string Evaluate(const cEvent* e, bool escapeStrings = false) { if (!e) return ""; char dateISO[11] = ""; struct tm tm_r; const time_t t = e->StartTime(); tm *tm = localtime_r(&t, &tm_r); strftime(dateISO, sizeof(dateISO), "%Y-%m-%d", tm); if (escapeStrings) return "'" + EscapeString(dateISO) + "'"; else return dateISO; } }; class cYearVar : public cInternalVar { public: cYearVar() : cInternalVar("year") {} string Evaluate(const cEvent* e, bool escapeStrings = false) { if (!e) return ""; char year[5] = ""; struct tm tm_r; const time_t t = e->StartTime(); tm *tm = localtime_r(&t, &tm_r); strftime(year, sizeof(year), "%Y", tm); if (escapeStrings) return "'" + EscapeString(year) + "'"; else return year; } }; class cMonthVar : public cInternalVar { public: cMonthVar() : cInternalVar("month") {} string Evaluate(const cEvent* e, bool escapeStrings = false) { if (!e) return ""; char month[3] = ""; struct tm tm_r; const time_t t = e->StartTime(); tm *tm = localtime_r(&t, &tm_r); strftime(month, sizeof(month), "%m", tm); if (escapeStrings) return "'" + EscapeString(month) + "'"; else return month; } }; class cDayVar : public cInternalVar { public: cDayVar() : cInternalVar("day") {} string Evaluate(const cEvent* e, bool escapeStrings = false) { if (!e) return ""; char day[3] = ""; struct tm tm_r; const time_t t = e->StartTime(); tm *tm = localtime_r(&t, &tm_r); strftime(day, sizeof(day), "%d", tm); if (escapeStrings) return "'" + EscapeString(day) + "'"; else return day; } }; class cWeekVar : public cInternalVar { public: cWeekVar() : cInternalVar("week") {} string Evaluate(const cEvent* e, bool escapeStrings = false) { if (!e) return ""; char day[3] = ""; struct tm tm_r; const time_t t = e->StartTime(); tm *tm = localtime_r(&t, &tm_r); strftime(day, sizeof(day), "%V", tm); if (escapeStrings) return "'" + EscapeString(day) + "'"; else return day; } }; class cChannelNrVar : public cInternalVar { public: cChannelNrVar() : cInternalVar("chnr") {} string Evaluate(const cEvent* e, bool escapeStrings = false) { int chnr = ChannelNrFromEvent(e); if (chnr < 0) return ""; return NumToString(chnr); } }; class cChannelShortVar : public cInternalVar { public: cChannelShortVar() : cInternalVar("chsh") {} string Evaluate(const cEvent* e, bool escapeStrings = false) { if (!e) return ""; LOCK_CHANNELS_READ; const cChannel *channel = Channels->GetByChannelID(e->ChannelID(), true); string res = channel?channel->ShortName(true):""; if (escapeStrings) return "'" + EscapeString(res) + "'"; else return res; } }; class cChannelLongVar : public cInternalVar { public: cChannelLongVar() : cInternalVar("chlng") {} string Evaluate(const cEvent* e, bool escapeStrings = false) { if (!e) return ""; LOCK_CHANNELS_READ; const cChannel *channel = Channels->GetByChannelID(e->ChannelID(), true); string res = channel?channel->Name():""; if (escapeStrings) return "'" + EscapeString(res) + "'"; else return res; } }; class cChannelDataVar : public cInternalVar { public: cChannelDataVar() : cInternalVar("chdata") {} string Evaluate(const cEvent* e, bool escapeStrings = false) { if (!e) return ""; LOCK_CHANNELS_READ; const cChannel *channel = Channels->GetByChannelID(e->ChannelID(), true); return channel?CHANNELSTRING(channel):""; } }; class cChannelGroupVar : public cInternalVar { public: cChannelGroupVar() : cInternalVar("chgrp") {} string Evaluate(const cEvent* e, bool escapeStrings = false) { if (!e) return ""; ostringstream os; LOCK_CHANNELS_READ; const cChannel *channel = Channels->GetByChannelID(e->ChannelID(), true); while(channel && !channel->GroupSep()) channel = Channels->Prev(channel); if (!channel || !channel->Name()) return ""; string grpName = channel->Name(); if (escapeStrings) return "'" + EscapeString(grpName) + "'"; else return grpName; } }; class cNEWTCmdVar : public cInternalVar { public: cNEWTCmdVar() : cInternalVar("newtcmd") {} string Evaluate(const cEvent* e, bool escapeStrings = false) { if (!e) return ""; cTimer* timer = new cTimer(e); string newtCmd = *(timer->ToText()); if (escapeStrings) return "'" + EscapeString(newtCmd) + "'"; else return newtCmd; } }; // independet variables class cColonVar : public cInternalVar { public: cColonVar() : cInternalVar("colon") {} string Evaluate(const cEvent*, bool escapeStrings = false) { return ":"; } }; class cDateNowVar : public cInternalVar { public: cDateNowVar() : cInternalVar("datenow") {} string Evaluate(const cEvent*, bool escapeStrings = false) { char date[9] = ""; struct tm tm_r; const time_t t = time(NULL); tm *tm = localtime_r(&t, &tm_r); strftime(date, sizeof(date), "%d.%m.%y", tm); if (escapeStrings) return "'" + EscapeString(date) + "'"; else return date; } }; class cDateShortNowVar : public cInternalVar { public: cDateShortNowVar() : cInternalVar("dateshnow") {} string Evaluate(const cEvent*, bool escapeStrings = false) { char dateshort[7] = ""; struct tm tm_r; const time_t t = time(NULL); tm *tm = localtime_r(&t, &tm_r); strftime(dateshort, sizeof(dateshort), "%d.%m.", tm); if (escapeStrings) return "'" + EscapeString(dateshort) + "'"; else return dateshort; } }; class cDateISONowVar : public cInternalVar { public: cDateISONowVar() : cInternalVar("date_iso_now") {} string Evaluate(const cEvent*, bool escapeStrings = false) { char dateISO[11] = ""; struct tm tm_r; const time_t t = time(NULL); tm *tm = localtime_r(&t, &tm_r); strftime(dateISO, sizeof(dateISO), "%Y-%m-%d", tm); if (escapeStrings) return "'" + EscapeString(dateISO) + "'"; else return dateISO; } }; class cTimeNowVar : public cInternalVar { public: cTimeNowVar() : cInternalVar("timenow") {} string Evaluate(const cEvent*, bool escapeStrings = false) { return TIMESTRING(time(NULL)); } }; class cVideodirVar : public cInternalVar { public: cVideodirVar() : cInternalVar("videodir") {} string Evaluate(const cEvent*, bool escapeStrings = false) { return cVideoDirectory::Name(); } }; class cPlugconfdirVar : public cInternalVar { public: static string dir; cPlugconfdirVar() : cInternalVar("plugconfdir") {} string Evaluate(const cEvent*, bool escapeStrings = false) { return dir; } }; class cEpgsearchconfdirVar : public cInternalVar { public: static string dir; cEpgsearchconfdirVar() : cInternalVar("epgsearchdir") {} string Evaluate(const cEvent*, bool escapeStrings = false) { return CONFIGDIR; } }; // timer variables class cTimerVar { static string nameSpace; const string name; public: cTimerVar(const string& Name) : name(Name) {} virtual ~cTimerVar() {} string Name() { return "%" + nameSpace + "." + name + "%"; } virtual string Evaluate(const cTimer* t) = 0; }; class cTimerDateVar : public cTimerVar { public: cTimerDateVar() : cTimerVar("date") {} string Evaluate(const cTimer* t) { if (!t) return ""; return DATESTRING(t->StartTime()); } }; class cTimerStartVar : public cTimerVar { public: cTimerStartVar() : cTimerVar("start") {} string Evaluate(const cTimer* t) { if (!t) return ""; return TIMESTRING(t->StartTime()); } }; class cTimerStopVar : public cTimerVar { public: cTimerStopVar() : cTimerVar("stop") {} string Evaluate(const cTimer* t) { if (!t) return ""; return TIMESTRING(t->StopTime()); } }; class cTimerFileVar : public cTimerVar { public: cTimerFileVar() : cTimerVar("file") {} string Evaluate(const cTimer* t) { if (!t) return ""; return t->File(); } }; class cTimerChnrVar : public cTimerVar { public: cTimerChnrVar() : cTimerVar("chnr") {} string Evaluate(const cTimer* t) { if (!t || !t->Channel()) return ""; return NumToString(t->Channel()->Number()); } }; class cTimerChannelShortVar : public cTimerVar { public: cTimerChannelShortVar() : cTimerVar("chsh") {} string Evaluate(const cTimer* t) { if (!t || !t->Channel()) return ""; return t->Channel()->ShortName(true); } }; class cTimerChannelLongVar : public cTimerVar { public: cTimerChannelLongVar() : cTimerVar("chlng") {} string Evaluate(const cTimer* t) { if (!t || !t->Channel()) return ""; return t->Channel()->Name(); } }; class cTimerSearchVar : public cTimerVar { public: cTimerSearchVar() : cTimerVar("search") {} string Evaluate(const cTimer* t) { if (!t) return ""; cSearchExt* s = TriggeredFromSearchTimer(t); if (!s) return ""; return s->search; } }; class cTimerSearchIDVar : public cTimerVar { public: cTimerSearchIDVar() : cTimerVar("searchid") {} string Evaluate(const cTimer* t) { if (!t) return ""; int ID = TriggeredFromSearchTimerID(t); if (ID < 0) return ""; return NumToString(ID); } }; class cTimerLiveIDVar : public cTimerVar { public: cTimerLiveIDVar() : cTimerVar("liveid") {} string Evaluate(const cTimer* t) { if (!t || !t->Channel()) return ""; ostringstream builder; builder << *(t->Channel()->GetChannelID().ToString()) << ":" << t->WeekDays() << ":" << t->Day() << ":" << t->Start() << ":" << t->Stop(); string res = builder.str(); res = "timer_" + res; res = ReplaceAll(res, ".", "p"); res = ReplaceAll(res, "-", "m"); res = ReplaceAll(res, ":", "c"); return res; } }; // search variables class cSearchVar { const string name; static string nameSpace; public: cSearchVar(const string& Name) : name(Name) {} virtual ~cSearchVar() {} string Name() { return "%" + nameSpace + "." + name + "%"; } virtual string Evaluate(const cSearchExt* s) = 0; }; class cSearchQueryVar : public cSearchVar { public: cSearchQueryVar() : cSearchVar("query") {} string Evaluate(const cSearchExt* s) { if (!s) return ""; return s->search; } }; class cSearchSeriesVar : public cSearchVar { public: cSearchSeriesVar() : cSearchVar("series") {} string Evaluate(const cSearchExt* s) { if (!s) return ""; return NumToString(s->useEpisode); } }; class cUserVars : public cList { public: cTitleVar titleVar; cSubtitleVar subtitleVar; cSummaryVar summaryVar; cHTMLSummaryVar htmlsummaryVar; cEventIDVar eventIDVar; cLiveEventIDVar liveeventIDVar; cTimeVar timeVar; cTimeEndVar timeEndVar; cTime_wVar time_wVar; cTime_dVar time_dVar; cTime_lngVar time_lngVar; cTimeSpanVar time_spanVar; cLength_Var length_Var; cDateVar dateVar; cDateShortVar dateShortVar; cDateISOVar dateISOVar; cYearVar yearVar; cMonthVar monthVar; cDayVar dayVar; cWeekVar weekVar; cChannelNrVar chnrVar; cChannelShortVar chShortVar; cChannelLongVar chLongVar; cChannelDataVar chDataVar; cChannelGroupVar chGroupVar; cNEWTCmdVar newtCmdVar; cSearchQueryVar searchQueryVar; cSearchSeriesVar searchSeriesVar; cColonVar colonVar; cDateNowVar dateNowVar; cDateShortNowVar dateShortNowVar; cDateISONowVar dateISONowVar; cTimeNowVar timeNowVar; cVideodirVar videodirVar; cPlugconfdirVar plugconfdirVar; cEpgsearchconfdirVar epgsearchconfdirVar; cTimerDateVar timerDateVar; cTimerStartVar timerStartVar; cTimerStopVar timerStopVar; cTimerFileVar timerFileVar; cTimerChnrVar timerChnrVar; cTimerChannelShortVar timerChShortVar; cTimerChannelLongVar timerChLongVar; cTimerSearchVar timerSearchVar; cTimerSearchIDVar timerSearchIDVar; cTimerLiveIDVar timerLiveIDVar; map extEPGVars; set userVars; map internalVars; map internalTimerVars; map internalSearchVars; void InitInternalVars() { internalVars[titleVar.Name()] = &titleVar; internalVars[subtitleVar.Name()] = &subtitleVar; internalVars[summaryVar.Name()] = &summaryVar; internalVars[htmlsummaryVar.Name()] = &htmlsummaryVar; internalVars[eventIDVar.Name()] = &eventIDVar; internalVars[liveeventIDVar.Name()] = &liveeventIDVar; internalVars[timeVar.Name()] = &timeVar; internalVars[timeEndVar.Name()] = &timeEndVar; internalVars[time_wVar.Name()] = &time_wVar; internalVars[time_dVar.Name()] = &time_dVar; internalVars[time_lngVar.Name()] = &time_lngVar; internalVars[time_spanVar.Name()] = &time_spanVar; internalVars[length_Var.Name()] = &length_Var; internalVars[dateVar.Name()] = &dateVar; internalVars[dateShortVar.Name()] = &dateShortVar; internalVars[dateISOVar.Name()] = &dateISOVar; internalVars[yearVar.Name()] = &yearVar; internalVars[monthVar.Name()] = &monthVar; internalVars[dayVar.Name()] = &dayVar; internalVars[weekVar.Name()] = &weekVar; internalVars[chnrVar.Name()] = &chnrVar; internalVars[chShortVar.Name()] = &chShortVar; internalVars[chLongVar.Name()] = &chLongVar; internalVars[chDataVar.Name()] = &chDataVar; internalVars[chGroupVar.Name()] = &chGroupVar; internalVars[newtCmdVar.Name()] = &newtCmdVar; internalVars[colonVar.Name()] = &colonVar; internalVars[dateNowVar.Name()] = &dateNowVar; internalVars[dateShortNowVar.Name()] = &dateShortNowVar; internalVars[dateISONowVar.Name()] = &dateISONowVar; internalVars[timeNowVar.Name()] = &timeNowVar; internalVars[videodirVar.Name()] = &videodirVar; internalVars[plugconfdirVar.Name()] = &plugconfdirVar; internalVars[epgsearchconfdirVar.Name()] = &epgsearchconfdirVar; internalTimerVars[timerDateVar.Name()] = &timerDateVar; internalTimerVars[timerStartVar.Name()] = &timerStartVar; internalTimerVars[timerStopVar.Name()] = &timerStopVar; internalTimerVars[timerFileVar.Name()] = &timerFileVar; internalTimerVars[timerChnrVar.Name()] = &timerChnrVar; internalTimerVars[timerChShortVar.Name()] = &timerChShortVar; internalTimerVars[timerChLongVar.Name()] = &timerChLongVar; internalTimerVars[timerSearchVar.Name()] = &timerSearchVar; internalTimerVars[timerSearchIDVar.Name()] = &timerSearchIDVar; internalTimerVars[timerLiveIDVar.Name()] = &timerLiveIDVar; internalSearchVars[searchQueryVar.Name()] = &searchQueryVar; internalSearchVars[searchSeriesVar.Name()] = &searchSeriesVar; } void InitExtEPGVars() { cSearchExtCat* SearchExtCat = SearchExtCats.First(); while (SearchExtCat) { string varName = SearchExtCat->name; std::transform(varName.begin(), varName.end(), varName.begin(), tolower); cExtEPGVar* extEPGVar = new cExtEPGVar(varName); extEPGVars[extEPGVar->Name()] = extEPGVar; SearchExtCat = SearchExtCats.Next(SearchExtCat); } } void ResetCache() { cUserVar* var = First(); while (var) { var->ResetCache(); var = Next(var); } } ~cUserVars() { std::map::iterator evar; for (evar = extEPGVars.begin(); evar != extEPGVars.end(); ++evar) delete evar->second; extEPGVars.clear(); std::set::iterator uvar; for (uvar = userVars.begin(); uvar != userVars.end(); ++uvar) delete (*uvar); userVars.clear(); } cUserVar* GetFromName(const string& varName, bool log = true); }; extern cUserVars UserVars; class cUserVarLine : public cListObject { public: static bool Parse(char *s); }; class cUserVarFile : public cConfig { public: cUserVarFile() { UserVars.Clear(); }; }; class cVarExpr { string expr; public: set usedVars; cVarExpr(const string& Expr) : expr(Expr) {} string Evaluate(const cEvent* e = NULL); string Evaluate(const cTimer* t); string Evaluate(const cSearchExt* s); bool DependsOnVar(const string& varName, const cEvent* e); }; #endif vdr-plugin-epgsearch/menu_commands.h0000644000175000017500000000351613145412721017433 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #ifndef __EPGSEARCHCMD_H #define __EPGSEARCHCMD_H #include #include "epgsearchext.h" // --- cMenuSearchCommands --------------------------------------------------------- class cMenuSearchCommands : public cOsdMenu { private: cCommands commands; eOSState Execute(void); const cEvent* event; cSearchExt* search; bool directCall; public: cMenuSearchCommands(const char *Title, const cEvent* Event, bool DirectCall = false, cSearchExt* Search = NULL); virtual ~cMenuSearchCommands(); virtual eOSState ProcessKey(eKeys Key); virtual eOSState Record(void); virtual eOSState Switch(void); virtual eOSState ExtendedSearch(void); virtual eOSState CreateSearchTimer(void); virtual eOSState MarkAsRecorded(void); virtual eOSState AddToSwitchList(void); virtual eOSState CreateBlacklist(void); void LoadCommands(); }; #endif vdr-plugin-epgsearch/menu_favorites.h0000644000175000017500000000270113145412721017627 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #ifndef __EPGSEARCHFAVORITES_H #define __EPGSEARCHFAVORITES_H #include "menu_searchresults.h" class cMenuFavorites : public cMenuSearchResults { private: bool BuildList(); virtual eOSState OnGreen(); virtual eOSState OnYellow(); public: cMenuFavorites(); virtual eOSState ProcessKey(eKeys Key); virtual void SetHelpKeys(bool Force=false); #ifdef USE_GRAPHTFT virtual const char* MenuKind(); virtual void Display(void); #endif }; #endif vdr-plugin-epgsearch/timerstatus.c0000644000175000017500000000324013145412721017157 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #include "timerstatus.h" cTimerStatusMonitor* gl_timerStatusMonitor = NULL; cTimerStatusMonitor::cTimerStatusMonitor() { conflictCheckAdvised = true; } void cTimerStatusMonitor::TimerChange(const cTimer *Timer, eTimerChange Change) { // vdr-1.5.15 and above will inform us, when there are any timer changes. // so timer changes (within epgsearch) in previous versions have to be tracked // at the correspondig places. conflictCheckAdvised = true; } void cTimerStatusMonitor::SetConflictCheckAdvised(bool ConflictCheckAdvised) { if (!ConflictCheckAdvised) conflictCheckAdvised = false; } bool cTimerStatusMonitor::ConflictCheckAdvised() { return conflictCheckAdvised; } vdr-plugin-epgsearch/varparser.h0000644000175000017500000000427013145412721016611 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #ifndef __VAR_PARSER_INC__ #define __VAR_PARSER_INC__ #include #include #include #include "epgsearchtools.h" using std::string; using std::vector; typedef enum { condEq = 0, condNeq } condOperator; class cVarParser { typedef enum { composed=0, condition, shellcmd, connectcmd, lengthcmd } exprType; public: string varName; string condEqLeft; string condEqRight; condOperator condOp; string condvarTrue; string condvarFalse; string compExpr; cCommand* cmd; string cmdArgs; string connectAddr; int connectPort; exprType type; cVarParser() : cmd(NULL), connectPort(-1), type(composed) { condOp=condEq; } bool Parse(const string& input); bool ParseExp(const string& input); bool IsCondExpr(); bool IsShellCmd(); bool IsConnectCmd(); bool IsLengthCmd(); private: bool ParseAssign(const string& input); bool ParseShellCmd(const string& input); bool ParseConnectCmd(const string& input); bool ParseLengthCmd(const string& input); bool ParseCondExp(const string& input); bool ParseEquality(const string& input); bool ParseVar(const string& input); }; #endif vdr-plugin-epgsearch/menu_quicksearch.c0000644000175000017500000002532113145412721020125 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #include "menu_quicksearch.h" #include "templatefile.h" #include "menu_searchresults.h" #include "epgsearchcats.h" #include "changrp.h" #include "epgsearchcfg.h" #include "blacklist.h" #define QUICKSEARCHSIMPLE 0 #define QUICKSEARCHEXT 1 #define GREENLABEL (editmode==QUICKSEARCHSIMPLE?tr("Button$Extended"):tr("Button$Simple")) // --- cMenuQuickSearch -------------------------------------------------------- cMenuQuickSearch::cMenuQuickSearch(cSearchExt* Quicksearch) :cMenuEditSearchExt(Quicksearch, true, true) { editmode = QUICKSEARCHSIMPLE; Set(); SetHelp(NULL, GREENLABEL, NULL, NULL); } void cMenuQuickSearch::Set() { int current = Current(); Clear(); Add(new cMenuEditStrItem( tr("Search term"), data.search, sizeof(data.search), tr(AllowedChars))); if (editmode == QUICKSEARCHEXT) { Add(new cMenuEditStraItem(tr("Search mode"), &data.mode, 6, SearchModes)); if (data.mode == 5) // fuzzy Add(new cMenuEditIntItem(IndentMenuItem(tr("Tolerance")), &data.fuzzyTolerance, 1, 9)); Add(new cMenuEditBoolItem( tr("Match case"), &data.useCase, trVDR("no"), trVDR("yes"))); Add(new cMenuEditBoolItem( tr("Use title"), &data.useTitle, trVDR("no"), trVDR("yes"))); Add(new cMenuEditBoolItem( tr("Use subtitle"), &data.useSubtitle, trVDR("no"), trVDR("yes"))); Add(new cMenuEditBoolItem( tr("Use description"), &data.useDescription, trVDR("no"), trVDR("yes"))); // show Categories only if we have them if (SearchExtCats.Count() > 0) { Add(new cMenuEditBoolItem( tr("Use extended EPG info"), &data.useExtEPGInfo, trVDR("no"), trVDR("yes"))); if (data.useExtEPGInfo) { cSearchExtCat *SearchExtCat = SearchExtCats.First(); int index = 0; while (SearchExtCat) { Add(new cMenuEditStrItem( IndentMenuItem(SearchExtCat->menuname), data.catvalues[index], MaxFileName, tr(AllowedChars))); SearchExtCat = SearchExtCats.Next(SearchExtCat); index++; } } } Add(new cMenuEditStraItem(tr("Use channel"), &data.useChannel, 4, UseChannelSel)); if (data.useChannel==1) { Add(new cMenuEditChanItem(tr(" from channel"), &channelMin)); Add(new cMenuEditChanItem(tr(" to channel"), &channelMax)); } if (data.useChannel==2) { // create the char array for the menu display if (menuitemsChGr) delete [] menuitemsChGr; menuitemsChGr = ChannelGroups.CreateMenuitemsList(); int oldchannelGroupNr = channelGroupNr; channelGroupNr = ChannelGroups.GetIndex(channelGroupName); if (channelGroupNr == -1) { if (oldchannelGroupNr > 0 && oldchannelGroupNr <= ChannelGroups.Count()) // perhaps its name was changed channelGroupNr = oldchannelGroupNr; else channelGroupNr = 0; // no selection } else channelGroupNr++; Add(new cMenuEditStraItem(IndentMenuItem(tr("Channel group")), &channelGroupNr, ChannelGroups.Count()+1, menuitemsChGr)); } Add(new cMenuEditBoolItem( tr("Use time"), &data.useTime, trVDR("no"), trVDR("yes"))); if (data.useTime == true) { Add(new cMenuEditTimeItem(tr(" Start after"), &data.startTime)); Add(new cMenuEditTimeItem(tr(" Start before"), &data.stopTime)); } Add(new cMenuEditBoolItem( tr("Use duration"), &data.useDuration, trVDR("no"), trVDR("yes"))); if (data.useDuration == true) { Add(new cMenuEditTimeItem(tr(" Min. duration"), &data.minDuration)); Add(new cMenuEditTimeItem(tr(" Max. duration"), &data.maxDuration)); } Add(new cMenuEditBoolItem( tr("Use day of week"), &data.useDayOfWeek, trVDR("no"), trVDR("yes"))); if (data.useDayOfWeek) { if (data.DayOfWeek < 0) { UserDefDayOfWeek = data.DayOfWeek; data.DayOfWeek = 7; } Add(new cMenuEditStraItem(IndentMenuItem(tr("Day of week")), &data.DayOfWeek, 8, DaysOfWeek)); } Add(new cMenuEditStraItem(tr("Use blacklists"), &data.blacklistMode, 3, BlacklistModes)); } SetCurrent(Get(current)); } eOSState cMenuQuickSearch::ProcessKey(eKeys Key) { bool bHadSubMenu = HasSubMenu(); int iTemp_mode = data.mode; int iTemp_useTime = data.useTime; int iTemp_useChannel = data.useChannel; int iTemp_useDuration = data.useDuration; int iTemp_useDayOfWeek = data.useDayOfWeek; int iTemp_useExtEPGInfo = data.useExtEPGInfo; int iTemp_avoidRepeats = data.avoidRepeats; int iTemp_allowedRepeats = data.allowedRepeats; int iTemp_delAfterDays = data.delAfterDays; int iTemp_action = data.action; eOSState state = cOsdMenu::ProcessKey(Key); if (iTemp_mode != data.mode || iTemp_useTime != data.useTime || iTemp_useChannel != data.useChannel || iTemp_useDuration != data.useDuration || iTemp_useDayOfWeek != data.useDayOfWeek || iTemp_useExtEPGInfo != data.useExtEPGInfo || iTemp_avoidRepeats != data.avoidRepeats || iTemp_allowedRepeats != data.allowedRepeats || iTemp_delAfterDays != data.delAfterDays || iTemp_action != data.action) { Set(); Display(); } const char* ItemText = Get(Current())->Text(); if (!HasSubMenu()) { if (strlen(ItemText)>0 && strstr(ItemText, tr(" from channel")) == ItemText && ((Key >= k0 && Key <= k9) || Key == kLeft || Key == kRight)) { channelMax = channelMin; Set(); Display(); } } int iOnUserDefDayItem = 0; int iOnUseChannelGroups = 0; int iOnChannelGroup = 0; int iOnCompareCats = 0; int iOnUseBlacklistsSelection = 0; int iOnExtCatItemBrowsable = 0; int iCatIndex = -1; char* catname = NULL; if (!HasSubMenu() && strlen(ItemText)>0) { // check, if on an item of ext. EPG info int iOnExtCatItem = 0; cSearchExtCat *SearchExtCat = SearchExtCats.First(); int index = 0; while (SearchExtCat) { if (strstr(ItemText, IndentMenuItem(SearchExtCat->menuname)) == ItemText) { iOnExtCatItem = 1; if (SearchExtCat->nvalues > 0) iOnExtCatItemBrowsable = 1; iCatIndex = index; catname = SearchExtCat->menuname; break; } index++; SearchExtCat = SearchExtCats.Next(SearchExtCat); } if (strstr(ItemText, tr("Search term")) == ItemText) { if (!InEditMode(ItemText, tr("Search term"), data.search)) // show template for a new search { SetHelp(NULL, GREENLABEL, NULL, NULL); } } if (strstr(ItemText, IndentMenuItem(tr("Day of week"))) == ItemText) { if (data.DayOfWeek == 7) { SetHelp(trVDR("Button$Edit"), GREENLABEL); iOnUserDefDayItem = 1; } else SetHelp(NULL); } else if (strstr(ItemText, tr("Use channel")) == ItemText && data.useChannel == 2) { SetHelp(NULL, GREENLABEL, NULL, tr("Button$Setup")); iOnUseChannelGroups = 1; } else if (strstr(ItemText, IndentMenuItem(tr("Channel group"))) == ItemText) { SetHelp(NULL, GREENLABEL, NULL, tr("Button$Setup")); iOnChannelGroup = 1; } else if (strstr(ItemText, tr("Use blacklists")) == ItemText && data.blacklistMode == blacklistsSelection) { SetHelp(NULL, GREENLABEL, NULL, tr("Button$Setup")); iOnUseBlacklistsSelection = 1; } else if (iOnExtCatItem) { if (!InEditMode(ItemText, IndentMenuItem(catname), data.catvalues[iCatIndex])) SetHelp(NULL, GREENLABEL, NULL, iOnExtCatItemBrowsable?tr("Button$Select"):NULL); } else if (strstr(ItemText, tr("Search term")) != ItemText) SetHelp(NULL, GREENLABEL, NULL, NULL); } if (state == osUnknown) { if (HasSubMenu()) return osContinue; switch (Key) { case kOk: if (data.useChannel==1) { LOCK_CHANNELS_READ; const cChannel *ch = Channels->GetByNumber(channelMin); if (ch) data.channelMin = ch; else { ERROR(tr("*** Invalid Channel ***")); break; } ch = Channels->GetByNumber(channelMax); if (ch) data.channelMax = ch; else { ERROR(tr("*** Invalid Channel ***")); break; } if (channelMin > channelMax) { ERROR(tr("Please check channel criteria!")); return osContinue; } } if (data.useChannel==2) data.channelGroup = strdup(menuitemsChGr[channelGroupNr]); if ((data.useTitle || data.useSubtitle || data.useDescription) && (int(strlen(data.search)) < 3) && !Interface->Confirm(tr("Edit$Search text too short - use anyway?"))) break; if (searchExt) { *searchExt = data; if (data.DayOfWeek == 7) searchExt->DayOfWeek = UserDefDayOfWeek; if (data.blacklistMode == blacklistsSelection) { searchExt->blacklists.Clear(); cBlacklistObject* blacklistObj = blacklists.First(); while(blacklistObj) { searchExt->blacklists.Add(new cBlacklistObject(blacklistObj->blacklist)); blacklistObj = blacklists.Next(blacklistObj); } } else searchExt->blacklists.Clear(); state = AddSubMenu(new cMenuSearchResultsForSearch(searchExt, cTemplFile::GetTemplateByName("MenuSearchResults"))); } break; case kRed: if (iOnUserDefDayItem) state = AddSubMenu(new cMenuEditDaysOfWeek(&UserDefDayOfWeek)); break; case kBlue: if (iOnUseChannelGroups || iOnChannelGroup) { if (channelGroupName) free(channelGroupName); channelGroupName = strdup(menuitemsChGr[channelGroupNr]); state = AddSubMenu(new cMenuChannelGroups(&channelGroupName)); } if (iOnUseBlacklistsSelection) state = AddSubMenu(new cMenuBlacklistsSelection(&blacklists)); if (iOnExtCatItemBrowsable) state = AddSubMenu(new cMenuCatValuesSelect(data.catvalues[iCatIndex], iCatIndex, SearchExtCats.Get(iCatIndex)->searchmode)); break; case kGreen: editmode = (editmode==QUICKSEARCHSIMPLE?QUICKSEARCHEXT:QUICKSEARCHSIMPLE); SetHelp(NULL, GREENLABEL, NULL, NULL); Set(); Display(); break; case kYellow: state = osContinue; default: break; } } if ((iOnUseChannelGroups || iOnChannelGroup || iOnCompareCats) && bHadSubMenu && !HasSubMenu()) // return form submenu { Set(); Display(); } return state; } vdr-plugin-epgsearch/menu_blacklistedit.c0000644000175000017500000003342413145412721020444 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #include #include "menu_blacklistedit.h" #include "changrp.h" #include "epgsearchcats.h" #include "epgsearchtools.h" #include "menu_dirselect.h" #include "menu_searchedit.h" #include "menu_searchtemplate.h" #include "epgsearchcfg.h" #include extern cChannelGroups ChannelGroups; extern cSearchExtCats SearchExtCats; extern const char AllowedChars[]; // --- cMenuBlacklistEdit -------------------------------------------------------- cMenuBlacklistEdit::cMenuBlacklistEdit(cBlacklist *Blacklist, bool New) :cOsdMenu(tr("Edit blacklist"),32) { SetMenuCategory(mcSetupPlugins); SearchModes[0] = strdup(tr("phrase")); SearchModes[1] = strdup(tr("all words")); SearchModes[2] = strdup(tr("at least one word")); SearchModes[3] = strdup(tr("match exactly")); SearchModes[4] = strdup(tr("regular expression")); SearchModes[5] = strdup(tr("fuzzy")); DaysOfWeek[0] = strdup(WeekDayName(0)); DaysOfWeek[1] = strdup(WeekDayName(1)); DaysOfWeek[2] = strdup(WeekDayName(2)); DaysOfWeek[3] = strdup(WeekDayName(3)); DaysOfWeek[4] = strdup(WeekDayName(4)); DaysOfWeek[5] = strdup(WeekDayName(5)); DaysOfWeek[6] = strdup(WeekDayName(6)); DaysOfWeek[7] = strdup(tr("user-defined")); UseChannelSel[0] = strdup(trVDR("no")); UseChannelSel[1] = strdup(tr("interval")); UseChannelSel[2] = strdup(tr("channel group")); UseChannelSel[3] = strdup(tr("only FTA")); if (New) { cSearchExt* SearchTempl = NULL; // copy the default settings, if we have a default template cMutexLock SearchTemplatesLock(&SearchTemplates); cSearchExt *SearchExtTempl = SearchTemplates.First(); while (SearchExtTempl) { if (SearchExtTempl->ID == EPGSearchConfig.DefSearchTemplateID) SearchTempl = SearchExtTempl; SearchExtTempl = SearchTemplates.Next(SearchExtTempl); } if (SearchTempl) Blacklist->CopyFromTemplate(SearchTempl); } blacklist = Blacklist; addIfConfirmed = New; if (blacklist) { data = *blacklist; UserDefDayOfWeek = 0; if (blacklist->DayOfWeek < 0) { UserDefDayOfWeek = blacklist->DayOfWeek; data.DayOfWeek = 7; } menuitemsChGr = NULL; channelGroupName = NULL; channelMin = channelMax = cDevice::CurrentChannel(); channelGroupNr = 0; if (data.useChannel==1) { channelMin = data.channelMin->Number(); channelMax = data.channelMax->Number(); } if (data.useChannel==2) { channelGroupNr = ChannelGroups.GetIndex(data.channelGroup); if (channelGroupNr == -1) { free(data.channelGroup); data.channelGroup = NULL; channelGroupNr = 0; // no selection } else { channelGroupName = strdup(data.channelGroup); channelGroupNr++; } } catvaluesNumeric = NULL; if (SearchExtCats.Count() > 0) { catvaluesNumeric = (int*) malloc(SearchExtCats.Count() * sizeof(int)); cSearchExtCat *SearchExtCat = SearchExtCats.First(); int index = 0; while (SearchExtCat) { catvaluesNumeric[index] = atol(blacklist->catvalues[index]); SearchExtCat = SearchExtCats.Next(SearchExtCat); index++; } } Set(); } } void cMenuBlacklistEdit::Set() { int current = Current(); Clear(); Add(new cMenuEditStrItem( tr("Search term"), data.search, sizeof(data.search), tr(AllowedChars))); Add(new cMenuEditStraItem(tr("Search mode"), &data.mode, 6, SearchModes)); if (data.mode == 5) // fuzzy Add(new cMenuEditIntItem(IndentMenuItem(tr("Tolerance")), &data.fuzzyTolerance, 1, 9)); Add(new cMenuEditBoolItem( tr("Match case"), &data.useCase, trVDR("no"), trVDR("yes"))); Add(new cMenuEditBoolItem( tr("Use title"), &data.useTitle, trVDR("no"), trVDR("yes"))); Add(new cMenuEditBoolItem( tr("Use subtitle"), &data.useSubtitle, trVDR("no"), trVDR("yes"))); Add(new cMenuEditBoolItem( tr("Use description"), &data.useDescription, trVDR("no"), trVDR("yes"))); // show Categories only if we have them if (SearchExtCats.Count() > 0) { Add(new cMenuEditBoolItem( tr("Use extended EPG info"), &data.useExtEPGInfo, trVDR("no"), trVDR("yes"))); if (data.useExtEPGInfo) { cSearchExtCat *SearchExtCat = SearchExtCats.First(); int index = 0; while (SearchExtCat) { if (SearchExtCat->searchmode >= 10) Add(new cMenuEditIntItem(IndentMenuItem(SearchExtCat->menuname), &catvaluesNumeric[index], 0, 999999, "")); else Add(new cMenuEditStrItem( IndentMenuItem(SearchExtCat->menuname), data.catvalues[index], MaxFileName, tr(AllowedChars))); SearchExtCat = SearchExtCats.Next(SearchExtCat); index++; } Add(new cMenuEditBoolItem(IndentMenuItem(tr("Ignore missing categories")), &data.ignoreMissingEPGCats, trVDR("no"), trVDR("yes"))); } } Add(new cMenuEditStraItem(tr("Use channel"), &data.useChannel, 4, UseChannelSel)); if (data.useChannel==1) { Add(new cMenuEditChanItem(tr(" from channel"), &channelMin)); Add(new cMenuEditChanItem(tr(" to channel"), &channelMax)); } if (data.useChannel==2) { // create the char array for the menu display if (menuitemsChGr) delete [] menuitemsChGr; menuitemsChGr = ChannelGroups.CreateMenuitemsList(); int oldchannelGroupNr = channelGroupNr; channelGroupNr = ChannelGroups.GetIndex(channelGroupName); if (channelGroupNr == -1) { if (oldchannelGroupNr > 0 && oldchannelGroupNr <= ChannelGroups.Count()) // perhaps its name was changed channelGroupNr = oldchannelGroupNr; else channelGroupNr = 0; // no selection } else channelGroupNr++; Add(new cMenuEditStraItem(IndentMenuItem(tr("Channel group")), &channelGroupNr, ChannelGroups.Count()+1, menuitemsChGr)); } Add(new cMenuEditBoolItem( tr("Use time"), &data.useTime, trVDR("no"), trVDR("yes"))); if (data.useTime == true) { Add(new cMenuEditTimeItem(tr(" Start after"), &data.startTime)); Add(new cMenuEditTimeItem(tr(" Start before"), &data.stopTime)); } Add(new cMenuEditBoolItem( tr("Use duration"), &data.useDuration, trVDR("no"), trVDR("yes"))); if (data.useDuration == true) { Add(new cMenuEditTimeItem(tr(" Min. duration"), &data.minDuration)); Add(new cMenuEditTimeItem(tr(" Max. duration"), &data.maxDuration)); } Add(new cMenuEditBoolItem( tr("Use day of week"), &data.useDayOfWeek, trVDR("no"), trVDR("yes"))); if (data.useDayOfWeek) { if (data.DayOfWeek < 0) { UserDefDayOfWeek = data.DayOfWeek; data.DayOfWeek = 7; } Add(new cMenuEditStraItem(IndentMenuItem(tr("Day of week")), &data.DayOfWeek, 8, DaysOfWeek)); } Add(new cMenuEditBoolItem( tr("Use global"), &data.isGlobal, trVDR("no"), trVDR("yes"))); SetCurrent(Get(current)); } cMenuBlacklistEdit::~cMenuBlacklistEdit() { if (blacklist && addIfConfirmed) delete blacklist; // apparently it wasn't confirmed if (menuitemsChGr) free(menuitemsChGr); if (channelGroupName) free(channelGroupName); if (catvaluesNumeric) free(catvaluesNumeric); int i; for(i=0; i<=4; i++) free(SearchModes[i]); for(i=0; i<=7; i++) free(DaysOfWeek[i]); for(i=0; i<=2; i++) free(UseChannelSel[i]); } eOSState cMenuBlacklistEdit::ProcessKey(eKeys Key) { bool bHadSubMenu = HasSubMenu(); int iTemp_mode = data.mode; int iTemp_useTime = data.useTime; int iTemp_useChannel = data.useChannel; int iTemp_useDuration = data.useDuration; int iTemp_useDayOfWeek = data.useDayOfWeek; int iTemp_useExtEPGInfo = data.useExtEPGInfo; eOSState state = cOsdMenu::ProcessKey(Key); if (iTemp_mode != data.mode || iTemp_useTime != data.useTime || iTemp_useChannel != data.useChannel || iTemp_useDuration != data.useDuration || iTemp_useDayOfWeek != data.useDayOfWeek || iTemp_useExtEPGInfo != data.useExtEPGInfo) { Set(); Display(); } const char* ItemText = Get(Current())->Text(); if (!HasSubMenu()) { if (strlen(ItemText)>0 && strstr(ItemText, tr(" from channel")) == ItemText && ((Key >= k0 && Key <= k9) || Key == kLeft || Key == kRight)) { channelMax = channelMin; Set(); Display(); } } int iOnUserDefDayItem = 0; int iOnUseChannelGroups = 0; int iOnChannelGroup = 0; int iOnTerm = 0; int iOnExtCatItemBrowsable = 0; int iCatIndex = -1; char* catname = NULL; if (!HasSubMenu() && strlen(ItemText)>0) { // check, if on an item of ext. EPG info int iOnExtCatItem = 0; cSearchExtCat *SearchExtCat = SearchExtCats.First(); int index = 0; while (SearchExtCat) { if (strstr(ItemText, IndentMenuItem(SearchExtCat->menuname)) == ItemText) { iOnExtCatItem = 1; if (SearchExtCat->nvalues > 0) iOnExtCatItemBrowsable = 1; iCatIndex = index; catname = SearchExtCat->menuname; break; } index++; SearchExtCat = SearchExtCats.Next(SearchExtCat); } if (strstr(ItemText, tr("Search term")) == ItemText) { if (!InEditMode(ItemText, tr("Search term"), data.search)) // show template for a new search { SetHelp(NULL, NULL, NULL, tr("Button$Templates")); iOnTerm = 1; } } if (strstr(ItemText, IndentMenuItem(tr("Day of week"))) == ItemText) { if (data.DayOfWeek == 7) { SetHelp(trVDR("Button$Edit")); iOnUserDefDayItem = 1; } else SetHelp(NULL); } else if (strstr(ItemText, tr("Use channel")) == ItemText && data.useChannel == 2) { SetHelp(NULL, NULL, NULL, tr("Button$Setup")); iOnUseChannelGroups = 1; } else if (strstr(ItemText, IndentMenuItem(tr("Channel group"))) == ItemText) { SetHelp(NULL, NULL, NULL, tr("Button$Setup")); iOnChannelGroup = 1; } else if (iOnExtCatItem) { if (!InEditMode(ItemText, IndentMenuItem(catname), data.catvalues[iCatIndex]) || SearchExtCats.Get(iCatIndex)->searchmode >= 10) SetHelp(NULL, NULL, NULL, iOnExtCatItemBrowsable?tr("Button$Select"):NULL); } else if (strstr(ItemText, tr("Search term")) != ItemText) SetHelp(NULL, NULL, NULL, NULL); } if (state == osUnknown) { if (HasSubMenu()) return osContinue; switch (Key) { case kOk: if (data.useChannel==1) { LOCK_CHANNELS_READ; const cChannel *ch = Channels->GetByNumber(channelMin); if (ch) data.channelMin = ch; else { ERROR(tr("*** Invalid Channel ***")); break; } ch = Channels->GetByNumber(channelMax); if (ch) data.channelMax = ch; else { ERROR(tr("*** Invalid Channel ***")); break; } if (channelMin > channelMax) { ERROR(tr("Please check channel criteria!")); return osContinue; } } if (data.useChannel==2) data.channelGroup = strdup(menuitemsChGr[channelGroupNr]); if (blacklist) { *blacklist = data; if (data.DayOfWeek == 7) blacklist->DayOfWeek = UserDefDayOfWeek; // transfer numeric cat values back to search cSearchExtCat *SearchExtCat = SearchExtCats.First(); int index = 0; while (SearchExtCat) { if (SearchExtCat->searchmode >= 10) { if (blacklist->catvalues[index]) free(blacklist->catvalues[index]); msprintf(&blacklist->catvalues[index], "%d", catvaluesNumeric[index]); } SearchExtCat = SearchExtCats.Next(SearchExtCat); index++; } if (addIfConfirmed) { cMutexLock BlacklistLock(&Blacklists); blacklist->ID = Blacklists.GetNewID(); Blacklists.Add(blacklist); } Blacklists.Save(); addIfConfirmed = false; } return osBack; case kRed: if (iOnUserDefDayItem) state = AddSubMenu(new cMenuEditDaysOfWeek(&UserDefDayOfWeek)); break; case kBlue: if (iOnUseChannelGroups || iOnChannelGroup) { if (channelGroupName) free(channelGroupName); channelGroupName = strdup(menuitemsChGr[channelGroupNr]); state = AddSubMenu(new cMenuChannelGroups(&channelGroupName)); } if (iOnTerm) state = AddSubMenu(new cMenuEPGSearchTemplate(NULL, &data, addIfConfirmed)); if (iOnExtCatItemBrowsable) state = AddSubMenu(new cMenuCatValuesSelect(data.catvalues[iCatIndex], iCatIndex, SearchExtCats.Get(iCatIndex)->searchmode)); break; case kGreen: case kYellow: state = osContinue; default: break; } } if ((iOnUseChannelGroups || iOnChannelGroup || iOnTerm || iOnExtCatItemBrowsable) && bHadSubMenu && !HasSubMenu()) // return form submenu { if (iOnTerm) { if (data.DayOfWeek < 0) { UserDefDayOfWeek = data.DayOfWeek; data.DayOfWeek = 7; } if (data.useChannel == 2) { channelGroupNr = ChannelGroups.GetIndex(data.channelGroup); channelGroupName = strdup(data.channelGroup); } } if (iOnExtCatItemBrowsable && SearchExtCats.Count() > 0) { cSearchExtCat *SearchExtCat = SearchExtCats.First(); int index = 0; while (SearchExtCat) { if (SearchExtCat->searchmode >= 10) catvaluesNumeric[index] = atoi(data.catvalues[index]); SearchExtCat = SearchExtCats.Next(SearchExtCat); index++; } } Set(); Display(); } return state; } vdr-plugin-epgsearch/menu_deftimercheckmethod.c0000644000175000017500000001127213145412721021621 0ustar tobiastobias/* -*- c++ -*- Copyright (C) 2004-2013 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch */ #ifdef __FreeBSD__ #include #endif #include "menu_deftimercheckmethod.h" #include "menu_myedittimer.h" const char *cMenuDefTimerCheckMethod::CheckModes[3]; cDefTimerCheckModes DefTimerCheckModes; // -- cDefTimerCheckMode ----------------------------------------------------------------- bool cDefTimerCheckMode::Parse(const char *s) { char *line; char *pos; char *pos_next; int parameter = 1; int valuelen; #define MAXVALUELEN (10 * MaxFileName) char value[MAXVALUELEN]; pos = line = strdup(s); pos_next = pos + strlen(pos); if (*pos_next == '\n') *pos_next = 0; while (*pos) { while (*pos == ' ') pos++; if (*pos) { if (*pos != '|') { pos_next = strchr(pos, '|'); if (!pos_next) pos_next = pos + strlen(pos); valuelen = pos_next - pos + 1; if (valuelen > MAXVALUELEN) { LogFile.eSysLog("entry '%s' is too long. Will be truncated!", pos); valuelen = MAXVALUELEN; } strn0cpy(value, pos, valuelen); pos = pos_next; switch (parameter) { case 1: channelID = tChannelID::FromString(value); break; case 2: mode = atol(value); break; default: break; } //switch } parameter++; } if (*pos) pos++; } //while free(line); return (parameter >= 2) ? true : false; } cString cDefTimerCheckMode::ToText(void) const { cString buffer = cString::sprintf("%s|%d", *channelID.ToString(), mode); return buffer; } bool cDefTimerCheckMode::Save(FILE *f) { if (mode == 0) return true; // don't save the default return fprintf(f, "%s\n", *ToText()) > 0; } int cDefTimerCheckModes::GetMode(const cChannel* channel) { if (!channel) return 0; tChannelID ChannelID = channel->GetChannelID(); for (cDefTimerCheckMode *defMode = First(); defMode; defMode = Next(defMode)) if (defMode->channelID == ChannelID) return defMode->mode; return 0; } void cDefTimerCheckModes::SetMode(const cChannel* channel, int mode) { if (!channel) return; tChannelID ChannelID = channel->GetChannelID(); for (cDefTimerCheckMode *defMode = First(); defMode; defMode = Next(defMode)) if (defMode->channelID == ChannelID) { defMode->mode = mode; return; } Add(new cDefTimerCheckMode(ChannelID, mode)); } // --- cMenuDefTimerCheckMethod --------------------------------------------------------- cMenuDefTimerCheckMethod::cMenuDefTimerCheckMethod() :cOsdMenu(tr("Default timer check method"), 20) { SetMenuCategory(mcSetupPlugins); CheckModes[0] = tr("no check"); CheckModes[UPD_CHDUR] = tr("by channel and time"); CheckModes[UPD_EVENTID] = tr("by event ID"); modes = NULL; Set(); } cMenuDefTimerCheckMethod::~cMenuDefTimerCheckMethod() { delete [] modes; } void cMenuDefTimerCheckMethod::Set() { int current = Current(); Clear(); delete modes; LOCK_CHANNELS_READ; modes = new int[Channels->Count()]; int i=0; for (const cChannel *channel = Channels->First(); channel; channel = Channels->Next(channel), i++) { if (!channel->GroupSep() && *channel->Name()) { modes[i] = DefTimerCheckModes.GetMode(channel); Add(new cMenuEditStraItem(channel->Name(), &modes[i], 3, CheckModes)); } } SetCurrent(Get(current)); } eOSState cMenuDefTimerCheckMethod::ProcessKey(eKeys Key) { eOSState state = cOsdMenu::ProcessKey(Key); if (state == osUnknown) { switch (Key) { case kOk: { int i=0; LOCK_CHANNELS_READ; for (const cChannel *channel = Channels->First(); channel; channel = Channels->Next(channel), i++) if (!channel->GroupSep() && *channel->Name()) DefTimerCheckModes.SetMode(channel, modes[i]); DefTimerCheckModes.Save(); return osBack; } default: break; } } return state; } vdr-plugin-epgsearch/doc-src/0000755000175000017500000000000013145412721015762 5ustar tobiastobiasvdr-plugin-epgsearch/doc-src/en/0000755000175000017500000000000013145412721016364 5ustar tobiastobiasvdr-plugin-epgsearch/doc-src/en/epgsearchuservars.conf.5.txt0000644000175000017500000001203413145412721023750 0ustar tobiastobias=head1 NAME F - User defined variables =head1 DESCRIPTION In this file you can defines variables which then can be used in epgsearch in any play where variables are possible. =head1 SYNTAX Variables looks like %Variablename%. "Variablename" can be consist of any alphanumerical character. Space and special characters are not allowed. The variable names are case-insensitive. Examples for possible names: %Series% %DocuVar1% %ThemesSubtitleDate1% =head2 Assignment %Series%=New series~Thriller The variable %Series% will be assigned with the string "New series~Thriller". Assignments are always strings. Spaces stay spaces. %Path%=%Series% The variable %Path% gets the content of the variable %Series%. You can do nearly everything: %Path%=%Serie%~Lost The variable %Path% contains now the string "New series~Thriller~Lost". =head2 Control structures You can use simple "if then else" constructions. These constructions cannot contain strings, only variables. Spaces are ignored. %Foo%=Other %Variable%=%Path% ? %Path% : %Foo% If %Path% is not empty, assign the content of %Path% to %Variable%, otherwise the content of %Foo%. "%Path% ?" means "not empty?". You can use other checks. %Variable%=%Path%!=5 ? %Path% : %Foo% "%Path%!=5 ?" means "is %Path% equal 5?" You can also compare variables. %Five%=5 %Variable%=%Path%!=%Five% ? %Path% : %Foo% Other possible checks: == equal != not equal =head2 Calling a system command You can call external commands. The returned string will be assigned to a variable %Result%=system(scriptname,%Variable1% %Variable2% -f %Variable3% --dir=%Variable4% --dummy) Calls the script "scriptname" with the parameters "%Variable1%", "%Variable2%", etc. The result will be stored in %Result%. You can use as many variables as you want. If needed, epgsearch will quote the variable. The script must return a string B line break! If the script returns nothing, an empty string will be assigned to the Variable %Result%. =head2 Possible variables The following variables exist: %time% - start time in format HH:MM %timeend% - end time in format HH:MM %date% - start date in format TT.MM.YY %datesh% - start date in format TT.MM. %time_w% - weekday name %time_d% - start day in format TT %time_lng% - start time in seconds since 1970-01-01 00:00 %title% - title %subtitle% - subtitle %summary% - summary %htmlsummary% - summary, where all CR are replaced with '
' %eventid% - numeric event ID %% - a value from the extended EPG categories, specified in F, like %genre% or %category% %chnr% - channel number %chsh% - the short channel name %chlng% - the 'normal' channel name %chdata% - VDR's internal channel representation (e.g. 'S19.2E-1-1101-28106') %colon% - the sign ':' %datenow% - current date in format TT.MM.YY %dateshnow% - current date in format TT.MM. %timenow% - current time in format HH:MM %videodir% - VDR video directory (e.g. /video) %plugconfdir% - VDR plugin config directory (e.g. /etc/vdr/plugins) %epgsearchdir% - epgsearch config directory (e.g. /etc/vdr/plugins/epgsearch) See also C. =head1 EXAMPLES # Weekday, Date, Time %DateStr%=%time_w% %date% %time% # Themes or Subtitle or Date %ThemesSubtitleDate1%=%Subtitle% ? %Subtitle% : %DateStr% %ThemesSubtitleDate%=%Themes% ? %Themes% : %ThemesSubtitleDate1% # Calls this script to get a recording path %DocuScript%=system(doku.pl,%Title%,%Subtitle%,%Episode%,%Themes%,%Category%,%Genre%) %Docu%=%DocuScript% =head1 SEE ALSO C, C =head1 AUTHOR (man pages) Mike Constabel =head1 REPORT BUGS Bug reports (german): L Mailing list: L =head1 COPYRIGHT and LICENSE Copyright (C) 2004-2010 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch The MD5 code is derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm. vdr-plugin-epgsearch/doc-src/en/noannounce.conf.5.txt0000644000175000017500000000406513145412721022364 0ustar tobiastobias=head1 NAME F - list of events that have been marked to not be announced via OSD =head1 DESCRIPTION This file contains a list of events that have been marked to not be announced via OSD by the search timer background thread. If the user presses one of the keys 'Ok', '0', ... '9' while the announcement of an event is displayed, he will be asked if further announcements of this event should be disabled for ever (user hit '0' or 'Ok') or for the next 'x' days (user hit '1' to '9'). After pressing 'Ok' again, this setting will be stored. =head1 FORMAT Events are stored one per line, where the fields are separated with ':'. The following fields exists: 1 - title 2 - short text 3 - channel ID 4 - start time 5 - next announce time =head1 SEE ALSO C =head1 AUTHOR (man pages) Mike Constabel =head1 REPORT BUGS Bug reports (german): L Mailing list: L =head1 COPYRIGHT and LICENSE Copyright (C) 2004-2010 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch The MD5 code is derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm. vdr-plugin-epgsearch/doc-src/en/epgsearchtemplates.conf.5.txt0000644000175000017500000000324313145412721024076 0ustar tobiastobias=head1 NAME F - Searchtimer templates =head1 DESCRIPTION In epgsearch searchtimer templates can be created for easy creating new searchtimers. These templates are saved in this file. =head1 SYNTAX This file has the same syntax as the epgsearch.conf. So please refer to F, see C. =head1 SEE ALSO C, C =head1 AUTHOR (man pages) Mike Constabel =head1 REPORT BUGS Bug reports (german): L Mailing list: L =head1 COPYRIGHT and LICENSE Copyright (C) 2004-2010 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch The MD5 code is derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm. vdr-plugin-epgsearch/doc-src/en/epgsearchcats.conf.5.txt0000644000175000017500000001025713145412721023035 0ustar tobiastobias=encoding utf8 =head1 NAME F - Configuration of the additional EPG information =head1 DESCRIPTION Some EPG providers deliver additional EPG information like the type of event, the video and audio format, cast,... Using tvm2vdr or epg4vdr you can import this into vdr. To use this information with search timers one has to configure it with the file epgsearchcats.conf in your plugins config directory. Sample files for F are delivered with the plugin in the directory 'conf'. Simply copy the one that fits for you to your plugins config directory with filename epgsearchcats.conf and then have a look to the search timers edit menu (after a restart of VDR). Since setting up a new F is a lot of work, I've added a small tool 'createcats', that makes the biggest part of the job. It should have been compiled with the plugin and exists in the sources directory. See C for information about how to use it. B epgsearch scans the summary of an event for the category name followed by ': ' for all categories that have a corresponding value set in the search timer. The search is case sensitive regarding the category name as also the value. =head1 SYNTAX ID|category name(,format)|name in menu|values separated by ','(option)|searchmode(option) - 'ID' should be a unique positive integer (changing the id later on will force you to re-edit your search timers!) - 'category name' is the name as delivered by the EPG provider, e.g. 'Genre' you can optionally provide a format specifier for numeric values, e.g. Episode,%02i - 'name in menu' is the name displayed in epgsearch. - 'values' is an optional list of possible values - 'searchmode' specifies the search mode: text comparison: 0 - the whole term must appear as substring 1 - all single terms (delimiters are ',', ';', '|' or '~') must exist as substrings. This is the default search mode. 2 - at least one term (delimiters are ',', ';', '|' or '~') must exist as substring. 3 - matches exactly 4 - regular expression numerical comparison: 10 - less 11 - less or equal 12 - greater 13 - greater or equal 14 - equal 15 - not equal =head1 EXAMPLE (Lines are shortened for correct displaying) Example for EPG from Hrzu, downloaded from epgdata.com with tvmovie2vdr. 1|Category|Kategorie|Information,Kinder,Musik,Serie,Show,Spielfilm,Sport|2 2|Genre|Genre|Abenteuer,Action,Wirtschaft,Wissen,Zeichentrick|2 3|Format|Video-Format|16:9,4:3|2 4|Audio|Audio|Dolby Surround,Dolby,Hoerfilm,Stereo|2 5|Year|Jahr||2 6|Cast|Besetzung||2 7|Director|Regisseur||2 8|Moderator|Moderation||2 9|Rating|Bewertung|Groartig besonders wertvoll,Annehmbar,Schwach|2 10|FSK|FSK|6,12,16,18|2 11|Country|Land||2 12|Episode|Episode||4 13|Themes|Thema||4 =head1 SEE ALSO C, C, C =head1 AUTHOR (man pages) Mike Constabel =head1 REPORT BUGS Bug reports (german): L Mailing list: L =head1 COPYRIGHT and LICENSE Copyright (C) 2004-2010 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch The MD5 code is derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm. vdr-plugin-epgsearch/doc-src/en/epgsearchchangrps.conf.5.txt0000644000175000017500000000352313145412721023706 0ustar tobiastobias=head1 NAME F - Channel groups =head1 DESCRIPTION You can define channel groups in epgsearch which can be used in searchtimers. In this file the groups will be saved. =head1 SYNTAX Each line contains one channel group. The line begins with the group name, after the name, split by '|', the list of channels. =head1 EXAMPLE (Lines are shortened for clean displaying) Private|S19.2E-133-33-46|S19.2E-133-33-51 ProsiebenSat.1|S19.2E-133-33-46|S19.2E-133-33-47 RTL World|S19.2E-1-1089-12003||S19.2E-1-1089-12090 =head1 SEE ALSO C =head1 AUTHOR (man pages) Mike Constabel =head1 REPORT BUGS Bug reports (german): L Mailing list: L =head1 COPYRIGHT and LICENSE Copyright (C) 2004-2010 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch The MD5 code is derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm. vdr-plugin-epgsearch/doc-src/en/epgsearchdirs.conf.5.txt0000644000175000017500000000624613145412721023047 0ustar tobiastobias=head1 NAME F - List of directories for selecting in epgsearch =head1 DESCRIPTION This is one source of the 'Select directory' menu. This file contain directories which can be used for search timers or ordinary timers. The items displayed are read from the following sources: * current recording directories * current timer directories * directories used in search timers * directories specified in F The menu merges theses directories and displays only distinct directories. With key 'yellow' one can change the depth of the directories shown. If there are items, that contain category variables like '%genre%', these entries are always shown before any other directories. They are also not level dependent, but are always shown with their full directory. If this menu is called from the timer edit menu and an item is selected that contains the variables "%title%" or "%subtitle" then the 'file' item of the timer gets cleared, since title or subtitle already exist in the 'directory' item. =head1 SYNTAX Each line contains a directory. You can use every variable, internal ones those defined in F and the variables of the extended EPG. See C and C. Internal ones: %time% - start time in format HH:MM %date% - start date in format TT.MM.YY %datesh% - start date in format TT.MM. %time_w% - weekday name %time_d% - start day in format TT %time_lng% - start time in seconds since 1970-01-01 00:00 %title% - title %subtitle% - subtitle =head1 EXAMPLE %Category%~%Genre% %Category%~%Genre%~%Title%~%Episode%: %Subtitle% Information~Nature~%Title%~%Episode%: %Subtitle% %Series% Movie~Action Movie~Docu Movie~Thriller Music Sports =head1 SEE ALSO C, C, C =head1 AUTHOR (man pages) Mike Constabel =head1 REPORT BUGS Bug reports (german): L Mailing list: L =head1 COPYRIGHT and LICENSE Copyright (C) 2004-2010 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch The MD5 code is derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm. vdr-plugin-epgsearch/doc-src/en/epgsearchmenu.conf.5.txt0000644000175000017500000001364613145412721023054 0ustar tobiastobias=head1 NAME F - Customizing the EPG menus =head1 DESCRIPTION The file F in your epgsearch config directory is used to store the entries for customizing the EPG menus. You specify the look of each menu (What's on now, What's on next, What's on at ..., Schedule, Search results, Favorites) with a separate line. =head1 EXAMPLE MenuWhatsOnNow=%chnr%:3|%progrt2s%:5| %time% %t_status%:8|%category%:6| %title% ~ %subtitle%:35 MenuWhatsOnNext=%chnr%:3|%time% %t_status%:8|%category%:8| %title% ~ %subtitle%:35 MenuWhatsOnElse=%chnr%:3|%time% %t_status%:8|%category%:8| %title% ~ %subtitle%:35 MenuSchedule=%time% %t_status%:8|%genre%:14| %title% ~ %subtitle%:35 MenuSearchResults=%chnr%:3|%datesh% %time% %t_status%:14|%genre%:8| %title%%colon% %subtitle%:35 MenuFavorites=%chnr%:3|%datesh% %time% %t_status%:14|%genre%:8| %title%%colon%%subtitle%:35 =head1 SYNTAX E.g. the entry 'MenuWhatsOnNow' tells epgsearch how you would like to build a line for the menu 'What's on now'. This would create a menu line starting with the channel number, followed by a progress bar in text2skin style, a space of one char, the start time, the timer status, the EPG category (like "movie") and finally the title and subtitle. The values for MenuWhatsOnNext, MenuWhatsOnElse, MenuSchedule, MenuSearchResults, MenuFavorites specify the menu 'What's on next', 'What's on at ...', 'Schedule', 'Search results' and 'Favorites' respectively. If you do not specify one entry, epgsearch uses its default menu look. 'MenuSearchResults' has something special: If you want to have different layouts for your search results depending on the search, you can use more then one menu template. Simply define e.g. an additional MenuSearchResultsTip of the Day=%chnr%:3|%time_w%:4|%t_status%:3|%genre%:10|%title%%colon% %subtitle%:35 This will produce an additional menu item "Result menu layout" in the edit menu of a search where you can choose between the default menu template and your own templates. In the example above you will get "Tip of the Day" as selection entry, since epgsearch simply cuts the leading "MenuSearchResults". When you display the search results the chosen template will be used instead of the default one. The following variables exist: %time% - start time in format HH:MM %date% - start date in format TT.MM.YY %datesh% - start date in format TT.MM. %time_w% - weekday name %time_d% - start day in format TT %time_lng% - start time in seconds since 1970-01-01 00:00 %title% - title %subtitle% - subtitle %t_status% - timer status ('T', 't', 'R') %v_status% - VPS status %r_status% - running status %status% - complete status, the same as '%t_status%%v_status%%r_status%' %colon% - the sign ':' %% - a value from the extended EPG categories, specified in epgsearchcats.conf, like %genre% or %category% for the 'Whats on...' and 'Search results' menu there is also: %chnr% - channel number %chsh% - the short channel name %chlng% - the 'normal' channel name %chdata% - VDR's internal channel representation (e.g. 'S19.2E-1-1101-28106') %progr% - graphical progress bar (not for menu 'Search results') %progrT2S% - progress bar in text2skin style (not for menu 'Search results') the variables are not case sensitive. An entry consists of up to 6 tables separated with '|'. The last entry of each table should declare the table width in chars, separated with ':'. If you use a separator like '~', '-' or '#' to separate items like title or subtitle, e.g. %title% ~ %subtitle%, and the subtitle is empty, then epgsearch will try to fix this automatically to avoid a trailing separator. You should vary the tab width values to fit your needs, since the look often depends on the selected skin. epgsearchmenu.conf is not reloaded with every plugin call, since this is only useful when testing the conf file. To activate the permanent reload for testing your conf, pass the new start parameter '-r' or '--reloadmenuconf' in your runvdr. There's a sample F in the subdirectory "conf". For a quick try copy it to your epgsearch config directory (e.g. /etc/vdr/plugins/epgsearch). To enable icons from the VDRSymbols font simply put the line WarEagleIcons=1 to F. The VDRSymbols font is available at +http://andreas.vdr-developer.org/fonts/download.html NOTE: As long as there is a file epgsearchmenu.conf with an entry for a special menu, all setup settings regarding the look of this menu are ignored. =head1 SEE ALSO C =head1 AUTHOR (man pages) Mike Constabel =head1 REPORT BUGS Bug reports (german): L Mailing list: L =head1 COPYRIGHT and LICENSE Copyright (C) 2004-2010 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch The MD5 code is derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm. vdr-plugin-epgsearch/doc-src/en/epgsearch.4.txt0000644000175000017500000011341113145412721021231 0ustar tobiastobias=head1 NAME F - Searchtimer and replacement of the VDR program menu =head1 OVERVIEW Since the README get bigger and bigger this man page shall be used to explain some things in detail. So it's not really a manual, but an extended README. =head1 CONTENT 1. Using variables in the directory entry of a search timer 2. The format of epgsearch.conf 3. Description of the search process 4. How do Search Timers work? 5. How to trigger a search timer update? 6. The sources of the 'Select directory' menu 7. Language dependent commands for EPG 8. Usage from other plugins or scripts 9. SVDRP interface 10. Customizing the EPG menus 11. Working with the timer conflict menu 12. User defined variables 13. Email notifications 14. The conf.d subdirectory =head1 1. Using variables in the directory entry of a search timer If you are using extended EPG information, you can use variables as part of a directory entry of a search timer. These variables always have the form '%variable%'. The name of a variable corresponds with the internal name of an extended EPG info, as specified in the file epgsearchcats.conf (samples can be found in subdirectory 'conf'). Example: 1|Category|Kategorie|Information,Kinder,Musik,Serie,Show,Spielfilm,Sport|3 The category with ID 1 has the internal name 'Category'. So you could use it with '%Category%'. The names are not case sensitive. Sample directory entries could look like this: My Movies~%Category% Childrens Movies~%category% %CATEGORY%~%genre% There are also three other variables: %Title%, %Subtitle% and %chlng%. If you don't use %Title%, the title is always automatically appended to the directory entry, when a timer will be created. If you set 'serial recording' to 'yes' in your search timer then also the subtitle will be automatically appended. So the directory entry %Category%~%Genre%~%Title%~%Subtitle% is the same as %Category%~%Genre% (with 'serial recording' set to 'yes'). The %chlng% variable gets replaced with the name of the channel. Attention: Automatically appending title and subtitle will not be done, if you use the variables %Title% or %Subtitle% in the directory entry. This allows one to form directory entries like this one: %Category%~%Genre%~%Title%~%Episode%~%Subtitle% There are also the following search variables: %search.query% that will be replaced with the query of the search timer %search.series% that is '1', if the search has its 'Series recording' flag set, else '0'. See also C. =head1 2. The format of epgsearch.conf Due to some new features there was a change in the format. The format is now signed with a comment in the first line. The field delimiter is B<':'>: 1 - unique search timer id 2 - the search term 3 - use time? 0/1 4 - start time in HHMM 5 - stop time in HHMM 6 - use channel? 0 = no, 1 = Interval, 2 = Channel group, 3 = FTA only 7 - if 'use channel' = 1 then channel id[|channel id] in vdr format, one entry or min/max entry separated with |, if 'use channel' = 2 then the channel group name 8 - match case? 0/1 9 - search mode: 0 - the whole term must appear as substring 1 - all single terms (delimiters are blank,',', ';', '|' or '~') must exist as substrings. 2 - at least one term (delimiters are blank, ',', ';', '|' or '~') must exist as substring. 3 - matches exactly 4 - regular expression 5 - fuzzy searching (specify tolerance in parameter 42, not available for EPG categories) 10 - use title? 0/1 11 - use subtitle? 0/1 12 - use description? 0/1 13 - use duration? 0/1 14 - min duration in minutes 15 - max duration in minutes 16 - use as search timer? 0/1/2 (with 2 one can specify time margins in parameter 48/49 where the search timer is active) 17 - use day of week? 0/1 18 - day of week (0 = Sunday, 1 = Monday...; -1 Sunday, -2 Monday, -4 Tuesday, ...; -7 Sun, Mon, Tue) 19 - use series recording? 0/1 20 - directory for recording 21 - priority of recording 22 - lifetime of recording 23 - time margin for start in minutes 24 - time margin for stop in minutes 25 - use VPS? 0/1 26 - action: 0 = create a timer 1 = announce only via OSD (no timer) 2 = switch only (no timer) 27 - use extended EPG info? 0/1 28 - extended EPG info values. This entry has the following format (delimiter is '|' for each category, '#' separates id and value): 1 - the id of the extended EPG info category as specified in epgsearchcats.conf 2 - the value of the extended EPG info category (a ':' will be translated to "!^colon^!", e.g. in "16:9") 29 - avoid repeats? 0/1 30 - allowed repeats 31 - compare title when testing for a repeat? 0/1 32 - compare subtitle when testing for a repeat? 0=no/1=yes/2=yes-if present 33 - compare description when testing for a repeat? 0/1 34 - compare extended EPG info when testing for a repeat? This entry is a bit field of the category IDs. 35 - accepts repeats only within x days 36 - delete a recording automatically after x days 37 - but keep this number of recordings anyway 38 - minutes before switch (if action = 2) 39 - pause if x recordings already exist 40 - blacklist usage mode (0 none, 1 selection, 2 all) 41 - selected blacklist IDs separated with '|' 42 - fuzzy tolerance value for fuzzy searching 43 - use this search in favorites menu (0 no, 1 yes) 44 - number of the search menu template to use (only available if multiple search result templates are defined in epgsearchmenu.conf) 45 - auto deletion mode (0 don't delete search timer, 1 delete after given count of recordings, 2 delete after given days after first recording) 46 - count of recordings after which to delete the search timer 47 - count of days after the first recording after which to delete the search timer 48 - first day where the search timer is active (see parameter 16) 49 - last day where the search timer is active (see parameter 16) 50 - ignore missing EPG categories? 0/1 51 - unmute sound if off when used as switch timer 52 - the minimum required match in percent when descriptions are compared to avoid repeats (-> 33) A ':' in the search term or the directory entry will be translated in a '|'. If a '|' exists in the search term, e.g. when using regular expressions, it will be translated to "!^pipe^!" (I know it's ugly ;-)) See also C. =head1 3. Description of the search process First, for each broadcasting a search text divided by '~' is created, depending on the settings of 'Use title', 'Use subtitle' and 'Use description': title~subtitle~description If "Match case" is not set, the search text and the search term are transformed to lower case. Now depending on the search mode, the search term will be looked up in the search text: =over 4 =item - 'Phrase' matches if the search term is found anywhere in the search text. =item - 'at least one word', 'all words' first the search term will be split in single words. Delimiters are a blank and the characters ',' ';' '|' '~'. Then we check if at least one or all words appear in the search text. =item - 'match exactly' matches if search term and search text are identical. =item - 'regular expression' the search is done with a regular expression. You don't need a leading and trailing '/' in your search term. Two standards of regular expression are supported: extended POSIX and Perl compatible regular expressions (PCRE) (see F). =back If the search was successful until now, the other criterions (start time, duration, week day) are checked. =head1 4. How do Search Timers work? With each update, the plugin first sorts the search timers by timer priority (descending) and search term and then searches for new matches of your search timers. If a new match is found then a new timer is created. For serial recordings, the subtitle is appended to the recording directory. Many providers deliver the subtitle just 1-2 days before the event. The plugin uses then a date/time string for the subtitle, but replaces this one later if the subtitle is present. Start and end times of a broadcasting often vary a little bit. To avoid getting many different timers for the same event, the plugin checks before adding a new timer, if there is one, that has start and end times which only differ by a maximum of 10 minutes (or the events duration if this is less then 10 minutes). If so, the present timer is modified, else a new timer is created. If the timer was set to inactive there will be no update. Also manually corrected priority or lifetime will not be changed when updating. If you have set 'Announce only (no timer)' to yes, no timer is created. Instead you get an OSD message about the event. This message is displayed at each scan, but only if there is no timer for the event. =head1 5. How to trigger a search timer update? the update of search timers runs in its own thread. There are several ways to trigger it: =over 4 =item - automatically after VDR starts there is always an update (after a few seconds). After this, the setup option 'Update interval' tells epgsearch when the next update should be done repeatedly (in minutes). =item - manually extern the thread observes the file '.epgsearchupdate' in the plugins config directory. When you touch /path_to_file/.epgsearchupdate this will also trigger an update. So this is a simple solution to make an update e.g. by a script. =item - manually intern calling actions or pressing '3' in the menu of searches asks also for an update. =item - from other plugins =back there's a service 'Epgsearch-updatesearchtimers-v1.0' that can be used with the service interface of VDR from other plugins with the option to inform via OSD when the update has finished =head1 6. The sources of the 'Select directory' menu This menu displays directories, that can be used for search timers or ordinary timers. The items displayed are read from the following sources: * current recording directories * current timer directories * directories used in search timers * directories specified in F, see C * entries in VDR's folders.conf The menu merges theses directories and displays only distinct directories. With key 'yellow' one can change the depth of the directories shown. If there are items, that contain category variables like '%genre%', these entries are always shown before any other directories. They are also not level dependent, but are always shown with their full directory. If this menu is called from the timer edit menu and an item is selected that contains the variables "%title%" or "%subtitle" then the 'file' item of the timer gets cleared, since title or subtitle already exist in the 'directory' item. This list can also be accessed via the SVDRP command 'LSRD'. =head1 7. Language dependent commands for EPG If you like to have a language dependent list of commands simply translate your present F to your preferred OSD language and store it with the filename epgsearchcmds-XXX.conf, where XXX is the language code from i18n.c: { "eng,dos", "deu,ger", "slv", "ita", "dut,nla,nld", "por", "fra,fre", "nor", "fin,smi", "pol", "esl,spa", "ell,gre", "sve,swe", "rom,rum", "hun", "cat,cln", "rus", "hrv", "est", "dan", } If there are more codes for one language (e.g. "deu,ger") choose one of them. If there is no language dependent file, epgsearch loads the file F. See also C. =head1 8. Usage from other plugins or scripts Searching the EPG and other functionality can be used by other plugins or scripts. There are two approaches: =head2 8.1. File-based (intended for use in scripts) Therefore simply create the file '.epgsearchrc' in the plugins config directory with the following lines in it: Search=your search term Searchmode=x // 0=phrase, 1=and, 2=or, 3=regular expression ChannelNr=x // add this line, to search on a specific channel UseTitle=x // 1(default) or 0 UseSubtitle=x // 1(default) or 0 UseDescr=x // 1(default) or 0 Then call Epgsearch via svdrpsend (you must have assigned a key to it), e.g. svdrpsend HITK green At startup Epgsearch will look for this file and give you the search results for your search, if it exists. After that the file is removed. A sample script F, that searches for the repeats of a recording exists in the scripts subdirectory of Epgsearch. =head2 8.2. via Plugin-Interface (intended for use in plugins) A plugin can directly call two functions of epgsearch with only some lines of source code: - searching the EPG for some criteria and display the result list - extended timer edit menu I have added a quick and dirty dummy plugin (source/vdr-epgsearchclient-0.0.1.tgz), that demonstrates the usage. =head1 9. SVDRP interface epgsearch implements a SVDRP interface, that can be accessed for example like this svdrpsend PLUG epgsearch LSTS the following commands are available: =head2 search management: * 'LSTS [ID]' to list all searches, or the one with the passed ID (format is the same as epgsearch.conf) * 'NEWS ' to add a new search REMARK: the value of element ID is ignored. epgsearch will always assign the next free ID * 'DELS ' to delete the search with ID * 'EDIS ' to modify an existing search * 'UPDS [OSD]' to update the search timers. Passing the optional keyword 'OSD' pops up an OSD message after the update has finished. * 'MODS ID ON|OFF' turns on/off the option 'Use as search timer'. * 'UPDD' to reload the file epgsearchdone.data, e.g. after an external tool has modified it. * 'SETS ' to temporarily activate or cancel the search timer background thread. * 'FIND ' for searching the EPG input is the same as with 'NEWS'. output is a list of found events formatted as 'NEWT' lines. So they can be immediately used to create a new timer for an event. * 'QRYS < ID(s) >' to get the results for a search with the given ID. Multiple IDs can also be passed and have to be separated with '|'. The results are formatted like this: search ID : // the ID of the corresponding search timer event ID : // VDR event ID title : // event title, any ':' will be converted to '|' episode name : // event short text, any ':' will be converted to '|' event start : // event start in seconds since 1970-01-01 event stop : // event stop in seconds since 1970-01-01 channel : // channel ID in VDR's internal representation (e.g. 'S19.2E-1-1101-28106') timer start : // timer start in seconds since 1970-01-01 (only valid if timer flag is > 0) timer stop : // timer stop in seconds since 1970-01-01 (only valid if timer flag is > 0) timer file : // timer file (only valid if timer flag is > 0) timer flag : // 0 = no timer needed, 1 = has timer, 2 timer planned for next update) * 'QRYS ' to get the results for a search with the given search settings. * 'QRYF [hours]' to get the results for the favorites menu, see QRYS for result format. The optional parameter specifies the number of hours to evaluate and defaults to 24h. * 'MENU [PRG|NOW|SUM]' calls one of the main menus of epgsearch or the summary of the current event. * 'UPDT' reloads the search timers from epgsearch.conf =head2 channel group management: * 'LSTC [channel group name]' list all channel groups or if given the one with name 'group name' * 'NEWC ' create a new channel group, format as in epgsearchchangrps.conf * 'EDIC ' modify an existing channel group, format as in epgsearchchangrps.conf * 'DELC ' delete an existing channel group * 'RENC ' rename an existing channel group =head2 blacklist management: * 'LSTB [ID]' to list all blacklists, or the one with the passed ID (format is the same as epgsearchblacklists.conf) * 'NEWB ' to add a new blacklist REMARK: the value of element ID is ignored. epgsearch will always assign the next free ID * 'DELB ' to delete the blacklist with ID * 'EDIB ' to modify an existing blacklist =head2 search template management: * 'LSTT [ID]' to list all search templates, or the one with the passed ID (format is the same as epgsearch.conf) * 'NEWT ' to add a new search template REMARK: the value of element ID is ignored. epgsearch will always assign the next free ID * 'DELT ' to delete the search template with ID * 'EDIT ' to modify an existing search template * 'DEFT [ID]' returns the ID of the default search template. When passing an ID it activates the corresponding template as default. =head2 extended EPG categories: * 'LSTE [ID] to get the extended EPG categories defined in epgsearchcats.conf or the one with the given ID. (format is the same as epgsearchcats.conf) =head2 misc: * 'SETP [option]' returns the current value of the given setup option or a list of all options with their current values. The following options can be accessed: - ShowFavoritesMenu - UseSearchTimers =head2 timer conflicts: * 'LSCC [REL]' returns the current timer conflicts. With the option 'REL' only relevant conflicts are listed. The result list looks like this for example when we have 2 timer conflicts at one time: 1190232780:152|30|50#152#45:45|10|50#152#45 '1190232780' is the time of the conflict in seconds since 1970-01-01. It's followed by list of timers that have a conflict at this time: '152|30|50#152#45' is the description of the first conflicting timer. Here: '152' is VDR's timer id of this timer as returned from VDR's LSTT command '30' is the percentage of recording that would be done (0...100) '50#152#45' is the list of concurrent timers at this conflict '45|10|50#152#45' describes the next conflict =head1 10. Customizing the EPG menus The file F in your epgsearch config directory is used to store the entries for customizing the EPG menus. You specify the look of each menu (What's on now, What's on next, What's on at ..., Schedule, Search results, Favorites) with a separate line. Here's a sample: MenuWhatsOnNow=%chnr%:3|%progrt2s%:5| %time% %t_status%:8|%category%:6| %title% ~ %subtitle%:35 MenuWhatsOnNext=%chnr%:3|%time% %t_status%:8|%category%:8| %title% ~ %subtitle%:35 MenuWhatsOnElse=%chnr%:3|%time% %t_status%:8|%category%:8| %title% ~ %subtitle%:35 MenuSchedule=%time% %t_status%:8|%genre%:14| %title% ~ %subtitle%:35 MenuSearchResults=%chnr%:3|%datesh% %time% %t_status%:14|%genre%:8| %title%%colon% %subtitle%:35 MenuFavorites=%chnr%:3|%time%:6|%timespan%:7|%t_status%:14|%genre%:8| %title%%colon%%subtitle%:35 E.g. the entry 'MenuWhatsOnNow' tells epgsearch how you would like to build a line for the menu 'What's on now'. This would create a menu line starting with the channel number, followed by a progress bar in text2skin style, a space of one char, the start time, the timer status, the EPG category (like "movie") and finally the title and subtitle. The values for MenuWhatsOnNext, MenuWhatsOnElse, MenuSchedule, MenuSearchResults, MenuFavorites specify the menu 'What's on next', 'What's on at ...', 'Schedule', 'Search results' and 'Favorites' respectively. If you do not specify one entry, epgsearch uses its default menu look. 'MenuSearchResults' has something special: If you want to have different layouts for your search results depending on the search, you can use more then one menu template. Simply define e.g. an additional MenuSearchResultsTip of the Day=%chnr%:3|%time_w%:4|%t_status%:3|%genre%:10|%title%%colon% %subtitle%:35 This will produce an additional menu item "Result menu layout" in the edit menu of a search where you can choose between the default menu template and your own templates. In the example above you will get "Tip of the Day" as selection entry, since epgsearch simply cuts the leading "MenuSearchResults". When you display the search results the chosen template will be used instead of the default one. The following variables exist: %time% - start time in format HH:MM %timeend% - end time in format HH:MM %date% - start date in format DD.MM.YY %datesh% - start date in format DD.MM. %date_iso% - start date in format YYYY-MM-DD. %year% - year with century %month% - month (1-12) %day% - day (1-31) %week% - week number of the year (Monday as the first day of the week) as a decimal number [01,53] %time_w% - weekday name %time_d% - start day in format TT %time_lng% - start time in seconds since 1970-01-01 00:00 %timespan% - timespan from now to the beginning of an event, e.g. 'in 15m' or the time an event is already running, e.g. '10m'. %length% - length in seconds %title% - title %subtitle% - subtitle %summary% - summary %htmlsummary% - summary, where all CR are replaced with '
' %eventid% - numeric event ID %liveeventid% - encoded event ID as used in the frontend 'live' %t_status% - timer status ('T', 't', 'R') %v_status% - VPS status %r_status% - running status %status% - complete status, the same as '%t_status%%v_status%%r_status%' %% - a value from the extended EPG categories, specified in epgsearchcats.conf, like %genre% or %category% for the 'Whats on...' and 'Search results' menu there are also: %chnr% - channel number %chsh% - the short channel name %chlng% - the 'normal' channel name %chdata% - VDR's internal channel representation (e.g. 'S19.2E-1-1101-28106') %progr% - graphical progress bar (not for menu 'Search results'), requires VDRSymbols font %progrT2S% - progress bar in text2skin style (not for menu 'Search results') some independent variables: %colon% - the sign ':' %datenow% - current date in format DD.MM.YY %dateshnow% - current date in format DD.MM. %date_iso_now% - current date in format YYYY-MM-DD %timenow% - current time in format HH:MM %videodir% - VDR video directory (e.g. /video) %plugconfdir% - VDR plugin config directory (e.g. /etc/vdr/plugins) %epgsearchdir% - epgsearch config directory (e.g. /etc/vdr/plugins/epgsearch) The variables are not case sensitive. You can also use variables for extended EPG categories defined in F or use your own user defined variables defined in F An entry consists of up to 6 tables separated with '|'. The last entry of each table should declare the table width in chars, separated with ':'. If you use a separator like '~', '-' or '#' to separate items like title or subtitle, e.g. %title% ~ %subtitle%, and the subtitle is empty, then epgsearch will try to fix this automatically to avoid a trailing separator. You should vary the tab width values to fit your needs, since the look often depends on the selected skin. epgsearchmenu.conf is not reloaded with every plugin call, since this is only useful when testing the conf file. To activate the permanent reload for testing your conf, pass the new start parameter '-r' or '--reloadmenuconf' in your runvdr. There's a sample F in the subdirectory "conf". For a quick try copy it to your epgsearch config directory (e.g. /etc/vdr/plugins/epgsearch). To enable icons from the VDRSymbols font simply put the line WarEagleIcons=1 to F. The VDRSymbols font is available at http://andreas.vdr-developer.org/fonts/download.html NOTE: As long as there is a file epgsearchmenu.conf with an entry for a special menu, all setup settings regarding the look of this menu are ignored. See also C. =head1 11. Working with the timer conflict menu If a conflict is detected within the periodic conflict background check you get an OSD message which informs you about it. Pressing 'Ok' you will get a menu that displays all relevant conflicts. You can manually call this menu in epgsearch in the menu 'Search/Actions'. Besides the relevant conflicts (relevance is controlled via the setup options of epgsearch) there may also be conflicts which are not classified as important. If so, you can press 'Show all' to get the complete list. The menu title always displays the number of relevant conflicts and the total number. The list displays first the time when a conflict appears and then all timers that will fail here. A timer entry consists of the channel number and its name followed by the timer priority and the percentage value that shows how much of the timer will be recorded. Finally the timer's file entry is displayed. When you select a timer entry and press 'Ok' or 'Details' you get a new menu which displays all concurrent timers. This menu allows you to resolve the conflict by - searching a repeat for an event - disabling a timer - deleting a timer - changing the timers start- or stop-time or its priority - executing any other commands on this timer An entry of this menu consists of the sign '>' to indicate an active timer, the channel number, the start and stop time, the priority, the number of the device that will do the recording (or 'C' for conflict) and the timer's file entry. Pressing 'Ok' on a timer entry will show you its event description if present. If one returns from this menu to the conflict overview menu there will be an automatic update to see if a conflict was really resolved. Some changes to a timer (like modifying start/stop or deleting a timer) in the conflict details menu also cause an immediate return to the overview menu and produce an update. Note: There's a 'hidden' setup option epgsearch.ConflCheckCmd, that allows executing a command for each timer causing a conflict. You have to set this directly in VDRs setup.conf like this: epgsearch.ConflCheckCmd = system(your_script_handling_the_conflict.sh, any_arguments like %timer.file%) (Please have a look at 'Calling a system command' below for the possible arguments) One could use this for example to forward a timer to another VDR machine in case of a conflict. This command is evaluated for each timer causing a conflict whenever an automatic conflict check is running. When calling the conflict check via OSD the command is not evaluated. =head1 12. User defined variables You can create your own variables to be used in any place that supports variables, like the default recording directory for manually created timers, the recording directory of a search timer or in your customized EPG menus. Put them in the file F. Variables looks like %Variablename%. "Variablename" can be consist of any alphanumerical character. Space and special characters are not allowed. The variable names are case-insensitive. Examples for possible names: %Series% %DocuVar1% %ThemesSubtitleDate1% =head2 Assignment %Series%=New series~Thriller The variable %Series% will be assigned with the string "New series~Thriller". Assignments are always strings. Spaces stay spaces. %Path%=%Series% The variable %Path% gets the content of the variable %Series%. You can do nearly everything: %Path%=%Serie%~Lost The variable %Path% contains now the string "New series~Thriller~Lost". =head2 Control structures You can use simple "if then else" constructions. These constructions cannot contain strings, only variables. Spaces are ignored. %Foo%=Other %Variable%=%Path% ? %Path% : %Foo% If %Path% is not empty, assign the content of %Path% to %Variable%, otherwise the content of %Foo%. "%Path% ?" means "not empty?". You can use other checks. %Variable%=%Path%!=5 ? %Path% : %Foo% "%Path%!=5 ?" means "is %Path% equal 5?" You can also compare variables. %Five%=5 %Variable%=%Path%!=%Five% ? %Path% : %Foo% Other possible checks: == equal != not equal =head2 Calling a system command You can call external commands. The returned string will be assigned to a variable %uservar%=system(scriptname[, parameters]) Calls the script "scriptname" with the parameters defined in the optional list of 'parameters'. This can be an arbitrary expression containing other user variables, but not again a system call or a conditional expression. Sample: %myVar%=system(/usr/local/bin/myscript.sh, -t %title% -s %subtitle% -u %myOtherVar%) The script must return a string B line break! If the script returns nothing, an empty string will be assigned to the Variable %Result%. =head2 Calling a TCP service You can call a TCP service with the following syntax: %uservar%=connect(, , []) This will connect to through the given port and pass the optional given data. can be an IP address or the domain name of the TCP service. The result returned by the service must be terminated with a line feed. =head2 Get the length of an argument When passing any values to the connect or system command it can be helpful to have the length of an argument for simple parsing. This can be done with %uservar%=length() Sample: %length_title%=length(%title%) =head2 Possible variables for a list of already builtin variables refer to the section "Customizing the EPG menus" Furthermore you can use every variable defined in F. See C. =head2 EXAMPLES # Weekday, Date, Time %DateStr%=%time_w% %date% %time% # Themes or Subtitle or Date %ThemesSubtitleDate1%=%Subtitle% ? %Subtitle% : %DateStr% %ThemesSubtitleDate%=%Themes% ? %Themes% : %ThemesSubtitleDate1% # Calls this script to get a recording path %DocuScript%=system(doku.pl, -t %Title% -s %Subtitle% -e %Episode% -th %Themes% -c %Category% -g %Genre%) %Docu%=%DocuScript% =head1 13. Email notification If you want to get email notifications about timers added/modified/removed by the search timer thread or about timer conflicts, first copy the script 'sendEmail.pl' to the place where your executables are (e.g. /usr/local/bin) and then configure your email account in the setup. Press 'Test' to check if it works. There should be something like 'Email successfully sent' at the end of the output. The content of the mails is defined by the files - epgsearchupdmail.templ (for search timer update notifications) - epgsearchconflmail.templ (for timer conflict notifications) You can find sample files in the 'conf' directory. Copy them to the epgsearch config directory (e.g. /etc/vdr/plugins/epgsearch). =head2 Customizing the notifications mails The content of the mails can be customized in many ways. You can use plain text or HTML (see the sample conf/epgsearchupdmail-html.templ). For an update mail you have to define the following sections: - "subject" to be used as mail subject - "mailbody" the body of the mail: put %update.newtimers% in the place where the list of new timers should appear. The same for %update.modtimers%, %update.deltimers% and %update.newevents% for the list of changed or deleted timers and event announcements. - "timer" the description of one timer and "event" with the description of one event. This section is used to display one timer within a timer list, e.g. in %update.newtimers%. The same for "event". All sections are optional, e.g. if you don't use event announcements you can drop "%update.newevents%" in the mailbody and the "event" section. But of course you should have at least a mailbody ;-) Each section is enclosed in a pseudo XML tag. The following variables can be used in the section : - %update.newtimers% - will be replaced with the list of new timers created with this update. The timers are displayed as defined in the section '' - %update.countnewtimers% - the number of new timers - %update.modtimers% - same as %update.newtimers% but for modified timers. - %update.countmodtimers% - the number of modified timers - %update.deltimers% - same as %update.newtimers% but for deleted timers. (Note: a deleted timer has eventually no event assigned to it. So all event variables within the timer section will be substituted to an empty string.) - %update.countdeltimers% - the number of deleted timers - %update.newevents% - will be replaced with the list of events to announce. These events are the search result of search timers with the action "announce by mail". The events are displayed as defined in the section '' - %update.countnewevents% - the number of new events - %colon% - the sign ':' - %datenow% - current date in format TT.MM.YY - %dateshnow% - current date in format TT.MM. - %timenow% - current time in format HH:MM The following variables can be used in the section : - %timer.date% - date of the timer - %timer.start% - start time of the timer - %timer.stop% - stop time of the timer - %timer.file% - recording directory of the timer - %timer.chnr% - channel number - %timer.chsh% - short channel name - %timer.chlng% - channel name - %timer.search% - name of the search timer, that created the timer - %timer.searchid% - id of the search timer, that created the timer - %timer.modreason% - the reason for a timer modification in plain text - %timer.liveid% - encoded timer ID as used in the frontend 'live' - any event variable (as in '10. Customizing the EPG menus') - any extended EPG variable as defined in epgsearchcats.conf - any user variable (as in '12. User defined variables') The following variables can be used in the section : - any event variable (as in '10. Customizing the EPG menus') - %search% - the name of the search timer that triggered this event - %searchid% - the ID of the corresponding search timer - any extended EPG variable as defined in epgsearchcats.conf - any user variable (as in '12. User defined variables') For a conflict notification mail the following sections exist: - "subject" to be used as mail subject - "mailbody" the body of the mail. Put %conflict.conflicts% in the place where the list of conflict times should appear (Note: there can be more than one timer conflict at the same time!). A conflict time uses the section 'conflictsat' to display its content. - "conflictsat" the description of one time where one or more conflicts exists. Put %conflict.confltimers% in the place where the list of conflict timers should appear. - "confltimer" the description of one conflicting timer The following variables can be used in the section : - %conflict.count% - complete number of timer conflicts - %conflict.conflicts% - list of times with conflicting timers The following variables can be used in the section : - %conflict.date% - date of the conflict - %conflict.time% - time of the conflict - %conflict.confltimers% - list of conflicting timers for this time The section can use the same variables as the section in an update mail (see above). =head1 14. The conf.d subdirectory epgsearch supports a configuration mechanism well-known in linux. The settings of the configuration files - epgsearchuservars.conf - epgsearchdirs.conf - epgsearchmenu.conf - epgsearchcats.conf can also be given in a file with arbitrary name in the subdirectory conf.d in /epgsearch. This allows one to quickly test different setups only by exchanging files instead of editing them. The format of these files is [
] ... [
] ... where is one of the following: - epgsearchuservars - epgsearchdirs - epgsearchmenu - epgsearchcats The format follows the one in the corresponding configuration file. Comments beginning with # are allowed, also blank lines. At startup epgsearch first reads its 'regular' configuration files and then the conf.d subdirectory. It's allowed to overwrite variables already defined in other files (although this is signaled with a warning in epgsearch's log file.). =head1 SEE ALSO C, C, C, C, C, C =head1 AUTHOR (man pages) Mike Constabel =head1 REPORT BUGS Bug reports (german): L Mailing list: L =head1 COPYRIGHT and LICENSE Copyright (C) 2004-2010 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch The MD5 code is derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm. vdr-plugin-epgsearch/doc-src/en/timersdone.conf.5.txt0000644000175000017500000000375013145412721022372 0ustar tobiastobias=head1 NAME F - list of current timers created by search timers =head1 DESCRIPTION This file contains the current timers that were created by search timers. If the setup option 'Recreate timers after deletion' is set to 'no', epgsearch uses this list to determine if a timer was already created and cancels further timer creations. If a corresponding recording was made for any timer in this list, the timer is automatically removed from it. =head1 FORMAT Timers are stored one per line, where the fields are separated with ':'. The following fields exists: 1 - channel-ID 2 - start time 3 - stop time 4 - search timer ID 5 - event title 6 - event episode =head1 SEE ALSO C =head1 AUTHOR (man pages) Mike Constabel =head1 REPORT BUGS Bug reports (german): L Mailing list: L =head1 COPYRIGHT and LICENSE Copyright (c) 2005-2006 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch The MD5 code is derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm. vdr-plugin-epgsearch/doc-src/en/epgsearchswitchtimers.conf.5.txt0000644000175000017500000000357213145412721024632 0ustar tobiastobias=head1 NAME F - The list of switchtimer =head1 DESCRIPTION In epgsearch switchtimer can be created via the program menu or the searchtimers. These switchtimer can switch the channel at the beginning of the event or only inform you about the start via OSD. The switchtimers are saved in this file. =head1 SYNTAX The delimiter is ':'. This fields are possible: 1 - Channel 2 - Event ID 3 - Start time 4 - Minutes to switch before event 5 - Only inform via OSD 6 - unmute sound if off =head1 EXAMPLE S19.2E-1-1089-12060:52221:1153322700:1:0 =head1 SEE ALSO C =head1 AUTHOR (man pages) Mike Constabel =head1 REPORT BUGS Bug reports (german): L Mailing list: L =head1 COPYRIGHT and LICENSE Copyright (C) 2004-2010 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch The MD5 code is derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm. vdr-plugin-epgsearch/doc-src/en/epgsearch.conf.5.txt0000644000175000017500000001324313145412721022160 0ustar tobiastobias=encoding utf8 =head1 NAME F - The searchtimers =head1 DESCRIPTION This file contains the searchtimers. Do not edit it manually, you should use SVDRP. =head1 SYNTAX Due to some new features there was a change in the format. The format is now signed with a comment in the first line. The field delimiter is B<':'>: 1 - unique search timer id 2 - the search term 3 - use time? 0/1 4 - start time in HHMM 5 - stop time in HHMM 6 - use channel? 0 = no, 1 = Interval, 2 = Channel group, 3 = FTA only 7 - if 'use channel' = 1 then channel id[|channel id] in VDR format, one entry or min/max entry separated with |, if 'use channel' = 2 then the channel group name 8 - match case? 0/1 9 - search mode: 0 - the whole term must appear as substring 1 - all single terms (delimiters are blank,',', ';', '|' or '~') must exist as substrings. 2 - at least one term (delimiters are blank, ',', ';', '|' or '~') must exist as substring. 3 - matches exactly 4 - regular expression 10 - use title? 0/1 11 - use subtitle? 0/1 12 - use description? 0/1 13 - use duration? 0/1 14 - min duration in hhmm 15 - max duration in hhmm 16 - use as search timer? 0/1 17 - use day of week? 0/1 18 - day of week (0 = Sunday, 1 = Monday...; -1 Sunday, -2 Monday, -4 Tuesday, ...; -7 Sun, Mon, Tue) 19 - use series recording? 0/1 20 - directory for recording 21 - priority of recording 22 - lifetime of recording 23 - time margin for start in minutes 24 - time margin for stop in minutes 25 - use VPS? 0/1 26 - action: 0 = create a timer 1 = announce only via OSD (no timer) 2 = switch only (no timer) 3 = announce via OSD and switch (no timer) 4 = announce via mail 27 - use extended EPG info? 0/1 28 - extended EPG info values. This entry has the following format (delimiter is '|' for each category, '#' separates id and value): 1 - the id of the extended EPG info category as specified in epgsearchcats.conf 2 - the value of the extended EPG info category (a ':' will be translated to "!^colon^!", e.g. in "16:9") 29 - avoid repeats? 0/1 30 - allowed repeats 31 - compare title when testing for a repeat? 0/1 32 - compare subtitle when testing for a repeat? 0/1/2 0 - no 1 - yes 2 - yes, if present 33 - compare description when testing for a repeat? 0/1 34 - compare extended EPG info when testing for a repeat? This entry is a bit field of the category IDs. 35 - accepts repeats only within x days 36 - delete a recording automatically after x days 37 - but keep this number of recordings anyway 38 - minutes before switch (if action = 2) 39 - pause if x recordings already exist 40 - blacklist usage mode (0 none, 1 selection, 2 all) 41 - selected blacklist IDs separated with '|' 42 - fuzzy tolerance value for fuzzy searching 43 - use this search in favorites menu (0 no, 1 yes) 44 - id of a menu search template 45 - auto deletion mode (0 don't delete search timer, 1 delete after given count of recordings, 2 delete after given days after first recording) 46 - count of recordings after which to delete the search timer 47 - count of days after the first recording after which to delete the search timer 48 - first day where the search timer is active (see parameter 16) 49 - last day where the search timer is active (see parameter 16) 50 - ignore missing EPG categories? 0/1 51 - unmute sound if off when used as switch timer 52 - percentage of match when comparing the summary of two events (with 'avoid repeats') 53 - HEX representation of the content descriptors, each descriptor ID is represented with 2 chars 54 - compare date when testing for a repeat? (0=no, 1=same day, 2=same week, 3=same month) A ':' in the search term or the directory entry will be translated in a '|'. If a '|' exists in the search term, e.g. when using regular expressions, it will be translated to "!^pipe^!" (I know it's ugly ;-)) There's no need to fill all fields, only the first 11 fields must exist. =head1 EXAMPLE #version 2 - DON'T TOUCH THIS! 1:Kommissar Beck:0:::2:ffRecht:0:0:1:0:0:0:::1:0:0:1:%Category%~%Genre%:50:99:10:60:0:0:0::1:0:1:1:0:0:0:0:0 2:* Sgebrecht:0:::2:Hauptsender:0:0:0:0:0:0:::0:0:0:0:%Category%~%Genre%:50:99:10:10:0:0:1:1#|2#|3#|4#|5#|6#Marianne Sgebrecht|7#|8#|9#|10#|11#|12#|13#:1:0:1:0:0:0:0:0:0 =head1 SEE ALSO C =head1 AUTHOR (man pages) Mike Constabel =head1 REPORT BUGS Bug reports (german): L Mailing list: L =head1 COPYRIGHT and LICENSE Copyright (C) 2004-2010 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch The MD5 code is derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm. vdr-plugin-epgsearch/doc-src/en/epgsearchblacklists.conf.5.txt0000644000175000017500000000417213145412721024235 0ustar tobiastobias=head1 NAME F - Blacklist =head1 DESCRIPTION You can create blacklists in epgsearch and use them in searchtimers. A blacklist entry is like a normal searchtimer which is saved in the file F. While editing an searchtimer you can select one ore more blacklist entries. =head2 USAGE Searchtimer "Action" use blacklist "Damme". Blacklist entry "Damme" searches "Damme" First the searchtimer searches all films with "Action". Then for each search result epgsearch will test if the result matches against "Damme". If so, the result will be dismissed. =head1 SYNTAX This file uses the same syntax as F except that theres no field. So there's a shift by one field from this position. Because that, see C. =head1 SEE ALSO C, C =head1 AUTHOR (man pages) Mike Constabel =head1 REPORT BUGS Bug reports (german): L Mailing list: L =head1 COPYRIGHT and LICENSE Copyright (C) 2004-2010 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch The MD5 code is derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm. vdr-plugin-epgsearch/doc-src/en/epgsearchcmds.conf.5.txt0000644000175000017500000000415413145412721023030 0ustar tobiastobias=head1 NAME F - EPG Commands =head1 DESCRIPTION This file contains commands, like the file commands.conf or reccmds.conf, which can be applied to the selected event in one of the EPG menues. (It does not support the nested commands as introduced in vdr-1.7.12) Internal epgsearch has 8 not changeable commands. If there is a F, the commands in it will be appended to the list of the internal commands, starting with 9. =head2 Language You can use different files for each language. For example F will be loaded if the, in VDR selected, language is english. If there is no file for the selected language, epgsearch tries to load F. =head1 SYNTAX Description : Command =head1 EXAMPLE epg2taste (de): /usr/local/vdr/epg2taste.sh =head1 SEE ALSO C =head1 AUTHOR (man pages) Mike Constabel =head1 REPORT BUGS Bug reports (german): L Mailing list: L =head1 COPYRIGHT and LICENSE Copyright (C) 2004-2010 Christian Wieninger This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html The author can be reached at cwieninger@gmx.de The project's page is at http://winni.vdr-developer.org/epgsearch The MD5 code is derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm. vdr-plugin-epgsearch/doc-src/en/epgsearch.1.txt0000644000175000017500000011553213145412721021234 0ustar tobiastobias=head1 NAME F - Searchtimer and replacement of the VDR program menu =head1 OVERVIEW EPG-Search can be used as a replacement for the default schedules menu entry. It looks like the standard schedules menu, but adds some additional functions: - Commands for EPG entries with 5 built-in commands like 'show repeats', 'create search'. One can add own commands for other needs, like adding a VDRAdmin auto-timer. - Add up to 4 user-defined times to 'now' and 'next' and an optional favorites menu - Searching the EPG: Create reusable queries, which can also be used as 'search timers'. - Search timers: Search for broadcasts in the background and add a timer if one matches (similar to VDRAdmin's auto-timers) or simply make an announcement about it via OSD - Avoid double recordings of the same event * timer preview * recognition of broken recordings * fuzzy event comparison - Progress bar in 'What's on now' and 'What's on next' - Shift the time displayed by key press, e.g. 'What's on now' + 30 minutes - Start menu can be setup between 'Schedule' or 'What's on now' - background check for timer conflicts with a timer conflict manager - detailed EPG menu (summary) allows jumping to the next/previous event - support for extended EPG info for search timers - extension of the timer edit menu with a directory item, user defined weekday selection and a subtitle completion. - Timer conflict check, informs you over the OSD about conflicts - Timer conflict menu, show detailed information about the conflicts and let you resolve them - Email notifications about search timer updates and timer conflicts Parts of the sources are based on the repeating-ECG patch from Gerhard Steiner, who gave me the permission to use them. Thanks for his work! =head1 OPTIONS =over 4 =item -f file, --svdrpsendcmd=file the path to svdrpsend for external SVDRP communication (default is internal communication, so this is usually not needed anymore) =item -c path, --config=path to specify a specific config directory for all epgsearch config files, default is '/epgsearch' =item -l file, --logfile=file to specify a specific log file for epgsearch (default log file is epgsearch.log in the epgsearch config directory) =item -v n, --verbose=n verbose level for log file. Value 0 means no logging. Other values are 1 (general messages), 2 (detailed messages), 3 (planned for extra detailed info for debugging purposes) =item -r, --reloadmenuconf reload epgsearchmenu.conf with plugin call. This can be useful when testing customized menu layouts. =item -m file, --mailcmd=file the external command to be used for mail delivery. The default uses 'sendEmail.pl'. If you are using a different command or script make sure that it has the same parameter interface as sendEmail.pl. =back =head1 CONTENT 1. Description 1.1 Menu commands 1.2 Menu search 1.2.1 Menu edit search 1.2.2 Menu search results 1.3 Extended 'now' and 'next' 1.4 Menu setup 2. Search timers 2.1 'Avoid repeats' - internals 2.2 How do we compare two events? 2.3 How and when do we compare? 3. Usage from other plugins or scripts 4. Using extended EPG info 5. Replacing the standard schedule menu 6. Add-ons =head1 1. Description At first glance EPG-Search looks like the schedules menu entry of VDR. By pressing the key '0', one can toggle the bottom color keys to access additional functions (the default assignment of the color keys can be adjusted by setup): =head2 1.1 Menu Commands This menu displays commands that can be executed on the current item. There are 8 built-in commands: - Repeats: Searches for repeats - Record - Switch - Create search Switches to search menu and adds a new search with the name of the current item (to avoid editing the name manually) - Search in recordings: Search the recordings for a broadcast with the same name - Mark as 'already recorded': This puts the selected event in the file epgsearchdone.data and instructs epgsearch to avoid recording this event if an according search timer is set to "avoid repeats". An already created timer will be automatically removed with the next search timer update. - Add/Remove to/from switch list?: Controls the switch list. If there is an event in the switch list, epgsearch will announce it and switch to the event before it starts. To access the complete switch list, call 'Search/Actions/Switch list'. - Create blacklist: A blacklist is used to ignore events when using search timers. A search timer can be setup to ignore events from arbitrary blacklists. You can add your own commands to this menu by editing the file epgsearchcmds.conf in the epgsearch config directory. There's a sample conf file with some sample commands (see directory 'scripts', taken from vdr-wiki.de, thanks to the authors). The format of the file is the same as VDR's commands.conf or reccmds.conf. When a command is executed the following parameters are passed to it: $1: the title of the EPG entry $2: the start time of the EPG entry as time_t value (like in the shutdown script) $3: the end time $4: the channel number of the EPG entry $5: the long channel name of the EPG entry $6: the subtitle of the EPG entry, "" if not present To execute a command from the main menu you can also press its associated number without opening the commands menu. =head2 1.2 Menu search Here you can add, edit, delete and execute your own queries on the EPG. The usage and behavior of this menu is similar to VDR's timer menu. =head3 1.2.1 Menu edit search Most things in this menu are quite clear, so only some notes on: =over 4 =item - B The term to search for. If you like to search for more words, separate them by blanks. Leaving this empty (combined with search mode 'Phrase') will match anything. This is useful, if you search e.g. for anything that starts between some times on a specific channel. With 'blue' you can also select a template for the new search. If one of the templates is set to default, new searches will automatically get the settings of the default template. Note: fuzzy searching is limited to 32 chars! =item - B 'Phrase' searches for the expression within the EPG. 'All words' requires, that each word of the expression occurs in the EPG item. 'at least one word' requires, that only one word occurs in the EPG item. 'Match exactly' requires, that your search term matches exactly the found title, subtitle or description. With 'Regular expression' you can setup a regular expression as search term. You don't need a leading and trailing '/' in the expression. By default these are POSIX extended regular expressions. If you like to have Herl compatible regular expression, simply edit the plugins Makefile and uncomment '#REGEXLIB = pcre' to 'REGEXLIB = pcre' (you will need pcreposix installed, comes with libpcre from www.pcre.org, but it's already part of most distributions). See also C 'Description of the search process'. =item - B Some providers deliver content descriptors in their EPG, like "Movie/Drama", "Documentation",...(available with vdr-1.7.11) Select here the descriptors to search for. Multiple choice is possible, that must match with all given descriptors (AND operator). =item - B Only available if configured, see below 'Using extended EPG info'. =item - B If set to 'Yes' this tells epgsearch that a missing EPG category should not exclude an event from the results. Caution: Using this without any other criterions could flood your timers. =item - B Search only for events in the given channels interval, channel groups or FTA channels only. Channel groups (e.g. sport channels or Pay-TV channels) can be managed with a sub-menu called with 'blue'. ATTENTION: After changing the channels order please check the settings of your search timers! =item - B Besides the weekdays you can also set up a user-defined selection, e.g. search only on Monday and Friday. You'll find the user-defined selection in the list after Friday. =item - B Blacklists are a way to exclude unwanted events. Select only global, one, more or all blacklists here. If any search result is also contained in one of the selected blacklists it will be skipped. =item - B Only available if turned on in setup. With this option you can mark a search to be used in the favorites menu. The search results of all these searches are listed in the favorites menu. =item - B Only available if you have defined more than one menu template for search results in epgsearchmenu.conf. This option is used to assign a different menu layout for the search results of this search. =item - B If set to yes, the plugin will do a background scan of the EPG in certain intervals and add a timer, if there is a match. You have to activate the 'search timers' in the setup. If set to "user defined" one can specify time margins with key 'blue' where the search timer is active or not. =item - B Default action is creating a timer for the search results. But you can also choose to simply announce the found event via OSD as soon as it is found or to automatically switch to the event before it starts. It's also possible to get an announcement via OSD before the event starts and to switch to its channel with 'Ok'. =item - B If set to yes, the recordings will be stored in a folder with the name of the broadcasting and the recordings itself will have the name of the episode. If there is no episode name, the date and time of the recording will be used. =item - B Here you can assign a directory, where the recording should be stored, e.g. 'SciFi'. Use the key 'blue' to select directory entries already used in other search entries or given by entries in the file epgsearchdirs.conf (simply place your directories here one at each line without the leading video directory, also see MANUAL). If your provider delivers extended EPG infos you can also use variables like "%Genre%" or "%Category%" in your directory entry. These are replaced with the current EPG info, when a timer is created. See also C 'Using variables in the directory entry of a search timer'. =item - B Some recordings should only be kept for a few days, like news. With this feature you can tell epgsearch to delete them automatically after ... days. =item - B If the given numbers of recordings currently exists, then epgsearch will not create further timers. After deleting one or more recordings it will go on generating new timers. =item - B If you don't want to record repeats, this feature tries to check if an event was already recorded/programmed and skips it. Please refer to the section 'Avoid repeats - internals' below before using it. =item - B If you like to accept a certain amount of repeats you can give here their number. =item - B Give here the number of days a repeat has to follow its first broadcast. 0 is equal to no restriction. =item - B When comparing to events then specify here if the title should be compared. =item - B When comparing to events then specify here if the subtitle should be compared. With 'if present' epgsearch will classify two events only as equal if their episode names match and are not empty. =item - B When comparing to events then specify here if the description should be compared. For comparison all parts of the description, that look like a category value, are removed first. The remaining text will be compared. If this is similar at the value of the next option (regarding the Levinshtein-Distance algorithm) then it will be accepted as equal. =item - C The needed minimum match of descriptions in percent. =item - B Sometimes an event is repeated many times within some period (day, week, month,...), but one cannot distinguish the repeats based on the EPG contents. So the only information is its time. To use this for comparison select the appropriate period. =item - B With the button 'setup' you can also specify which categories should be compared. As with subtitles an event is different if it has no according category value. =item - B Each search timer can have its own settings for these parameters. Defaults can be adjusted in the plugins setup. =item - B If set to yes, VPS is used, but only, if activated in VDR's setup menu and if the broadcasting has VPS information. =item - B to automatically delete a search timer if the following is true: * after x recordings, or * after x days after the first recording Only complete recordings are counted. The deletion is executed directly after the correspondig recording =back To toggle the flag 'Use as search timer' without editing the search entry you can use the key '2'. This will call directly the second command of the command menu. =head3 1.2.2 Menu search results This menu displays the search results. A 'T' lets you know, that there is already a timer for the event. A 't' means that there's only a partial timer for it, as in standard schedules menu. =head2 1.3 Extended 'now' and 'next' and favorites By setup, one can add up to 4 additional times to extend the green button, e.g. 'afternoon', 'prime time', 'late night'. Times, that are already passed, are skipped (you will not get 'afternoon' at evening) with the exception that a time will be displayed for the next day, if it is less then 20h in the future. In these menus you can shift the currently displayed time by pressing FastRew or FastFwd to move back and forward in time. If you don't have these keys on your remote, you can access this function by pressing '0' to toggle the green and yellow button to '<<' and '>>'. This toggling can be adjusted by setup. You can display a progress bar in 'now' and 'next'. Furthermore you can enable in the setup an favorites list. You can configure your searchtimers ("Use in favorite list") to display their results in you favorite list. This list display event in the next 24 hours ordered by time. =head2 1.4 Menu setup =head3 1.4.1 General =over 4 =item - B This hides the main menu entry 'search'. Attention: when the plugin is assigned to key 'green' then hiding the plugin will give you VDR's standard schedule menu (see below to avoid this). =item - B
If not hidden, the name of main menu entry can be set here. Default is 'Program guide'. Note: If you set it to something different from the default then the main menu entry is no longer dependent on the OSD language. Setting it back to default or empty restores this behavior again. =item - B Select the starting menu 'Schedules' or 'Now' =back =head3 1.4.2 EPG menus =over 4 =item - B Choose here the behavior of key 'Ok'. You can use it to display the summary or to switch to the corresponding channel. Note: the functionality of key 'blue' (Switch/Info/Search) depends on this setting. =item - B Select if you like to have Standard ('Record') or 'Commands' as assignment for key 'red'. =item - B select if you like to have Standard ('Switch') or 'Search' as assignment for key 'blue'. =item - B In the menu 'what's on now' you can display a progress bar, that displays the progress of the current item. =item - B Select this if you like to have a leading channel number before each item in the EPG menus. =item - B Display channel group separators between channel in the menus 'Overview now',... =item - B Display a day separator between events on different days in the schedule menu. =item - B Also list radio channels. =item - B If you have a large channel set you can speed up things when you limit the displayed channels with this setting. Use '0' to disable the limit. If the current channel is above the limit, the limit is ignored and all channels will be displayed again. =item - B<'One press' timer creation:> If set to 'yes' a timer is immediately created when pressing 'Record', else the timer edit menu is displayed. =item - B Display channels without EPG to allow switching or create a timer. =item - B