diff options
author | Martin Prochnow <nordlicht@martins-kabuff.de> | 2007-02-04 23:31:11 +0100 |
---|---|---|
committer | Andreas Mair <andreas@vdr-developer.org> | 2007-02-04 23:31:11 +0100 |
commit | 8adfaaf81b104b8e981026da593e40f9d780c251 (patch) | |
tree | 0a72c71d85e1d5bbac8729cefa9e41ec9e58758b | |
parent | 074a396ce9f5c5239dd790c6566e0f19dff45f59 (diff) | |
download | vdr-plugin-extrecmenu-8adfaaf81b104b8e981026da593e40f9d780c251.tar.gz vdr-plugin-extrecmenu-8adfaaf81b104b8e981026da593e40f9d780c251.tar.bz2 |
Version 0.13v0.13
- added two setup option to adjust the plugin behaviour to whose of VDR's recording menu (jumping to last replayed recording, call plugin after replay ends)
- only editing of cutting recordings is prevented now
- moving recordings between filesystems is now possible; includes:
* check for enough free disk space on target filesystem
* switch to limit bandwith (a.t.m. 2MBytes/sec)
* prevent editing of recordings that are moved
* marker for recordings, that are moved
- added marker for cutting and moving recording entries
- added marker to title bar for cutting and moving recordings
- recording info menu shows additional informations (name, path, channel, size, lifetime, priority)
- added setup option to select between plugin's and VDR's recording info menu
- dvd.vdr is ignored, as long as a 001.vdr is present
- fixed following issue (again): if there are more then one recording with the same name, only one of it is shown if all recording details are hidden
-rw-r--r-- | HISTORY | 21 | ||||
-rw-r--r-- | README | 36 | ||||
-rw-r--r-- | extrecmenu.c | 21 | ||||
-rw-r--r-- | i18n.c | 232 | ||||
-rw-r--r-- | i18n.c.orig | 1087 | ||||
-rw-r--r-- | mymenueditrecording.c | 304 | ||||
-rw-r--r-- | mymenurecordings.c | 723 | ||||
-rw-r--r-- | mymenurecordings.h | 35 | ||||
-rw-r--r-- | mymenusetup.c | 16 | ||||
-rw-r--r-- | mymenusetup.h | 8 | ||||
-rw-r--r-- | myreplaycontrol.c | 25 | ||||
-rw-r--r-- | myreplaycontrol.h | 4 | ||||
-rw-r--r-- | patchfont.c | 98 | ||||
-rw-r--r-- | tools.c | 329 | ||||
-rw-r--r-- | tools.h | 65 |
15 files changed, 2424 insertions, 580 deletions
@@ -1,6 +1,25 @@ VDR Plugin 'extrecmenu' Revision History ---------------------------------------- +2007-01-??: Version 0.13 +- added two setup option to adjust the plugin behaviour to whose of VDR's + recording menu (jumping to last replayed recording, call plugin after + replay ends) +- only editing of cutting recordings is prevented now +- moving recordings between filesystems is now possible; includes: + * check for enough free disk space on target filesystem + * switch to limit bandwith (a.t.m. 2MBytes/sec) + * prevent editing of recordings that are moved + * marker for recordings, that are moved +- added marker for cutting and moving recording entries +- added marker to title bar for cutting and moving recordings +- recording info menu shows additional informations (name, path, channel, + size, lifetime, priority) +- added setup option to select between plugin's and VDR's recording info menu +- dvd.vdr is ignored, as long as a 001.vdr is present +- fixed following issue (again): if there are more then one recording with the + same name, only one of it is shown if all recording details are hidden + 2006-12-31: Version 0.12c - dvd id for archive dvd would be first read out when the corresponding entry is selected; this should prevent delays while opening the plugin @@ -59,7 +78,7 @@ VDR Plugin 'extrecmenu' Revision History - 'Play' and 'Menu'->'Blue' for resuming a replay work now; BUT: the replay isn't done with the plugin if you start replaying this way, means if you stop the replay you come to VDR's recordings menu -- switched off editing of details (priority and lifetime) or archive dvd +- switched off editing of details (priority and lifetime) of archive dvd recordings to avoid trouble with the dir name that identifies it on the media - added option to mark last replayed recording while opening the plugin - added possibilty to include video dvds into the recordings hierarchy; see @@ -1,6 +1,7 @@ This is a "plugin" for the Video Disk Recorder (VDR). + Written by: Martin Prochnow (nordlicht@martins-kabuff.de) -Project's homepage: http://martins-kabuff.de/extrecmenu.html +Project's homepage: http://martins-kabuff.de/extrecmenu_en.html See the file COPYING for license information. See top of *.c for additional copyright information. @@ -14,13 +15,23 @@ I want to thank to following contributors: ------------------------------------------------------------------------------- Description ------------------------------------------------------------------------------- -This plugin provides a recordings menu enhanced with the possibility to -rename or move recordings and directories. The display of recording date, time -and length is configurable. Sorting by name or date is selectable for each -directory. If you use the PIN-plugin, the replay and editing of recordings is -protected. The plugin also handles archive dvds of VDR recordings (as known -from the DVDArchive-patch for VDR). This plugin extends VDR's '-r'-option with -messages for deleting, moving and renaming a recording. +The EXTended RECordings MENU plugin provides additional functions to VDR's +recordings menu: + +* renaming recordings and directories +* moving recordings and directories, also between different filesystems +* functionality of the DVDArchiv-patch (see below) +* adjustable display of recording's length, date and size +* directories are always shown on top of the list +* reworked layout using icons for showing the status of list entries + (directory, new recording, moving recording, cutting recording, dvd archiv + entry) +* sorting by name or date, adjustable for each directory +* ascending/descending sorting +* extends VDR's '-r'-option commands with 'move' and 'rename' +* extended recordings info menu, shows name, path, channel, size, lifetime and + priority of the recording +* protects recordings in co-work with the PIN-plugin ------------------------------------------------------------------------------- Installation @@ -56,7 +67,9 @@ renaming will be executed. Moving: Press 'Yellow', then 'Green'. Now you are at the base directory of the /video-directory-hierarchy. 'Ok' opens sub-directories, with 'Yellow' you can -create new dirs. With 'Blue' moving to the selected dir will be executed. +create new dirs. With 'Blue' moving to the selected dir will be executed. At +the moment it is only possible to move one recording or directory to another +filesystem. Details: Select a recording, press 'Yellow', then 'Blue'. In this menu you can edit the lifetime and priority of the selected recording. Editing the details @@ -66,7 +79,8 @@ which the recording is found on the disc. Sort recordings ------------------------------------------------------------------------------- All directories are sorted by date by default. To change the sorting, simply -press '0'. +press '0'. Ascending or descending sorting is selectable at plugin's setup +menu. ------------------------------------------------------------------------------- Archiv-DVD-functionality @@ -102,5 +116,5 @@ is started to play the video dvd. ------------------------------------------------------------------------------- Do you like this plugin? Support the developer! Go to the project homepage and -make a donation over the PayPal donation button. +make a donation over the PayPal button. ------------------------------------------------------------------------------- diff --git a/extrecmenu.c b/extrecmenu.c index 87c0321..0b900a8 100644 --- a/extrecmenu.c +++ b/extrecmenu.c @@ -2,13 +2,16 @@ * See the README file for copyright information and how to reach the author. */ +#include <string> #include <vdr/plugin.h> #include "mymenusetup.h" #include "mymenurecordings.h" #include "i18n.h" #include "tools.h" -static const char *VERSION = "0.12c"; +using namespace std; + +static const char *VERSION = "0.13"; static const char *DESCRIPTION = "Extended recordings menu"; static const char *MAINMENUENTRY = "ExtRecMenu"; @@ -29,6 +32,7 @@ class cPluginExtrecmenu:public cPlugin virtual bool Start(void); virtual void Stop(void); virtual void Housekeeping(void); + virtual cString Active(void); virtual const char *MainMenuEntry(void){return mysetup.HideMainMenuEntry?NULL:MAINMENUENTRY;} virtual cOsdObject *MainMenuAction(void); virtual cMenuSetupPage *SetupMenu(void); @@ -80,6 +84,13 @@ void cPluginExtrecmenu::Housekeeping(void) { } +cString cPluginExtrecmenu::Active(void) +{ + if(MoveThread.Active()) + return tr("Move recordings in progress"); + return NULL; +} + cOsdObject *cPluginExtrecmenu::MainMenuAction(void) { return new myMenuRecordings(); @@ -111,6 +122,14 @@ bool cPluginExtrecmenu::SetupParse(const char *Name,const char *Value) mysetup.ShowNewRecs=atoi(Value); else if(!strcasecmp(Name,"DescendSorting")) mysetup.DescendSorting=atoi(Value); + else if(!strcasecmp(Name,"GoLastReplayed")) + mysetup.GoLastReplayed=atoi(Value); + else if(!strcasecmp(Name,"ReturnToPlugin")) + mysetup.ReturnToPlugin=atoi(Value); + else if(!strcasecmp(Name,"LimitBandwidth")) + mysetup.LimitBandwidth=atoi(Value); + else if(!strcasecmp(Name,"UseVDRsRecInfoMenu")) + mysetup.UseVDRsRecInfoMenu=atoi(Value); else return false; return true; @@ -55,6 +55,7 @@ const tI18nPhrase Phrases[] = { "", "", "", + "Retour", "", "", "", @@ -68,8 +69,7 @@ const tI18nPhrase Phrases[] = { "", "", "", - "", - "", + "Zpět", }, { "Button$Cancel", "Abbrechen", @@ -451,7 +451,7 @@ const tI18nPhrase Phrases[] = { "", "", "", - "", + "Afficher les nouveaux symbols alternatifs", "", "Merkitse uudet tallenteet symbolilla", "", @@ -627,7 +627,7 @@ const tI18nPhrase Phrases[] = { "", "", "", - "", + "Erreur sudo ou mount --bind / umount (Systeme VFAT)", "", "Sudo tai mount --bind / umount -komento epäonnistui (VFAT)!", "", @@ -709,15 +709,15 @@ const tI18nPhrase Phrases[] = { "", "Přejmenování/Přesun selhal!", }, - { "Creating directories failed!", - "Verzeichnisse anlegen fehlgeschlagen!", + { "Invalid filename!", + "Ungültiger Dateiname!", "", "", "", "", - "Echecs lors de la création du dossier!", + "Nom de fichiers n'est pas valide'", "", - "Hakemiston luonti epäonnistui!", + "Virheellinen tiedoston nimi!", "", "", "", @@ -729,17 +729,17 @@ const tI18nPhrase Phrases[] = { "", "", "", - "Selhalo vytvoření adresáře!", + "Chybné jméno souboru!", }, - { "Invalid filename!", - "Ungültiger Dateiname!", + { "Moving into own sub-directory not allowed!", + "Verschieben in eigenes Unterverzeichnis nicht erlaubt!", "", "", "", "", - "Nom de fichiers n'est pas valide'", + "Déplacer dans le sous-dossier propre, n'est pas possible!", "", - "Virheellinen tiedoston nimi!", + "Siirto omaan alihakemistoon ei ole sallittu!", "", "", "", @@ -751,17 +751,17 @@ const tI18nPhrase Phrases[] = { "", "", "", - "Chybné jméno souboru!", + "Přesun do vlastního podadresáře není povolen!", }, - { "Editing not allowed while cutting!", - "Editieren während des Schneidens nicht erlaubt!", + { "Sort by name", + "Sortieren nach Namen", "", "", "", "", - "Editer pendant la découpe n'est pas possible!", + "Triage selon le nom", "", - "Muokkaus leikkauksen aikana ei ole sallittu!", + "Tallenteet järjestetään nimen mukaan", "", "", "", @@ -773,17 +773,17 @@ const tI18nPhrase Phrases[] = { "", "", "", - "Je spuštěn střih - Editovat nyní nelze!", + "Třídit podle jména", }, - { "Moving into own sub-directory not allowed!", - "Verschieben in eigenes Unterverzeichnis nicht erlaubt!", + { "Sort by date", + "Sortieren nach Datum", "", "", "", "", - "Déplacer dans le sous-dossier propre, n'est pas possible!", + "Triage selon date", "", - "Siirto omaan alihakemistoon ei ole sallittu!", + "Tallenteet järjestetään päivämäärän mukaan", "", "", "", @@ -795,22 +795,41 @@ const tI18nPhrase Phrases[] = { "", "", "", - "Přesun do vlastního podadresáře není povolen!", + "Třídit podle data", }, - { "Sort by name", - "Sortieren nach Namen", + { "Show nr. of new recordings in a directory", + "Anzahl der neuen Aufz. im Ordner anzeigen", + "", + "", + "", + "", + "Afficher le nombre de nouveaux enregistrements dans les dossiers", + "", + "Näytä uusien tallenteiden lukumäärä", "", "", "", "", "", "", - "Tallenteet järjestetään nimen mukaan", "", "", "", "", "", + "Zobrazovat počet nových nahrávek v adresáři", + }, + { "Sorting", + "Sortierung", + "", + "", + "", + "", + "Triage", + "", + "Järjestys", + "", + "", "", "", "", @@ -818,16 +837,23 @@ const tI18nPhrase Phrases[] = { "", "", "", + "", + "", + "Třídění", }, - { "Sort by date", - "Sortieren nach Datum", + { "ascending", + "aufsteigend", "", "", "", "", + "montant", + "", + "nouseva", + "", + "", "", "", - "Tallenteet järjestetään päivämäärän mukaan", "", "", "", @@ -835,21 +861,42 @@ const tI18nPhrase Phrases[] = { "", "", "", + "vzestupně", + }, + { "descending", + "absteigend", + "", + "", + "", + "", + "descendant", + "", + "laskeva", + "", + "", "", "", "", "", "", + "", + "", + "", + "", + "sestupně", }, - { "Show nr. of new recordings in a directory", - "Anzahl der neuen Aufn. im Ordners anzeigen", + { "Jump to last replayed recording", + "Springe zur zuletzt abgespielten Aufzeichnung", "", "", "", "", + "Retour au dernier enregistrement lu", + "", + "Siirry viimeksi toistettuun tallenteeseen", + "", "", "", - "Näytä uusien tallenteiden lukumäärä", "", "", "", @@ -858,13 +905,41 @@ const tI18nPhrase Phrases[] = { "", "", "", + "Skočit na poslední přehrávanou nahrávku", + }, + { "Call plugin after playback", + "Nach Wiedergabe Plugin aufrufen", + "", "", "", "", + "Aprčs la lecture démarer le plugin", "", + "Avaa laajennos toiston loputtua", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "Návrat do modulu po ukončení přehrávání", }, - { "Sorting", - "Sortierung", + { "Move recordings already in progress!", + "Es werden schon Aufzeichnungen verschoben!", + "", + "", + "", + "", + "Des enregistrements sont déjŕ en déplacement!", + "", + "Tallenteiden siirto on jo käynnissä!", + "", + "", "", "", "", @@ -874,7 +949,17 @@ const tI18nPhrase Phrases[] = { "", "", "", + "Právě probíhá přesouvání nahrávek!", + }, + { "Move recordings in progress", + "Es werden Aufzeichungen verschoben", + "", + "", + "", + "", + "Enregistrements en cours de déplacement", "", + "Tallenteiden siirto käynnissä", "", "", "", @@ -884,13 +969,19 @@ const tI18nPhrase Phrases[] = { "", "", "", + "", + "", + "Probíhá přesouvání nahrávek", }, - { "ascending", - "aufsteigend", + { "Limit bandwidth for move recordings", + "Bandbreite beim Verschieben begrenzen", + "", "", "", "", + "Limiter la bande passante lors du déplacement", "", + "Rajoita tallenteiden siirtokaistaa", "", "", "", @@ -902,13 +993,76 @@ const tI18nPhrase Phrases[] = { "", "", "", + "Omezit rychlost pro přesun nahrávek", + }, + { "Target filesystem filled- try anyway?", + "Zielpartition voll - trotzdem versuchen?", + "", + "", + "", + "", + "La partition de déstination est pleine - essayer tout de męme?", + "", + "Kohdepartitio täynnä - yritetäänkö silti?", + "", + "", + "", + "", "", "", "", "", + "", + "", + "", + "Cílový oddíl je plný - zkusit znovu?", }, - { "descending", - "absteigend", + { "Path", + "Pfad", + "", + "", + "", + "", + "Chemin", + "", + "Polku", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "Cesta", + }, + { "Size", + "Größe", + "", + "", + "", + "", + "Taille", + "", + "Koko", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "Velikost", + }, + { "Use VDR's recording info menu", + "VDR-Aufz.-Info-Menü benutzen", "", "", "", diff --git a/i18n.c.orig b/i18n.c.orig new file mode 100644 index 0000000..bdf130f --- /dev/null +++ b/i18n.c.orig @@ -0,0 +1,1087 @@ +/* + * See the README file for copyright information and how to reach the author. + */ + +#include "i18n.h" + +const tI18nPhrase Phrases[] = { + { "Extended recordings menu", + "Erweitertes Aufzeichnungs-Menü", + "", + "", + "", + "", + "Menu enregistrement étandu", + "", + "Laajennettu tallennevalikko", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "Rozšířené menu nahrávek", + }, + { "Button$Open", + "Öffnen", + "", + "", + "", + "", + "Ouvrir", + "", + "Avaa", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "Otevřít", + }, + { "Button$Back", + "Zurück", + "", + "", + "", + "", + "Retour", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + }, + { "Button$Cancel", + "Abbrechen", + "", + "", + "", + "", + "Interrompre", + "", + "Peruuta", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "Zrušit", + }, + { "Button$Play", + "Wiedergabe", + "", + "", + "", + "", + "Montrer", + "", + "Toista", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "Přehrát", + }, + { "Button$Commands", + "Befehle", + "", + "", + "", + "", + "Commande", + "", + "Komennot", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "Příkazy", + }, + { "Button$Rewind", + "Anfang", + "", + "", + "", + "", + "Début", + "", + "Alkuun", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "Na začátek", + }, + { "Button$Create", + "Anlegen", + "", + "", + "", + "", + "Créer", + "", + "Luo", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "Vytvořit", + }, + { "Button$Edit", + "Editieren", + "", + "", + "", + "", + "Éditer", + "", + "Muokkaa", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "Editovat", + }, + { "Button$Rename", + "Umbenennen", + "", + "", + "", + "", + "Renommer", + "", + "Nimeä", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "Přejmenovat", + }, + { "Button$Move", + "Verschieben", + "", + "", + "", + "", + "Déplacer", + "", + "Siirrä", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "Přesunout", + }, + { "Button$Delete", + "Löschen", + "", + "", + "", + "", + "Effacer", + "", + "Poista", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "Smazat", + }, + { "Button$Info", + "Info", + "", + "", + "", + "", + "Info", + "", + "Tiedot", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "Info", + }, + { "New folder", + "Neues Verzeichnis", + "", + "", + "", + "", + "Nouveau dossier", + "", + "Uusi kansio", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "Nový adresář", + }, + { "Rename", + "Umbenennen", + "", + "", + "", + "", + "Renommer", + "", + "Nimeä", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "Přejmenovat", + }, + { "Show recording date", + "Aufnahmedatum anzeigen", + "", + "", + "", + "", + "Afiicher la date d'enregistrement", + "", + "Näytä tallenteen päiväys", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "Zobrazit datum nahrávky", + }, + { "Show recording time", + "Aufnahmezeit anzeigen", + "", + "", + "", + "", + "Afficher l'heure d'enregistrement", + "", + "Näytä tallenteen ajankohta", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "Zobrazit čas nahrávky", + }, + { "Show recording length", + "Aufnahmelänge anzeigen", + "", + "", + "", + "", + "Afficher la longeur de l'enregistrement", + "", + "Näytä tallenteen kesto", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "Zobrazit délku nahrávky", + }, + { "Hide main menu entry", + "Hauptmenüeintrag ausblenden", + "", + "", + "", + "", + "Menu Enregistrement étandu invisible", + "", + "Piilota valinta päävalikosta", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "Skrýt položku v hlavním menu", + }, + { "Replace original recordings menu", + "Originales Aufzeichnungsmenü ersetzen", + "", + "", + "", + "", + "Remplacer le nenu original Enregistrement", + "", + "Korvaa alkuperäinen tallennevalikko", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "Nahradit originální menu nahrávek", + }, + { "Show alternative to new marker", + "Alternative zu Neu-Marker anzeigen", + "", + "", + "", + "", + "Afficher les nouveaux symbols alternatifs", + "", + "Merkitse uudet tallenteet symbolilla", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "Zobrazit alternativu k novým značkám", + }, + { "Please insert DVD %s", + "Bitte DVD %s einlegen", + "", + "", + "", + "", + "Mettez le DVD %s dans le lecteur", + "", + "Laita DVD %s asemaan", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "Vložte prosím DVD %s", + }, + { "Error while mounting DVD!", + "Fehler beim Einhängen der DVD!", + "", + "", + "", + "", + "Erreur lors du montage du DVD!", + "", + "DVD:n avaaminen epäonnistui!", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "Chyba během připojování DVD!", + }, + { "Recording not found on DVD!", + "Aufzeichnung auf DVD nicht gefunden!", + "", + "", + "", + "", + "Il n'y a pas d'enregistrement sur le DVD!", + "", + "Tallennetta ei löydy DVD:ltä!", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "Nahrávka nebyla na DVD nalezena!", + }, + { "Script 'dvdarchive.sh' not found!", + "Skript 'dvdarchive.sh' wurde nicht gefunden!", + "", + "", + "", + "", + "Impossible de trouver le script 'dvdarchive.sh'!", + "", + "'dvdarchive.sh'-skriptiä ei löydetä!", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "Skript 'dvdarchive.sh' nebyl nalezen!", + }, + { "[base dir]", + "[Stammverzeichnis]", + "", + "", + "", + "", + "[Dossier racine]", + "", + "[juurihakemisto]", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "[základní adresář]", + }, + { "No DVD in drive!", + "Keine DVD im Laufwerk!", + "", + "", + "", + "", + "Pas de DVD dans le lecteur!", + "", + "Asemassa ei ole DVD-levyä!", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "V jednotce není DVD!", + }, + { "Error while linking [0-9]*.vdr!", + "Fehler beim Anlegen der Symlinks [0-9]*.vdr!", + "", + "", + "", + "", + "Erreur lors de la création des racourcis [0-9]*.vdr!", + "", + "Tiedostojen [0-9]*.vdr linkittäminen epäonnistui!", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "Chyba při spojování [0-9]*.vdr!", + }, + { "sudo or mount --bind / umount error (vfat system)", + "sudo oder mount --bind / umount Fehler (VFAT-System)", + "", + "", + "", + "", + "Erreur sudo ou mount --bind / umount (Systeme VFAT)", + "", + "Sudo tai mount --bind / umount -komento epäonnistui (VFAT)!", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "sudo nebo mount --bind / umount selhal (VFAT-systém)", + }, + { "Details", + "Details", + "", + "", + "", + "", + "Détails", + "", + "Lisätiedot", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "Detaily", + }, + { "DVD plugin is not installed!", + "Das DVD-Plugin ist nicht installiert!", + "", + "", + "", + "", + "Le plugin DVD n'est pas installé!", + "", + "DVD-laajennosta ei löydy!", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "Modul DVD není nainstalován!", + }, + { "Rename/Move failed!", + "Umbenennen/Verschieben fehlgeschlagen!", + "", + "", + "", + "", + "Renommer/déplacer ŕ échoué!", + "", + "Nimeäminen/siirto epäonnistui!", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "Přejmenování/Přesun selhal!", + }, + { "Invalid filename!", + "Ungültiger Dateiname!", + "", + "", + "", + "", + "Nom de fichiers n'est pas valide'", + "", + "Virheellinen tiedoston nimi!", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "Chybné jméno souboru!", + }, + { "Moving into own sub-directory not allowed!", + "Verschieben in eigenes Unterverzeichnis nicht erlaubt!", + "", + "", + "", + "", + "Déplacer dans le sous-dossier propre, n'est pas possible!", + "", + "Siirto omaan alihakemistoon ei ole sallittu!", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "Přesun do vlastního podadresáře není povolen!", + }, + { "Sort by name", + "Sortieren nach Namen", + "", + "", + "", + "", + "Triage selon le nom", + "", + "Tallenteet järjestetään nimen mukaan", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + }, + { "Sort by date", + "Sortieren nach Datum", + "", + "", + "", + "", + "Triage selon date", + "", + "Tallenteet järjestetään päivämäärän mukaan", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + }, + { "Show nr. of new recordings in a directory", + "Anzahl der neuen Aufz. im Ordner anzeigen", + "", + "", + "", + "", + "Afficher le nombre de nouveaux enregistrements dans les dossiers", + "", + "Näytä uusien tallenteiden lukumäärä", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + }, + { "Sorting", + "Sortierung", + "", + "", + "", + "", + "Triage", + "", + "Järjestys", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + }, + { "ascending", + "aufsteigend", + "", + "", + "", + "", + "montant", + "", + "nouseva", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + }, + { "descending", + "absteigend", + "", + "", + "", + "", + "descendant", + "", + "laskeva", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + }, + { "Jump to last replayed recording", + "Springe zur zuletzt abgespielten Aufzeichnung", + "", + "", + "", + "", + "Retour au dernier enregistrement lu", + "", + "Siirry viimeksi toistettuun tallenteeseen", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + }, + { "Call plugin after playback", + "Nach Wiedergabe Plugin aufrufen", + "", + "", + "", + "", + "Aprčs la lecture démarer le plugin", + "", + "Avaa laajennos toiston loputtua", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + }, + { "Move recordings already in progress!", + "Es werden schon Aufzeichnungen verschoben!", + "", + "", + "", + "", + "Des enregistrements sont déjŕ en déplacement!", + "", + "Tallenteiden siirto on jo käynnissä!", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + }, + { "Move recordings in progress", + "Es werden Aufzeichungen verschoben", + "", + "", + "", + "", + "Enregistrements en cours de déplacement", + "", + "Tallenteiden siirto käynnissä", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + }, + { "Limit bandwidth for move recordings", + "Bandbreite beim Verschieben begrenzen", + "", + "", + "", + "", + "Limiter la bande passante lors du déplacement", + "", + "Rajoita tallenteiden siirtokaistaa", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + }, + { "Target filesystem filled- try anyway?", + "Zielpartition voll - trotzdem versuchen?", + "", + "", + "", + "", + "La partition de déstination est pleine - essayer tout de męme?", + "", + "Kohdepartitio täynnä - yritetäänkö silti?", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + }, + { "Path", + "Pfad", + "", + "", + "", + "", + "Chemin", + "", + "Polku", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + }, + { "Size", + "Größe", + "", + "", + "", + "", + "Taille", + "", + "Koko", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + }, + { "Use VDR's recording info menu", + "VDR-Aufz.-Info-Menü benutzen", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + }, + { NULL } + }; diff --git a/mymenueditrecording.c b/mymenueditrecording.c index 3c89292..f9ce9eb 100644 --- a/mymenueditrecording.c +++ b/mymenueditrecording.c @@ -2,12 +2,17 @@ * See the README file for copyright information and how to reach the author. */ +#include <sys/vfs.h> +#include <string> #include <vdr/videodir.h> #include <vdr/remote.h> #include <vdr/menu.h> +#include <vdr/interface.h> #include "mymenurecordings.h" #include "tools.h" +using namespace std; + // --- myMenuRenameRecording -------------------------------------------------- myMenuRenameRecording::myMenuRenameRecording(myMenuRecordings *MenuRecordings,cRecording *Recording,const char *DirBase,const char *DirName):cOsdMenu(tr("Rename"),12) { @@ -53,50 +58,54 @@ myMenuRenameRecording::~myMenuRenameRecording() eOSState myMenuRenameRecording::ProcessKey(eKeys Key) { - eOSState state=cOsdMenu::ProcessKey(Key); - if(state==osContinue) - { - if(Key==kOk) + eOSState state=cOsdMenu::ProcessKey(Key); + if(state==osContinue) { - char *oldname=NULL; - char *newname=NULL; - char *tmppath=path[0]?ExchangeChars(strdup(path),true):NULL; - char *tmpname=name[0]?ExchangeChars(strdup(name),true):NULL; - - if(strchr(name,'.')==name||!strlen(name)) - { - Skins.Message(mtError,tr("Invalid filename!")); - cRemote::Put(kRight); - return osContinue; - } - - if(isdir) - asprintf(&oldname,"%s%s%s/%s",VideoDirectory,tmppath?"/":"",dirbase?dirbase:"",dirname); - else - oldname=strdup(recording->FileName()); - - asprintf(&newname,"%s%s%s/%s%s",VideoDirectory,tmppath?"/":"",tmppath?tmppath:"",tmpname,isdir?"":strrchr(recording->FileName(),'/')); - - if(MoveRename(oldname,newname,isdir?NULL:recording,false)) - { - state=osBack; - menurecordings->Set(true,isdir?NULL:newname); - } - else - { - cRemote::Put(kRight); - state=osContinue; - } - - free(oldname); - free(newname); - free(tmppath); - free(tmpname); + if(Key==kOk) + { + char *oldname=NULL; + char *newname=NULL; + char *tmppath=path[0]?ExchangeChars(strdup(path),true):NULL; + char *tmpname=name[0]?ExchangeChars(strdup(name),true):NULL; + + if(strchr(name,'.')==name||!strlen(name)) + { + Skins.Message(mtError,tr("Invalid filename!")); + cRemote::Put(kRight); + return osContinue; + } + + if(isdir) + asprintf(&oldname,"%s%s%s/%s",VideoDirectory,tmppath?"/":"",dirbase?dirbase:"",dirname); + else + oldname=strdup(recording->FileName()); + + asprintf(&newname,"%s%s%s/%s%s",VideoDirectory,tmppath?"/":"",tmppath?tmppath:"",tmpname,isdir?"":strrchr(recording->FileName(),'/')); + + if(!MakeDirs(newname,true)) + Skins.Message(mtError,tr("Creating directories failed!")); + else + { + if(MoveRename(oldname,newname,isdir?NULL:recording,false)) + { + state=osBack; + menurecordings->Set(true,isdir?NULL:newname); + } + else + { + cRemote::Put(kRight); + state=osContinue; + } + } + free(oldname); + free(newname); + free(tmppath); + free(tmpname); + } + if(Key==kBack) + return osBack; } - if(Key==kBack) - return osBack; - } - return state; + return state; } // --- myMenuNewName ---------------------------------------------------------- @@ -222,38 +231,38 @@ myMenuMoveRecording::~myMenuMoveRecording() void myMenuMoveRecording::Set() { - if(level==0) - Add(new myMenuMoveRecordingItem(tr("[base dir]"),0)); + if(level==0) + Add(new myMenuMoveRecordingItem(tr("[base dir]"),0)); - char *lastitemtext=NULL; - myMenuMoveRecordingItem *lastitem=NULL; - for(cRecording *recording=Recordings.First();recording;recording=Recordings.Next(recording)) - { - if(!base||(strstr(recording->Name(),base)==recording->Name()&&recording->Name()[strlen(base)]=='~')) + char *lastitemtext=NULL; + myMenuMoveRecordingItem *lastitem=NULL; + for(cRecording *recording=Recordings.First();recording;recording=Recordings.Next(recording)) { - myMenuMoveRecordingItem *item=new myMenuMoveRecordingItem(recording,level); - if(*item->Text()) - { - if(lastitemtext&&!strcmp(lastitemtext,item->Text())) // same text - { - if(lastitem&&lastitem->Level()<item->Level()) // if level of the previous item is lower, set it to the new value - lastitem->SetLevel(item->Level()); - - delete item; - } - else + if(!base||(strstr(recording->Name(),base)==recording->Name()&&recording->Name()[strlen(base)]=='~')) { - Add(item); // different text means a new item to add - lastitem=item; - free(lastitemtext); - lastitemtext=strdup(lastitem->Text()); + myMenuMoveRecordingItem *item=new myMenuMoveRecordingItem(recording,level); + if(*item->Text()) + { + if(lastitemtext&&!strcmp(lastitemtext,item->Text())) // same text + { + if(lastitem&&lastitem->Level()<item->Level()) // if level of the previous item is lower, set it to the new value + lastitem->SetLevel(item->Level()); + + delete item; + } + else + { + Add(item); // different text means a new item to add + lastitem=item; + free(lastitemtext); + lastitemtext=strdup(lastitem->Text()); + } + } + else + delete item; } - } - else - delete item; } - } - free(lastitemtext); + free(lastitemtext); } eOSState myMenuMoveRecording::Open() @@ -278,70 +287,123 @@ eOSState myMenuMoveRecording::Open() eOSState myMenuMoveRecording::MoveRec() { - char *oldname=NULL; - char *newname=NULL; - char *dir=NULL; - char *tmpdirbase=dirbase?ExchangeChars(strdup(dirbase),true):NULL; - char *tmpdirname=dirname?ExchangeChars(strdup(dirname),true):NULL; + char *oldname=NULL; + char *newname=NULL; + char *dir=NULL; + char *tmpdirbase=dirbase?ExchangeChars(strdup(dirbase),true):NULL; + char *tmpdirname=dirname?ExchangeChars(strdup(dirname),true):NULL; - eOSState state=osContinue; + eOSState state=osContinue; - if(dirname) - asprintf(&oldname,"%s%s%s/%s",VideoDirectory,dirbase?"/":"",tmpdirbase?tmpdirbase:"",tmpdirname); - else - oldname=strdup(recording->FileName()); + if(dirname) + asprintf(&oldname,"%s%s%s/%s",VideoDirectory,dirbase?"/":"",tmpdirbase?tmpdirbase:"",tmpdirname); + else + oldname=strdup(recording->FileName()); - myMenuMoveRecordingItem *item=(myMenuMoveRecordingItem*)Get(Current()); - if(item) - { - if(strcmp(tr("[base dir]"),item->Text())) + myMenuMoveRecordingItem *item=(myMenuMoveRecordingItem*)Get(Current()); + if(item) { - if(dirname) - asprintf(&dir,"%s%s%s",base?base:"",base?"~":"",item->Text()); - else - { - char *p=strrchr(recording->Name(),'~'); - asprintf(&dir,"%s%s%s~%s",base?base:"",base?"~":"",item->Text(),p?p+1:recording->Name()); - } + if(strcmp(tr("[base dir]"),item->Text())) + { + if(dirname) + asprintf(&dir,"%s%s%s",base?base:"",base?"~":"",item->Text()); + else + { + char *p=strrchr(recording->Name(),'~'); + asprintf(&dir,"%s%s%s~%s",base?base:"",base?"~":"",item->Text(),p?p+1:recording->Name()); + } + } + else + { + if(!dirname) + { + char *p=strrchr(recording->Name(),'~'); + asprintf(&dir,"%s",p?++p:recording->Name()); + } + } } else { - if(!dirname) - { - char *p=strrchr(recording->Name(),'~'); - asprintf(&dir,"%s",p?++p:recording->Name()); - } + if(dirname) + asprintf(&dir,"%s",base); + else + { + char *p=strrchr(recording->Name(),'~'); + asprintf(&dir,"%s~%s",base,p?p:recording->Name()); + } } - } - else - { - if(dirname) - asprintf(&dir,"%s",base); + if(dir) + dir=ExchangeChars(dir,true); + + asprintf(&newname,"%s%s%s%s",VideoDirectory,dir?"/":"",dir?dir:"",strrchr(dirname?oldname:recording->FileName(),'/')); + + if(!MakeDirs(newname,true)) + Skins.Message(mtError,tr("Creating directories failed!")); else { - char *p=strrchr(recording->Name(),'~'); - asprintf(&dir,"%s~%s",base,p?p:recording->Name()); + struct stat stat1,stat2; + stat(oldname,&stat1); + stat(newname,&stat2); + if(stat1.st_dev==stat2.st_dev) + { + if(MoveRename(oldname,newname,dirname?NULL:recording,true)) + { + clearall=true; + state=osBack; + menurecordings->Set(true); + } + } + else + { + if(MoveThread.Active()) + Skins.Message(mtError,tr("Move recordings already in progress!")); + else + { + struct statfs fsstat; + statfs(newname,&fsstat); + int freemb=int(fsstat.f_bavail/(1024*1024/fsstat.f_bsize)); + int recmb=0; + + if(recording) + recmb=DirSizeMB(recording->FileName()); + else + { + for(cRecording *rec=Recordings.First();rec;rec=Recordings.Next(rec)) + { + if(!strncmp(oldname,rec->FileName(),strlen(oldname))) + recmb+=DirSizeMB(rec->FileName()); + } + } + + if(freemb-recmb <= 0) + { + if(Interface->Confirm(tr("Target filesystem filled - try anyway?"))) + { + MoveThread.Start(oldname,newname,dirname?NULL:recording); + clearall=true; + state=osBack; + menurecordings->Set(true); + } + else + remove(newname); // remove created directory + } + else + { + MoveThread.Start(oldname,newname,dirname?NULL:recording); + clearall=true; + state=osBack; + menurecordings->Set(true); + } + } + } } - } - if(dir) - dir=ExchangeChars(dir,true); + free(oldname); + free(newname); + free(dir); + free(tmpdirbase); + free(tmpdirname); - asprintf(&newname,"%s%s%s%s",VideoDirectory,dir?"/":"",dir?dir:"",strrchr(dirname?oldname:recording->FileName(),'/')); - - if(MoveRename(oldname,newname,dirname?NULL:recording,true)) - { - clearall=true; - state=osBack; - menurecordings->Set(true); - } - - free(oldname); - free(newname); - free(dir); - free(tmpdirbase); - free(tmpdirname); - - return state; + return state; } eOSState myMenuMoveRecording::Create() diff --git a/mymenurecordings.c b/mymenurecordings.c index 7eb996d..d0cabc1 100644 --- a/mymenurecordings.c +++ b/mymenurecordings.c @@ -2,11 +2,16 @@ * See the README file for copyright information and how to reach the author. */ +#include <string> +#include <sstream> +#include <iomanip> +#include <fstream> #include <vdr/interface.h> #include <vdr/videodir.h> #include <vdr/status.h> #include <vdr/plugin.h> #include <vdr/cutter.h> +#include <vdr/menu.h> #include "myreplaycontrol.h" #include "mymenurecordings.h" #include "mymenusetup.h" @@ -14,6 +19,8 @@ #include "patchfont.h" #include "tools.h" +using namespace std; + extern SortList *mySortList; // --- myMenuRecordingInfo ---------------------------------------------------- @@ -40,9 +47,52 @@ myMenuRecordingInfo::myMenuRecordingInfo(const cRecording *Recording, bool WithB void myMenuRecordingInfo::Display(void) { - cOsdMenu::Display(); - DisplayMenu()->SetRecording(recording); - cStatus::MsgOsdTextItem(recording->Info()->Description()); + cOsdMenu::Display(); + + if(mysetup.UseVDRsRecInfoMenu) + { + DisplayMenu()->SetRecording(recording); + if(recording->Info()->Description()) + cStatus::MsgOsdTextItem(recording->Info()->Description()); + } + else + { + stringstream text; + text << *DateString(recording->start) << ", " << *TimeString(recording->start) << "\n\n"; + + if(recording->Info()->Title()) + { + text << recording->Info()->Title() << "\n\n"; + if(recording->Info()->Description()) + text << recording->Info()->Description() << "\n\n"; + } + + string recname=recording->Name(); + string::size_type i=recname.rfind('~'); + if(i!=string::npos) + text << tr("Name") << ": " << recname.substr(i+1,recname.length()) << "\n" + << tr("Path") << ": " << recname.substr(0,i) << "\n"; + else + text << tr("Name") << ": " << recname << "\n"; + + cChannel *chan=Channels.GetByChannelID(((cRecordingInfo*)recording->Info())->ChannelID()); + if(chan) + text << tr("Channel") << ": " << *ChannelString(chan,0) << "\n"; + + int recmb=DirSizeMB(recording->FileName()); + if(recmb<0) + recmb=0; + if(recmb > 1023) + text << tr("Size") << ": " << setprecision(3) << recmb/1024.0 << " GB\n"; + else + text << tr("Size") << ": " << recmb << " MB\n"; + + text << tr("Priority") << ": " << recording->priority << "\n"; + text << tr("Lifetime") << ": " << recording->lifetime << "\n"; + + DisplayMenu()->SetText(text.str().c_str(),false); + cStatus::MsgOsdTextItem(recording->Info()->Description()); + } } eOSState myMenuRecordingInfo::ProcessKey(eKeys Key) @@ -83,185 +133,198 @@ eOSState myMenuRecordingInfo::ProcessKey(eKeys Key) // --- myMenuRecordingsItem --------------------------------------------------- myMenuRecordingsItem::myMenuRecordingsItem(cRecording *Recording,int Level) { - totalentries=newentries=0; - isdvd=false; - name=NULL; - filename=Recording->FileName(); - - // get the level of this recording - level=0; - const char *s=Recording->Name(); - while(*++s) - { - if(*s=='~') - level++; - } - - // create the title of this item - if(Level<level) // directory entries - { - s=Recording->Name(); - const char *p=s; + totalentries=newentries=0; + isdvd=false; + name=NULL; + filename=Recording->FileName(); + + // get the level of this recording + level=0; + const char *s=Recording->Name(); while(*++s) { - if(*s=='~') - { - if(Level--) - p=s+1; - else - break; - } + if(*s=='~') + level++; } - title=MALLOC(char,s-p+3); - *title='\t'; - *(title+1)='\t'; - strn0cpy(title+2,p,s-p+1); - name=strdup(title+2); - } - else - { - if(Level==level) // recording entries - { - char *buffer=NULL; - string titlebuffer; - - // dvdarchive-patch functionality - asprintf(&buffer,"%s/dvd.vdr",filename); - isdvd=!access(buffer,R_OK); - - // marker - titlebuffer=' '; - if(Recording->IsNew()&&!mysetup.PatchNew) - titlebuffer='*'; - if(!Recording->IsNew()&&mysetup.PatchNew) - titlebuffer=char(128); - if(isdvd) - titlebuffer=char(129); - - titlebuffer+='\t'; - - // date and time of recording - struct tm tm_r; - struct tm *t=localtime_r(&Recording->start,&tm_r); - - char recdate[9],rectime[6]; - strn0cpy(recdate,"",sizeof(recdate)); - strn0cpy(rectime,"",sizeof(rectime)); - snprintf(recdate,sizeof(recdate),"%02d.%02d.%02d",t->tm_mday,t->tm_mon+1,t->tm_year%100); - snprintf(rectime,sizeof(rectime),"%02d:%02d",t->tm_hour,t->tm_min); - - if(mysetup.ShowRecDate) - { - titlebuffer+=recdate; - titlebuffer+='\t'; - } - - if(mysetup.ShowRecTime) - { - titlebuffer+=rectime; - titlebuffer+='\t'; - } - - // recording length - if(mysetup.ShowRecLength) - { - char reclength[21]; - strn0cpy(reclength,"",sizeof(reclength)); - asprintf(&buffer,"%s/index.vdr",filename); - int haslength=!access(buffer,R_OK); - if(haslength) // calculate recording length from the size of index.vdr - { - struct stat buf; - if(!stat(buffer,&buf)) - snprintf(reclength,sizeof(reclength),"%3d'",(int)(buf.st_size/12000)); - } - else // no index -> is there a length.vdr, containing recording length as a string? + // create the title of this item + if(Level<level) // directory entries + { + s=Recording->Name(); + const char *p=s; + while(*++s) { - free(buffer); - asprintf(&buffer,"%s/length.vdr",filename); - FILE *f; - if((f=fopen(buffer,"r"))!=NULL) - { - char buf[8]; - if(fgets(buf,sizeof(buf),f)) + if(*s=='~') { - char *p=strchr(buf,'\n'); - if(p) - *p=0; + if(Level--) + p=s+1; + else + break; } - fclose(f); - snprintf(reclength,sizeof(reclength),"%3s'\n",buf); - } } - free(buffer); - - strreplace(reclength,' ',char(131)); - - titlebuffer+=reclength; - titlebuffer+='\t'; - } - - if(!mysetup.ShowRecDate&&!mysetup.ShowRecTime&&!mysetup.ShowRecLength) - titlebuffer+='\t'; - - // recording title - s=strrchr(Recording->Name(),'~'); - titlebuffer+=s?s+1:Recording->Name(); - - title=strdup(titlebuffer.c_str()); + title=MALLOC(char,s-p+3); + *title='\t'; + *(title+1)='\t'; + strn0cpy(title+2,p,s-p+1); + name=strdup(title+2); + uniqid=name; } else { - if(Level>level) // any other - title=""; - } - } + if(Level==level) // recording entries + { + string buffer; + stringstream titlebuffer; + stringstream idbuffer; + + buffer=filename; + buffer+="/001.vdr"; + if(access(buffer.c_str(),R_OK)) + { + buffer=filename; + buffer+="/dvd.vdr"; + isdvd=!access(buffer.c_str(),R_OK); + } + + // marker + if(MoveThread.IsMoving(filename)) + titlebuffer << char(133); // move in progress + else if(isdvd) + titlebuffer << char(129); // dvd-archiv + else if(cCutter::Active() && myReplayControl::Cut && myReplayControl::Cutted && + (!strcmp(filename,myReplayControl::Cut) || !strcmp(filename,myReplayControl::Cutted))) + titlebuffer << char(132); // cut in progress + else if(Recording->IsNew() && !mysetup.PatchNew) + titlebuffer << '*'; // new recording + else if(!Recording->IsNew() && mysetup.PatchNew) + titlebuffer << char(128); // alternative to new marker + else titlebuffer << ' '; + + titlebuffer << '\t'; + + // date and time of recording + struct tm tm_r; + struct tm *t=localtime_r(&Recording->start,&tm_r); + + if(mysetup.ShowRecDate) + titlebuffer << setw(2) << setfill('0') << t->tm_mday << '.' + << setw(2) << setfill('0') << t->tm_mon+1 << '.' + << setw(2) << setfill('0') << t->tm_year%100 << '\t'; + + if(mysetup.ShowRecTime) + titlebuffer << setw(2) << setfill('0') << t->tm_hour << '.' + << setw(2) << setfill('0') << t->tm_min << '\t'; + + + idbuffer << t->tm_mday << t->tm_mon << t->tm_year + << t->tm_hour << t->tm_min; - SetText(title); + // recording length + if(mysetup.ShowRecLength) + { + buffer=filename; + buffer+="/index.vdr"; + struct stat statbuf; + if(!stat(buffer.c_str(),&statbuf)) + { + ostringstream strbuf; + strbuf << setw(3) << setfill(' ') << right << (int)(statbuf.st_size/12000) << "'"; + + titlebuffer << myStrReplace(strbuf.str(),' ',char(131)) << '\t'; + } + else + { + // get recording length from file 'length.vdr' + buffer=filename; + buffer+="/length.vdr"; + + ifstream in(buffer.c_str()); + if(in) + { + if(!in.eof()) + getline(in,buffer); + + buffer+="'"; + + while(buffer.length()<=3) + buffer.insert(0,1,char(131)); + + titlebuffer << buffer << '\t'; + + in.close(); + } + } + } + if(!mysetup.ShowRecDate && !mysetup.ShowRecTime && !mysetup.ShowRecLength) + titlebuffer << '\t'; + + // recording title + string s=Recording->Name(); + string::size_type i=s.rfind('~'); + if(i!=string::npos) + { + titlebuffer << s.substr(i+1,s.length()-i); + idbuffer << s.substr(i+1,s.length()-i); + } + else + { + titlebuffer << s; + idbuffer << s; + } + + title=strdup(titlebuffer.str().c_str()); + uniqid=idbuffer.str(); + } + else + { + if(Level>level) // any other + title=""; + } + } + SetText(title); } myMenuRecordingsItem::~myMenuRecordingsItem() { - free(title); - free(name); + free(title); + free(name); } void myMenuRecordingsItem::IncrementCounter(bool IsNew) { - totalentries++; - if(IsNew) - newentries++; + totalentries++; + if(IsNew) + newentries++; - char *buffer=NULL; - char entries[8]; - snprintf(entries,sizeof(entries),"%3d",totalentries); - strreplace(entries,' ',char(131)); + char *buffer=NULL; + char entries[8]; + snprintf(entries,sizeof(entries),"%3d",totalentries); + strreplace(entries,' ',char(131)); - if(mysetup.ShowNewRecs) - { - asprintf(&buffer,"%c\t%s (%d)%s%s%s%s%s", - char(130), - entries, - newentries, - (!mysetup.ShowRecDate&&!mysetup.ShowRecTime&&!mysetup.ShowRecLength)?"\t":"", - (mysetup.ShowRecDate||mysetup.ShowRecTime||mysetup.ShowRecLength)?"\t":"", - (mysetup.ShowRecDate&&mysetup.ShowRecTime||mysetup.ShowRecTime&&mysetup.ShowRecLength||mysetup.ShowRecLength&&mysetup.ShowRecDate)?"\t":"", - (mysetup.ShowRecDate&&mysetup.ShowRecTime&&mysetup.ShowRecLength)?"\t":"", - name); - } - else - { - asprintf(&buffer,"%c\t%s%s%s%s%s%s", - char(130), - entries, - (!mysetup.ShowRecDate&&!mysetup.ShowRecTime&&!mysetup.ShowRecLength)?"\t":"", - (mysetup.ShowRecDate||mysetup.ShowRecTime||mysetup.ShowRecLength)?"\t":"", - (mysetup.ShowRecDate&&mysetup.ShowRecTime||mysetup.ShowRecTime&&mysetup.ShowRecLength||mysetup.ShowRecLength&&mysetup.ShowRecDate)?"\t":"", - (mysetup.ShowRecDate&&mysetup.ShowRecTime&&mysetup.ShowRecLength)?"\t":"", - name); - } - SetText(buffer,false); + if(mysetup.ShowNewRecs) + { + asprintf(&buffer,"%c\t%s (%d)%s%s%s%s%s", + char(130), + entries, + newentries, + (!mysetup.ShowRecDate&&!mysetup.ShowRecTime&&!mysetup.ShowRecLength)?"\t":"", + (mysetup.ShowRecDate||mysetup.ShowRecTime||mysetup.ShowRecLength)?"\t":"", + (mysetup.ShowRecDate&&mysetup.ShowRecTime||mysetup.ShowRecTime&&mysetup.ShowRecLength||mysetup.ShowRecLength&&mysetup.ShowRecDate)?"\t":"", + (mysetup.ShowRecDate&&mysetup.ShowRecTime&&mysetup.ShowRecLength)?"\t":"", + name); + } + else + { + asprintf(&buffer,"%c\t%s%s%s%s%s%s", + char(130), + entries, + (!mysetup.ShowRecDate&&!mysetup.ShowRecTime&&!mysetup.ShowRecLength)?"\t":"", + (mysetup.ShowRecDate||mysetup.ShowRecTime||mysetup.ShowRecLength)?"\t":"", + (mysetup.ShowRecDate&&mysetup.ShowRecTime||mysetup.ShowRecTime&&mysetup.ShowRecLength||mysetup.ShowRecLength&&mysetup.ShowRecDate)?"\t":"", + (mysetup.ShowRecDate&&mysetup.ShowRecTime&&mysetup.ShowRecLength)?"\t":"", + name); + } + SetText(buffer,false); } // --- myMenuRecordings ------------------------------------------------------- @@ -270,9 +333,9 @@ void myMenuRecordingsItem::IncrementCounter(bool IsNew) bool myMenuRecordings::golastreplayed=false; bool myMenuRecordings::wasdvd; -myMenuRecordings::myMenuRecordings(const char *Base,int Level):cOsdMenu(Base?Base:"") +myMenuRecordings::myMenuRecordings(const char *Base,int Level):cOsdMenu("") { - // only called if plugin menu is opened + // only called if plugin menu was opened if(Level==0) { // patch font @@ -283,23 +346,20 @@ myMenuRecordings::myMenuRecordings(const char *Base,int Level):cOsdMenu(Base?Bas } // set tabs if(mysetup.ShowRecDate&&mysetup.ShowRecTime&&!mysetup.ShowRecLength) // recording date and time are shown, recording length not - SetCols(2,8,6); - else - if(mysetup.ShowRecDate&&mysetup.ShowRecTime) // all details are shown + SetCols(2,8,6); + else if(mysetup.ShowRecDate&&mysetup.ShowRecTime) // all details are shown SetCols(2,8,6,4); - else - if(mysetup.ShowRecDate&&!mysetup.ShowRecTime) // recording time is not shown - SetCols(2,8,4); + else if(mysetup.ShowRecDate&&!mysetup.ShowRecTime) // recording time is not shown + SetCols(2,8,4); + else if(!mysetup.ShowRecDate&&mysetup.ShowRecTime&&mysetup.ShowRecLength) // recording date is not shown + SetCols(2,6,4); + else // recording date and time are not shown; even if recording length should be not shown we must set two tabs because the details of the directories + { + if(mysetup.ShowNewRecs) + SetCols(2,8,3); else - if(!mysetup.ShowRecDate&&mysetup.ShowRecTime&&mysetup.ShowRecLength) // recording date is not shown - SetCols(2,6,4); - else // recording date and time are not shown; even if recording length should be not shown we must set two tabs because the details of the directories - { - if(mysetup.ShowNewRecs) - SetCols(2,8,3); - else - SetCols(2,4,3); - } + SetCols(2,4,3); + } edit=false; level=Level; @@ -350,124 +410,149 @@ myMenuRecordings::~myMenuRecordings() } } -void myMenuRecordings::SetFreeSpaceTitle() +void myMenuRecordings::Title() { - int freemb; - VideoDiskSpace(&freemb); - int minutes=int(double(freemb)/MB_PER_MINUTE); - char buffer[40]; - snprintf(buffer,sizeof(buffer),"%s - %2d:%02d %s",tr("Recordings"),minutes/60,minutes%60,tr("free")); - SetTitle(buffer); + int freemb; + VideoDiskSpace(&freemb); + int minutes=int(double(freemb)/MB_PER_MINUTE); + + stringstream buffer; + if(MoveThread.Active()) + buffer << char(133); + if(cCutter::Active()) + buffer << char(132); + + if(MoveThread.Active() || cCutter::Active()) + buffer << ' '; + + if(base) + buffer << base; + else + buffer << tr("Recordings")<< " - " + << minutes/60 << ":" + << setw(2) << setfill('0') << minutes%60 << " " + << tr("free"); + + SetTitle(buffer.str().c_str()); } void myMenuRecordings::SetHelpKeys() { - if(!HasSubMenu()) - { - myMenuRecordingsItem *item=(myMenuRecordingsItem*)Get(Current()); - int newhelpkeys=0; - if(item) + if(!HasSubMenu()) { - if(item->IsDirectory()) - newhelpkeys=1; - else - { - newhelpkeys=2; - cRecording *recording=GetRecording(item); - if(recording&&recording->Info()->Title()) - newhelpkeys=3; - } - if(newhelpkeys!=helpkeys) - { - switch(newhelpkeys) + myMenuRecordingsItem *item=(myMenuRecordingsItem*)Get(Current()); + int newhelpkeys=0; + if(item) { - case 0: SetHelp(NULL);break; - case 1: SetHelp(tr("Button$Open"),NULL,tr("Button$Edit"));break; - case 2: SetHelp(RecordingCommands.Count()?tr("Button$Commands"):tr("Button$Play"),tr("Button$Rewind"),tr("Button$Edit"),NULL);break; - case 3: SetHelp(RecordingCommands.Count()?tr("Button$Commands"):tr("Button$Play"),tr("Button$Rewind"),tr("Button$Edit"),tr("Button$Info"));break; + if(item->IsDirectory()) + newhelpkeys=1; + else + { + newhelpkeys=2; + cRecording *recording=GetRecording(item); + if(mysetup.UseVDRsRecInfoMenu) + { + if(!recording->Info()->Title()) + { + newhelpkeys=4; + if(MoveThread.IsMoving(recording->FileName()) || IsCutted()) + newhelpkeys=5; + } + } + if(MoveThread.IsMoving(recording->FileName()) || IsCutted()) + newhelpkeys=3; + } + if(newhelpkeys!=helpkeys) + { + switch(newhelpkeys) + { + case 0: SetHelp(NULL);break; + case 1: SetHelp(tr("Button$Open"),NULL,tr("Button$Edit"));break; + case 2: SetHelp(RecordingCommands.Count()?tr("Button$Commands"):tr("Button$Play"),tr("Button$Rewind"),tr("Button$Edit"),tr("Button$Info"));break; + case 3: SetHelp(RecordingCommands.Count()?tr("Button$Commands"):tr("Button$Play"),tr("Button$Rewind"),NULL,tr("Button$Info"));break; + case 4: SetHelp(RecordingCommands.Count()?tr("Button$Commands"):tr("Button$Play"),tr("Button$Rewind"),tr("Button$Edit"),NULL);break; + case 5: SetHelp(RecordingCommands.Count()?tr("Button$Commands"):tr("Button$Play"),tr("Button$Rewind"),NULL,NULL);break; + } + } + helpkeys=newhelpkeys; } - } - helpkeys=newhelpkeys; } - } } // create the menu list void myMenuRecordings::Set(bool Refresh,char *current) { - const char *lastreplayed=current?current:myReplayControl::LastReplayed(); + const char *lastreplayed=current?current:myReplayControl::LastReplayed(); - if(level==0) - SetFreeSpaceTitle(); + Title(); - cThreadLock RecordingsLock(&Recordings); + cThreadLock RecordingsLock(&Recordings); - if(Refresh&&!current) - { - myMenuRecordingsItem *item=(myMenuRecordingsItem*)Get(Current()); - if(item) + if(Refresh&&!current) { - cRecording *recording=Recordings.GetByName(item->FileName()); - if(recording) - lastreplayed=recording->FileName(); + myMenuRecordingsItem *item=(myMenuRecordingsItem*)Get(Current()); + if(item) + { + cRecording *recording=Recordings.GetByName(item->FileName()); + if(recording) + lastreplayed=recording->FileName(); + } } - } - Clear(); + Clear(); - // create my own recordings list from VDR's - myRecList *list=new myRecList(); - for(cRecording *recording=Recordings.First();recording;recording=Recordings.Next(recording)) - list->Add(new myRecListItem(recording)); - // sort my recordings list - char path[BUFSIZ]; - snprintf(path,sizeof(path),"%s/%s",VideoDirectory,base?base:""); - list->Sort(mySortList->Find(path)); - - // needed for move recording menu - Recordings.Sort(); - - char *lastitemtext=NULL; - myMenuRecordingsItem *lastitem=NULL; - for(myRecListItem *listitem=list->First();listitem;listitem=list->Next(listitem)) - { - cRecording *recording=listitem->recording; - if(!base||(strstr(listitem->recording->Name(),base)==listitem->recording->Name()&&listitem->recording->Name()[strlen(base)]=='~')) + // create my own recordings list from VDR's + myRecList *list=new myRecList(); + for(cRecording *recording=Recordings.First();recording;recording=Recordings.Next(recording)) + list->Add(new myRecListItem(recording)); + // sort my recordings list + char path[BUFSIZ]; + snprintf(path,sizeof(path),"%s/%s",VideoDirectory,base?base:""); + list->Sort(mySortList->Find(path)); + + // needed for move recording menu + Recordings.Sort(); + + char *lastitemtext=NULL; + myMenuRecordingsItem *lastitem=NULL; + for(myRecListItem *listitem=list->First();listitem;listitem=list->Next(listitem)) { - myMenuRecordingsItem *recitem=new myMenuRecordingsItem(listitem->recording,level); - if(*recitem->Text()&&((!lastitem||strcmp(recitem->Text(),lastitemtext))||!recitem->IsDirectory())) - { - Add(recitem); - lastitem=recitem; - free(lastitemtext); - lastitemtext=strdup(lastitem->Text()); - } - else - delete recitem; - - if(lastitem) - { - if(lastitem->IsDirectory()) - lastitem->IncrementCounter(recording->IsNew()); - if(lastreplayed&&!strcmp(lastreplayed,recording->FileName())) + cRecording *recording=listitem->recording; + if(!base||(strstr(listitem->recording->Name(),base)==listitem->recording->Name()&&listitem->recording->Name()[strlen(base)]=='~')) { - if(golastreplayed||Refresh) - { - SetCurrent(lastitem); - if(recitem&&!recitem->IsDirectory()) - if(!cControl::Control()) - golastreplayed=false; - } - if(recitem&&!recitem->IsDirectory()&&recitem->IsDVD()&&!cControl::Control()) - cReplayControl::ClearLastReplayed(cReplayControl::LastReplayed()); + myMenuRecordingsItem *recitem=new myMenuRecordingsItem(listitem->recording,level); + if(*recitem->UniqID() && ((!lastitem || strcmp(recitem->UniqID(),lastitemtext)))) + { + Add(recitem); + lastitem=recitem; + free(lastitemtext); + lastitemtext=strdup(lastitem->UniqID()); + } + else + delete recitem; + + if(lastitem) + { + if(lastitem->IsDirectory()) + lastitem->IncrementCounter(recording->IsNew()); + if(lastreplayed&&!strcmp(lastreplayed,recording->FileName())) + { + if(golastreplayed||Refresh) + { + SetCurrent(lastitem); + if(recitem && !recitem->IsDirectory() && !cControl::Control() && !mysetup.GoLastReplayed) + golastreplayed=false; + } + if(recitem&&!recitem->IsDirectory()&&recitem->IsDVD()&&!cControl::Control()) + cReplayControl::ClearLastReplayed(cReplayControl::LastReplayed()); + } + } } - } } - } - free(lastitemtext); - delete list; - if(Refresh) - Display(); + free(lastitemtext); + delete list; + if(Refresh) + Display(); } // returns the corresponding recording to an item @@ -750,17 +835,19 @@ eOSState myMenuRecordings::MoveRec() // opens an info screen to a recording eOSState myMenuRecordings::Info(void) { - if(HasSubMenu()||Count()==0) - return osContinue; + if(HasSubMenu()||Count()==0) + return osContinue; - myMenuRecordingsItem *item=(myMenuRecordingsItem*)Get(Current()); - if(item&&!item->IsDirectory()) - { - cRecording *recording=GetRecording(item); - if(recording&&recording->Info()->Title()) - return AddSubMenu(new myMenuRecordingInfo(recording,true)); - } - return osContinue; + myMenuRecordingsItem *item=(myMenuRecordingsItem*)Get(Current()); + if(item&&!item->IsDirectory()) + { + cRecording *recording=GetRecording(item); + if(mysetup.UseVDRsRecInfoMenu && (!recording || recording && !recording->Info()->Title())) + return osContinue; + else + return AddSubMenu(new myMenuRecordingInfo(recording,true)); + } + return osContinue; } // execute a command for a recording @@ -816,6 +903,30 @@ eOSState myMenuRecordings::ChangeSorting() return osContinue; } +bool myMenuRecordings::IsCutted() +{ + if(cCutter::Active()) // cut in progress? + { + if(myReplayControl::Cut && myReplayControl::Cutted) // are there the paths to the cutted recording? + { + myMenuRecordingsItem *item=(myMenuRecordingsItem*)Get(Current()); + if(item) + { + cRecording *recording=GetRecording(item); + if(recording) + { + if(!strcmp(recording->FileName(),myReplayControl::Cut) || !strcmp(recording->FileName(),myReplayControl::Cutted)) + return true; // selected recording is cutted + else + return false; // seleted recording is not cutted + } + } + } + return true; // cut is in progress but i don't know for which recording, so editing for all recordings is prohibited + } + return false; // no cut in progress +} + eOSState myMenuRecordings::ProcessKey(eKeys Key) { eOSState state; @@ -854,23 +965,30 @@ eOSState myMenuRecordings::ProcessKey(eKeys Key) case kOk: return Play(); case kRed: return (helpkeys>1&&RecordingCommands.Count())?Commands():Play(); case kGreen: return Rewind(); - case kYellow: if(cCutter::Active()) - Skins.Message(mtError,tr("Editing not allowed while cutting!")); - else + case kYellow: if(!IsCutted()) { - myMenuRecordingsItem *item=(myMenuRecordingsItem*)Get(Current()); + myMenuRecordingsItem *item=(myMenuRecordingsItem*)Get(Current()); + if(item) + { + cRecording *rec=GetRecording(item); + if(rec) + { + if(MoveThread.IsMoving(rec->FileName())) + break; #ifdef WITHPINPLUGIN - if(item&&cStatus::MsgReplayProtected(GetRecording(item),item->Name(),base,item->IsDirectory())==true) - return osContinue; -#endif - if(!HasSubMenu()&&item) - { - edit=true; - if(item->IsDirectory()) - SetHelp(tr("Button$Rename"),tr("Button$Move")); - else - SetHelp(tr("Button$Rename"),tr("Button$Move"),tr("Button$Delete"),(!item->IsDVD())?tr("Details"):NULL); - } + if(cStatus::MsgReplayProtected(rec,item->Name(),base,item->IsDirectory())==true) + break; +#endif + } + if(!HasSubMenu()) + { + edit=true; + if(item->IsDirectory()) + SetHelp(tr("Button$Rename"),tr("Button$Move")); + else + SetHelp(tr("Button$Rename"),tr("Button$Move"),tr("Button$Delete"),(!item->IsDVD())?tr("Details"):NULL); + } + } } break; case kBlue: return Info(); @@ -886,6 +1004,21 @@ eOSState myMenuRecordings::ProcessKey(eKeys Key) // update menu list after sub menu has closed if(hadsubmenu&&!HasSubMenu()||Recordings.StateChanged(recordingsstate)||cCutter::Active()) Set(true); + + if(!cCutter::Active()) + { + // no cut in progress so delete the paths to the cutted recording + if(myReplayControl::Cut) + { + free(myReplayControl::Cut); + myReplayControl::Cut=NULL; + } + if(myReplayControl::Cutted) + { + free(myReplayControl::Cutted); + myReplayControl::Cutted=NULL; + } + } if(!HasSubMenu()&&Key!=kNone); SetHelpKeys(); diff --git a/mymenurecordings.h b/mymenurecordings.h index ebaf588..c112be2 100644 --- a/mymenurecordings.h +++ b/mymenurecordings.h @@ -1,21 +1,23 @@ // --- myMenuRecordingsItem --------------------------------------------------- class myMenuRecordingsItem:public cOsdItem { - private: - bool isdvd; - int level,isdirectory; - int totalentries,newentries; - char *title; - char *name; - const char *filename; - public: - myMenuRecordingsItem(cRecording *Recording,int Level); - ~myMenuRecordingsItem(); - const char *FileName(){return filename;} - const char *Name(){return name;} - bool IsDirectory(){return name!=NULL;} - void IncrementCounter(bool IsNew); - bool IsDVD(){return isdvd;} + private: + bool isdvd; + int level,isdirectory; + int totalentries,newentries; + char *title; + char *name; + const char *filename; + std::string uniqid; // this is the unique name that identifies a recording + public: + myMenuRecordingsItem(cRecording *Recording,int Level); + ~myMenuRecordingsItem(); + const char *FileName(){return filename;} + const char *Name(){return name;} + bool IsDirectory(){return name!=NULL;} + void IncrementCounter(bool IsNew); + bool IsDVD(){return isdvd;} + const char *UniqID(){return uniqid.length()?uniqid.c_str():"";} }; // --- myMenuRecordings ------------------------------------------------------- @@ -30,7 +32,7 @@ class myMenuRecordings:public cOsdMenu char *base; bool Open(); void SetHelpKeys(); - void SetFreeSpaceTitle(); + void Title(); cRecording *GetRecording(myMenuRecordingsItem *Item); eOSState Play(); eOSState Rewind(); @@ -41,6 +43,7 @@ class myMenuRecordings:public cOsdMenu eOSState Details(); eOSState Commands(eKeys Key=kNone); eOSState ChangeSorting(); + bool IsCutted(); public: myMenuRecordings(const char *Base=NULL,int Level=0); ~myMenuRecordings(); diff --git a/mymenusetup.c b/mymenusetup.c index f6cf128..40442e8 100644 --- a/mymenusetup.c +++ b/mymenusetup.c @@ -15,6 +15,10 @@ mySetup::mySetup() mysetup.ShowRecLength=0; mysetup.ShowNewRecs=1; mysetup.DescendSorting=0; + mysetup.GoLastReplayed=0; + mysetup.ReturnToPlugin=1; + mysetup.LimitBandwidth=0; + mysetup.UseVDRsRecInfoMenu=0; } mySetup mysetup; @@ -29,6 +33,10 @@ myMenuSetup::myMenuSetup() showreclength=mysetup.ShowRecLength; shownewrecs=mysetup.ShowNewRecs; descendsorting=mysetup.DescendSorting; + golastreplayed=mysetup.GoLastReplayed; + returntoplugin=mysetup.ReturnToPlugin; + limitbandwidth=mysetup.LimitBandwidth; + usevdrsrecinfomenu=mysetup.UseVDRsRecInfoMenu; sortingtypetexts[0]=tr("ascending"); sortingtypetexts[1]=tr("descending"); @@ -41,6 +49,10 @@ myMenuSetup::myMenuSetup() Add(new cMenuEditBoolItem(tr("Show recording length"),&showreclength)); Add(new cMenuEditBoolItem(tr("Show nr. of new recordings in a directory"),&shownewrecs)); Add(new cMenuEditBoolItem(tr("Show alternative to new marker"),&patchnew)); + Add(new cMenuEditBoolItem(tr("Jump to last replayed recording"),&golastreplayed)); + Add(new cMenuEditBoolItem(tr("Call plugin after playback"),&returntoplugin)); + Add(new cMenuEditBoolItem(tr("Limit bandwidth for move recordings"),&limitbandwidth)); + Add(new cMenuEditBoolItem(tr("Use VDR's recording info menu"),&usevdrsrecinfomenu)); } void myMenuSetup::Store() @@ -53,4 +65,8 @@ void myMenuSetup::Store() SetupStore("ShowRecLength",mysetup.ShowRecLength=showreclength); SetupStore("ShowNewRecs",mysetup.ShowNewRecs=shownewrecs); SetupStore("DescendSorting",mysetup.DescendSorting=descendsorting); + SetupStore("GoLastReplayed",mysetup.GoLastReplayed=golastreplayed); + SetupStore("ReturnToPlugin",mysetup.ReturnToPlugin=returntoplugin); + SetupStore("LimitBandwidth",mysetup.LimitBandwidth=limitbandwidth); + SetupStore("UseVDRsRecInfoMenu",mysetup.UseVDRsRecInfoMenu=usevdrsrecinfomenu); } diff --git a/mymenusetup.h b/mymenusetup.h index ad0091b..740cd25 100644 --- a/mymenusetup.h +++ b/mymenusetup.h @@ -12,6 +12,10 @@ class mySetup int PatchNew; int ShowNewRecs; int DescendSorting; + int GoLastReplayed; + int ReturnToPlugin; + int LimitBandwidth; + int UseVDRsRecInfoMenu; }; extern mySetup mysetup; @@ -28,6 +32,10 @@ class myMenuSetup:public cMenuSetupPage int patchnew; int shownewrecs; int descendsorting; + int golastreplayed; + int returntoplugin; + int limitbandwidth; + int usevdrsrecinfomenu; protected: virtual void Store(); public: diff --git a/myreplaycontrol.c b/myreplaycontrol.c index bdfb123..5305746 100644 --- a/myreplaycontrol.c +++ b/myreplaycontrol.c @@ -4,18 +4,35 @@ #include <vdr/interface.h> #include <vdr/status.h> +#include <vdr/menu.h> #include "myreplaycontrol.h" #include "mymenusetup.h" +using namespace std; + +char *myReplayControl::Cut=NULL; +char *myReplayControl::Cutted=NULL; + myReplayControl::~myReplayControl() { - cRemote::CallPlugin("extrecmenu"); + if(mysetup.ReturnToPlugin) + cRemote::CallPlugin("extrecmenu"); } eOSState myReplayControl::ProcessKey(eKeys Key) { - if(Key==kBack) - return osEnd; + if(Key==kBack) + return osEnd; + + if(Key==kEditCut) + { + free(Cut); + Cut=strdup(LastReplayed()); - return cReplayControl::ProcessKey(Key); + cRecording recording(LastReplayed()); + free(Cutted); + Cutted=strdup(recording.PrefixFileName('%')); + } + + return cReplayControl::ProcessKey(Key); } diff --git a/myreplaycontrol.h b/myreplaycontrol.h index 01980ac..2819dd1 100644 --- a/myreplaycontrol.h +++ b/myreplaycontrol.h @@ -1,8 +1,8 @@ -#include <vdr/menu.h> - class myReplayControl:public cReplayControl { public: + static char *Cut; + static char *Cutted; eOSState ProcessKey(eKeys Key); ~myReplayControl(); }; diff --git a/patchfont.c b/patchfont.c index d85bcd2..72c023b 100644 --- a/patchfont.c +++ b/patchfont.c @@ -28,7 +28,7 @@ void PatchFont(eDvbFont DvbFont) font_data[i*num_rows+0] = (num_char>=127 && num_char<=129)?6:char_data->width; font_data[i*num_rows+1] = char_data->height; - // new marker + // alternative new marker if(num_char==128&&mysetup.PatchNew) { if(DvbFont==fontOsd) @@ -198,6 +198,102 @@ void PatchFont(eDvbFont DvbFont) font_data[i*num_rows+ 1]=22; } } + // scissor + else if(num_char==132) + { + if(DvbFont==fontOsd) + { + font_data[i*num_rows+ 0]=22; + font_data[i*num_rows+ 1]=27; + font_data[i*num_rows+ 8]=0x018060; // .. ...# #... .... .##. .... + font_data[i*num_rows+ 9]=0x018060; // .. ...# #... .... .##. .... + font_data[i*num_rows+10]=0x00c0c0; // .. .... ##.. .... ##.. .... + font_data[i*num_rows+11]=0x00c0c0; // .. .... ##.. .... ##.. .... + font_data[i*num_rows+12]=0x006180; // .. .... .##. ...# #... .... + font_data[i*num_rows+13]=0x006180; // .. .... .##. ...# #... .... + font_data[i*num_rows+14]=0x003300; // .. .... ..## ..## .... .... + font_data[i*num_rows+15]=0x003300; // .. .... ..## ..## .... .... + font_data[i*num_rows+16]=0x001e00; // .. .... ...# ###. .... .... + font_data[i*num_rows+17]=0x001e00; // .. .... ...# ###. .... .... + font_data[i*num_rows+18]=0x003300; // .. .... ..## ..## #... .... + font_data[i*num_rows+19]=0x01f3e0; // .. ...# #### ..## ###. .... + font_data[i*num_rows+20]=0x033330; // .. ..## ..## ..## ..## .... + font_data[i*num_rows+21]=0x033330; // .. ..## ..## ..## ..## .... + font_data[i*num_rows+22]=0x033330; // .. ..## ..## ..## ..## .... + font_data[i*num_rows+23]=0x033330; // .. ..## ..## ..## ..## .... + font_data[i*num_rows+24]=0x01f3e0; // .. ...# #### ..## ###. .... + } + else + { + font_data[i*num_rows+ 0]=22; + font_data[i*num_rows+ 1]=22; + font_data[i*num_rows+ 5]=0x018060; // .. ...# #... .... .##. .... + font_data[i*num_rows+ 6]=0x018060; // .. ...# #... .... .##. .... + font_data[i*num_rows+ 7]=0x00c0c0; // .. .... ##.. .... ##.. .... + font_data[i*num_rows+ 8]=0x00c0c0; // .. .... ##.. .... ##.. .... + font_data[i*num_rows+ 9]=0x006180; // .. .... .##. ...# #... .... + font_data[i*num_rows+10]=0x006180; // .. .... .##. ...# #... .... + font_data[i*num_rows+11]=0x003300; // .. .... ..## ..## .... .... + font_data[i*num_rows+12]=0x003300; // .. .... ..## ..## .... .... + font_data[i*num_rows+13]=0x001e00; // .. .... ...# ###. .... .... + font_data[i*num_rows+14]=0x001e00; // .. .... ...# ###. .... .... + font_data[i*num_rows+15]=0x003300; // .. .... ..## ..## #... .... + font_data[i*num_rows+16]=0x01f3e0; // .. ...# #### ..## ###. .... + font_data[i*num_rows+17]=0x033330; // .. ..## ..## ..## ..## .... + font_data[i*num_rows+18]=0x033330; // .. ..## ..## ..## ..## .... + font_data[i*num_rows+19]=0x033330; // .. ..## ..## ..## ..## .... + font_data[i*num_rows+20]=0x033330; // .. ..## ..## ..## ..## .... + font_data[i*num_rows+21]=0x01f3e0; // .. ...# #### ..## ###. .... + } + } + // move symbol + else if(num_char==133) + { + if(DvbFont==fontOsd) + { + font_data[i*num_rows+ 0]=22; + font_data[i*num_rows+ 1]=27; + font_data[i*num_rows+ 8]=0x000000; // .. .... .... .... .... .... + font_data[i*num_rows+ 9]=0x0001fe; // .. .... .... .... .... .... + font_data[i*num_rows+10]=0x0001fe; // .. .... .... .... .... .... + font_data[i*num_rows+11]=0x000186; // .. .... .... .... .... .... + font_data[i*num_rows+12]=0x000006; // .. .... .... .... .... .... + font_data[i*num_rows+13]=0x0ff7e6; // .. .... .... .... .... .... + font_data[i*num_rows+14]=0x0fe3c6; // .. .... .... .... .... .... + font_data[i*num_rows+15]=0x0c07c6; // .. .... .... .... .... .... + font_data[i*num_rows+16]=0x0c1f86; // .. .... .... .... .... .... + font_data[i*num_rows+17]=0x0c7906; // .. .... .... .... .... .... + font_data[i*num_rows+18]=0x0de07e; // .. .... .... .... .... .... + font_data[i*num_rows+19]=0x0d80fe; // .. .... .... .... .... .... + font_data[i*num_rows+20]=0x0c3000; // .. .... .... .... .... .... + font_data[i*num_rows+21]=0x0c3000; // .. .... .... .... .... .... + font_data[i*num_rows+22]=0x0ff000; // .. .... .... .... .... .... + font_data[i*num_rows+23]=0x0ff000; // .. .... .... .... .... .... + font_data[i*num_rows+24]=0x000000; // .. .... .... .... .... .... + } + else + { + font_data[i*num_rows+ 0]=22; + font_data[i*num_rows+ 1]=22; + font_data[i*num_rows+ 5]=0x0001fe; // .. .... .... ...# #### ###. + font_data[i*num_rows+ 6]=0x0001fe; // .. .... .... ...# #### ###. + font_data[i*num_rows+ 7]=0x000186; // .. .... .... ...# #... .##. + font_data[i*num_rows+ 8]=0x000186; // .. .... .... ...#.#... .##. + font_data[i*num_rows+ 9]=0x000006; // .. .... .... .... .... .##. + font_data[i*num_rows+10]=0x1fe7e6; // .# #### ###. .### ###. .##. + font_data[i*num_rows+11]=0x1fe3c6; // .# #### ###. ..## ##.. .##. + font_data[i*num_rows+12]=0x1847c6; // .# #... .#.. .### ##.. .##. + font_data[i*num_rows+13]=0x181f86; // .# #... ...# #### #... .##. + font_data[i*num_rows+14]=0x187906; // .# #... .### #..# .... .##. + font_data[i*num_rows+15]=0x19e07e; // .# #..# ###. .... .### ###. + font_data[i*num_rows+16]=0x1981fe; // .# #..# #... ...# #### ###. + font_data[i*num_rows+17]=0x182000; // .# #... ..#. .... .... .... + font_data[i*num_rows+18]=0x186000; // .# #... .##. .... .... .... + font_data[i*num_rows+19]=0x186000; // .# #... .##. .... .... .... + font_data[i*num_rows+20]=0x1fe000; // .# #### ###. .... .... .... + font_data[i*num_rows+21]=0x1fe000; // .# #### ###. .... .... .... + } + } else { for(j = 0; j<(int)char_data->height; j++) @@ -2,13 +2,48 @@ * See the README file for copyright information and how to reach the author. */ +#include <string> +#include <fstream> +#include <iostream> #include <vdr/plugin.h> #include <vdr/videodir.h> #include <vdr/recording.h> #include "tools.h" #include "mymenusetup.h" +using namespace std; + #define CONFIGFILE "/extrecmenu.sort.conf" +#define BUFFERSIZE 20972 // (2*1024*1024)/100 + +MoveBetweenFileSystems MoveThread; + +string myStrEscape(string S,const char *Chars) +{ + int i=0; + while(Chars[i]!=0) + { + string::size_type j=0; + while((j=S.find(Chars[i],j))!=string::npos) + { + S.insert(j,1,'\\'); + j+=2; + } + i++; + } + return S; +} + +string myStrReplace(string S,char C1,char C2) +{ + string::size_type i=0; + while((i=S.find(C1,i))!=string::npos) + { + S.replace(i,1,1,C2); + i++; + } + return S; +} // --- SortList --------------------------------------------------------------- void SortList::ReadConfigFile() @@ -50,84 +85,252 @@ bool SortList::Find(char *Path) return false; } -// --- MoveRename ------------------------------------------------------------- -// creates the necassery directories and renames the given old name to the new name -bool MoveRename(const char *OldName,const char *NewName,cRecording *Recording,bool Move) +// --- MoveBetweenFileSystems ------------------------------------------------- +MoveBetweenFileSystems::MoveBetweenFileSystems():cThread("moving files between filesystems") { - char *buf=NULL; +} - // is OldName different to NewName - if(!strcmp(OldName,NewName)) - return true; +bool MoveBetweenFileSystems::Start(string OldName,string NewName,cRecording *Recording) +{ + oldname=OldName; + newname=NewName; + recording=Recording; + + return cThread::Start(); +} - // move/rename a recording - if(Recording) - { - if(!MakeDirs(NewName,true)) +bool MoveBetweenFileSystems::IsMoving(string Path) +{ + if(Active()) { - Skins.Message(mtError,tr("Creating directories failed!")); - return false; + if(recording) + { + if(Path==oldname) + return true; + } + else + { + if(!strncmp(oldname.c_str(),Path.c_str(),oldname.length())) + return true; + } } - isyslog("[extrecmenu] moving %s to %s",OldName,NewName); - - if(rename(OldName,NewName)==-1) + return false; +} + +bool MoveBetweenFileSystems::Move(string From,string To,cRecording *Recording) +{ + if(Recording) { - esyslog("[extrecmenu] %s",strerror(errno)); - Skins.Message(mtError,tr("Rename/Move failed!")); - return false; + isyslog("[extrecmenu] moving %s to %s",From.c_str(),To.c_str()); + + DIR *dir; + struct dirent *entry; + dir=opendir(From.c_str()); + while((entry=readdir(dir))!=NULL) + { + string from,to; + from=From+'/'+entry->d_name; + to=To+'/'+entry->d_name; + + struct stat st; + stat(from.c_str(),&st); + if(S_ISREG(st.st_mode)) + { + isyslog("[extrecmenu] moving %s",entry->d_name); + + time_t copytime=time(NULL); + + char buf[BUFFERSIZE]; + int infile=-1,outfile=-1; + struct stat from_stat; + ssize_t sz,sz_read=1,sz_write; + + if(stat(from.c_str(),&from_stat)!=0 || + (infile=open(from.c_str(),O_RDONLY))<0 || + (outfile=open(to.c_str(),O_WRONLY|O_CREAT|O_EXCL,from_stat.st_mode))<0) + { + if(infile>=0) + close(infile); + closedir(dir); + + Skins.Message(mtError,strerror(errno)); + return false; + } + + while(sz_read>0 && (sz_read=read(infile,buf,BUFFERSIZE))>0) + { + sz_write=0; + do + { + if((sz=write(outfile,buf+sz_write,sz_read-sz_write))<0) + { + close(infile); + close(outfile); + closedir(dir); + + Skins.Message(mtError,tr("Rename/Move failed!")); + esyslog("[extrecmenu] %s",strerror(errno)); + return false; + } + sz_write+=sz; + } + while(sz_write<sz_read); + + if(mysetup.LimitBandwidth) + usleep(10); + } + close(infile); + close(outfile); + + copytime=time(NULL)-copytime; + isyslog("[extrecmenu] needed %d secs for %d bytes",(int)copytime,(int)st.st_size); + } + } + closedir(dir); + + Recordings.AddByName(To.c_str()); + Recording->Delete(); + Recordings.DelByName(From.c_str()); + + string buf="move \""; + buf+=myStrEscape(From,"'\\\"$"); + buf+="\""; + cRecordingUserCommand::InvokeCommand(buf.c_str(),To.c_str()); } - - // set user command for '-r'-option of VDR - asprintf(&buf,"%s \"%s\"",Move?"move":"rename",*strescape(OldName,"'\\\"$")); - cRecordingUserCommand::InvokeCommand(buf,NewName); - free(buf); - - // update recordings list - Recordings.AddByName(NewName); - Recordings.Del(Recording); - } - // move/rename a directory - else - { - // is the new path within the old? - asprintf(&buf,"%s/",OldName); // we have to append a / to make sure that we search for a directory - if(!strncmp(buf,NewName,strlen(buf))) + else { - Skins.Message(mtError,tr("Moving into own sub-directory not allowed!")); - free(buf); - return false; + string buf; + buf=From+'/'; + if(!strncmp(buf.c_str(),To.c_str(),buf.length())) + { + Skins.Message(mtError,tr("Moving into own sub-directory not allowed!")); + return false; + } + + myRecList *list=new myRecList(); + for(cRecording *recording=Recordings.First();recording;recording=Recordings.Next(recording)) + list->Add(new myRecListItem(recording)); + + myRecListItem *item=list->First(); + while(item) + { + if(!strncmp(From.c_str(),item->recording->FileName(),From.length())) + { + char *buffer=NULL; + buffer=strdup(From.c_str()+strlen(VideoDirectory)+1); + buffer=ExchangeChars(buffer,false); + + if(strcmp(item->recording->Name(),buffer)) + { + buf=To+(item->recording->FileName()+From.length()); + if(!MakeDirs(buf.c_str(),true)) + { + Skins.Message(mtError,tr("Rename/Move failed!")); + esyslog("[extrecmenu] %s",strerror(errno)); + free(buffer); + delete list; + return false; + } + if(Move(item->recording->FileName(),buf,item->recording)==false) + { + free(buffer); + delete list; + return false; + } + } + free(buffer); + } + item=list->Next(item); + } + delete list; } - free(buf); - - // build my own recordings list - myRecList *list=new myRecList(); - for(cRecording *recording=Recordings.First();recording;recording=Recordings.Next(recording)) - list->Add(new myRecListItem(recording)); + return true; +} + +void MoveBetweenFileSystems::Action() +{ + Move(oldname,newname,recording); +} + +// --- MoveRename ------------------------------------------------------------- +// creates the necassery directories and renames the given old name to the new name +bool MoveRename(const char *OldName,const char *NewName,cRecording *Recording,bool Move) +{ + char *buf=NULL; + + if(!strcmp(OldName,NewName)) + return true; - myRecListItem *item=list->First(); - while(item) + if(Recording) { - // find recordings within the path of OldName - if(!strncmp(OldName,item->recording->FileName(),strlen(OldName))) - { - buf=strdup(OldName+strlen(VideoDirectory)+1); - buf=ExchangeChars(buf,false); - - // exclude recordings with the same name as OldName - if(strcmp(item->recording->Name(),buf)) + isyslog("[extrecmenu] moving %s to %s",OldName,NewName); + + if(rename(OldName,NewName)==-1) { - free(buf); - asprintf(&buf,"%s%s",NewName,item->recording->FileName()+strlen(OldName)); - // move/rename the recording - MoveRename(item->recording->FileName(),buf,item->recording,Move); + remove(NewName); // remove created directory + Skins.Message(mtError,tr("Rename/Move failed!")); + esyslog("[extrecmenu] %s",strerror(errno)); + return false; } + + Recordings.AddByName(NewName); + Recordings.Del(Recording); + + // set user command for '-r'-option of VDR + asprintf(&buf,"%s \"%s\"",Move?"move":"rename",*strescape(OldName,"'\\\"$")); + cRecordingUserCommand::InvokeCommand(buf,NewName); free(buf); - } - item=list->Next(item); } - delete list; - } - return true; + else + { + // is the new path within the old? + asprintf(&buf,"%s/",OldName); // we have to append a / to make sure that we search for a directory + if(!strncmp(buf,NewName,strlen(buf))) + { + Skins.Message(mtError,tr("Moving into own sub-directory not allowed!")); + free(buf); + return false; + } + free(buf); + + myRecList *list=new myRecList(); + for(cRecording *recording=Recordings.First();recording;recording=Recordings.Next(recording)) + list->Add(new myRecListItem(recording)); + + myRecListItem *item=list->First(); + while(item) + { + if(!strncmp(OldName,item->recording->FileName(),strlen(OldName))) + { + buf=strdup(OldName+strlen(VideoDirectory)+1); + buf=ExchangeChars(buf,false); + + if(strcmp(item->recording->Name(),buf)) + { + free(buf); + asprintf(&buf,"%s%s",NewName,item->recording->FileName()+strlen(OldName)); + if(!MakeDirs(buf,true)) + { + Skins.Message(mtError,tr("Creating directories failed!")); + esyslog("[extrecmenu] %s",strerror(errno)); + free(buf); + delete list; + return false; + } + if(MoveRename(item->recording->FileName(),buf,item->recording,Move)==false) + { + free(buf); + delete list; + return false; + } + } + free(buf); + } + item=list->Next(item); + } + delete list; + } + return true; } // --- myRecListItem ---------------------------------------------------------- @@ -1,44 +1,57 @@ -#include <string> -#include <fstream> -#include <iostream> - -using namespace std; +std::string myStrReplace(std::string S,char C1,char C2); class SortListItem:public cListObject { - private: - string path; - public: - SortListItem(const char *Path){path=Path;}; - const char *Path(){return path.c_str();} + private: + std::string path; + public: + SortListItem(const char *Path){path=Path;}; + const char *Path(){return path.c_str();} }; class SortList:public cList<SortListItem> { - public: - void ReadConfigFile(); - void WriteConfigFile(); - bool Find(char *Path); + public: + void ReadConfigFile(); + void WriteConfigFile(); + bool Find(char *Path); }; +class MoveBetweenFileSystems:public cThread +{ + private: + std::string oldname; + std::string newname; + cRecording *recording; + bool Move(std::string From,std::string To,cRecording *Recording); + protected: + virtual void Action(); + public: + MoveBetweenFileSystems(); + bool Start(std::string OldName,std::string NewName,cRecording *Recording); + bool IsMoving(std::string Path); +}; + +extern MoveBetweenFileSystems MoveThread; + bool MoveRename(const char *OldName,const char *NewName,cRecording *Recording,bool Move); class myRecListItem:public cListObject { - friend class myRecList; - private: - static bool SortByName; - char *filename; - static char *StripEpisodeName(char *s); - public: - myRecListItem(cRecording *Recording); - ~myRecListItem(); - virtual int Compare(const cListObject &ListObject)const; - cRecording *recording; + friend class myRecList; + private: + static bool SortByName; + char *filename; + static char *StripEpisodeName(char *s); + public: + myRecListItem(cRecording *Recording); + ~myRecListItem(); + virtual int Compare(const cListObject &ListObject)const; + cRecording *recording; }; class myRecList:public cList<myRecListItem> { - public: - void Sort(bool SortByName); + public: + void Sort(bool SortByName); }; |