diff --git a/data/icons/Makefile.am b/data/icons/Makefile.am index be51314e4..67d8b603d 100644 --- a/data/icons/Makefile.am +++ b/data/icons/Makefile.am @@ -127,6 +127,7 @@ install_DATA += \ hint_tvradio_switch.png \ hint_vfd.png \ hint_video.png \ + hint_ytplay.png \ home.png \ icon_green.png \ icon_movieplayer.png \ diff --git a/data/icons/hint_ytplay.png b/data/icons/hint_ytplay.png new file mode 100644 index 000000000..0d687cca0 Binary files /dev/null and b/data/icons/hint_ytplay.png differ diff --git a/data/locale/Makefile.am b/data/locale/Makefile.am index feed9a7bc..845a8b4f4 100644 --- a/data/locale/Makefile.am +++ b/data/locale/Makefile.am @@ -1,6 +1,7 @@ installdir = $(DATADIR)/neutrino/locale locale = \ + nederlands.locale \ deutsch.locale \ english.locale @@ -12,7 +13,6 @@ locale_unmaintained = \ unmaintained/czech.locale \ unmaintained/francais.locale \ unmaintained/italiano.locale \ - unmaintained/nederlands.locale \ unmaintained/polski.locale \ unmaintained/portugues.locale \ unmaintained/russkij.locale \ diff --git a/data/locale/english.locale b/data/locale/english.locale index 1d3a0c7dc..89f1aee37 100644 --- a/data/locale/english.locale +++ b/data/locale/english.locale @@ -98,6 +98,7 @@ GENRE.TRAVEL_HOBBIES.7 gardening GENRE.UNKNOWN unknown apidselector.head Select language audio.srs_algo Type +audio.srs_algo_heavy Heavy audio.srs_algo_light Light audio.srs_algo_normal Normal audio.srs_iq SRS TruVolume algo @@ -325,7 +326,7 @@ eventfinder.search_all_epg whole eventfinder.search_within_epg Search within eventfinder.search_within_list Search within eventfinder.searching Search for keyword in EPG... -eventfinder.start_search Start Search +eventfinder.start_search Start Search eventlist.additional Additional informations eventlist.name Eventlist eventlistbar.channelswitch schedule @@ -856,6 +857,7 @@ menu.hint_key_mpplay Assign button to resume record/file playback menu.hint_key_mpplugin Assign button to start selected plugin\nwhile playing record/file menu.hint_key_mprewind Assign button to rewind record playback menu.hint_key_mpstop Assign button to stop record/file playback +menu.hint_key_mpsubtitle Assign button to show subtitle selection menu.hint_key_mptime Assign button to show play time\nleft time menu.hint_key_mptimeshift Assign button to start timeshift menu.hint_key_pagedown Assign button to show next items page @@ -1119,6 +1121,7 @@ menu.hint_video_scart_mode Select analog output mode for SCART connectors menu.hint_volume Configure Volume GUI options menu.hint_volume_digits Numeric display of the volumebar on/off menu.hint_volume_pos Select volume indicator position +menu.hint_ytplay Play selected youtube feeds menu.hint_zap_cycle When swithing channels, stay in current bouquet menu.next Next (press Menu to quit) messagebox.back Back @@ -1352,6 +1355,22 @@ moviebrowser.update_if_dest_empty_only Copy if destination is empty only moviebrowser.use_dir Use directory moviebrowser.use_movie_dir Use movie directory moviebrowser.use_rec_dir Use record directory +moviebrowser.yt_error Failed to load youtube feed +moviebrowser.yt_max_results Max results to fetch +moviebrowser.yt_most_discussed Most discussed +moviebrowser.yt_most_popular Most popular +moviebrowser.yt_most_resent Most resent +moviebrowser.yt_most_responded Most responded +moviebrowser.yt_most_shared Most shared +moviebrowser.yt_next_results Next results +moviebrowser.yt_on_the_web Trending videos +moviebrowser.yt_prev_results Previous results +moviebrowser.yt_recently_featured Recently featured +moviebrowser.yt_region Region +moviebrowser.yt_related Related videos +moviebrowser.yt_search Search keyword +moviebrowser.yt_top_favorites Top favorites +moviebrowser.yt_top_rated Top rated movieplayer.bookmark Bookmarks movieplayer.bookmarkname Bookmarkname movieplayer.bookmarkname_hint1 Enter a name for your new bookmark @@ -1373,6 +1392,7 @@ movieplayer.tshelp7 skip approx. 1 minute movieplayer.tshelp8 approx. 5 minutes back movieplayer.tshelp9 skip approx. 5 minutes movieplayer.tsplayback Play TS +movieplayer.ytplayback Youtube feeds playback mpkey.audio Audio track mpkey.bookmark save bookmark mpkey.forward Forward @@ -1381,6 +1401,7 @@ mpkey.play Play mpkey.plugin Run plugin mpkey.rewind Rewind mpkey.stop Stop +mpkey.subtitle Subtitles mpkey.time Show time networkmenu.apply_settings Changes are applied... networkmenu.apply_settings_now Do you want to apply settings now? diff --git a/data/locale/unmaintained/dutch.locale b/data/locale/nederlands.locale similarity index 100% rename from data/locale/unmaintained/dutch.locale rename to data/locale/nederlands.locale diff --git a/data/locale/unmaintained/nederlands.locale b/data/locale/unmaintained/nederlands.locale deleted file mode 100644 index b23984063..000000000 --- a/data/locale/unmaintained/nederlands.locale +++ /dev/null @@ -1,667 +0,0 @@ -EPGMenu.epgplus Preview overzicht -EPGMenu.eventinfo Info over uitzending -EPGMenu.eventlist Preview programma -EPGMenu.head EPG - Programma Informatie -EPGMenu.streaminfo technische Informatie -EPGPlus.actions Aktie's -EPGPlus.head Preview (EPG Plus) -EPGPlus.next_bouquet Volgend Boeket -EPGPlus.options Optie's -EPGPlus.page_down Vorige pagina. -EPGPlus.page_up Volgende pagina. -EPGPlus.prev_bouquet Vorig Boeket. -EPGPlus.record Opname -EPGPlus.refresh_epg Aktualiseren -EPGPlus.remind Herinneren -EPGPlus.scroll_mode Scroll Mode -EPGPlus.select_font_name Lettertype kiezen -EPGPlus.stretch_mode Stretch Mode -EPGPlus.swap_mode Bladeren -EPGPlus.view_mode Mode -GENRE.ARTS.0 Kunst/ cultuur -GENRE.ARTS.1 Beeldende kunst -GENRE.ARTS.10 kunst/culturele magazines -GENRE.ARTS.11 mode -GENRE.ARTS.2 fijne kunst -GENRE.ARTS.3 religie -GENRE.ARTS.4 populair cultuur/traditionele kunst -GENRE.ARTS.5 literatuur -GENRE.ARTS.6 film/cinema -GENRE.ARTS.7 experimentele film/video -GENRE.ARTS.8 uitzendingen/pers -GENRE.ARTS.9 nieuwe media -GENRE.CHILDRENs_PROGRAMMES.0 Kinderprogramma/ animatie -GENRE.CHILDRENs_PROGRAMMES.1 Kleuterprogramma -GENRE.CHILDRENs_PROGRAMMES.2 Ontspanningsprogramma (leeftijd: 6 tot 14) -GENRE.CHILDRENs_PROGRAMMES.3 Ontspanningsprogramma (leeftijd: 10 tot 16) -GENRE.CHILDRENs_PROGRAMMES.4 informationeel/educationeel/schoolprogramma -GENRE.CHILDRENs_PROGRAMMES.5 tekenfilms/animatie -GENRE.DOCUS_MAGAZINES.0 documentatie/magazine -GENRE.DOCUS_MAGAZINES.1 natuur/dieren/omgeving -GENRE.DOCUS_MAGAZINES.2 technologie/natuurkunde -GENRE.DOCUS_MAGAZINES.3 Geneeskunde/psychologie/ -GENRE.DOCUS_MAGAZINES.4 Vreemde landen/expeditie's -GENRE.DOCUS_MAGAZINES.5 sociale- en spirituele wetenschappen -GENRE.DOCUS_MAGAZINES.6 andere opvoedingen -GENRE.DOCUS_MAGAZINES.7 Talen -GENRE.MOVIE.0 film/drama -GENRE.MOVIE.1 detectieve/thriller -GENRE.MOVIE.2 aventuren/western/oorlog -GENRE.MOVIE.3 science-fiction/fantasy/horror -GENRE.MOVIE.4 comedy -GENRE.MOVIE.5 soap/melodrama/folkloristisch -GENRE.MOVIE.6 romantiek -GENRE.MOVIE.7 ernstig/klassiek/religieus/historische film/drama -GENRE.MOVIE.8 +18 / drama -GENRE.MUSIC_DANCE.0 muziek / ballet / dance -GENRE.MUSIC_DANCE.1 rock/pop -GENRE.MUSIC_DANCE.2 klassieke music -GENRE.MUSIC_DANCE.3 folk/traditionele muziek -GENRE.MUSIC_DANCE.4 jazz -GENRE.MUSIC_DANCE.5 musical/opera -GENRE.MUSIC_DANCE.6 ballet -GENRE.NEWS.0 nieuws -GENRE.NEWS.1 nieuws/weerbulletin -GENRE.NEWS.2 nieuwsmagazine -GENRE.NEWS.3 documentaire -GENRE.NEWS.4 discussie/interview/debat -GENRE.SHOW.0 Show / Spelshow -GENRE.SHOW.1 game show/quiz/contest -GENRE.SHOW.2 varieteit show -GENRE.SHOW.3 talk show -GENRE.SOCIAL_POLITICAL.0 sociale en politieke evenementen/zaken -GENRE.SOCIAL_POLITICAL.1 magazines/verslagen/documentaire -GENRE.SOCIAL_POLITICAL.2 economische /sociale adviezen -GENRE.SOCIAL_POLITICAL.3 Opmerkzame personen -GENRE.SPORTS.0 sport -GENRE.SPORTS.1 speciale evenementen (Olympische spelen,Wereldbeker, etc.) -GENRE.SPORTS.10 paardensport -GENRE.SPORTS.11 gevechtsporten -GENRE.SPORTS.2 sportmagazine -GENRE.SPORTS.3 Voetbal -GENRE.SPORTS.4 tennis/squash -GENRE.SPORTS.5 teamsporten -GENRE.SPORTS.6 atletiek -GENRE.SPORTS.7 motorsport -GENRE.SPORTS.8 watersport -GENRE.SPORTS.9 wintersport -GENRE.TRAVEL_HOBBIES.0 reizen en ontspanning -GENRE.TRAVEL_HOBBIES.1 tourisme/reizen -GENRE.TRAVEL_HOBBIES.2 werk -GENRE.TRAVEL_HOBBIES.3 autotoerisme -GENRE.TRAVEL_HOBBIES.4 fitness & gezondheid -GENRE.TRAVEL_HOBBIES.5 koken -GENRE.TRAVEL_HOBBIES.6 adverteren/shopping -GENRE.TRAVEL_HOBBIES.7 tuinieren -GENRE.UNKNOWN Onbekend -apids.hint_1 Geef de te streamen APIDs in -apids.hint_2 in hex-weergave scheiden met ' ' -apidselector.head Kies taal -audiomenu.PCMOffset Volume Decrease PCM -audiomenu.analogout Analoge uitgang -audiomenu.avs avs -audiomenu.dolbydigital Dolby Digital -audiomenu.monoleft mono links -audiomenu.monoright mono rechts -audiomenu.stereo stereo -audioplayer.add Voeg toe -audioplayer.artist_title Artiest, Titel -audioplayer.defdir Startdirectory -audioplayer.delete Wis -audioplayer.deleteall Wis alles -audioplayer.display_order display order -audioplayer.fastforward Vooruitspoelen -audioplayer.follow auto Kies huidig -audioplayer.head Audio Speellijst -audioplayer.highprio Hoge decoderingsprioriteit -audioplayer.id3scan Scannen van ID3 tags -audioplayer.keylevel key level -audioplayer.name Audioplayer -audioplayer.pause pauze -audioplayer.play Play -audioplayer.playing Huidig nummer -audioplayer.rewind terugspoelen -audioplayer.screensaver_timeout screensaver timeout (min, 0=uit) -audioplayer.shuffle shuffle -audioplayer.stop Stop -audioplayer.title_artist Titel, Artiest -audioplayerpicsettings.general Audioplayer/ beeldviewer -bookmarkmanager.delete Verwijderen -bookmarkmanager.name Favorieten -bookmarkmanager.rename Hernoemen -bookmarkmanager.select Kiezen -bouqueteditor.add Voeg toe -bouqueteditor.bouquetname Naam van het boeket -bouqueteditor.delete Wis -bouqueteditor.discardingchanges Wegzetten van de wijzigingen, even geduld a.u.b... -bouqueteditor.hide Verberg -bouqueteditor.lock Slot -bouqueteditor.move Verzet -bouqueteditor.name Boeket-editor -bouqueteditor.newbouquetname Nieuwe naam van het boeket -bouqueteditor.rename Hernoem -bouqueteditor.return Klaar -bouqueteditor.savechanges? Wilt u de wijzigingen bewaren? -bouqueteditor.savingchanges Bewaren van wijzigingen, even geduld... -bouqueteditor.switch Toevoegen/verwijderen -bouqueteditor.switchmode TV/Radio -bouquetlist.head Boeket -cablesetup.provider Kabelprovider -channellist.head Alle Services -channellist.nonefound Geen kanalen gevonden!\nVoer aub een scan uit\n(dbox-toets -> service) -channellist.since sinds -colorchooser.alpha alpha -colorchooser.blue blauw -colorchooser.green groen -colorchooser.red rood -colormenu.background Achtergrond -colormenu.background_head Achtergrond -colormenu.fade Fade menu's -colormenu.font lettergrootte -colormenu.menucolors Menu kleuren -colormenu.statusbar Infobar -colormenu.textcolor Tekstkleur -colormenu.textcolor_head Tekstkleur -colormenu.themeselect selecteer onderwerp -colormenu.timing OSD Tijd -colormenusetup.menucontent Vensterinhoud -colormenusetup.menucontent_inactive Vensterinhoud niet actief -colormenusetup.menucontent_selected Vensterinhoud geactiveerd -colormenusetup.menuhead Menu bovenkant -colorstatusbar.head Infobar -colorstatusbar.text Infobar -colorthememenu.classic_theme Classic thema -colorthememenu.dblue_theme Donkerblauw thema -colorthememenu.dvb2k_theme DVB2000 thema -colorthememenu.head Themakeuze -colorthememenu.neutrino_theme Neutrino thema -date.Apr April -date.Aug Augustus -date.Dec December -date.Feb Februari -date.Fri vrijdag -date.Jan Januari -date.Jul Juli -date.Jun Juni -date.Mar Maart -date.May Mei -date.Mon maandag -date.Nov November -date.Oct Oktober -date.Sat zaterdag -date.Sep September -date.Sun zondag -date.Thu donderdag -date.Tue dinsdag -date.Wed woensdag -epglist.head Event-list - %s -epglist.noevents EPG is niet beschikbaar -epgviewer.More_Screenings Meerdere Screenings op dit kanaal -epgviewer.nodetailed Geen details beschikbaar -epgviewer.notfound Geen EPG gevonden -eventlistbar.channelswitch Planning -eventlistbar.eventsort Sorteren -eventlistbar.recordevent Opnemen -favorites.addchannel Huidig kanaal zal toegevoegd worden\naan het boeket "mijn favorieten".\nDit zal enkele seconden durens... -favorites.bouquetname Mijn favorieten -favorites.bqcreated Bouquet "Mijn favorieten" is gemaakt...\n -favorites.chadded Huidig kanaal is aan de favorieten toegevoegd...\n -favorites.chalreadyinbq Huidig kanaal staat reeds bij de favorieten...\n -favorites.finalhint \nGebruik de boeketeditor om de favorieten aan te passen.\n -favorites.menueadd Voeg kanaal aan favorieten toe. -favorites.nobouquets Favorieten zijn alleen beschikbaar met geactiveerde boeketten. -filebrowser.delete Verwijderen -filebrowser.dodelete1 Moet -filebrowser.dodelete2 gewist worden? -filebrowser.filter.active Filter aan -filebrowser.filter.inactive Filter uit -filebrowser.head Browser -filebrowser.mark Markeer -filebrowser.nextpage Volgende pagina -filebrowser.prevpage Vorige pagina -filebrowser.scan Folders doorzoeken -filebrowser.select Kies -filebrowser.showrights Toon rechten -filebrowser.sort.date (datum) -filebrowser.sort.name (bestandsname) -filebrowser.sort.namedirsfirst (Dateiname2) -filebrowser.sort.size (Grootte) -filebrowser.sort.type (Type) -flashupdate.actionreadflash lezen -flashupdate.cantopenfile Kan bestand niet openen -flashupdate.cantopenmtd Kan het mtd-device niet openen -flashupdate.checkupdate Zoek nieuwe versie -flashupdate.currentversion_sep Huidige versie -flashupdate.currentversiondate Datum -flashupdate.currentversiontime Tijd -flashupdate.erasefailed Wissen van de flash mislukt -flashupdate.erasing Wissen van de flash -flashupdate.experimentalimage De gekozen image is nog niet getest.D.w.z.dat\nuw ontvanger misschien niet opstart na de update.\n\nWilt u echt deze versie updaten? -flashupdate.expertfunctions Expert-functie's -flashupdate.fileis0bytes De grootte van het bestand is 0 Byte -flashupdate.fileselector File kiezen -flashupdate.flashreadyreboot De image is succesvol geflashed.\nDe DBox zal nu herstarten. -flashupdate.getinfofile Haalt info versie op -flashupdate.getinfofileerror Geen info van de versie gevonden -flashupdate.getupdatefile Krijgt een update -flashupdate.getupdatefileerror Krijgt geen update -flashupdate.globalprogress Globale vooruitgang: -flashupdate.head Software Update -flashupdate.md5check controleer image -flashupdate.md5sumerror Image heeft fouten -flashupdate.msgbox De volgende nieuwe image is gevonden:\nDatum: %s, %s\nBaseImage: %s\nImageType: %s\n\nWilt u de nieuwe image nu downloaden en installeren? -flashupdate.msgbox_manual De volgende nieuwe image is gevonden:\nDatum: %s, %s\nBaseImage: %s\nImageType: %s\n\nWilt u deze versie nu installeren? -flashupdate.mtdselector Partitie kiezen -flashupdate.programmingflash Programmeren van de flash -flashupdate.proxypassword Paswoord -flashupdate.proxypassword_hint1 Geef het paswoord voor de proxyserver -flashupdate.proxypassword_hint2 Leeg betekent geen proxy -flashupdate.proxyserver Hostnaam -flashupdate.proxyserver_hint1 Geef naam of IP proxyserver, Gebruik host: poort -flashupdate.proxyserver_hint2 Geen invoer = geen proxy -flashupdate.proxyserver_sep Proxyserver -flashupdate.proxyusername Gebruikersnaam -flashupdate.proxyusername_hint1 Geef de gebruikersnaam van de proxyserver -flashupdate.proxyusername_hint2 Geen invoer= geen proxy-auth -flashupdate.readflash Lees de hele image -flashupdate.readflashmtd Lees een partitie -flashupdate.ready Klaar -flashupdate.reallyflashmtd Wilt u echt flashen?\n\nAls er een fout optreed is de image niet\ngeldig, De Dbox zal niet starten na het flashen.\n\nImagename: %s\nTarget: %s -flashupdate.savesuccess De image is succesvol bewaard \nonder %s. -flashupdate.selectimage Beschikbare Images -flashupdate.squashfs.noversion Versiecontrole van SquashFS gaat momenteel enkel via webupdating -flashupdate.titlereadflash Lezen Flash -flashupdate.titlewriteflash Writing Flash -flashupdate.updatemode Updatemode -flashupdate.updatemode_internet Internet -flashupdate.updatemode_manual Manueel (ftp) -flashupdate.url_file config file -flashupdate.versioncheck Controleer versie -flashupdate.writeflash Schrijf de hele image -flashupdate.writeflashmtd Schrijf een partitie -flashupdate.wrongbase Your Release cycle differs, unable to update\nwithout having installed the right version! -fontmenu.channellist kanalenlijst -fontmenu.epg EPG -fontmenu.eventlist Eventlist -fontmenu.gamelist Spellijst -fontmenu.head Settings lettergrootte -fontmenu.infobar Infobar -fontsize.channel_num_zap Directe selectie -fontsize.channellist Kanalenlijst -fontsize.channellist_descr Omschrijving -fontsize.channellist_number Nummer -fontsize.epg_date EPG datum -fontsize.epg_info1 EPG Info 1 -fontsize.epg_info2 EPG Info 2 -fontsize.epg_title EPG Titel -fontsize.eventlist_datetime datum/tijd -fontsize.eventlist_itemlarge groot -fontsize.eventlist_itemsmall klein -fontsize.eventlist_title Titel -fontsize.filebrowser_item filebrowser item -fontsize.gamelist_itemlarge groot -fontsize.gamelist_itemsmall klein -fontsize.hint lettertype instellen,\ngeduld aub... -fontsize.infobar_channame Kanaalnaam -fontsize.infobar_info info -fontsize.infobar_number Nummer -fontsize.infobar_small klein -fontsize.menu Menutekst -fontsize.menu_info Menu Info -fontsize.menu_title Menu Titel -gtxalpha.alpha1 Alpha 1 -gtxalpha.alpha2 Alpha 2 -infoviewer.epgnotload EPG niet geladen.... -infoviewer.epgwait wachten op EPG... -infoviewer.eventlist Event-Lijst -infoviewer.languages Geluid -infoviewer.motor_moving Positionering van de antenne -infoviewer.nocurrent Geen info beschikbaar voor dit programma -infoviewer.noepg EPG is niet beschikbaar -infoviewer.notavailable Kanaal is niet beschikbaar -infoviewer.selecttime Tijdskeuze -infoviewer.streaminfo Kenmerken -infoviewer.subservice Subservices -infoviewer.waittime Wacht op de tijd... -ipsetup.hint_1 Gebruik 0 tot 9, of Use 0..9, of gebruik Up/Down, -ipsetup.hint_2 OK bewaar, Home afbreken -keybindingmenu.RC Key herhaal-blocker -keybindingmenu.addrecord Voeg record timer toe -keybindingmenu.addrecord_head Voeg record timer toe -keybindingmenu.addremind add zapto timer -keybindingmenu.addremind_head add zapto timer -keybindingmenu.allchannels_on_ok Alle services -keybindingmenu.bouquetchannels_on_ok Huidig boeket -keybindingmenu.bouquetdown vorig boeket -keybindingmenu.bouquetdown_head keysetup vorig boeket back -keybindingmenu.bouquethandling Boeket-control -keybindingmenu.bouquetlist_on_ok Boeketlijst -keybindingmenu.bouquetup Volgend boeket -keybindingmenu.bouquetup_head keysetup Volgend boeket -keybindingmenu.cancel Sluit kanalenlijst -keybindingmenu.cancel_head Kanalenlijst gesloten -keybindingmenu.channeldown Kanaal omlaag -keybindingmenu.channeldown_head Keysetup channel down -keybindingmenu.channellist Kanaallijst -keybindingmenu.channelup kanaal omhoog -keybindingmenu.channelup_head Keysetup channel up -keybindingmenu.head Keybinding Setup -keybindingmenu.modechange Modechange -keybindingmenu.pagedown Volgende pagina -keybindingmenu.pagedown_head Keysetup page down -keybindingmenu.pageup Vorige pagina -keybindingmenu.pageup_head Keysetup page up -keybindingmenu.quickzap Quickzap -keybindingmenu.repeatblock generic delay -keybindingmenu.repeatblockgeneric Herhaal delay -keybindingmenu.sort Verander sorteervolgorde -keybindingmenu.sort_head Verander sorteervolgorde -keybindingmenu.subchanneldown subchannel omlaag -keybindingmenu.subchanneldown_head key subkanaal omlaag -keybindingmenu.subchannelup subkanaal omhoog -keybindingmenu.subchannelup_head key subkanaal omhoog -keybindingmenu.tvradiomode TV/Radio-mode -keybindingmenu.tvradiomode_head TV/Radio-mode -keychooser.head Setup nieuwe Key -keychooser.text1 Geef de nieuwe key in -keychooser.text2 Wacht enkele sec. om af te breken -keychoosermenu.currentkey Huidige key -keychoosermenu.setnew setup nieuwe key -keychoosermenu.setnone Geen key -languagesetup.head Setup Taal -languagesetup.select Taalkeuze -lcdcontroler.brightness normale helderheid -lcdcontroler.brightnessstandby Standby helderheid -lcdcontroler.contrast Contrast -lcdcontroler.head Display-instellingen -lcdmenu.head LCD Settings -lcdmenu.lcdcontroler Contrast / Helderheid -lcdmenu.statusline status lijn -lcdmenu.statusline.both Volume/Speelduur -lcdmenu.statusline.playtime Speelduur -lcdmenu.statusline.volume Volume -mainmenu.audioplayer Audioplayer -mainmenu.games Spelletjes -mainmenu.head Hoofdmenu -mainmenu.movieplayer Filmspeler -mainmenu.pausesectionsd Lees EPG -mainmenu.pictureviewer Weergeven van afbeeldingen -mainmenu.radiomode Radio-Mode -mainmenu.recording Opnemen -mainmenu.recording_start Start opname -mainmenu.recording_stop Stop opname -mainmenu.service Service -mainmenu.settings Instellingen -mainmenu.shutdown Uitschakelen -mainmenu.sleeptimer SleepTimer -mainmenu.tvmode TV-Mode -mainsettings.audio Geluid -mainsettings.colors Kleuren/lettertype -mainsettings.head Settings -mainsettings.keybinding Key Setup -mainsettings.language Taal -mainsettings.lcd LCD-display -mainsettings.misc Overige settings -mainsettings.network Netwerk -mainsettings.recording Opnemen -mainsettings.savesettingsnow Bewaar de settings nu -mainsettings.savesettingsnow_hint Even geduld, settings worden bewaard -mainsettings.video Beeld -menu.back Terug -messagebox.back terug -messagebox.cancel Annuleren -messagebox.discard Bewaren van de wijzigingen? -messagebox.error Fout -messagebox.info Informatie -messagebox.no Neen -messagebox.yes Ja -miscsettings.general Algemeen -miscsettings.head Overige settings -miscsettings.infobar_sat_display Satelliet display in infobar -miscsettings.shutdown_real standby -miscsettings.shutdown_real_rcdelay vertraagde shutdown -miscsettings.startbhdriver load BH-Mode drivers -motorcontrol.head Motor-Setup -movieplayer.bookmark Favorieten -movieplayer.bookmarkname Bookmark Naam -movieplayer.bookmarkname_hint1 Geef de naam voor de -movieplayer.bookmarkname_hint2 nieuwe favoriet in -movieplayer.fileplayback Bestand via VLC -movieplayer.head Filmplayer -movieplayer.toomanybookmarks U heeft te veel favorieten.\nEr moet een andere favoriet gewist worden. -movieplayer.tshelp Rood/Home Stop\nGROEN Kies audio track\nGEEL Pause/Continue\nBLUE Create bookmark\nd-box Show progress\n1 approx. 1 minute back\n3 skip approx. 1 minute\n4 approx. 5 minuten terug\n6 sla over ongeveer 5 minuten\n7 ongeveer 10 minuten terug\n9 sla ongeveer 10 minutes\nHelp: http://www.giggo.de/dbox2/movieplayer.html\n -movieplayer.tsplayback Speel TS -movieplayer.vlchelp ROOD/Home Stop\nGROEN Resync\nGEEL Pause/verder\nBLAUW Favoriet instellen\n1 ca. 1 Minuut terug\n3 ca. 1 Minuut vooruit\n4 ca. 5 Minuten terug\n6 ca. 5 Minuten vooruit\n7 ca. 10 Minuten terug\n9 ca. 10 Minuten vooruit\nHelp: http://www.giggo.de/dbox2/movieplayer.html\n -networkmenu.broadcast Broadcast -networkmenu.dhcp DHCP -networkmenu.gateway Standaard Gateway -networkmenu.ipaddress IP-Addres -networkmenu.mount NFS/CIFS -networkmenu.nameserver Nameserver -networkmenu.netmask Netmasker -networkmenu.setupnow Netwerk nu activeren -networkmenu.setuponstartup Netwerk activeren bij opstarten -networkmenu.show Toon actieve netwerksettings -networkmenu.test Test nu het netwerk -nfs.alreadymounted directory reeds gemount -nfs.automount mount bij starten -nfs.dir directory/share -nfs.ip NFS/CIFS Server IP -nfs.localdir plaatselijke directory -nfs.mount Mount NFS/CIFS volume -nfs.mount_options mountoptie's -nfs.mounterror mountfout -nfs.mounterror_notsup Type filesysteem niet ondersteund -nfs.mountnow direct mounten -nfs.mounttimeout mountfout: timeout -nfs.password paswoord Common Internet File System (CIFS) -nfs.remount Lijst opnieuw mounten -nfs.type type -nfs.type_cifs Common Internet File System (CIFS) -nfs.type_nfs Network File System (NFS) -nfs.umount Umount NFS/CIFS volume -nfs.umounterror umountingfout: volume -nfs.username Gebruikersnaam Common Internet File System (CIFS) -nfsmenu.head NFS/CIFS instellingen -nvod.percentage (%d%% over) -nvod.starting (start binnen %d minuten) -nvodselector.directormode Direct-Mode -nvodselector.head Kies starttijd -nvodselector.subservice Kies Subservice -options.default Reset naar standaard -options.fb Framebuffer -options.null Null -options.off Uit -options.on Aan -options.serial Serieel -parentallock.changepin verander PIN code -parentallock.changepin_hint1 Geef hier de nieuwe PIN-code in! -parentallock.changetolocked on locked bouquets -parentallock.head Voer PIN-code v.h. kinderslot in -parentallock.lockage Programma op slot -parentallock.lockage12 Voor jonger dan 12j -parentallock.lockage16 Voor jonger dan 16j -parentallock.lockage18 Voor jonger dan 18j -parentallock.lockedprogram Gesloten programma (vanaf %d jaar en hoger) -parentallock.never nooit -parentallock.onsignal Bij uitzenden op slot -parentallock.parentallock Kinderslot -parentallock.prompt prompt voor PIN -pictureviewer.defdir startdirectory -pictureviewer.head Weergave van afbeeldingen -pictureviewer.resize.color_average Geavanceerd -pictureviewer.resize.none Geen -pictureviewer.resize.simple Eenvoudig -pictureviewer.scaling schaal -pictureviewer.show Toon -pictureviewer.slide_time toon tijd van slideshow -pictureviewer.slideshow slideshow -pictureviewer.sortorder verander volgorde -pictureviewer.sortorder.date (datum) -pictureviewer.sortorder.filename (bestandsnaam) -ping.ok Bereikbaar door Ping -ping.protocol Niet bereikbaar (fout bij host of protocol) -ping.socket Niet bereikbaar (socketfout) -ping.unreachable Onbereikbaar door Ping -pinprotection.head Voer PIN-code in -pinprotection.wrongcode Foute PIN-Code! Probeer opnieuw -rclock.lockmsg Uw afstandsbediening van de DBox2 zal vergrendeld worden.\nOm de DBox2 vrij te geven druk op \nen op uw afstandsbediening. -rclock.menueadd Vergrendelen afstandsbediening -rclock.title Vergrendel afstandsbediening -rclock.unlockmsg Afstandsbediening in werking. -recordingmenu.defdir Opnamefolder -recordingmenu.file Direct (file) -recordingmenu.filesettingsseparator Direct opnemen -recordingmenu.off Uit -recordingmenu.server server -recordingmenu.server_mac MAC adres -recordingmenu.setupnow Activeer veranderingen -recordingmenu.stream_all_audio_pids Alle audiopids opnemen -recordingmenu.vcr vcr -recordtimer.announce Opname start in enkele minuten -repeatblocker.hint_1 Kortste tijd (in ms) tussen 2 drukken op de knop -repeatblocker.hint_2 Druk op 0 om de blocker uit te zetten (rood is spatie) -satsetup.diseqc DiSEqC -satsetup.diseqc10 DiSEqC 1.0 -satsetup.diseqc11 DiSEqC 1.1 -satsetup.diseqc12 DiSEqC 1.2 -satsetup.diseqcrepeat DiSEqC-herhaling -satsetup.extended DiSEqC-Settings -satsetup.extended_motor Motorsettings -satsetup.minidiseqc Mini-DiSEqC -satsetup.nodiseqc Geen DiSEqC -satsetup.satellite Satelliet -satsetup.smatvremote SMATV Remote Tuning -scants.actcable Kabel: -scants.actsatellite Satelliet: -scants.bouquet Boeket -scants.bouquet_create Maak een nieuw -scants.bouquet_erase Wis alles -scants.bouquet_leave Verlaat huidig -scants.bouquet_satellite Satellietboeket -scants.bouquet_update update -scants.channel Kanaal: -scants.failed Faling transponderscan! -scants.finished Transponderscan succesvol! -scants.freqdata Frequentie -scants.head Scan transponder -scants.numberofdataservices Data: -scants.numberofradioservices Radio: -scants.numberoftotalservices Totaal: -scants.numberoftvservices TV: -scants.provider Provider: -scants.startnow Start scan -scants.transponders Transponders: -screensetup.lowerright groen = setup lower right -screensetup.upperleft rood = setup upper left -servicemenu.head Service -servicemenu.reload Herlaad Kanalenlijst -servicemenu.reload_hint Even geduld, herladen van kanalenlijst -servicemenu.scants Service scan -servicemenu.update Software Update -settings.missingoptionsconffile De neutrino-settings zijn geupdate.\nNew Opties worden standaard gezet. -settings.noconffile Geen neutrino-settings gevonden.\nStandaart in gebruik. -shutdowntimer.announce Box zal uitschakelen in 1 min.\nUitschakelen aflassen? -sleeptimerbox.announce Sleeptimer in 1 min -sleeptimerbox.hint1 Schakel uit in ...minuten. (000=uit) -sleeptimerbox.hint2 dbox2 zal uitgaan na deze tijd. -sleeptimerbox.title Sleeptimer -streaminfo.aratio Aspect Ratio -streaminfo.aratio_unknown Aspect Ratio: onbekend -streaminfo.audiotype Audiotype -streaminfo.bitrate Bitrate -streaminfo.framerate Framerate -streaminfo.framerate_unknown Framerate: onbekend -streaminfo.head Stream-Informatie -streaminfo.not_available Niet beschikbaar -streaminfo.resolution Resolutie -streaming.busy Een of meerdere opnames zijn bezig.\nAls U deze oodschap krijgt en er is geen opname\nbezig herstart dan Neutrino. -streaming.dir_not_writable De opnamefolder is niet bereikbaar.\nOpnemen zal niet gaan. -streaming.write_error De opname is afgebroken \nomdat er een schrijffout opgetreden is. -stringinput.caps caps/geen caps -stringinput.clear Wis alles -timer.eventrecord.msg OK, niet OK -timer.eventrecord.title Opname plannen -timer.eventtimed.msg Dit programma is opgeslagen.\ndbox2 zal opstarten en \nschakelt naar dit programma op het gegeven tijdstip. -timer.eventtimed.title Programmeren -timerbar.channelswitch Overzicht -timerbar.recordevent Opnemen -timerlist.alarmtime Alarm time -timerlist.apids Audio PIDs -timerlist.bouquetselect Kies boeket -timerlist.channel Kanaal -timerlist.channelselect Kies kanaal -timerlist.delete Wis -timerlist.menumodify Pas timer aan -timerlist.menunew nieuwe timer -timerlist.message Boodschap -timerlist.moderadio Radio-kanalen -timerlist.modeselect Mode selection -timerlist.modetv TV-kanalen -timerlist.modify Modify -timerlist.name Timer list -timerlist.new Nieuwe timer -timerlist.program.unknown Programma onbekend -timerlist.reload Herlaad -timerlist.repeat Herhaal -timerlist.repeat.biweekly Tweewekelijks -timerlist.repeat.byeventdescription Bekijk programmatie -timerlist.repeat.daily Dagelijks -timerlist.repeat.fourweekly Vierweekelijks -timerlist.repeat.friday Vr -timerlist.repeat.monday Ma -timerlist.repeat.monthly Maandelijks -timerlist.repeat.once Eenmalig -timerlist.repeat.saturday Za -timerlist.repeat.sunday Zo -timerlist.repeat.thursday Do -timerlist.repeat.tuesday Di -timerlist.repeat.unknown Onbekend -timerlist.repeat.wednesday Woe -timerlist.repeat.weekdays Op weekdagen -timerlist.repeat.weekly weekelijks -timerlist.save Bewaar timer -timerlist.standby SB mode -timerlist.standby.off Standby laten -timerlist.standby.on Enter standby -timerlist.stoptime Stop time -timerlist.type Timer typ -timerlist.type.nextprogram Volgend programma -timerlist.type.record Opnemen -timerlist.type.remind Herinnering -timerlist.type.shutdown Uitschakelen -timerlist.type.sleeptimer Sleeptimer -timerlist.type.standby Standby -timerlist.type.unknown Onbekend -timerlist.type.zapto Zap naar -timerlist.weekdays Weekdagen -timerlist.weekdays.hint_1 Ma Di Wo Do Vr Za Zo -timerlist.weekdays.hint_2 'X'=timer '-' geen timer -timersettings.record_safety_time_after Stop opname tijdscorrectie -timersettings.record_safety_time_after.hint_1 Correctie van tijd in min. (00=uit). Deze tijd -timersettings.record_safety_time_after.hint_2 wordt toegevoegd aan iedere stoptijd van de timer. -timersettings.record_safety_time_before Start opname tijdscorrectie -timersettings.record_safety_time_before.hint_1 Correctie van tijd in min. (00=uit). Deze tijd -timersettings.record_safety_time_before.hint_2 will be deducted of every record timer. -timersettings.separator Timer instellingen -timing.chanlist Kanalenlijst -timing.epg Epg -timing.filebrowser Browser voor bestanden -timing.head OSD Timeouts -timing.hint_1 Tijd in sec. Na deze tijd zal de -timing.hint_2 infobar verdwijnen. -timing.infobar Infobar -timing.menu Menu -videomenu.csync Sync.-correctie -videomenu.screensetup Scherm Setup -videomenu.videoformat Formaat -videomenu.videoformat_169 16:9 -videomenu.videoformat_43 4:3 (LB) -videomenu.videoformat_431 4:3 (PS) -videomenu.videosignal Video uit -videomenu.videosignal_composite CVBS -videomenu.videosignal_rgb RGB + CVBS -videomenu.videosignal_svideo S-Video -videomenu.videosignal_yuv_c YUV + CVBS -videomenu.videosignal_yuv_v YUV + VBS -zaptotimer.announce Zapto timer in 1 minuut. diff --git a/lib/libcoolstream/playback_cs.h b/lib/libcoolstream/playback_cs.h index a9192bfdc..f65bdc6f0 100644 --- a/lib/libcoolstream/playback_cs.h +++ b/lib/libcoolstream/playback_cs.h @@ -11,6 +11,8 @@ #define __PLAYBACK_CS_H_ #include +#include +#include typedef enum { PLAYMODE_TS = 0, @@ -61,7 +63,9 @@ public: bool IsEnabled(void) const { return enabled; } void FindAllPids(playback_audio_pid_info_t *audiopids, uint16_t size, uint16_t *numpida); void FindAllPids(uint16_t *apids, unsigned short *ac3flags, uint16_t *numpida, std::string *language); - + void FindAllSubs(uint16_t *pids, unsigned short *supported, uint16_t *numpida, std::string *language); + bool SelectSubtitles(int pid); + void GetChapters(std::vector &positions, std::vector &titles); }; #endif // __PLAYBACK_CS_H_ diff --git a/lib/libcoolstream2/ca_cs.h b/lib/libcoolstream2/ca_cs.h index d7afc535f..ab14441aa 100644 --- a/lib/libcoolstream2/ca_cs.h +++ b/lib/libcoolstream2/ca_cs.h @@ -23,7 +23,7 @@ enum CA_INIT_MASK { enum CA_SLOT_TYPE { CA_SLOT_TYPE_SMARTCARD, CA_SLOT_TYPE_CI, - CA_SLOT_TYPE_ALL, + CA_SLOT_TYPE_ALL }; enum CA_MESSAGE_FLAGS { @@ -49,7 +49,7 @@ enum CA_MESSAGE_FLAGS { CA_MESSAGE_HAS_PARAM1_LONG = (1 << 19), CA_MESSAGE_HAS_PARAM2_LONG = (1 << 20), CA_MESSAGE_HAS_PARAM3_LONG = (1 << 21), - CA_MESSAGE_HAS_PARAM4_LONG = (1 << 22), + CA_MESSAGE_HAS_PARAM4_LONG = (1 << 22) }; enum CA_MESSAGE_MSGID { @@ -72,7 +72,7 @@ enum CA_MESSAGE_MSGID { CA_MESSAGE_MSG_EMM_ARRIVED, CA_MESSAGE_MSG_CHANNEL_CHANGE, CA_MESSAGE_MSG_GUI_READY, - CA_MESSAGE_MSG_EXIT, + CA_MESSAGE_MSG_EXIT }; typedef struct CA_MESSAGE { @@ -117,13 +117,13 @@ private: /// Thread method virtual void run(void); public: - /// Returns the number of CI slots - u32 GetNumberCISlots(void); - /// Returns the number of Smartcard slots - u32 GetNumberSmartCardSlots(void); + /// Returns the number of CA slots (CI+SC, CI, SC) + u32 GetNumberSlots(enum CA_SLOT_TYPE SlotType = CA_SLOT_TYPE_ALL); + u32 GetNumberCISlots(void) { return GetNumberSlots(CA_SLOT_TYPE_CI); } + u32 GetNumberSmartCardSlots(void) { return GetNumberSlots(CA_SLOT_TYPE_SMARTCARD); } /// Singleton static cCA *GetInstance(void); - /// Send PMT to a individual or to all available modules + /// Send PMT to a individual or to all available modules (DEPRECATED) bool SendPMT(int Unit, unsigned char *Data, int Len, enum CA_SLOT_TYPE SlotType = CA_SLOT_TYPE_ALL); /// Sends a message to the CA thread bool SendMessage(const CA_MESSAGE *Msg); @@ -154,9 +154,9 @@ public: /// Notify the module we closed the menu void MenuClose(enum CA_SLOT_TYPE, u32 Slot); /// Get the supported CAIDs - int GetCAIDS(CaIdVector & Caids); + int GetCAIDS(CaIdVector & Caids, enum CA_SLOT_TYPE SlotType = CA_SLOT_TYPE_ALL); /// Send a CA-PMT object and Raw unparsed PMT to the CA layer - bool SendCAPMT(u64 Source, u8 DemuxSource, u8 DemuxMask, const unsigned char *CAPMT, u32 CAPMTLen, const unsigned char *RawPMT, u32 RawPMTLen); + bool SendCAPMT(u64 ChannelId, u8 DemuxSource, u8 DemuxMask, const unsigned char *CAPMT, u32 CAPMTLen, const unsigned char *RawPMT, u32 RawPMTLen, enum CA_SLOT_TYPE SlotType = CA_SLOT_TYPE_ALL); /// Virtual destructor virtual ~cCA(); }; diff --git a/lib/libcoolstream2/playback_cs.h b/lib/libcoolstream2/playback_cs.h index 80ecb4ccd..f65bdc6f0 100644 --- a/lib/libcoolstream2/playback_cs.h +++ b/lib/libcoolstream2/playback_cs.h @@ -12,6 +12,7 @@ #include #include +#include typedef enum { PLAYMODE_TS = 0, @@ -62,7 +63,9 @@ public: bool IsEnabled(void) const { return enabled; } void FindAllPids(playback_audio_pid_info_t *audiopids, uint16_t size, uint16_t *numpida); void FindAllPids(uint16_t *apids, unsigned short *ac3flags, uint16_t *numpida, std::string *language); - + void FindAllSubs(uint16_t *pids, unsigned short *supported, uint16_t *numpida, std::string *language); + bool SelectSubtitles(int pid); + void GetChapters(std::vector &positions, std::vector &titles); }; #endif // __PLAYBACK_CS_H_ diff --git a/src/driver/record.cpp b/src/driver/record.cpp index 436a5ccdc..6f86c9e7e 100644 --- a/src/driver/record.cpp +++ b/src/driver/record.cpp @@ -677,8 +677,10 @@ void CRecordInstance::GetRecordString(std::string &str) int err = GetStatus(); strftime(stime, sizeof(stime), "%H:%M:%S ", localtime(&start_time)); time_t duration = time(0) - start_time; - char dtime[15]; - snprintf(dtime, sizeof(dtime), " (%02d:%02d)", (int) duration/3600, (int) duration/60); + char dtime[20]; + int h = duration/3600; + int m = duration/60; + snprintf(dtime, sizeof(dtime), " (%02d %s %02d min)", h, h == 1 ? "hour" : "hours", m); str = stime + channel->getName() + ": " + GetEpgTitle() + ((err & REC_STATUS_OVERFLOW) ? " [!]" : "") + dtime; } diff --git a/src/gui/audio_select.cpp b/src/gui/audio_select.cpp index cabf99de6..c2a5f4a3c 100644 --- a/src/gui/audio_select.cpp +++ b/src/gui/audio_select.cpp @@ -179,8 +179,11 @@ int CAudioSelectMenuHandler::doMenu () } } - if(sep_added) - AudioSelector.addItem(new CMenuForwarder(LOCALE_SUBTITLES_STOP, true, NULL, &SubtitleChanger, "off", CRCInput::RC_stop)); + if(sep_added) { + CMenuForwarder * item = new CMenuForwarder(LOCALE_SUBTITLES_STOP, true, NULL, &SubtitleChanger, "off", CRCInput::RC_stop); + item->setItemButton(NEUTRINO_ICON_BUTTON_STOP, false); + AudioSelector.addItem(item); + } } AudioSelector.addItem(new CMenuSeparator(CMenuSeparator::LINE | CMenuSeparator::STRING, LOCALE_AUDIOMENU_VOLUME_ADJUST)); diff --git a/src/gui/audio_setup.cpp b/src/gui/audio_setup.cpp index ec407188b..e35724472 100644 --- a/src/gui/audio_setup.cpp +++ b/src/gui/audio_setup.cpp @@ -87,11 +87,18 @@ const CMenuOptionChooser::keyval AUDIOMENU_ANALOGOUT_OPTIONS[AUDIOMENU_ANALOGOUT { 2, LOCALE_AUDIOMENU_MONORIGHT } }; +#ifdef BOXMODEL_APOLLO +#define AUDIOMENU_SRS_OPTION_COUNT 3 +#else #define AUDIOMENU_SRS_OPTION_COUNT 2 +#endif const CMenuOptionChooser::keyval AUDIOMENU_SRS_OPTIONS[AUDIOMENU_SRS_OPTION_COUNT] = { { 0 , LOCALE_AUDIO_SRS_ALGO_LIGHT }, - { 1 , LOCALE_AUDIO_SRS_ALGO_NORMAL } + { 1 , LOCALE_AUDIO_SRS_ALGO_NORMAL }, +#ifdef BOXMODEL_APOLLO + { 2 , LOCALE_AUDIO_SRS_ALGO_HEAVY } +#endif }; #define AUDIOMENU_AVSYNC_OPTION_COUNT 3 diff --git a/src/gui/keybind_setup.cpp b/src/gui/keybind_setup.cpp index 98839eb20..e59c52c30 100644 --- a/src/gui/keybind_setup.cpp +++ b/src/gui/keybind_setup.cpp @@ -178,6 +178,7 @@ const key_settings_struct_t key_settings[CKeybindSetup::KEYBINDS_COUNT] = {LOCALE_MPKEY_STOP, &g_settings.mpkey_stop, LOCALE_MENU_HINT_KEY_MPSTOP }, {LOCALE_MPKEY_PLAY, &g_settings.mpkey_play, LOCALE_MENU_HINT_KEY_MPPLAY }, {LOCALE_MPKEY_AUDIO, &g_settings.mpkey_audio, LOCALE_MENU_HINT_KEY_MPAUDIO }, + {LOCALE_MPKEY_SUBTITLE, &g_settings.mpkey_subtitle, LOCALE_MENU_HINT_KEY_MPSUBTITLE }, {LOCALE_MPKEY_TIME, &g_settings.mpkey_time, LOCALE_MENU_HINT_KEY_MPTIME }, {LOCALE_MPKEY_BOOKMARK, &g_settings.mpkey_bookmark, LOCALE_MENU_HINT_KEY_MPBOOKMARK }, {LOCALE_EXTRA_KEY_TIMESHIFT, &g_settings.key_timeshift, LOCALE_MENU_HINT_KEY_MPTIMESHIFT }, diff --git a/src/gui/keybind_setup.h b/src/gui/keybind_setup.h index 2a4c15ae1..fcbb47a8c 100644 --- a/src/gui/keybind_setup.h +++ b/src/gui/keybind_setup.h @@ -69,6 +69,7 @@ class CKeybindSetup : public CMenuTarget, public CChangeObserver MPKEY_STOP, MPKEY_PLAY, MPKEY_AUDIO, + MPKEY_SUBTITLE, MPKEY_TIME, MPKEY_BOOKMARK, KEY_TIMESHIFT, diff --git a/src/gui/mediaplayer.cpp b/src/gui/mediaplayer.cpp index b120e528d..50e0a72b0 100644 --- a/src/gui/mediaplayer.cpp +++ b/src/gui/mediaplayer.cpp @@ -252,6 +252,8 @@ void CMediaPlayerMenu::showMoviePlayer(CMenuWidget *moviePlayer, CPersonalizeGui fw_mbrowser->setHint(NEUTRINO_ICON_HINT_MB, LOCALE_MENU_HINT_MB); CMenuForwarder *fw_file = new CMenuForwarder(LOCALE_MOVIEPLAYER_FILEPLAYBACK, true, NULL, &CMoviePlayerGui::getInstance(), "fileplayback", CRCInput::RC_green, NEUTRINO_ICON_BUTTON_GREEN); fw_file->setHint(NEUTRINO_ICON_HINT_FILEPLAY, LOCALE_MENU_HINT_FILEPLAY); + CMenuForwarder *fw_yt = new CMenuForwarder(LOCALE_MOVIEPLAYER_YTPLAYBACK, true, NULL, &CMoviePlayerGui::getInstance(), "ytplayback", CRCInput::RC_yellow, NEUTRINO_ICON_BUTTON_YELLOW); + fw_yt->setHint(NEUTRINO_ICON_HINT_YTPLAY, LOCALE_MENU_HINT_YTPLAY); p->addIntroItems(moviePlayer); @@ -260,6 +262,8 @@ void CMediaPlayerMenu::showMoviePlayer(CMenuWidget *moviePlayer, CPersonalizeGui //fileplayback p->addItem(moviePlayer, fw_file, &g_settings.personalize[SNeutrinoSettings::P_MPLAYER_FILEPLAY]); + //ytplayback + p->addItem(moviePlayer, fw_yt, &g_settings.personalize[SNeutrinoSettings::P_MPLAYER_YTPLAY]); // #if 0 // //moviePlayer->addItem(new CMenuForwarder(LOCALE_MOVIEPLAYER_PESPLAYBACK, true, NULL, moviePlayerGui, "pesplayback")); diff --git a/src/gui/moviebrowser.cpp b/src/gui/moviebrowser.cpp index e55beb61c..62251ea81 100644 --- a/src/gui/moviebrowser.cpp +++ b/src/gui/moviebrowser.cpp @@ -175,12 +175,12 @@ const neutrino_locale_t m_localizedItemName[MB_INFO_MAX_NUMBER+1] = #define MB_ROW_WIDTH_FILEPATH 22 #define MB_ROW_WIDTH_TITLE 35 #define MB_ROW_WIDTH_SERIE 15 -#define MB_ROW_WIDTH_INFO1 25 +#define MB_ROW_WIDTH_INFO1 15 #define MB_ROW_WIDTH_MAJOR_GENRE 15 #define MB_ROW_WIDTH_MINOR_GENRE 8 #define MB_ROW_WIDTH_INFO2 25 #define MB_ROW_WIDTH_PARENTAL_LOCKAGE 4 -#define MB_ROW_WIDTH_CHANNEL 12 +#define MB_ROW_WIDTH_CHANNEL 15 #define MB_ROW_WIDTH_BOOKMARK 4 #define MB_ROW_WIDTH_QUALITY 10 #define MB_ROW_WIDTH_PREVPLAYDATE 12 @@ -189,8 +189,8 @@ const neutrino_locale_t m_localizedItemName[MB_INFO_MAX_NUMBER+1] = #define MB_ROW_WIDTH_COUNTRY 8 #define MB_ROW_WIDTH_GEOMETRIE 8 #define MB_ROW_WIDTH_AUDIO 8 -#define MB_ROW_WIDTH_LENGTH 6 -#define MB_ROW_WIDTH_SIZE 10 +#define MB_ROW_WIDTH_LENGTH 10 +#define MB_ROW_WIDTH_SIZE 12 const int m_defaultRowWidth[MB_INFO_MAX_NUMBER+1] = { @@ -479,7 +479,7 @@ void CMovieBrowser::init(void) break; } } - +#if 0 /***** Browser List **************/ if(m_settings.browserRowNr == 0) { @@ -494,7 +494,7 @@ void CMovieBrowser::init(void) m_settings.browserRowItem[5] = MB_INFO_QUALITY; reinit_rows = true; } - +#endif if (reinit_rows) { for (i = 0; i < m_settings.browserRowNr; i++) @@ -513,7 +513,8 @@ void CMovieBrowser::init(void) refreshLastRecordList(); refreshBrowserList(); refreshFilterList(); - g_PicViewer->getSupportedImageFormats(PicExts); + g_PicViewer->getSupportedImageFormats(PicExts); + show_mode = MB_SHOW_RECORDS; //FIXME #if 0 TRACE_1("Frames\r\n\tScren:\t%3d,%3d,%3d,%3d\r\n\tMain:\t%3d,%3d,%3d,%3d\r\n\tTitle:\t%3d,%3d,%3d,%3d \r\n\tBrowsr:\t%3d,%3d,%3d,%3d \r\n\tPlay:\t%3d,%3d,%3d,%3d \r\n\tRecord:\t%3d,%3d,%3d,%3d\r\n\r\n", g_settings.screen_StartX, @@ -582,12 +583,21 @@ void CMovieBrowser::initGlobalSettings(void) m_settings.browserFrameHeight = 50; /* percent */ m_settings.browserRowNr = 6; +#if 0 m_settings.browserRowItem[0] = MB_INFO_TITLE; m_settings.browserRowItem[1] = MB_INFO_INFO1; m_settings.browserRowItem[2] = MB_INFO_RECORDDATE; m_settings.browserRowItem[3] = MB_INFO_SIZE; m_settings.browserRowItem[4] = MB_INFO_PARENTAL_LOCKAGE; m_settings.browserRowItem[5] = MB_INFO_QUALITY; +#endif + m_settings.browserRowItem[0] = MB_INFO_CHANNEL; + m_settings.browserRowItem[1] = MB_INFO_TITLE; + m_settings.browserRowItem[2] = MB_INFO_RECORDDATE; + m_settings.browserRowItem[3] = MB_INFO_SIZE; + m_settings.browserRowItem[4] = MB_INFO_LENGTH; + m_settings.browserRowItem[5] = MB_INFO_INFO1; + m_settings.browserRowWidth[0] = m_defaultRowWidth[m_settings.browserRowItem[0]]; //300; m_settings.browserRowWidth[1] = m_defaultRowWidth[m_settings.browserRowItem[1]]; //100; m_settings.browserRowWidth[2] = m_defaultRowWidth[m_settings.browserRowItem[2]]; //80; @@ -595,6 +605,9 @@ void CMovieBrowser::initGlobalSettings(void) m_settings.browserRowWidth[4] = m_defaultRowWidth[m_settings.browserRowItem[4]]; //30; m_settings.browserRowWidth[5] = m_defaultRowWidth[m_settings.browserRowItem[5]]; //30; + m_settings.ytmode = cYTFeedParser::MOST_POPULAR; + m_settings.ytresults = 10; + m_settings.ytregion = "default"; } void CMovieBrowser::initFrames(void) @@ -757,6 +770,11 @@ bool CMovieBrowser::loadSettings(MB_SETTINGS* settings) snprintf(cfg_key, sizeof(cfg_key), "mb_browserRowWidth_%d", i); settings->browserRowWidth[i] = configfile.getInt32(cfg_key, 50); } + settings->ytmode = configfile.getInt32("mb_ytmode", cYTFeedParser::MOST_POPULAR); + settings->ytresults = configfile.getInt32("mb_ytresults", 10); + settings->ytregion = configfile.getString("mb_ytregion", "default"); + settings->ytsearch = configfile.getString("mb_ytsearch", ""); + settings->ytvid = configfile.getString("mb_ytvid", ""); return (result); } @@ -806,6 +824,11 @@ bool CMovieBrowser::saveSettings(MB_SETTINGS* settings) snprintf(cfg_key, sizeof(cfg_key), "mb_browserRowWidth_%d", i); configfile.setInt32(cfg_key, settings->browserRowWidth[i]); } + configfile.setInt32("mb_ytmode", settings->ytmode); + configfile.setInt32("mb_ytresults", settings->ytresults); + configfile.setString("mb_ytregion", settings->ytregion); + configfile.setString("mb_ytsearch", settings->ytsearch); + configfile.setString("mb_ytvid", settings->ytvid); if (configfile.getModifiedFlag()) configfile.saveConfig(MOVIEBROWSER_SETTINGS_FILE); @@ -959,6 +982,7 @@ int CMovieBrowser::exec(const char* path) if(m_file_info_stale == true) { TRACE("[mb] reload\r\n"); + loadMovies(); } else @@ -1227,11 +1251,18 @@ void CMovieBrowser::refreshMovieInfo(void) bool logo_ok = false; int picw = (int)(((float)16 / (float)9) * (float)m_cBoxFrameInfo.iHeight); int pich = m_cBoxFrameInfo.iHeight; - std::string fname = getScreenshotName(m_movieSelectionHandler->file.Name); - if(fname.empty()) { - std::string cover = m_movieSelectionHandler->file.Name; - cover.replace((cover.length()-18),15,""); //covername without yyyymmdd_hhmmss - fname = getScreenshotName(cover); + + std::string fname; +printf("CMovieBrowser::refreshMovieInfo\n"); + if (show_mode == MB_SHOW_YT) { + fname = m_movieSelectionHandler->tfile; + } else { + fname = getScreenshotName(m_movieSelectionHandler->file.Name); + if((fname.empty()) && (m_movieSelectionHandler->file.Name.length() > 18)) { + std::string cover = m_movieSelectionHandler->file.Name; + cover.replace((cover.length()-18),15,""); //covername without yyyymmdd_hhmmss + fname = getScreenshotName(cover); + } } logo_ok = (!fname.empty()); int flogo_w = 0, flogo_h = 0; @@ -1269,6 +1300,7 @@ void CMovieBrowser::refreshMovieInfo(void) } } } + void CMovieBrowser::info_hdd_level(bool paint_hdd) { struct statfs s; @@ -1576,7 +1608,15 @@ void CMovieBrowser::refreshBookmarkList(void) // P3 void CMovieBrowser::refreshTitle(void) { //Paint Text Background - TRACE("[mb]->refreshTitle : %s\r\n",m_textTitle.c_str()); + std::string title = m_textTitle.c_str(); + if (show_mode == MB_SHOW_YT) { + title = g_Locale->getText(LOCALE_MOVIEPLAYER_YTPLAYBACK); + title += " : "; + title += g_Locale->getText(getFeedLocale()); + } + + TRACE("[mb]->refreshTitle : %s\r\n", title.c_str()); + const short text_border_width = 8; int start_y = m_cBoxFrame.iY+ m_cBoxFrameTitleRel.iY; @@ -1587,7 +1627,7 @@ void CMovieBrowser::refreshTitle(void) CFrameBuffer::getInstance()->getIconSize(NEUTRINO_ICON_MOVIEPLAYER, &iconw, &iconh); m_pcWindow->paintIcon(NEUTRINO_ICON_MOVIEPLAYER, m_cBoxFrame.iX+m_cBoxFrameTitleRel.iX+6, start_y+ m_cBoxFrameTitleRel.iHeight/2 - iconh/2); - m_pcFontTitle->RenderString(m_cBoxFrame.iX+m_cBoxFrameTitleRel.iX + iconw + text_border_width, start_y + m_cBoxFrameTitleRel.iHeight, m_cBoxFrameTitleRel.iWidth - (text_border_width << 1), m_textTitle.c_str(), TITLE_FONT_COLOR, 0, true); // UTF-8 + m_pcFontTitle->RenderString(m_cBoxFrame.iX+m_cBoxFrameTitleRel.iX + iconw + text_border_width, start_y + m_cBoxFrameTitleRel.iHeight, m_cBoxFrameTitleRel.iWidth - (text_border_width << 1), title.c_str(), TITLE_FONT_COLOR, 0, true); // UTF-8 info_hdd_level(true); } @@ -1735,6 +1775,9 @@ bool CMovieBrowser::onButtonPressMainFrame(neutrino_msg_t msg) } else if (msg == CRCInput::RC_blue) { + if (show_mode == MB_SHOW_YT) + ytparser.Cleanup(); + loadMovies(); refresh(); } @@ -1797,10 +1840,15 @@ bool CMovieBrowser::onButtonPressMainFrame(neutrino_msg_t msg) else if (msg == CRCInput::RC_setup) { //if(m_movieSelectionHandler != NULL) - showMenu(m_movieSelectionHandler); + if (show_mode == MB_SHOW_YT) + showYTMenu(); + else + showMenu(m_movieSelectionHandler); + } else if (msg == CRCInput::RC_text || msg == CRCInput::RC_radio) { - if(ShowMsgUTF (LOCALE_MESSAGEBOX_INFO, msg == CRCInput::RC_radio ? "Copy jumps from movie to new file ?" : "Copy jumps from movie to new files ?", CMessageBox::mbrNo, CMessageBox::mbYes | CMessageBox::mbNo) == CMessageBox::mbrYes) { + if((show_mode == MB_SHOW_RECORDS) && + (ShowMsgUTF (LOCALE_MESSAGEBOX_INFO, msg == CRCInput::RC_radio ? "Copy jumps from movie to new file ?" : "Copy jumps from movie to new files ?", CMessageBox::mbrNo, CMessageBox::mbYes | CMessageBox::mbNo) == CMessageBox::mbrYes)) { CHintBox * hintBox = new CHintBox(LOCALE_MESSAGEBOX_INFO, "Coping, please wait"); hintBox->paint(); sleep(1); @@ -1822,7 +1870,8 @@ bool CMovieBrowser::onButtonPressMainFrame(neutrino_msg_t msg) ShowMsgUTF(LOCALE_MESSAGEBOX_ERROR, "Impossible to cut playing movie.", CMessageBox::mbrCancel, CMessageBox::mbCancel, NEUTRINO_ICON_ERROR); else #endif - if(ShowMsgUTF (LOCALE_MESSAGEBOX_INFO, "Cut jumps from movie ?", CMessageBox::mbrNo, CMessageBox::mbYes | CMessageBox::mbNo) == CMessageBox::mbrYes) { + if((show_mode == MB_SHOW_RECORDS) && + (ShowMsgUTF (LOCALE_MESSAGEBOX_INFO, "Cut jumps from movie ?", CMessageBox::mbrNo, CMessageBox::mbYes | CMessageBox::mbNo) == CMessageBox::mbrYes)) { CHintBox * hintBox = new CHintBox(LOCALE_MESSAGEBOX_INFO, "Cutting, please wait"); hintBox->paint(); sleep(1); @@ -1840,26 +1889,28 @@ bool CMovieBrowser::onButtonPressMainFrame(neutrino_msg_t msg) } } else if (msg == CRCInput::RC_games) { - if((m_movieSelectionHandler == playing_info) && (NeutrinoMessages::mode_ts == CNeutrinoApp::getInstance()->getMode())) - ShowMsgUTF(LOCALE_MESSAGEBOX_ERROR, "Impossible to truncate playing movie.", CMessageBox::mbrCancel, CMessageBox::mbCancel, NEUTRINO_ICON_ERROR); - else if(m_movieSelectionHandler->bookmarks.end == 0) - ShowMsgUTF(LOCALE_MESSAGEBOX_ERROR, "No End bookmark defined!", CMessageBox::mbrCancel, CMessageBox::mbCancel, NEUTRINO_ICON_ERROR); - else { - if(ShowMsgUTF (LOCALE_MESSAGEBOX_INFO, "Truncate movie ?", CMessageBox::mbrNo, CMessageBox::mbYes | CMessageBox::mbNo) == CMessageBox::mbrYes) { - CHintBox * hintBox = new CHintBox(LOCALE_MESSAGEBOX_INFO, "Truncating, please wait"); - hintBox->paint(); - off64_t res = truncate_movie(m_movieSelectionHandler); - hintBox->hide(); - delete hintBox; - g_RCInput->clearRCMsg(); - if(res == 0) - ShowMsgUTF(LOCALE_MESSAGEBOX_ERROR, "Truncate failed.", CMessageBox::mbrCancel, CMessageBox::mbCancel, NEUTRINO_ICON_ERROR); - else { -//printf("New movie info: size %lld len %d\n", res, m_movieSelectionHandler->bookmarks.end/60); - m_movieInfo.saveMovieInfo( *m_movieSelectionHandler); - loadMovies(); + if((show_mode == MB_SHOW_RECORDS) && m_movieSelectionHandler != NULL) { + if((m_movieSelectionHandler == playing_info) && (NeutrinoMessages::mode_ts == CNeutrinoApp::getInstance()->getMode())) + ShowMsgUTF(LOCALE_MESSAGEBOX_ERROR, "Impossible to truncate playing movie.", CMessageBox::mbrCancel, CMessageBox::mbCancel, NEUTRINO_ICON_ERROR); + else if(m_movieSelectionHandler->bookmarks.end == 0) + ShowMsgUTF(LOCALE_MESSAGEBOX_ERROR, "No End bookmark defined!", CMessageBox::mbrCancel, CMessageBox::mbCancel, NEUTRINO_ICON_ERROR); + else { + if(ShowMsgUTF (LOCALE_MESSAGEBOX_INFO, "Truncate movie ?", CMessageBox::mbrNo, CMessageBox::mbYes | CMessageBox::mbNo) == CMessageBox::mbrYes) { + CHintBox * hintBox = new CHintBox(LOCALE_MESSAGEBOX_INFO, "Truncating, please wait"); + hintBox->paint(); + off64_t res = truncate_movie(m_movieSelectionHandler); + hintBox->hide(); + delete hintBox; + g_RCInput->clearRCMsg(); + if(res == 0) + ShowMsgUTF(LOCALE_MESSAGEBOX_ERROR, "Truncate failed.", CMessageBox::mbrCancel, CMessageBox::mbCancel, NEUTRINO_ICON_ERROR); + else { + //printf("New movie info: size %lld len %d\n", res, m_movieSelectionHandler->bookmarks.end/60); + m_movieInfo.saveMovieInfo( *m_movieSelectionHandler); + loadMovies(); + } + refresh(); } - refresh(); } } } else if (msg == CRCInput::RC_topleft) { @@ -2813,18 +2864,22 @@ void CMovieBrowser::loadMovies(bool doRefresh) loadBox.paint(); //clock_act = clock()/10000;TRACE("[mb] *1: time %9ld clock %6ld dclock %6ld*\n",(long)time(NULL),clock_act,clock_act - clock_prev);clock_prev = clock_act; - loadAllTsFileNamesFromStorage(); // P1 -//clock_act = clock()/10000;TRACE("[mb] *2: time %9ld clock %6ld dclock %6ld*\n",(long)time(NULL),clock_act,clock_act - clock_prev);clock_prev = clock_act; - //loadAllMovieInfo(); // P1 -//clock_act = clock()/10000;TRACE("[mb] *3: time %9ld clock %6ld dclock %6ld*\n",(long)time(NULL),clock_act,clock_act - clock_prev);clock_prev = clock_act; m_file_info_stale = false; - m_seriename_stale = true; // we reloded the movie info, so make sure the other list are updated later on as well - updateSerienames(); -//clock_act = clock()/10000;TRACE("[mb] *4: time %9ld clock %6ld dclock %6ld*\n",(long)time(NULL),clock_act,clock_act - clock_prev);clock_prev = clock_act; - if(m_settings.serie_auto_create == 1) - { - autoFindSerie(); - } + if (show_mode == MB_SHOW_YT) { + loadYTitles(m_settings.ytmode, m_settings.ytsearch, m_settings.ytvid); + } else { + loadAllTsFileNamesFromStorage(); // P1 + //clock_act = clock()/10000;TRACE("[mb] *2: time %9ld clock %6ld dclock %6ld*\n",(long)time(NULL),clock_act,clock_act - clock_prev);clock_prev = clock_act; + //loadAllMovieInfo(); // P1 + //clock_act = clock()/10000;TRACE("[mb] *3: time %9ld clock %6ld dclock %6ld*\n",(long)time(NULL),clock_act,clock_act - clock_prev);clock_prev = clock_act; + m_seriename_stale = true; // we reloded the movie info, so make sure the other list are updated later on as well + updateSerienames(); + //clock_act = clock()/10000;TRACE("[mb] *4: time %9ld clock %6ld dclock %6ld*\n",(long)time(NULL),clock_act,clock_act - clock_prev);clock_prev = clock_act; + if(m_settings.serie_auto_create == 1) + { + autoFindSerie(); + } + } loadBox.hide(); @@ -3329,10 +3384,15 @@ bool CMovieBrowser::getMovieInfoItem(MI_MOVIE_INFO& movie_info, MB_INFO_ITEM ite snprintf(str_tmp,MAX_STR_TMP,"%02d.%02d.%02d",tm_tmp->tm_mday,(tm_tmp->tm_mon)+ 1, tm_tmp->tm_year >= 100 ? tm_tmp->tm_year-100 : tm_tmp->tm_year); *item_string = str_tmp; break; + case MB_INFO_RECORDDATE: // = 13, - tm_tmp = localtime(&movie_info.file.Time); - snprintf(str_tmp,MAX_STR_TMP,"%02d.%02d.%02d",tm_tmp->tm_mday,(tm_tmp->tm_mon) + 1,tm_tmp->tm_year >= 100 ? tm_tmp->tm_year-100 : tm_tmp->tm_year); - *item_string = str_tmp; + if (show_mode == MB_SHOW_YT) { + *item_string = movie_info.ytdate; + } else { + tm_tmp = localtime(&movie_info.file.Time); + snprintf(str_tmp,MAX_STR_TMP,"%02d.%02d.%02d",tm_tmp->tm_mday,(tm_tmp->tm_mon) + 1,tm_tmp->tm_year >= 100 ? tm_tmp->tm_year-100 : tm_tmp->tm_year); + *item_string = str_tmp; + } break; case MB_INFO_PRODDATE: // = 14, snprintf(str_tmp,MAX_STR_TMP,"%d",movie_info.productionDate); @@ -3421,7 +3481,8 @@ bool CMovieBrowser::getMovieInfoItem(MI_MOVIE_INFO& movie_info, MB_INFO_ITEM ite #endif // MB_INFO_AUDIO test break; case MB_INFO_LENGTH: // = 18, - snprintf(str_tmp,MAX_STR_TMP,"%4d",movie_info.length); + //snprintf(str_tmp,MAX_STR_TMP,"%4d",movie_info.length); + snprintf(str_tmp,MAX_STR_TMP,"%dh %dm", movie_info.length/60, movie_info.length%60); *item_string = str_tmp; break; case MB_INFO_SIZE: // = 19, @@ -3492,6 +3553,189 @@ void CMovieBrowser::autoFindSerie(void) } } +void CMovieBrowser::loadYTitles(int mode, std::string search, std::string id) +{ + printf("CMovieBrowser::loadYTitles: parsed %d old mode %d new mode %d region %s\n", ytparser.Parsed(), ytparser.GetFeedMode(), m_settings.ytmode, m_settings.ytregion.c_str()); + if (m_settings.ytregion == "default") + ytparser.SetRegion(""); + else + ytparser.SetRegion(m_settings.ytregion); + + ytparser.SetMaxResults(m_settings.ytresults); + + if (!ytparser.Parsed() || (ytparser.GetFeedMode() != mode)) { + if (ytparser.ParseFeed((cYTFeedParser::yt_feed_mode_t)mode, search, id)) { + ytparser.DownloadThumbnails(); + } else { + //FIXME show error + DisplayErrorMessage(g_Locale->getText(LOCALE_MOVIEBROWSER_YT_ERROR)); + return; + } + } + m_vMovieInfo.clear(); + yt_video_list_t &ylist = ytparser.GetVideoList(); + for (unsigned i = 0; i < ylist.size(); i++) { + MI_MOVIE_INFO movieInfo; + m_movieInfo.clearMovieInfo(&movieInfo); // refresh structure + movieInfo.epgChannel = ylist[i].author; + movieInfo.epgTitle = ylist[i].title; + movieInfo.epgInfo1 = ylist[i].category; + movieInfo.epgInfo2 = ylist[i].description; + movieInfo.length = ylist[i].duration/60 ; + movieInfo.tfile = ylist[i].tfile; + movieInfo.ytdate = ylist[i].published; + movieInfo.ytid = ylist[i].id; + + movieInfo.file.Name = ylist[i].title; + movieInfo.file.Url = ylist[i].GetUrl(); + m_vMovieInfo.push_back(movieInfo); + } + m_currentBrowserSelection = 0; + m_currentRecordSelection = 0; + m_currentPlaySelection = 0; + m_pcBrowser->setSelectedLine(m_currentBrowserSelection); + m_pcLastRecord->setSelectedLine(m_currentRecordSelection); + m_pcLastPlay->setSelectedLine(m_currentPlaySelection); +} + +const CMenuOptionChooser::keyval YT_FEED_OPTIONS[] = +{ + { cYTFeedParser::TOP_RATED, LOCALE_MOVIEBROWSER_YT_TOP_RATED }, + { cYTFeedParser::TOP_FAVORITES, LOCALE_MOVIEBROWSER_YT_TOP_FAVORITES }, + { cYTFeedParser::MOST_SHARED, LOCALE_MOVIEBROWSER_YT_MOST_SHARED }, + { cYTFeedParser::MOST_POPULAR, LOCALE_MOVIEBROWSER_YT_MOST_POPULAR }, + { cYTFeedParser::MOST_RESENT, LOCALE_MOVIEBROWSER_YT_MOST_RESENT }, + { cYTFeedParser::MOST_DISCUSSED, LOCALE_MOVIEBROWSER_YT_MOST_DISCUSSED }, + { cYTFeedParser::MOST_RESPONDED, LOCALE_MOVIEBROWSER_YT_MOST_RESPONDED }, + { cYTFeedParser::RECENTLY_FEATURED, LOCALE_MOVIEBROWSER_YT_RECENTLY_FEATURED }, + { cYTFeedParser::ON_THE_WEB, LOCALE_MOVIEBROWSER_YT_ON_THE_WEB }, +}; + +#define YT_FEED_OPTION_COUNT (sizeof(YT_FEED_OPTIONS)/sizeof(CMenuOptionChooser::keyval)) + +neutrino_locale_t CMovieBrowser::getFeedLocale(void) +{ + neutrino_locale_t ret = LOCALE_MOVIEBROWSER_YT_MOST_POPULAR; + + if (m_settings.ytmode == cYTFeedParser::RELATED) + return LOCALE_MOVIEBROWSER_YT_RELATED; + + if (m_settings.ytmode == cYTFeedParser::SEARCH) + return LOCALE_MOVIEBROWSER_YT_SEARCH; + + for (unsigned i = 0; i < YT_FEED_OPTION_COUNT; i++) { + if (m_settings.ytmode == YT_FEED_OPTIONS[i].key) + return YT_FEED_OPTIONS[i].value; + } + return ret; +} + +bool CMovieBrowser::showYTMenu() +{ + m_pcWindow->paintBackground(); + + CMenuWidget mainMenu(LOCALE_MOVIEBROWSER_HEAD, NEUTRINO_ICON_MOVIEPLAYER); + mainMenu.addIntroItems(LOCALE_MOVIEPLAYER_YTPLAYBACK); + + int select = -1; + CMenuSelectorTarget * selector = new CMenuSelectorTarget(&select); + + char cnt[5]; + for (unsigned i = 0; i < YT_FEED_OPTION_COUNT; i++) { + sprintf(cnt, "%d", YT_FEED_OPTIONS[i].key); + mainMenu.addItem(new CMenuForwarder(YT_FEED_OPTIONS[i].value, true, NULL, selector, cnt, CRCInput::convertDigitToKey(i + 1)), m_settings.ytmode == (int) YT_FEED_OPTIONS[i].key); + } + mainMenu.addItem(GenericMenuSeparatorLine); + + bool enabled = (!m_vMovieInfo.empty()) && (m_movieSelectionHandler != NULL); + sprintf(cnt, "%d", cYTFeedParser::RELATED); + mainMenu.addItem(new CMenuForwarder(LOCALE_MOVIEBROWSER_YT_RELATED, enabled, NULL, selector, cnt, CRCInput::RC_red, NEUTRINO_ICON_BUTTON_RED)); + + sprintf(cnt, "%d", cYTFeedParser::NEXT); + mainMenu.addItem(new CMenuForwarder(LOCALE_MOVIEBROWSER_YT_NEXT_RESULTS, ytparser.HaveNext(), NULL, selector, cnt, CRCInput::RC_green, NEUTRINO_ICON_BUTTON_GREEN)); + sprintf(cnt, "%d", cYTFeedParser::PREV); + mainMenu.addItem(new CMenuForwarder(LOCALE_MOVIEBROWSER_YT_PREV_RESULTS, ytparser.HavePrev(), NULL, selector, cnt, CRCInput::RC_yellow, NEUTRINO_ICON_BUTTON_YELLOW)); + + mainMenu.addItem(GenericMenuSeparatorLine); + + std::string search = m_settings.ytsearch; + CStringInputSMS stringInput(LOCALE_MOVIEBROWSER_YT_SEARCH, &search, 20, NONEXISTANT_LOCALE, NONEXISTANT_LOCALE, "abcdefghijklmnopqrstuvwxyz0123456789"); + mainMenu.addItem(new CMenuForwarder(LOCALE_MOVIEBROWSER_YT_SEARCH, true, search, &stringInput, NULL, CRCInput::RC_nokey, "")); + sprintf(cnt, "%d", cYTFeedParser::SEARCH); + mainMenu.addItem(new CMenuForwarder(LOCALE_EVENTFINDER_START_SEARCH, true, NULL, selector, cnt, CRCInput::RC_blue, NEUTRINO_ICON_BUTTON_BLUE)); + + mainMenu.addItem(GenericMenuSeparatorLine); + mainMenu.addItem(new CMenuOptionNumberChooser(LOCALE_MOVIEBROWSER_YT_MAX_RESULTS, &m_settings.ytresults, true, 10, 50, NULL)); + + char rstr[20]; + sprintf(rstr, "%s", m_settings.ytregion.c_str()); + CMenuOptionStringChooser * region = new CMenuOptionStringChooser(LOCALE_MOVIEBROWSER_YT_REGION, rstr, true, NULL, CRCInput::RC_nokey, "", true); + region->addOption("default"); + region->addOption("DE"); + region->addOption("PL"); + region->addOption("RU"); + region->addOption("NL"); + region->addOption("CZ"); + region->addOption("FR"); + region->addOption("HU"); + region->addOption("US"); + mainMenu.addItem(region); + + mainMenu.exec(NULL, ""); + delete selector; + + bool reload = false; + printf("MovieBrowser::showYTMenu(): selected: %d\n", select); + int newmode = -1; + if (select >= 0) { + newmode = select; + if (newmode == cYTFeedParser::NEXT || newmode == cYTFeedParser::PREV) { + reload = true; + } + else if (select == cYTFeedParser::RELATED) { + if (m_settings.ytvid != m_movieSelectionHandler->ytid) { + printf("get related for: %s\n", m_movieSelectionHandler->ytid.c_str()); + m_settings.ytvid = m_movieSelectionHandler->ytid; + m_settings.ytmode = newmode; + reload = true; + } + } + else if (select == cYTFeedParser::SEARCH) { + printf("search for: %s\n", search.c_str()); + if (!search.empty()) { + reload = true; + m_settings.ytsearch = search; + m_settings.ytmode = newmode; + } + } + else if (m_settings.ytmode != newmode) { + m_settings.ytmode = newmode; + reload = true; + } + } + if(rstr != m_settings.ytregion) { + m_settings.ytregion = rstr; + if (newmode < 0) + newmode = m_settings.ytmode; + reload = true; + printf("change region to %s\n", m_settings.ytregion.c_str()); + } + if (reload) { + CHintBox loadBox(LOCALE_MOVIEPLAYER_YTPLAYBACK, g_Locale->getText(LOCALE_MOVIEBROWSER_SCAN_FOR_MOVIES)); + loadBox.paint(); + ytparser.Cleanup(); + loadYTitles(newmode, m_settings.ytsearch, m_settings.ytvid); + loadBox.hide(); + } + refreshBrowserList(); + refreshLastPlayList(); + refreshLastRecordList(); + refreshFilterList(); + //refreshMovieInfo(); + refresh(); + return true; +} + CMenuSelector::CMenuSelector(const char * OptionName, const bool Active , char * OptionValue, int* ReturnInt ,int ReturnIntValue ) : CMenuItem() { height = g_Font[SNeutrinoSettings::FONT_TYPE_MENU]->getHeight(); @@ -3758,7 +4002,6 @@ printf("updateDirState: %d: state %d nfs %d\n", i, dirState[i], dirNfsMountNr[i] } } - int CDirMenu::show(void) { if(dirList->empty()) diff --git a/src/gui/moviebrowser.h b/src/gui/moviebrowser.h index a4df89ba4..1126404a8 100644 --- a/src/gui/moviebrowser.h +++ b/src/gui/moviebrowser.h @@ -80,6 +80,7 @@ #include #include #include +#include #define MAX_NUMBER_OF_BOOKMARK_ITEMS MI_MOVIE_BOOK_USER_MAX // we just use the same size as used in Movie info (MAX_NUMBER_OF_BOOKMARK_ITEMS is used for the number of menu items) #define MOVIEBROWSER_SETTINGS_FILE CONFIGDIR "/moviebrowser.conf" @@ -181,6 +182,13 @@ typedef struct int* used; }MB_DIR; +typedef enum +{ + MB_SHOW_RECORDS, + MB_SHOW_FILES, + MB_SHOW_YT +} MB_SHOW_MODE; + #define MB_MAX_ROWS 6 #define MB_MAX_DIRS 5 /* MB_SETTINGS to be stored in g_settings anytime ....*/ @@ -219,6 +227,11 @@ typedef struct int lastRecordRowNr; MB_INFO_ITEM lastRecordRow[MB_MAX_ROWS]; int lastRecordRowWidth[MB_MAX_ROWS]; + int ytmode; + int ytresults; + std::string ytregion; + std::string ytvid; + std::string ytsearch; } MB_SETTINGS; // Priorities for Developmemt: P1: critical feature, P2: important feature, P3: for next release, P4: looks nice, lets see @@ -303,6 +316,11 @@ class CMovieBrowser : public CMenuTarget //bool restart_mb_timeout; int menu_ret; + cYTFeedParser ytparser; + int show_mode; + void loadYTitles(int mode, std::string search = "", std::string id = ""); + bool showYTMenu(void); + public: // Functions //////////////////////////////////////////////////////////7 CMovieBrowser(const char* path); //P1 CMovieBrowser(); //P1 @@ -324,6 +342,8 @@ class CMovieBrowser : public CMenuTarget bool delFile_vlc(CFile& file); bool delFile_std(CFile& file); int getMenuRet() { return menu_ret; } + int getMode() { return show_mode; } + void setMode(int mode) { show_mode = mode; } private: //Functions ///// MovieBrowser init /////////////// @@ -402,6 +422,8 @@ class CMovieBrowser : public CMenuTarget void autoFindSerie(void); void info_hdd_level(bool paint_hdd=false); + + neutrino_locale_t getFeedLocale(void); }; // Class to show Moviebrowser Information, to be used by menu diff --git a/src/gui/movieinfo.cpp b/src/gui/movieinfo.cpp index 78252c708..94dc72954 100644 --- a/src/gui/movieinfo.cpp +++ b/src/gui/movieinfo.cpp @@ -922,6 +922,9 @@ void CMovieInfo::clearMovieInfo(MI_MOVIE_INFO * movie_info) movie_info->bookmarks.user[i].length = 0; movie_info->bookmarks.user[i].name = ""; } + movie_info->tfile.clear(); + movie_info->ytdate.clear(); + movie_info->ytid.clear(); } /************************************************************************ diff --git a/src/gui/movieinfo.h b/src/gui/movieinfo.h index d90369b63..cc4d6683d 100644 --- a/src/gui/movieinfo.h +++ b/src/gui/movieinfo.h @@ -169,7 +169,10 @@ typedef struct int epgVideoPid; // currently not used, we just do not want to loose this info if movie info is saved backed int VideoType; int epgVTXPID; // currently not used, we just do not want to loose this info if movie info is saved backed -}MI_MOVIE_INFO; + std::string tfile; // thumbnail/cover file name + std::string ytdate; // yt published + std::string ytid; // yt published +} MI_MOVIE_INFO; class CMovieInfo diff --git a/src/gui/movieplayer.cpp b/src/gui/movieplayer.cpp index 2a78bc7a4..44c00ccaf 100644 --- a/src/gui/movieplayer.cpp +++ b/src/gui/movieplayer.cpp @@ -27,6 +27,7 @@ #include #endif +#define __STDC_CONSTANT_MACROS #include #include @@ -39,6 +40,7 @@ #include #include #include +#include #include #include @@ -187,6 +189,11 @@ int CMoviePlayerGui::exec(CMenuTarget * parent, const std::string & actionKey) timeshift = 0; if (actionKey == "tsmoviebrowser") { isMovieBrowser = true; + moviebrowser->setMode(MB_SHOW_RECORDS); + } + else if (actionKey == "ytplayback") { + isMovieBrowser = true; + moviebrowser->setMode(MB_SHOW_YT); } else if (actionKey == "fileplayback") { } @@ -305,6 +312,8 @@ bool CMoviePlayerGui::SelectFile() language[i].clear(); } numpida = 0; currentapid = 0; + currentspid = -1; + numsubs = 0; is_file_player = false; p_movie_info = NULL; @@ -340,15 +349,17 @@ bool CMoviePlayerGui::SelectFile() Path_local = moviebrowser->getCurrentDir(); CFile *file; if ((file = moviebrowser->getSelectedFile()) != NULL) { - full_name = file->Name.c_str(); - // get the movie info handle (to be used for e.g. bookmark handling) p_movie_info = moviebrowser->getCurrentMovieInfo(); -#if 0 - bool recfile = CRecordManager::getInstance()->RecordingStatus(p_movie_info->epgId) && - CRecordManager::getInstance()->GetFileName(p_movie_info->epgId) == file->Name; -#endif + if (moviebrowser->getMode() == MB_SHOW_RECORDS) { + full_name = file->Name; + } + else if (moviebrowser->getMode() == MB_SHOW_YT) { + full_name = file->Url; + is_file_player = true; + } fillPids(); + // get the start position for the movie startposition = 1000 * moviebrowser->getCurrentStartPos(); printf("CMoviePlayerGui::SelectFile: file %s start %d apid %X atype %d vpid %x vtype %d\n", full_name.c_str(), startposition, currentapid, currentac3, vpid, vtype); @@ -357,7 +368,7 @@ bool CMoviePlayerGui::SelectFile() } } else menu_ret = moviebrowser->getMenuRet(); - } + } else { // filebrowser CAudioMute::getInstance()->enableMuteIcon(false); if (filebrowser->exec(Path_local.c_str()) == true) { @@ -433,6 +444,8 @@ void CMoviePlayerGui::PlayFile(void) handleMovieBrowser(CRCInput::RC_nokey, position); cutNeutrino(); + clearSubtitle(); + playback->Open(is_file_player ? PLAYMODE_FILE : PLAYMODE_TS); printf("IS FILE PLAYER: %s\n", is_file_player ? "true": "false" ); @@ -533,6 +546,7 @@ void CMoviePlayerGui::PlayFile(void) handleMovieBrowser(0, position); FileTime.update(position, duration); } + showSubtitle(0); if (msg == (neutrino_msg_t) g_settings.mpkey_plugin) { //g_PluginList->start_plugin_by_name (g_settings.movieplayer_plugin.c_str (), pidt); @@ -570,29 +584,37 @@ void CMoviePlayerGui::PlayFile(void) callInfoViewer(/*duration, position*/); } else if (msg == (neutrino_msg_t) g_settings.mpkey_bookmark) { - handleMovieBrowser((neutrino_msg_t) g_settings.mpkey_bookmark, position); + if (is_file_player) + selectChapter(); + else + handleMovieBrowser((neutrino_msg_t) g_settings.mpkey_bookmark, position); + update_lcd = true; + clearSubtitle(); } else if (msg == (neutrino_msg_t) g_settings.mpkey_audio) { selectAudioPid(is_file_player); update_lcd = true; + clearSubtitle(); + } else if ( msg == (neutrino_msg_t) g_settings.mpkey_subtitle) { + selectSubtitle(); + clearSubtitle(); + update_lcd = true; } else if (msg == (neutrino_msg_t) g_settings.mpkey_time) { FileTime.switchMode(position, duration); - } else if ((msg == (neutrino_msg_t) g_settings.mpkey_rewind) || - (msg == (neutrino_msg_t) g_settings.mpkey_forward)) { + } else if (/*!is_file_player &&*/ ((msg == (neutrino_msg_t) g_settings.mpkey_rewind) || + (msg == (neutrino_msg_t) g_settings.mpkey_forward))) { int newspeed; if (msg == (neutrino_msg_t) g_settings.mpkey_rewind) { newspeed = (speed >= 0) ? -1 : speed - 1; - if (playstate != CMoviePlayerGui::PAUSE) - playstate = CMoviePlayerGui::REW; } else { newspeed = (speed <= 0) ? 2 : speed + 1; - if (playstate != CMoviePlayerGui::PAUSE) - playstate = CMoviePlayerGui::FF; } /* if paused, playback->SetSpeed() start slow motion */ if (playback->SetSpeed(newspeed)) { printf("SetSpeed: update speed\n"); speed = newspeed; + if (playstate != CMoviePlayerGui::PAUSE) + playstate = msg == (neutrino_msg_t) g_settings.mpkey_rewind ? CMoviePlayerGui::REW : CMoviePlayerGui::FF; updateLcd(); } //update_lcd = true; @@ -605,32 +627,44 @@ void CMoviePlayerGui::PlayFile(void) time_forced = true; } } else if (msg == CRCInput::RC_1) { // Jump Backwards 1 minute + clearSubtitle(); playback->SetPosition(-60 * 1000); } else if (msg == CRCInput::RC_3) { // Jump Forward 1 minute + clearSubtitle(); playback->SetPosition(60 * 1000); } else if (msg == CRCInput::RC_4) { // Jump Backwards 5 minutes + clearSubtitle(); playback->SetPosition(-5 * 60 * 1000); } else if (msg == CRCInput::RC_6) { // Jump Forward 5 minutes + clearSubtitle(); playback->SetPosition(5 * 60 * 1000); } else if (msg == CRCInput::RC_7) { // Jump Backwards 10 minutes + clearSubtitle(); playback->SetPosition(-10 * 60 * 1000); } else if (msg == CRCInput::RC_9) { // Jump Forward 10 minutes + clearSubtitle(); playback->SetPosition(10 * 60 * 1000); } else if (msg == CRCInput::RC_2) { // goto start + clearSubtitle(); playback->SetPosition(0, true); } else if (msg == CRCInput::RC_5) { // goto middle + clearSubtitle(); playback->SetPosition(duration/2, true); } else if (msg == CRCInput::RC_8) { // goto end + clearSubtitle(); playback->SetPosition(duration - 60 * 1000, true); } else if (msg == CRCInput::RC_page_up) { + clearSubtitle(); playback->SetPosition(10 * 1000); } else if (msg == CRCInput::RC_page_down) { + clearSubtitle(); playback->SetPosition(-10 * 1000); } else if (msg == CRCInput::RC_0) { // cancel bookmark jump handleMovieBrowser(CRCInput::RC_0, position); } else if (msg == CRCInput::RC_help || msg == CRCInput::RC_info) { callInfoViewer(/*duration, position*/); update_lcd = true; + clearSubtitle(); //showHelpTS(); } else if(timeshift && (msg == CRCInput::RC_text || msg == CRCInput::RC_epg || msg == NeutrinoMessages::SHOW_EPG)) { bool restore = FileTime.IsVisible(); @@ -677,6 +711,8 @@ void CMoviePlayerGui::PlayFile(void) sc->EnableVideo(true); sc->Start(); + } else if ( msg == NeutrinoMessages::EVT_SUBT_MESSAGE) { + showSubtitle(data); } else if ( msg == NeutrinoMessages::ANNOUNCE_RECORD || msg == NeutrinoMessages::RECORD_START) { CNeutrinoApp::getInstance()->handleMsg(msg, data); @@ -702,6 +738,7 @@ void CMoviePlayerGui::PlayFile(void) } else if ( msg <= CRCInput::RC_MaxRC ) { update_lcd = true; + clearSubtitle(); } } @@ -713,6 +750,7 @@ void CMoviePlayerGui::PlayFile(void) } FileTime.hide(); + clearSubtitle(); playback->SetSpeed(1); playback->Close(); @@ -764,13 +802,13 @@ bool CMoviePlayerGui::getAudioName(int apid, std::string &apidtitle) return false; } -void CMoviePlayerGui::addAudioFormat(int count, std::string &apidtitle, bool file_player, bool& enabled) +void CMoviePlayerGui::addAudioFormat(int count, std::string &apidtitle, bool& enabled) { enabled = true; switch(ac3flags[count]) { case 1: /*AC3,EAC3*/ - if (apidtitle.find("AC3") == std::string::npos || file_player) + if (apidtitle.find("AC3") == std::string::npos) apidtitle.append(" (AC3)"); break; case 2: /*teletext*/ @@ -787,7 +825,8 @@ void CMoviePlayerGui::addAudioFormat(int count, std::string &apidtitle, bool fil apidtitle.append(" (AAC)"); break; case 6: /*DTS*/ - apidtitle.append(" (DTS)"); + if (apidtitle.find("DTS") == std::string::npos) + apidtitle.append(" (DTS)"); #ifndef BOXMODEL_APOLLO enabled = false; #endif @@ -809,14 +848,13 @@ void CMoviePlayerGui::getCurrentAudioName( bool file_player, std::string &audion } bool dumm = true; for (unsigned int count = 0; count < numpida; count++) { - if(currentapid == apids[count]){ if(!file_player){ getAudioName(apids[count], audioname); return ; - }else if (!language[count].empty()){ + } else if (!language[count].empty()){ audioname = language[count]; - addAudioFormat(count, audioname, file_player, dumm); + addAudioFormat(count, audioname, dumm); if(!dumm && (count < numpida)){ currentapid = apids[count+1]; continue; @@ -826,7 +864,7 @@ void CMoviePlayerGui::getCurrentAudioName( bool file_player, std::string &audion char apidnumber[20]; sprintf(apidnumber, "Stream %d %X", count + 1, apids[count]); audioname = apidnumber; - addAudioFormat(count, audioname, file_player, dumm); + addAudioFormat(count, audioname, dumm); if(!dumm && (count < numpida)){ currentapid = apids[count+1]; continue; @@ -867,7 +905,7 @@ void CMoviePlayerGui::selectAudioPid(bool file_player) sprintf(apidnumber, "Stream %d %X", count + 1, apids[count]); apidtitle = apidnumber; } - addAudioFormat(count, apidtitle, file_player, enabled); + addAudioFormat(count, apidtitle, enabled); if(defpid && !enabled && (count < numpida)){ currentapid = apids[count+1]; defpid = false; @@ -879,7 +917,7 @@ void CMoviePlayerGui::selectAudioPid(bool file_player) APIDSelector.addItem(item, defpid); } - if (p_movie_info) { + if (p_movie_info && numpida <= p_movie_info->audioPids.size()) { APIDSelector.addItem(new CMenuSeparator(CMenuSeparator::LINE | CMenuSeparator::STRING, LOCALE_AUDIOMENU_VOLUME_ADJUST)); CVolume::getInstance()->SetCurrentChannel(p_movie_info->epgId); @@ -1059,7 +1097,7 @@ void CMoviePlayerGui::handleMovieBrowser(neutrino_msg_t msg, int /*position*/) jump_not_until = (position / 1000) + 10; // avoid bookmark jumping for the next 10 seconds, , TODO: might be moved to another key } return; - } + } else if (msg == (neutrino_msg_t) g_settings.mpkey_bookmark) { if (newComHintBox.isPainted() == true) { // yes, let's get the end pos of the jump forward @@ -1119,7 +1157,7 @@ void CMoviePlayerGui::handleMovieBrowser(neutrino_msg_t msg, int /*position*/) DisplayErrorMessage(g_Locale->getText(LOCALE_MOVIEPLAYER_TOOMANYBOOKMARKS)); // UTF-8 } cSelectedMenuBookStart[0].selected = false; // clear for next bookmark menu - } else + } else #endif if (cSelectedMenuBookStart[1].selected == true) { /* Moviebrowser plain bookmark */ @@ -1188,3 +1226,234 @@ void CMoviePlayerGui::showHelpTS() helpbox.addLine(g_Locale->getText(LOCALE_MOVIEPLAYER_TSHELP12)); helpbox.show(LOCALE_MESSAGEBOX_INFO); } + +void CMoviePlayerGui::selectChapter() +{ + if (!is_file_player) + return; + + std::vector positions; std::vector titles; + playback->GetChapters(positions, titles); + if (positions.empty()) + return; + + CMenuWidget ChSelector(LOCALE_MOVIEBROWSER_MENU_MAIN_BOOKMARKS, NEUTRINO_ICON_AUDIO); + ChSelector.addIntroItems(); + + int select = -1; + CMenuSelectorTarget * selector = new CMenuSelectorTarget(&select); + char cnt[5]; + for (unsigned i = 0; i < positions.size(); i++) { + sprintf(cnt, "%d", i); + CMenuForwarderNonLocalized * item = new CMenuForwarderNonLocalized(titles[i].c_str(), true, NULL, selector, cnt, CRCInput::convertDigitToKey(i + 1)); + ChSelector.addItem(item, position > positions[i]); + } + ChSelector.exec(NULL, ""); + delete selector; + printf("CMoviePlayerGui::selectChapter: selected %d (%d)\n", select, (select >= 0) ? positions[select] : -1); + if(select >= 0) + playback->SetPosition(positions[select], true); +} + +void CMoviePlayerGui::selectSubtitle() +{ + if (!is_file_player) + return; + + CMenuWidget APIDSelector(LOCALE_SUBTITLES_HEAD, NEUTRINO_ICON_AUDIO); + APIDSelector.addIntroItems(); + + int select = -1; + CMenuSelectorTarget * selector = new CMenuSelectorTarget(&select); + if(!numsubs) { + playback->FindAllSubs(spids, sub_supported, &numsubs, slanguage); + } + char cnt[5]; + unsigned int count; + for (count = 0; count < numsubs; count++) { + bool enabled = sub_supported[count]; + bool defpid = currentspid >= 0 ? (currentspid == spids[count]) : (count == 0); + std::string title = slanguage[count]; + if (title.empty()) { + char pidnumber[20]; + sprintf(pidnumber, "Stream %d %X", count + 1, spids[count]); + title = pidnumber; + } + sprintf(cnt, "%d", count); + CMenuForwarderNonLocalized * item = new CMenuForwarderNonLocalized(title.c_str(), enabled, NULL, selector, cnt, CRCInput::convertDigitToKey(count + 1)); + item->setItemButton(NEUTRINO_ICON_BUTTON_STOP, false); + APIDSelector.addItem(item, defpid); + } + sprintf(cnt, "%d", count); + APIDSelector.addItem(new CMenuForwarder(LOCALE_SUBTITLES_STOP, true, NULL, selector, cnt, CRCInput::RC_stop), currentspid < 0); + + APIDSelector.exec(NULL, ""); + delete selector; + printf("CMoviePlayerGui::selectSubtitle: selected %d (%x) current %x\n", select, (select >= 0) ? spids[select] : -1, currentspid); + if((select >= 0) && (select < numsubs) && (currentspid != spids[select])) { + currentspid = spids[select]; + playback->SelectSubtitles(currentspid); + printf("[movieplayer] spid changed to %d\n", currentspid); + } else if ( select > 0) { + currentspid = -1; + playback->SelectSubtitles(currentspid); + printf("[movieplayer] spid changed to %d\n", currentspid); + } +} + +extern "C" { +#include +#include +} + +void CMoviePlayerGui::clearSubtitle() +{ + if ((max_x-min_x > 0) && (max_y-min_y > 0)) + frameBuffer->paintBackgroundBoxRel(min_x, min_y, max_x-min_x, max_y-min_y); + + min_x = CFrameBuffer::getInstance()->getScreenWidth(); + min_y = CFrameBuffer::getInstance()->getScreenHeight(); + max_x = CFrameBuffer::getInstance()->getScreenX(); + max_y = CFrameBuffer::getInstance()->getScreenY(); + end_time = 0; +} + +fb_pixel_t * simple_resize32(uint8_t * orgin, uint32_t * colors, int nb_colors, int ox, int oy, int dx, int dy); + +void CMoviePlayerGui::showSubtitle(neutrino_msg_data_t data) +{ + if (!data) { + if (end_time && time_monotonic_ms() > end_time) { + printf("************************* hide subs *************************\n"); + clearSubtitle(); + } + return; + } + AVSubtitle * sub = (AVSubtitle *) data; + + printf("************************* EVT_SUBT_MESSAGE: num_rects %d fmt %d *************************\n", sub->num_rects, sub->format); + if (!sub->num_rects) + return; + + if (sub->format == 0) { + int xres = 0, yres = 0, framerate; + videoDecoder->getPictureInfo(xres, yres, framerate); + + double xc = (double) CFrameBuffer::getInstance()->getScreenWidth(/*true*/)/(double) xres; + double yc = (double) CFrameBuffer::getInstance()->getScreenHeight(/*true*/)/(double) yres; + + clearSubtitle(); + + for (unsigned i = 0; i < sub->num_rects; i++) { + uint32_t * colors = (uint32_t *) sub->rects[i]->pict.data[1]; + + int nw = (double) sub->rects[i]->w * xc; + int nh = (double) sub->rects[i]->h * yc; + int xoff = (double) sub->rects[i]->x * xc; + int yoff = (double) sub->rects[i]->y * yc; + + printf("Draw: #%d at %d,%d size %dx%d colors %d (x=%d y=%d w=%d h=%d) \n", i+1, + sub->rects[i]->x, sub->rects[i]->y, sub->rects[i]->w, sub->rects[i]->h, + sub->rects[i]->nb_colors, xoff, yoff, nw, nh); + + fb_pixel_t * newdata = simple_resize32 (sub->rects[i]->pict.data[0], colors, + sub->rects[i]->nb_colors, sub->rects[i]->w, sub->rects[i]->h, nw, nh); + frameBuffer->blit2FB(newdata, nw, nh, xoff, yoff); + free(newdata); + + min_x = std::min(min_x, xoff); + max_x = std::max(max_x, xoff + nw); + min_y = std::min(min_y, yoff); + max_y = std::max(max_y, yoff + nh); + } + end_time = sub->end_display_time + time_monotonic_ms(); + avsubtitle_free(sub); + delete sub; + return; + } + std::vector subtext; + for (unsigned i = 0; i < sub->num_rects; i++) { + char * txt = NULL; + if (sub->rects[i]->type == SUBTITLE_TEXT) + txt = sub->rects[i]->text; + else if (sub->rects[i]->type == SUBTITLE_ASS) + txt = sub->rects[i]->ass; + printf("subt[%d] type %d [%s]\n", i, sub->rects[i]->type, txt ? txt : ""); + if (txt) { + int len = strlen(txt); + if (len > 10 && memcmp(txt, "Dialogue: ", 10) == 0) { + char* p = txt; + int skip_commas = 4; + /* skip ass times */ + for (int j = 0; j < skip_commas && *p != '\0'; p++) + if (*p == ',') + j++; + /* skip ass tags */ + if (*p == '{') { + char * d = strchr(p, '}'); + if (d) + p += d - p + 1; + } + char * d = strchr(p, '{'); + if (d && strchr(d, '}')) + *d = 0; + + len = strlen(p); + /* remove newline */ + for (int j = len-1; j > 0; j--) { + if (p[j] == '\n' || p[j] == '\r') + p[j] = 0; + else + break; + } + if (*p == '\0') + continue; + txt = p; + } + //printf("title: [%s]\n", txt); + std::string str(txt); + int start = 0, end = 0; + /* split string with \N as newline */ + std::string delim("\\N"); + while ((end = str.find(delim, start)) != string::npos) { + subtext.push_back(str.substr(start, end - start)); + start = end + 2; + } + subtext.push_back(str.substr(start)); + + } + } + for (unsigned i = 0; i < subtext.size(); i++) + printf("subtext %d: [%s]\n", i, subtext[i].c_str()); + printf("********************************************************************\n"); + + if (!subtext.empty()) { + int sh = frameBuffer->getScreenHeight(); + int sw = frameBuffer->getScreenWidth(); + int h = g_Font[SNeutrinoSettings::FONT_TYPE_MENU]->getHeight(); + int height = h*subtext.size(); + + clearSubtitle(); + + int x[subtext.size()]; + int y[subtext.size()]; + for (unsigned i = 0; i < subtext.size(); i++) { + int w = g_Font[SNeutrinoSettings::FONT_TYPE_MENU]->getRenderWidth (subtext[i].c_str(), true); + x[i] = (sw - w) / 2; + y[i] = sh - height + h*(i + 1); + min_x = std::min(min_x, x[i]); + max_x = std::max(max_x, x[i]+w); + min_y = std::min(min_y, y[i]-h); + max_y = std::max(max_y, y[i]); + } + + frameBuffer->paintBoxRel(min_x, min_y, max_x - min_x, max_y-min_y, COL_MENUCONTENT_PLUS_0); + + for (unsigned i = 0; i < subtext.size(); i++) + g_Font[SNeutrinoSettings::FONT_TYPE_MENU]->RenderString(x[i], y[i], sw, subtext[i].c_str(), COL_MENUCONTENT, 0, true); + + end_time = sub->end_display_time + time_monotonic_ms(); + } + avsubtitle_free(sub); + delete sub; +} diff --git a/src/gui/movieplayer.h b/src/gui/movieplayer.h index e25d565d7..c3356e12e 100644 --- a/src/gui/movieplayer.h +++ b/src/gui/movieplayer.h @@ -87,6 +87,15 @@ class CMoviePlayerGui : public CMenuTarget unsigned short ac3flags[REC_MAX_APIDS]; unsigned short currentapid, currentac3; + /* subtitles vars */ + unsigned short numsubs; + std::string slanguage[REC_MAX_APIDS]; + unsigned short spids[REC_MAX_APIDS]; + unsigned short sub_supported[REC_MAX_APIDS]; + int currentspid; + int min_x, min_y, max_x, max_y; + time_t end_time; + /* playback from MB */ bool isMovieBrowser; CMovieBrowser* moviebrowser; @@ -118,12 +127,17 @@ class CMoviePlayerGui : public CMenuTarget bool getAudioName(int pid, std::string &apidtitle); void selectAudioPid(bool file_player); void getCurrentAudioName( bool file_player, std::string &audioname); - void addAudioFormat(int count, std::string &apidtitle, bool file_player, bool& enabled ); + void addAudioFormat(int count, std::string &apidtitle, bool& enabled ); void handleMovieBrowser(neutrino_msg_t msg, int position = 0); bool SelectFile(); void updateLcd(); + void selectSubtitle(); + void showSubtitle(neutrino_msg_data_t data); + void clearSubtitle(); + void selectChapter(); + CMoviePlayerGui(const CMoviePlayerGui&) {}; CMoviePlayerGui(); diff --git a/src/gui/scan_setup.cpp b/src/gui/scan_setup.cpp index f3991aad2..00c4dba68 100644 --- a/src/gui/scan_setup.cpp +++ b/src/gui/scan_setup.cpp @@ -623,31 +623,33 @@ int CScanSetup::showScanMenuFrontendSetup() nc->setHint("", LOCALE_MENU_HINT_SCAN_FETIMEOUT); setupMenu->addItem(nc); - sprintf(zapit_lat, "%02.6f", zapitCfg.gotoXXLatitude); - sprintf(zapit_long, "%02.6f", zapitCfg.gotoXXLongitude); + if (CFEManager::getInstance()->haveSat()) { + sprintf(zapit_lat, "%02.6f", zapitCfg.gotoXXLatitude); + sprintf(zapit_long, "%02.6f", zapitCfg.gotoXXLongitude); - setupMenu->addItem(new CMenuSeparator(CMenuSeparator::LINE | CMenuSeparator::STRING, LOCALE_SATSETUP_EXTENDED_MOTOR)); - CMenuOptionChooser * mc = new CMenuOptionChooser(LOCALE_EXTRA_LADIRECTION, (int *)&zapitCfg.gotoXXLaDirection, OPTIONS_SOUTH0_NORTH1_OPTIONS, OPTIONS_SOUTH0_NORTH1_OPTION_COUNT, true, NULL, CRCInput::convertDigitToKey(shortcut++)); - mc->setHint("", LOCALE_MENU_HINT_SCAN_LADIRECTION); - setupMenu->addItem(mc); + setupMenu->addItem(new CMenuSeparator(CMenuSeparator::LINE | CMenuSeparator::STRING, LOCALE_SATSETUP_EXTENDED_MOTOR)); + CMenuOptionChooser * mc = new CMenuOptionChooser(LOCALE_EXTRA_LADIRECTION, (int *)&zapitCfg.gotoXXLaDirection, OPTIONS_SOUTH0_NORTH1_OPTIONS, OPTIONS_SOUTH0_NORTH1_OPTION_COUNT, true, NULL, CRCInput::convertDigitToKey(shortcut++)); + mc->setHint("", LOCALE_MENU_HINT_SCAN_LADIRECTION); + setupMenu->addItem(mc); - CStringInput * toff1 = new CStringInput(LOCALE_EXTRA_LATITUDE, (char *) zapit_lat, 10, NONEXISTANT_LOCALE, NONEXISTANT_LOCALE, "0123456789."); - mf = new CMenuDForwarder(LOCALE_EXTRA_LATITUDE, true, zapit_lat, toff1, "", CRCInput::convertDigitToKey(shortcut++)); - mf->setHint("", LOCALE_MENU_HINT_SCAN_LATITUDE); - setupMenu->addItem(mf); + CStringInput * toff1 = new CStringInput(LOCALE_EXTRA_LATITUDE, (char *) zapit_lat, 10, NONEXISTANT_LOCALE, NONEXISTANT_LOCALE, "0123456789."); + mf = new CMenuDForwarder(LOCALE_EXTRA_LATITUDE, true, zapit_lat, toff1, "", CRCInput::convertDigitToKey(shortcut++)); + mf->setHint("", LOCALE_MENU_HINT_SCAN_LATITUDE); + setupMenu->addItem(mf); - mc = new CMenuOptionChooser(LOCALE_EXTRA_LODIRECTION, (int *)&zapitCfg.gotoXXLoDirection, OPTIONS_EAST0_WEST1_OPTIONS, OPTIONS_EAST0_WEST1_OPTION_COUNT, true, NULL, CRCInput::convertDigitToKey(shortcut++)); - mc->setHint("", LOCALE_MENU_HINT_SCAN_LODIRECTION); - setupMenu->addItem(mc); + mc = new CMenuOptionChooser(LOCALE_EXTRA_LODIRECTION, (int *)&zapitCfg.gotoXXLoDirection, OPTIONS_EAST0_WEST1_OPTIONS, OPTIONS_EAST0_WEST1_OPTION_COUNT, true, NULL, CRCInput::convertDigitToKey(shortcut++)); + mc->setHint("", LOCALE_MENU_HINT_SCAN_LODIRECTION); + setupMenu->addItem(mc); - CStringInput * toff2 = new CStringInput(LOCALE_EXTRA_LONGITUDE, (char *) zapit_long, 10, NONEXISTANT_LOCALE, NONEXISTANT_LOCALE, "0123456789."); - mf = new CMenuDForwarder(LOCALE_EXTRA_LONGITUDE, true, zapit_long, toff2, "", CRCInput::convertDigitToKey(shortcut++)); - mf->setHint("", LOCALE_MENU_HINT_SCAN_LONGITUDE); - setupMenu->addItem(mf); + CStringInput * toff2 = new CStringInput(LOCALE_EXTRA_LONGITUDE, (char *) zapit_long, 10, NONEXISTANT_LOCALE, NONEXISTANT_LOCALE, "0123456789."); + mf = new CMenuDForwarder(LOCALE_EXTRA_LONGITUDE, true, zapit_long, toff2, "", CRCInput::convertDigitToKey(shortcut++)); + mf->setHint("", LOCALE_MENU_HINT_SCAN_LONGITUDE); + setupMenu->addItem(mf); - nc = new CMenuOptionNumberChooser(LOCALE_SATSETUP_USALS_REPEAT, (int *)&zapitCfg.repeatUsals, true, 0, 10, NULL, 0, 0, LOCALE_OPTIONS_OFF); - nc->setHint("", LOCALE_MENU_HINT_SCAN_USALS_REPEAT); - setupMenu->addItem(nc); + nc = new CMenuOptionNumberChooser(LOCALE_SATSETUP_USALS_REPEAT, (int *)&zapitCfg.repeatUsals, true, 0, 10, NULL, 0, 0, LOCALE_OPTIONS_OFF); + nc->setHint("", LOCALE_MENU_HINT_SCAN_USALS_REPEAT); + setupMenu->addItem(nc); + } int res = setupMenu->exec(NULL, ""); delete setupMenu; diff --git a/src/gui/widget/icons.h b/src/gui/widget/icons.h index ceebb84f0..f6a40518c 100644 --- a/src/gui/widget/icons.h +++ b/src/gui/widget/icons.h @@ -244,6 +244,7 @@ #define NEUTRINO_ICON_HINT_FACTORY "hint_factory" /* misc */ +#define NEUTRINO_ICON_HINT_YTPLAY "hint_ytplay" #define NEUTRINO_ICON_VARPATH "/var/share/tuxbox/neutrino/icons/" //alternatively path for user-defined icons diff --git a/src/neutrino.cpp b/src/neutrino.cpp index 02087eeb3..9be0abbdd 100644 --- a/src/neutrino.cpp +++ b/src/neutrino.cpp @@ -391,11 +391,11 @@ int CNeutrinoApp::loadSetup(const char * fname) g_settings.infobar_show_channeldesc = configfile.getBool("infobar_show_channeldesc" , false ); g_settings.infobar_subchan_disp_pos = configfile.getInt32("infobar_subchan_disp_pos" , 0 ); g_settings.progressbar_color = configfile.getBool("progressbar_color", true ); - g_settings.progressbar_design = configfile.getInt32("progressbar_design",0); + g_settings.progressbar_design = configfile.getInt32("progressbar_design", 2); //horizontal bars g_settings.infobar_show = configfile.getInt32("infobar_show", 1); g_settings.infobar_show_channellogo = configfile.getInt32("infobar_show_channellogo" , 3 ); - g_settings.infobar_progressbar = configfile.getInt32("infobar_progressbar" , 0 ); - g_settings.casystem_display = configfile.getInt32("casystem_display", 2 );//mini ca mode default + g_settings.infobar_progressbar = configfile.getInt32("infobar_progressbar" , 1 ); // below channel name + g_settings.casystem_display = configfile.getInt32("casystem_display", 1 );//discreet ca mode default g_settings.scrambled_message = configfile.getBool("scrambled_message", true ); g_settings.volume_pos = configfile.getInt32("volume_pos", 0 ); g_settings.volume_digits = configfile.getBool("volume_digits", true); @@ -504,7 +504,7 @@ int CNeutrinoApp::loadSetup(const char * fname) g_settings.personalize[i] = configfile.getInt32( personalize_settings[i].personalize_settings_name, personalize_settings[i].personalize_default_val ); g_settings.colored_events_channellist = configfile.getInt32( "colored_events_channellist" , 0 ); - g_settings.colored_events_infobar = configfile.getInt32( "colored_events_infobar" , 0 ); + g_settings.colored_events_infobar = configfile.getInt32( "colored_events_infobar" , 2 ); // next g_settings.colored_events_alpha = configfile.getInt32( "colored_events_alpha", 0x00 ); g_settings.colored_events_red = configfile.getInt32( "colored_events_red", 95 ); g_settings.colored_events_green = configfile.getInt32( "colored_events_green", 70 ); @@ -586,12 +586,12 @@ int CNeutrinoApp::loadSetup(const char * fname) g_settings.recording_zap_on_announce = configfile.getBool("recording_zap_on_announce" , false); g_settings.shutdown_timer_record_type = configfile.getBool("shutdown_timer_record_type" , false); - g_settings.recording_stream_vtxt_pid = configfile.getBool("recordingmenu.stream_vtxt_pid" , false); - g_settings.recording_stream_subtitle_pids = configfile.getBool("recordingmenu.stream_subtitle_pids", false); + g_settings.recording_stream_vtxt_pid = configfile.getBool("recordingmenu.stream_vtxt_pid" , true); + g_settings.recording_stream_subtitle_pids = configfile.getBool("recordingmenu.stream_subtitle_pids", true); g_settings.recording_stream_pmt_pid = configfile.getBool("recordingmenu.stream_pmt_pid" , false); g_settings.recording_choose_direct_rec_dir = configfile.getInt32( "recording_choose_direct_rec_dir", 0 ); g_settings.recording_epg_for_filename = configfile.getBool("recording_epg_for_filename" , true); - g_settings.recording_epg_for_end = configfile.getBool("recording_epg_for_end" , false); + g_settings.recording_epg_for_end = configfile.getBool("recording_epg_for_end" , true); g_settings.recording_save_in_channeldir = configfile.getBool("recording_save_in_channeldir" , false); g_settings.recording_slow_warning = configfile.getBool("recording_slow_warning" , true); @@ -3710,6 +3710,7 @@ void CNeutrinoApp::loadKeys(const char * fname) g_settings.mpkey_time = tconfig.getInt32( "mpkey.time", CRCInput::RC_setup ); g_settings.mpkey_bookmark = tconfig.getInt32( "mpkey.bookmark", CRCInput::RC_blue ); g_settings.mpkey_plugin = tconfig.getInt32( "mpkey.plugin", CRCInput::RC_red ); + g_settings.mpkey_subtitle = tconfig.getInt32( "mpkey.subtitle", CRCInput::RC_sub ); /* options */ g_settings.menu_left_exit = tconfig.getInt32( "menu_left_exit", 0 ); @@ -3773,6 +3774,7 @@ void CNeutrinoApp::saveKeys(const char * fname) tconfig.setInt32( "mpkey.time", g_settings.mpkey_time ); tconfig.setInt32( "mpkey.bookmark", g_settings.mpkey_bookmark ); tconfig.setInt32( "mpkey.plugin", g_settings.mpkey_plugin ); + tconfig.setInt32( "mpkey.subtitle", g_settings.mpkey_subtitle ); tconfig.setInt32( "menu_left_exit", g_settings.menu_left_exit ); tconfig.setInt32( "audio_run_player", g_settings.audio_run_player ); diff --git a/src/neutrinoMessages.h b/src/neutrinoMessages.h index 7eeaaae4a..b349eb19e 100644 --- a/src/neutrinoMessages.h +++ b/src/neutrinoMessages.h @@ -110,6 +110,7 @@ struct NeutrinoMessages { EVT_PMT_CHANGED = CRCInput::RC_Events + 40, /* NEVER CHANGE THIS */ EVT_CA_MESSAGE = CRCInput::RC_Events + 60, /* data = CA_MESSAGE pointer */ + EVT_SUBT_MESSAGE = CRCInput::RC_Events + 61, /* data = subtitles pointer */ /* END */ EVT_CURRENTEPG = CRCInput::RC_WithData + 1, diff --git a/src/system/Makefile.am b/src/system/Makefile.am index 081507c44..2ed9e2309 100644 --- a/src/system/Makefile.am +++ b/src/system/Makefile.am @@ -38,4 +38,5 @@ libneutrino_system_a_SOURCES = \ helpers.cpp \ ping.c \ settings.cpp \ + ytparser.cpp \ setting_helpers.cpp diff --git a/src/system/flashtool.cpp b/src/system/flashtool.cpp index c4da668f4..1e1333783 100644 --- a/src/system/flashtool.cpp +++ b/src/system/flashtool.cpp @@ -101,13 +101,7 @@ bool CFlashTool::readFromMTD( const std::string & filename, int globalProgressEn filesize = CMTDInfo::getInstance()->getMTDSize(mtdDevice); - unsigned char * buf = new unsigned char[meminfo.writesize]; - if (buf == NULL) { - printf("CFlashTool::program: mem alloc failed\n"); - close(fd); - close(fd1); - return false; - } + unsigned char buf[meminfo.writesize]; unsigned mtdoffset = 0; long fsize = filesize; while(fsize > 0) { @@ -150,7 +144,6 @@ bool CFlashTool::readFromMTD( const std::string & filename, int globalProgressEn if(statusViewer) statusViewer->showLocalStatus(100); - delete[] buf; close(fd); close(fd1); return true; @@ -211,13 +204,7 @@ bool CFlashTool::program( const std::string & filename, int globalProgressEndEra if(statusViewer) globalProgressBegin = statusViewer->getGlobalStatus(); - unsigned char * buf = new unsigned char[meminfo.writesize]; - if (buf == NULL) { - printf("CFlashTool::program: mem alloc failed\n"); - close(fd); - close(fd1); - return false; - } + unsigned char buf[meminfo.writesize]; unsigned mtdoffset = 0; unsigned fsize = filesize; printf("CFlashTool::program: file %s write size %d, erase size %d\n", filename.c_str(), meminfo.writesize, meminfo.erasesize); @@ -270,7 +257,6 @@ bool CFlashTool::program( const std::string & filename, int globalProgressEndEra if(statusViewer) statusViewer->showLocalStatus(100); - delete[] buf; close(fd1); close(fd); // FIXME error message @@ -290,7 +276,7 @@ bool CFlashTool::getInfo() meminfo.writesize = 1024; isnand = (meminfo.type == MTD_NANDFLASH); - printf("CFlashTool::getInfo: NAND: %s\n", isnand ? "yes" : "no"); + printf("CFlashTool::getInfo: NAND: %s writesize %d\n", isnand ? "yes" : "no", meminfo.writesize); return true; } diff --git a/src/system/locals.h b/src/system/locals.h index 93fc95a96..24640fe80 100644 --- a/src/system/locals.h +++ b/src/system/locals.h @@ -125,6 +125,7 @@ typedef enum LOCALE_GENRE_UNKNOWN, LOCALE_APIDSELECTOR_HEAD, LOCALE_AUDIO_SRS_ALGO, + LOCALE_AUDIO_SRS_ALGO_HEAVY, LOCALE_AUDIO_SRS_ALGO_LIGHT, LOCALE_AUDIO_SRS_ALGO_NORMAL, LOCALE_AUDIO_SRS_IQ, @@ -883,6 +884,7 @@ typedef enum LOCALE_MENU_HINT_KEY_MPPLUGIN, LOCALE_MENU_HINT_KEY_MPREWIND, LOCALE_MENU_HINT_KEY_MPSTOP, + LOCALE_MENU_HINT_KEY_MPSUBTITLE, LOCALE_MENU_HINT_KEY_MPTIME, LOCALE_MENU_HINT_KEY_MPTIMESHIFT, LOCALE_MENU_HINT_KEY_PAGEDOWN, @@ -1146,6 +1148,7 @@ typedef enum LOCALE_MENU_HINT_VOLUME, LOCALE_MENU_HINT_VOLUME_DIGITS, LOCALE_MENU_HINT_VOLUME_POS, + LOCALE_MENU_HINT_YTPLAY, LOCALE_MENU_HINT_ZAP_CYCLE, LOCALE_MENU_NEXT, LOCALE_MESSAGEBOX_BACK, @@ -1379,6 +1382,22 @@ typedef enum LOCALE_MOVIEBROWSER_USE_DIR, LOCALE_MOVIEBROWSER_USE_MOVIE_DIR, LOCALE_MOVIEBROWSER_USE_REC_DIR, + LOCALE_MOVIEBROWSER_YT_ERROR, + LOCALE_MOVIEBROWSER_YT_MAX_RESULTS, + LOCALE_MOVIEBROWSER_YT_MOST_DISCUSSED, + LOCALE_MOVIEBROWSER_YT_MOST_POPULAR, + LOCALE_MOVIEBROWSER_YT_MOST_RESENT, + LOCALE_MOVIEBROWSER_YT_MOST_RESPONDED, + LOCALE_MOVIEBROWSER_YT_MOST_SHARED, + LOCALE_MOVIEBROWSER_YT_NEXT_RESULTS, + LOCALE_MOVIEBROWSER_YT_ON_THE_WEB, + LOCALE_MOVIEBROWSER_YT_PREV_RESULTS, + LOCALE_MOVIEBROWSER_YT_RECENTLY_FEATURED, + LOCALE_MOVIEBROWSER_YT_REGION, + LOCALE_MOVIEBROWSER_YT_RELATED, + LOCALE_MOVIEBROWSER_YT_SEARCH, + LOCALE_MOVIEBROWSER_YT_TOP_FAVORITES, + LOCALE_MOVIEBROWSER_YT_TOP_RATED, LOCALE_MOVIEPLAYER_BOOKMARK, LOCALE_MOVIEPLAYER_BOOKMARKNAME, LOCALE_MOVIEPLAYER_BOOKMARKNAME_HINT1, @@ -1400,6 +1419,7 @@ typedef enum LOCALE_MOVIEPLAYER_TSHELP8, LOCALE_MOVIEPLAYER_TSHELP9, LOCALE_MOVIEPLAYER_TSPLAYBACK, + LOCALE_MOVIEPLAYER_YTPLAYBACK, LOCALE_MPKEY_AUDIO, LOCALE_MPKEY_BOOKMARK, LOCALE_MPKEY_FORWARD, @@ -1408,6 +1428,7 @@ typedef enum LOCALE_MPKEY_PLUGIN, LOCALE_MPKEY_REWIND, LOCALE_MPKEY_STOP, + LOCALE_MPKEY_SUBTITLE, LOCALE_MPKEY_TIME, LOCALE_NETWORKMENU_APPLY_SETTINGS, LOCALE_NETWORKMENU_APPLY_SETTINGS_NOW, diff --git a/src/system/locals_intern.h b/src/system/locals_intern.h index d890b41f4..da73becf4 100644 --- a/src/system/locals_intern.h +++ b/src/system/locals_intern.h @@ -125,6 +125,7 @@ const char * locale_real_names[] = "GENRE.UNKNOWN", "apidselector.head", "audio.srs_algo", + "audio.srs_algo_heavy", "audio.srs_algo_light", "audio.srs_algo_normal", "audio.srs_iq", @@ -883,6 +884,7 @@ const char * locale_real_names[] = "menu.hint_key_mpplugin", "menu.hint_key_mprewind", "menu.hint_key_mpstop", + "menu.hint_key_mpsubtitle", "menu.hint_key_mptime", "menu.hint_key_mptimeshift", "menu.hint_key_pagedown", @@ -1146,6 +1148,7 @@ const char * locale_real_names[] = "menu.hint_volume", "menu.hint_volume_digits", "menu.hint_volume_pos", + "menu.hint_ytplay", "menu.hint_zap_cycle", "menu.next", "messagebox.back", @@ -1379,6 +1382,22 @@ const char * locale_real_names[] = "moviebrowser.use_dir", "moviebrowser.use_movie_dir", "moviebrowser.use_rec_dir", + "moviebrowser.yt_error", + "moviebrowser.yt_max_results", + "moviebrowser.yt_most_discussed", + "moviebrowser.yt_most_popular", + "moviebrowser.yt_most_resent", + "moviebrowser.yt_most_responded", + "moviebrowser.yt_most_shared", + "moviebrowser.yt_next_results", + "moviebrowser.yt_on_the_web", + "moviebrowser.yt_prev_results", + "moviebrowser.yt_recently_featured", + "moviebrowser.yt_region", + "moviebrowser.yt_related", + "moviebrowser.yt_search", + "moviebrowser.yt_top_favorites", + "moviebrowser.yt_top_rated", "movieplayer.bookmark", "movieplayer.bookmarkname", "movieplayer.bookmarkname_hint1", @@ -1400,6 +1419,7 @@ const char * locale_real_names[] = "movieplayer.tshelp8", "movieplayer.tshelp9", "movieplayer.tsplayback", + "movieplayer.ytplayback", "mpkey.audio", "mpkey.bookmark", "mpkey.forward", @@ -1408,6 +1428,7 @@ const char * locale_real_names[] = "mpkey.plugin", "mpkey.rewind", "mpkey.stop", + "mpkey.subtitle", "mpkey.time", "networkmenu.apply_settings", "networkmenu.apply_settings_now", diff --git a/src/system/settings.cpp b/src/system/settings.cpp index 1f75181e6..d848aec29 100644 --- a/src/system/settings.cpp +++ b/src/system/settings.cpp @@ -92,6 +92,7 @@ const struct personalize_settings_t personalize_settings[SNeutrinoSettings::P_SE //media menu->movieplayer {"personalize_mplayer_mbrowswer" , CPersonalizeGui::PERSONALIZE_MODE_VISIBLE}, {"personalize_mplayer_fileplay" , CPersonalizeGui::PERSONALIZE_MODE_VISIBLE}, + {"personalize_mplayer_ytplay" , CPersonalizeGui::PERSONALIZE_MODE_VISIBLE}, //key {"personalize_feat_key_fav" , CPersonalizeGui::PERSONALIZE_FEAT_KEY_GREEN}, diff --git a/src/system/settings.h b/src/system/settings.h index d6ffa8cec..d1d2fc516 100644 --- a/src/system/settings.h +++ b/src/system/settings.h @@ -213,6 +213,7 @@ struct SNeutrinoSettings //movieplayer menu P_MPLAYER_MBROWSER, P_MPLAYER_FILEPLAY, + P_MPLAYER_YTPLAY, //feature keys P_FEAT_KEY_FAVORIT, @@ -393,6 +394,7 @@ struct SNeutrinoSettings int mpkey_time; int mpkey_bookmark; int mpkey_plugin; + int mpkey_subtitle; int key_timeshift; int key_plugin; diff --git a/src/system/ytparser.cpp b/src/system/ytparser.cpp new file mode 100644 index 000000000..0c0b833bb --- /dev/null +++ b/src/system/ytparser.cpp @@ -0,0 +1,597 @@ +/* + Copyright (C) 2013 CoolStream International Ltd + + License: GPLv2 + + 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; + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "ytparser.h" + +#if LIBCURL_VERSION_NUM < 0x071507 +#error +#include +#endif + +#define URL_TIMEOUT 60 + +std::string cYTVideoUrl::GetUrl() +{ + std::string fullurl = url; + fullurl += "&signature="; + fullurl += sig; + return fullurl; +} + +void cYTVideoInfo::Dump() +{ + printf("id: %s\n", id.c_str()); + printf("author: %s\n", author.c_str()); + printf("title: %s\n", title.c_str()); + printf("duration: %d\n", duration); + //printf("description: %s\n", description.c_str()); + printf("urls: %d\n", formats.size()); + for (yt_urlmap_iterator_t it = formats.begin(); it != formats.end(); ++it) { + printf("format %d type [%s] url %s\n", it->first, it->second.type.c_str(), it->second.GetUrl().c_str()); + } + printf("===================================================================\n"); +} + +std::string cYTVideoInfo::GetUrl(int fmt) +{ + yt_urlmap_iterator_t it; + if (fmt) { + if ((it = formats.find(fmt)) != formats.end()) + return it->second.GetUrl(); + return ""; + } + if ((it = formats.find(37)) != formats.end()) + return it->second.GetUrl(); + if ((it = formats.find(22)) != formats.end()) + return it->second.GetUrl(); + if ((it = formats.find(18)) != formats.end()) + return it->second.GetUrl(); + return ""; +} + +cYTFeedParser::cYTFeedParser() +{ + thumbnail_dir = "/tmp/ytparser"; + parsed = false; + feedmode = -1; + tquality = "mqdefault"; + max_results = 25; +} + +cYTFeedParser::~cYTFeedParser() +{ +} + +size_t cYTFeedParser::CurlWriteToString(void *ptr, size_t size, size_t nmemb, void *data) +{ + std::string* pStr = (std::string*) data; + pStr->append((char*) ptr, nmemb); + return size*nmemb; +} + +bool cYTFeedParser::getUrl(std::string &url, std::string &answer) +{ + CURL * curl_handle = curl_easy_init(); + curl_easy_setopt(curl_handle, CURLOPT_URL, url.c_str()); + curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, &cYTFeedParser::CurlWriteToString); + curl_easy_setopt(curl_handle, CURLOPT_FILE, (void *)&answer); + curl_easy_setopt(curl_handle, CURLOPT_FAILONERROR, 1); + curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, URL_TIMEOUT); + curl_easy_setopt(curl_handle, CURLOPT_NOSIGNAL, (long)1); + + char cerror[CURL_ERROR_SIZE]; + curl_easy_setopt(curl_handle, CURLOPT_ERRORBUFFER, cerror); + + printf("try to get [%s] ...\n", url.c_str()); + CURLcode httpres = curl_easy_perform(curl_handle); + + curl_easy_cleanup(curl_handle); + + printf("http: res %d size %d\n", httpres, answer.size()); + + if (httpres != 0 || answer.empty()) { + printf("error: %s\n", cerror); + return false; + } + return true; +} + +bool cYTFeedParser::DownloadUrl(std::string &url, std::string &file) +{ + FILE * fp = fopen(file.c_str(), "wb"); + if (fp == NULL) { + perror(file.c_str()); + return false; + } + CURL * curl_handle = curl_easy_init(); + curl_easy_setopt(curl_handle, CURLOPT_URL, url.c_str()); + curl_easy_setopt(curl_handle, CURLOPT_FILE, fp); + curl_easy_setopt(curl_handle, CURLOPT_FAILONERROR, 1); + curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, URL_TIMEOUT); + curl_easy_setopt(curl_handle, CURLOPT_NOSIGNAL, (long)1); + + char cerror[CURL_ERROR_SIZE]; + curl_easy_setopt(curl_handle, CURLOPT_ERRORBUFFER, cerror); + + printf("try to get [%s] ...\n", url.c_str()); + CURLcode httpres = curl_easy_perform(curl_handle); + + double dsize; + curl_easy_getinfo(curl_handle, CURLINFO_SIZE_DOWNLOAD, &dsize); + curl_easy_cleanup(curl_handle); + fclose(fp); + + printf("http: res %d size %f.\n", httpres, dsize); + + if (httpres != 0) { + printf("curl error: %s\n", cerror); + unlink(file.c_str()); + return false; + } + return true; +} + +void cYTFeedParser::decodeUrl(std::string &url) +{ + CURL * curl_handle = curl_easy_init(); + char * str = curl_easy_unescape(curl_handle, url.c_str(), 0, NULL); + curl_easy_cleanup(curl_handle); + if(str) + url = str; + curl_free(str); +} + +void cYTFeedParser::splitString(std::string &str, std::string delim, std::vector &strlist, int start) +{ + strlist.clear(); + int end = 0; + while ((end = str.find(delim, start)) != std::string::npos) { + strlist.push_back(str.substr(start, end - start)); + start = end + delim.size(); + } + strlist.push_back(str.substr(start)); +} + +void cYTFeedParser::splitString(std::string &str, std::string delim, std::map &strmap, int start) +{ + int end = 0; + if ((end = str.find(delim, start)) != std::string::npos) { + strmap[str.substr(start, end - start)] = str.substr(end - start + delim.size()); + } +} + +bool cYTFeedParser::saveToFile(const char * name, std::string str) +{ + FILE * fp = fopen(name, "w+"); + if (fp) { + fprintf(fp, "%s", str.c_str()); + fclose(fp); + return false; + } + printf("cYTFeedParser::saveToFile: failed to open %s\n", name); + return false; +} + +std::string cYTFeedParser::getXmlName(xmlNodePtr node) +{ + std::string result; + char * name = xmlGetName(node); + if (name) + result = name; + return result; +} + +std::string cYTFeedParser::getXmlAttr(xmlNodePtr node, const char * attr) +{ + std::string result; + char * value = xmlGetAttribute(node, attr); + if (value) + result = value; + return result; +} + +std::string cYTFeedParser::getXmlData(xmlNodePtr node) +{ + std::string result; + char * value = xmlGetData(node); + if (value) + result = value; + return result; +} + +bool cYTFeedParser::parseFeedXml(std::string &answer) +{ + xmlDocPtr answer_parser = parseXmlFile(curfeedfile.c_str()); + if (answer_parser == NULL) + answer_parser = parseXml(answer.c_str()); + + if (answer_parser == NULL) { + printf("failed to parse xml\n"); + return false; + } + next.clear(); + prev.clear(); + total.clear(); + start.clear(); + xmlNodePtr entry = xmlDocGetRootElement(answer_parser)->xmlChildrenNode; + while (entry) { + std::string name = getXmlName(entry); +#ifdef DEBUG_PARSER + printf("entry: %s\n", name.c_str()); +#endif + if (name == "openSearch:startIndex") { + start = getXmlData(entry); + printf("start %s\n", start.c_str()); + } else if (name == "openSearch:totalResults") { + total = getXmlData(entry); + printf("total %s\n", total.c_str()); + } + else if (name == "link") { + std::string link = getXmlAttr(entry, "rel"); + if (link == "next") { + next = getXmlAttr(entry, "href"); + printf(" next [%s]\n", next.c_str()); + } else if (link == "previous") { + prev = getXmlAttr(entry, "href"); + printf(" prev [%s]\n", prev.c_str()); + } + } + else if (name != "entry") { + entry = entry->xmlNextNode; + continue; + } + xmlNodePtr node = entry->xmlChildrenNode; + cYTVideoInfo vinfo; + std::string thumbnail; + while (node) { + name = getXmlName(node); +#ifdef DEBUG_PARSER + printf(" node: %s\n", name.c_str()); +#endif + if (name == "title") { +#ifdef DEBUG_PARSER + printf(" title [%s]\n", getXmlData(node).c_str()); +#endif + vinfo.title = getXmlData(node); + } + else if (name == "published") { + vinfo.published = getXmlData(node).substr(0, 10); + } + else if (name == "author") { + xmlNodePtr author = node->xmlChildrenNode; + while(author) { + name = getXmlName(author); + if (name == "name") { +#ifdef DEBUG_PARSER + printf(" author [%s]\n", getXmlData(author).c_str()); +#endif + vinfo.author = getXmlData(author); + } + author = author->xmlNextNode; + } + } + else if (name == "media:group") { + xmlNodePtr media = node->xmlChildrenNode; + while (media) { + name = getXmlName(media); + if (name == "media:description") { + vinfo.description = getXmlData(media).c_str(); + } + else if (name == "media:category") { + if (vinfo.category.size() < 3) + vinfo.category = getXmlData(media).c_str(); + } + else if (name == "yt:videoid") { +#ifdef DEBUG_PARSER + printf(" id [%s]\n", getXmlData(media).c_str()); +#endif + vinfo.id = getXmlData(media).c_str(); + } + else if (name == "media:thumbnail") { + /* save first found */ + if (thumbnail.empty()) + thumbnail = getXmlAttr(media, "url"); + + /* check wanted quality */ + if (tquality == getXmlAttr(media, "yt:name")) { + vinfo.thumbnail = getXmlAttr(media, "url"); +#ifdef DEBUG_PARSER + printf("vinfo.thumbnail [%s]\n", vinfo.thumbnail.c_str()); +#endif + } + } + else if (name == "yt:duration") { + vinfo.duration = atoi(getXmlAttr(media, "seconds").c_str()); + } +#if 0 + else if (name == "media:player") { + std::string url = getXmlAttr(media, "url"); + printf(" media:player [%s]\n", url.c_str()); + } + else if (name == "media:title") { + } +#endif + media = media->xmlNextNode; + } + } + node = node->xmlNextNode; + } + if (!vinfo.id.empty()) { + /* save first one, if wanted not found */ + if (vinfo.thumbnail.empty()) + vinfo.thumbnail = thumbnail; + if (ParseVideoInfo(vinfo)) + videos.push_back(vinfo); + } + entry = entry->xmlNextNode; + } + xmlFreeDoc(answer_parser); + parsed = !videos.empty(); + return parsed; +} + +bool cYTFeedParser::supportedFormat(int fmt) +{ + if((fmt == 37) || (fmt == 22) || (fmt == 18)) + return true; + return false; +} + +bool cYTFeedParser::decodeVideoInfo(std::string &answer, cYTVideoInfo &vinfo) +{ + bool ret = false; + decodeUrl(answer); +#if 0 + std::string infofile = thumbnail_dir; + infofile += "/"; + infofile += vinfo.id; + infofile += ".txt" + saveToFile(infofile.c_str(), answer); +#endif + if(answer.find("token=") == std::string::npos) + return ret; + + //FIXME check expire + std::vector ulist; + unsigned fmt = answer.find("url_encoded_fmt_stream_map="); + if (fmt != std::string::npos) { + fmt = answer.find("=", fmt); + splitString(answer, ",", ulist, fmt+1); + for (unsigned i = 0; i < ulist.size(); i++) { +#if 0 // to decode all params + decodeUrl(ulist[i]); + printf("URL: %s\n", ulist[i].c_str()); +#endif + std::map smap; + std::vector uparams; + splitString(ulist[i], "&", uparams); + if (uparams.size() < 3) + continue; + for (unsigned j = 0; j < uparams.size(); j++) { + decodeUrl(uparams[j]); +#ifdef DEBUG_PARSER + printf(" param: %s\n", uparams[j].c_str()); +#endif + splitString(uparams[j], "=", smap); + } +#ifdef DEBUG_PARSER + printf("=========================================================\n"); +#endif + cYTVideoUrl yurl; + yurl.url = smap["url"]; + yurl.sig = smap["sig"]; + int id = atoi(smap["itag"].c_str()); + if (supportedFormat(id) && !yurl.url.empty() && !yurl.sig.empty()) { + yurl.quality = smap["quality"]; + yurl.type = smap["type"]; + vinfo.formats.insert(yt_urlmap_pair_t(id, yurl)); + ret = true; + } + } + } + return ret; +} + +bool cYTFeedParser::ParseFeed(std::string &url) +{ + videos.clear(); + + std::string answer; + curfeedfile = thumbnail_dir; + curfeedfile += "/"; + curfeedfile += curfeed; + curfeedfile += ".xml"; +#ifdef CACHE_FILES + if(!DownloadUrl(url, cfile)) + return false; +#else + if (!getUrl(url, answer)) + return false; +#endif + return parseFeedXml(answer); +} + +bool cYTFeedParser::ParseFeed(yt_feed_mode_t mode, std::string search, std::string vid) +{ + std::string url = "http://gdata.youtube.com/feeds/api/standardfeeds/"; + bool append_res = true; + if (mode < FEED_LAST) { + switch(mode) { + case TOP_RATED: + curfeed = "top_rated"; + break; + case TOP_FAVORITES: + curfeed = "top_favorites"; + break; + case MOST_SHARED: + curfeed = "most_shared"; + break; + case MOST_POPULAR: + default: + curfeed = "most_popular"; + break; + case MOST_RESENT: + curfeed = "most_recent"; + break; + case MOST_DISCUSSED: + curfeed = "most_discussed"; + break; + case MOST_RESPONDED: + curfeed = "most_responded"; + break; + case RECENTLY_FEATURED: + curfeed = "recently_featured"; + break; + case ON_THE_WEB: + curfeed = "on_the_web"; + break; + } + if (!region.empty()) { + url += region; + url += "/"; + } + url += curfeed; + url += "?"; + } + else if (mode == NEXT) { + if (next.empty()) + return false; + url = next; + append_res = false; + } + else if (mode == PREV) { + if (prev.empty()) + return false; + url = prev; + append_res = false; + } + else if (mode == RELATED) { + if (vid.empty()) + return false; + url = "http://gdata.youtube.com/feeds/api/videos/"; + url += vid; + url += "/related?"; + } + else if (mode == SEARCH) { + if (search.empty()) + return false; + url = "http://gdata.youtube.com/feeds/api/videos?q="; + url += search; + url += "&"; + } + + feedmode = mode; + if (append_res) { + url += "v=2&max-results="; + char res[10]; + sprintf(res, "%d", max_results); + url+= res; + } + + return ParseFeed(url); +} + +bool cYTFeedParser::ParseVideoInfo(cYTVideoInfo &vinfo) +{ + bool ret = false; + std::vector estr; + estr.push_back("&el=embedded"); + estr.push_back("&el=vevo"); + estr.push_back("&el=detailpage"); + + for (unsigned i = 0; i < estr.size(); i++) { + std::string vurl = "http://www.youtube.com/get_video_info?video_id="; + vurl += vinfo.id; + vurl += estr[i]; + vurl += "&ps=default&eurl=&gl=US&hl=en"; + printf("cYTFeedParser::ParseVideoInfo: get [%s]\n", vurl.c_str()); + std::string answer; + if (!getUrl(vurl, answer)) + continue; + ret = decodeVideoInfo(answer, vinfo); + if (ret) + break; + } + return ret; +} + +bool cYTFeedParser::DownloadThumbnails() +{ + bool ret = false; + if (mkdir(thumbnail_dir.c_str(), 0755)) { + perror(thumbnail_dir.c_str()); + //return ret; + } + for (unsigned i = 0; i < videos.size(); i++) { + if (!videos[i].thumbnail.empty()) { + std::string fname = thumbnail_dir; + fname += "/"; + fname += videos[i].id; + fname += ".jpg"; + bool found = !access(fname.c_str(), F_OK); + if (!found) + found = DownloadUrl(videos[i].thumbnail, fname); + if (found) + videos[i].tfile = fname; + ret |= found; + } + } + return ret; +} + +bool cYTFeedParser::GetVideoUrls() +{ + bool ret = false; + for (unsigned i = 0; i < videos.size(); i++) { + ret |= ParseVideoInfo(videos[i]); + } + return ret; +} + +void cYTFeedParser::Cleanup(bool delete_thumbnails) +{ + printf("cYTFeedParser::Cleanup: %d videos\n", videos.size()); + if (delete_thumbnails) { + for (unsigned i = 0; i < videos.size(); i++) { + unlink(videos[i].tfile.c_str()); + } + } + unlink(curfeedfile.c_str()); + videos.clear(); + parsed = false; + feedmode = -1; +} + +void cYTFeedParser::Dump() +{ + printf("feed: %d videos\n", videos.size()); + for (unsigned i = 0; i < videos.size(); i++) + videos[i].Dump(); +} diff --git a/src/system/ytparser.h b/src/system/ytparser.h new file mode 100644 index 000000000..357ac1409 --- /dev/null +++ b/src/system/ytparser.h @@ -0,0 +1,142 @@ +/* + Copyright (C) 2013 CoolStream International Ltd + + License: GPLv2 + + 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; + + 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __YT_PARSER__ +#define __YT_PARSER__ + +#include +#include + +#include +#include +#include +#include + +class cYTVideoUrl +{ + public: + std::string quality; + std::string type; + std::string sig; + std::string url; + + std::string GetUrl(); +}; + +typedef std::map yt_urlmap_t; +typedef std::pair yt_urlmap_pair_t; +typedef yt_urlmap_t::iterator yt_urlmap_iterator_t; + +class cYTVideoInfo +{ + public: + std::string id; + std::string title; + std::string author; + std::string description; + std::string category; + std::string thumbnail; + std::string tfile; + std::string published; + int duration; + yt_urlmap_t formats; + + void Dump(); + std::string GetUrl(int fmt = 0); + +}; + +typedef std::vector yt_video_list_t; + +class cYTFeedParser +{ + private: + std::string error; + std::string thumbnail_dir; + std::string curfeed; + std::string curfeedfile; + std::string tquality; // thumbnail size + std::string region; // more results + std::string next; // next results + std::string prev; // prev results + std::string start; // start index + std::string total; // total results + + int feedmode; + int max_results; + bool parsed; + yt_video_list_t videos; + + std::string getXmlName(xmlNodePtr node); + std::string getXmlAttr(xmlNodePtr node, const char * attr); + std::string getXmlData(xmlNodePtr node); + + static size_t CurlWriteToString(void *ptr, size_t size, size_t nmemb, void *data); + static void decodeUrl(std::string &url); + static void splitString(std::string &str, std::string delim, std::vector &strlist, int start = 0); + static void splitString(std::string &str, std::string delim, std::map &strmap, int start = 0); + static bool saveToFile(const char * name, std::string str); + bool getUrl(std::string &url, std::string &answer); + bool DownloadUrl(std::string &url, std::string &file); + bool parseFeedXml(std::string &answer); + bool decodeVideoInfo(std::string &answer, cYTVideoInfo &vinfo); + bool supportedFormat(int fmt); + bool ParseFeed(std::string &url); + public: + enum yt_feed_mode_t + { + TOP_RATED, + TOP_FAVORITES, + MOST_SHARED, + MOST_POPULAR, + MOST_RESENT, + MOST_DISCUSSED, + MOST_RESPONDED, + RECENTLY_FEATURED, + ON_THE_WEB, + FEED_LAST, + NEXT, + PREV, + RELATED, + SEARCH, + MODE_LAST + }; + cYTFeedParser(); + ~cYTFeedParser(); + + bool ParseFeed(yt_feed_mode_t mode = MOST_POPULAR, std::string search = "", std::string vid = ""); + bool ParseVideoInfo(cYTVideoInfo &vinfo); + bool GetVideoUrls(); + bool DownloadThumbnails(); + void Dump(); + void Cleanup(bool delete_thumbnails = true); + + yt_video_list_t &GetVideoList() { return videos; } + bool Parsed() { return parsed; } + int GetFeedMode() { return feedmode; } + bool HaveNext(void) { return !next.empty(); } + bool HavePrev(void) { return !prev.empty(); } + std::string GetTotal(void) { return total; } + std::string GetError(void) { return error; } + + void SetRegion(std::string reg) { region = reg; } + void SetMaxResults(int count) { max_results = count; } +}; + +#endif diff --git a/src/timerd/timermanager.cpp b/src/timerd/timermanager.cpp index 3b11dfdec..a9bfa47e2 100644 --- a/src/timerd/timermanager.cpp +++ b/src/timerd/timermanager.cpp @@ -625,8 +625,8 @@ void CTimerManager::loadRecordingSafety() { /* set defaults if no configuration file exists */ dprintf("%s not found\n", CONFIGFILE); - m_extraTimeStart = 0; - m_extraTimeEnd = 0; + m_extraTimeStart = 300; + m_extraTimeEnd = 300; config.saveConfig(CONFIGFILE); } else diff --git a/src/zapit/src/femanager.cpp b/src/zapit/src/femanager.cpp index 345408dfd..cfa2d7f65 100644 --- a/src/zapit/src/femanager.cpp +++ b/src/zapit/src/femanager.cpp @@ -206,6 +206,9 @@ bool CFEManager::loadSettings() int def_mode0 = CFrontend::FE_MODE_INDEPENDENT; int def_modeX = CFrontend::FE_MODE_UNUSED; + if (cableOnly()) + def_modeX = CFrontend::FE_MODE_INDEPENDENT; + int newmode = (fe_mode_t) configfile.getInt32("mode", -1); if (newmode >= 0) { INFO("old mode param: %d\n", newmode);