├── .settings ├── org.eclipse.wst.jsdt.ui.superType.name └── org.eclipse.wst.jsdt.ui.superType.container ├── widget.info ├── images ├── Logo.png ├── album.png ├── bg1.jpg ├── done.png ├── arrowUp.png ├── artist.png ├── loading.png ├── missing.png ├── server.png ├── splash.jpg ├── unaired.png ├── arrowDown.png ├── cc-50x40.png ├── collection.png ├── film-54x60.png ├── help_blue.png ├── help_green.png ├── help_red.png ├── SeasonBlank.png ├── ShowNoImage.png ├── arrowUpDown.png ├── film-93x105.png ├── fresh-40x40.png ├── help_yellow.png ├── return-34x36.png ├── rotten-40x40.png ├── usernoimage.png ├── Live-TV-108x98.png ├── MediaInfo │ ├── blank.png │ ├── res_480.png │ ├── res_540.png │ ├── res_576.png │ ├── res_720.png │ ├── res_SD.png │ ├── aspect_133.png │ ├── aspect_166.png │ ├── aspect_178.png │ ├── aspect_185.png │ ├── aspect_235.png │ ├── aspect_240.png │ ├── channels_1.png │ ├── channels_2.png │ ├── channels_3.png │ ├── channels_4.png │ ├── channels_5.png │ ├── channels_6.png │ ├── channels_7.png │ ├── channels_8.png │ ├── codec_ac3.png │ ├── codec_divx.png │ ├── codec_dts.png │ ├── codec_flac.png │ ├── codec_h264.png │ ├── codec_h265.png │ ├── codec_mp3.png │ ├── codec_pcm.png │ ├── codec_vc1.png │ ├── codec_wma.png │ ├── codec_xvid.png │ ├── fullscreen.png │ ├── media_3d.png │ ├── media_SBS.png │ ├── media_TAB.png │ ├── media_dvd.png │ ├── media_m2ts.png │ ├── media_mp4.png │ ├── res_1080.png │ ├── widescreen.png │ ├── codec_aac-2.png │ ├── codec_dtses.png │ ├── codec_dtshra.png │ ├── codec_dtsma.png │ ├── codec_mpeg2.png │ ├── codec_vorbis.png │ ├── media_avi-2.png │ ├── media_bluray.png │ ├── media_mkv-2.png │ ├── codec_ddtruehd.png │ └── codec_mpeg4visual.png ├── ShowPosterBlank.png ├── favorite-36x33.png ├── favorite-45x41.png ├── menu │ ├── Film-46x37.png │ ├── Home-46x37.png │ ├── Play-46x37.png │ ├── Stop-46x37.png │ ├── TV-46x37.png │ ├── Folder-46x37.png │ ├── Guide-46x37.png │ ├── Logout-46x37.png │ ├── Movies-46x37.png │ ├── Music-46x37.png │ ├── Person-46x37.png │ ├── Photos-46x37.png │ ├── Resume-46x37.png │ ├── Search-46x37.png │ ├── photos-54x54.png │ ├── AddToList-56x37.png │ ├── AddToList-60x37.png │ ├── Channels-46x37.png │ ├── Live_TV-46x37.png │ ├── Playlists-46x37.png │ ├── Settings-46x37.png │ ├── Collections-46x37.png │ ├── Favourites-46x37.png │ ├── Home_Movies-46x37.png │ ├── Recordings-46x37.png │ └── Media_Folders-46x37.png ├── qualityflyout.png ├── sliderPosition.png ├── star_full-46x40.png ├── star_half-46x40.png ├── loginusernoimage.png ├── star_empty-46x40.png ├── trailerBackground.png ├── EmptyFolder-122x98.png ├── ShowPosterBlankSmaller.png └── musicplayer │ ├── play-29x37.png │ ├── stop-37x37.png │ ├── pause-32x37.png │ ├── skip-next-36x37.png │ ├── fast-forward-53x37.png │ ├── fast-rewind-54x37.png │ ├── pause-active-32x37.png │ ├── play-active-29x37.png │ ├── stop-active-37x37.png │ ├── pause-selected-32x37.png │ ├── play-selected-29x37.png │ ├── skip-previous-36x37.png │ ├── stop-selected-37x37.png │ ├── skip-next-active-36x37.png │ ├── skip-next-selected-36x37.png │ ├── fast-forward-selected-53x37.png │ ├── fast-rewind-selected-54x37.png │ ├── skip-previous-active-36x37.png │ └── skip-previous-selected-36x37.png ├── icon ├── MB3_85_70.png ├── MB3_95_78.png ├── MB3_106_87.png └── MB3_115_95.png ├── README.md ├── .project ├── app └── javascript │ ├── Support │ ├── polyfill.js │ ├── ServerVersion.js │ ├── GuiNotifications.js │ ├── FileLog.js │ ├── srt-parser.js │ ├── GuiHelper.js │ └── File.js │ ├── Gui │ ├── GuiPage_Contributors.js │ ├── GuiImagePlayer │ │ ├── GuiImagePlayer_Screensaver.js │ │ └── GuiImagePlayer.js │ ├── GuiPage_Servers.js │ ├── GuiPage_NewServer.js │ ├── GuiUsers_Manual.js │ ├── GuiPage_SettingsLog.js │ ├── GuiPlayer │ │ └── GuiPlayer_Transcoding.js │ ├── GuiPage_CastMember.js │ ├── GuiPage_AddToPlaylist.js │ ├── GuiMainMenu.js │ ├── GuiDisplayOneItem.js │ ├── GuiPage_Music.js │ └── GuiPage_Search.js │ └── Main.js ├── LICENSE └── config.xml /.settings/org.eclipse.wst.jsdt.ui.superType.name: -------------------------------------------------------------------------------- 1 | Global -------------------------------------------------------------------------------- /widget.info: -------------------------------------------------------------------------------- 1 | Use Alpha Blending? = Yes 2 | Screen Resolution = 1920x1080 -------------------------------------------------------------------------------- /.settings/org.eclipse.wst.jsdt.ui.superType.container: -------------------------------------------------------------------------------- 1 | org.eclipse.wst.jsdt.launching.JRE_CONTAINER -------------------------------------------------------------------------------- /images/Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/Logo.png -------------------------------------------------------------------------------- /images/album.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/album.png -------------------------------------------------------------------------------- /images/bg1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/bg1.jpg -------------------------------------------------------------------------------- /images/done.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/done.png -------------------------------------------------------------------------------- /icon/MB3_85_70.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/icon/MB3_85_70.png -------------------------------------------------------------------------------- /icon/MB3_95_78.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/icon/MB3_95_78.png -------------------------------------------------------------------------------- /images/arrowUp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/arrowUp.png -------------------------------------------------------------------------------- /images/artist.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/artist.png -------------------------------------------------------------------------------- /images/loading.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/loading.png -------------------------------------------------------------------------------- /images/missing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/missing.png -------------------------------------------------------------------------------- /images/server.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/server.png -------------------------------------------------------------------------------- /images/splash.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/splash.jpg -------------------------------------------------------------------------------- /images/unaired.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/unaired.png -------------------------------------------------------------------------------- /icon/MB3_106_87.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/icon/MB3_106_87.png -------------------------------------------------------------------------------- /icon/MB3_115_95.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/icon/MB3_115_95.png -------------------------------------------------------------------------------- /images/arrowDown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/arrowDown.png -------------------------------------------------------------------------------- /images/cc-50x40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/cc-50x40.png -------------------------------------------------------------------------------- /images/collection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/collection.png -------------------------------------------------------------------------------- /images/film-54x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/film-54x60.png -------------------------------------------------------------------------------- /images/help_blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/help_blue.png -------------------------------------------------------------------------------- /images/help_green.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/help_green.png -------------------------------------------------------------------------------- /images/help_red.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/help_red.png -------------------------------------------------------------------------------- /images/SeasonBlank.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/SeasonBlank.png -------------------------------------------------------------------------------- /images/ShowNoImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/ShowNoImage.png -------------------------------------------------------------------------------- /images/arrowUpDown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/arrowUpDown.png -------------------------------------------------------------------------------- /images/film-93x105.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/film-93x105.png -------------------------------------------------------------------------------- /images/fresh-40x40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/fresh-40x40.png -------------------------------------------------------------------------------- /images/help_yellow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/help_yellow.png -------------------------------------------------------------------------------- /images/return-34x36.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/return-34x36.png -------------------------------------------------------------------------------- /images/rotten-40x40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/rotten-40x40.png -------------------------------------------------------------------------------- /images/usernoimage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/usernoimage.png -------------------------------------------------------------------------------- /images/Live-TV-108x98.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/Live-TV-108x98.png -------------------------------------------------------------------------------- /images/MediaInfo/blank.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/MediaInfo/blank.png -------------------------------------------------------------------------------- /images/ShowPosterBlank.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/ShowPosterBlank.png -------------------------------------------------------------------------------- /images/favorite-36x33.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/favorite-36x33.png -------------------------------------------------------------------------------- /images/favorite-45x41.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/favorite-45x41.png -------------------------------------------------------------------------------- /images/menu/Film-46x37.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/menu/Film-46x37.png -------------------------------------------------------------------------------- /images/menu/Home-46x37.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/menu/Home-46x37.png -------------------------------------------------------------------------------- /images/menu/Play-46x37.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/menu/Play-46x37.png -------------------------------------------------------------------------------- /images/menu/Stop-46x37.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/menu/Stop-46x37.png -------------------------------------------------------------------------------- /images/menu/TV-46x37.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/menu/TV-46x37.png -------------------------------------------------------------------------------- /images/qualityflyout.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/qualityflyout.png -------------------------------------------------------------------------------- /images/sliderPosition.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/sliderPosition.png -------------------------------------------------------------------------------- /images/star_full-46x40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/star_full-46x40.png -------------------------------------------------------------------------------- /images/star_half-46x40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/star_half-46x40.png -------------------------------------------------------------------------------- /images/MediaInfo/res_480.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/MediaInfo/res_480.png -------------------------------------------------------------------------------- /images/MediaInfo/res_540.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/MediaInfo/res_540.png -------------------------------------------------------------------------------- /images/MediaInfo/res_576.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/MediaInfo/res_576.png -------------------------------------------------------------------------------- /images/MediaInfo/res_720.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/MediaInfo/res_720.png -------------------------------------------------------------------------------- /images/MediaInfo/res_SD.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/MediaInfo/res_SD.png -------------------------------------------------------------------------------- /images/loginusernoimage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/loginusernoimage.png -------------------------------------------------------------------------------- /images/menu/Folder-46x37.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/menu/Folder-46x37.png -------------------------------------------------------------------------------- /images/menu/Guide-46x37.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/menu/Guide-46x37.png -------------------------------------------------------------------------------- /images/menu/Logout-46x37.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/menu/Logout-46x37.png -------------------------------------------------------------------------------- /images/menu/Movies-46x37.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/menu/Movies-46x37.png -------------------------------------------------------------------------------- /images/menu/Music-46x37.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/menu/Music-46x37.png -------------------------------------------------------------------------------- /images/menu/Person-46x37.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/menu/Person-46x37.png -------------------------------------------------------------------------------- /images/menu/Photos-46x37.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/menu/Photos-46x37.png -------------------------------------------------------------------------------- /images/menu/Resume-46x37.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/menu/Resume-46x37.png -------------------------------------------------------------------------------- /images/menu/Search-46x37.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/menu/Search-46x37.png -------------------------------------------------------------------------------- /images/menu/photos-54x54.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/menu/photos-54x54.png -------------------------------------------------------------------------------- /images/star_empty-46x40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/star_empty-46x40.png -------------------------------------------------------------------------------- /images/trailerBackground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/trailerBackground.png -------------------------------------------------------------------------------- /images/EmptyFolder-122x98.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/EmptyFolder-122x98.png -------------------------------------------------------------------------------- /images/MediaInfo/aspect_133.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/MediaInfo/aspect_133.png -------------------------------------------------------------------------------- /images/MediaInfo/aspect_166.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/MediaInfo/aspect_166.png -------------------------------------------------------------------------------- /images/MediaInfo/aspect_178.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/MediaInfo/aspect_178.png -------------------------------------------------------------------------------- /images/MediaInfo/aspect_185.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/MediaInfo/aspect_185.png -------------------------------------------------------------------------------- /images/MediaInfo/aspect_235.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/MediaInfo/aspect_235.png -------------------------------------------------------------------------------- /images/MediaInfo/aspect_240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/MediaInfo/aspect_240.png -------------------------------------------------------------------------------- /images/MediaInfo/channels_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/MediaInfo/channels_1.png -------------------------------------------------------------------------------- /images/MediaInfo/channels_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/MediaInfo/channels_2.png -------------------------------------------------------------------------------- /images/MediaInfo/channels_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/MediaInfo/channels_3.png -------------------------------------------------------------------------------- /images/MediaInfo/channels_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/MediaInfo/channels_4.png -------------------------------------------------------------------------------- /images/MediaInfo/channels_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/MediaInfo/channels_5.png -------------------------------------------------------------------------------- /images/MediaInfo/channels_6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/MediaInfo/channels_6.png -------------------------------------------------------------------------------- /images/MediaInfo/channels_7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/MediaInfo/channels_7.png -------------------------------------------------------------------------------- /images/MediaInfo/channels_8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/MediaInfo/channels_8.png -------------------------------------------------------------------------------- /images/MediaInfo/codec_ac3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/MediaInfo/codec_ac3.png -------------------------------------------------------------------------------- /images/MediaInfo/codec_divx.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/MediaInfo/codec_divx.png -------------------------------------------------------------------------------- /images/MediaInfo/codec_dts.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/MediaInfo/codec_dts.png -------------------------------------------------------------------------------- /images/MediaInfo/codec_flac.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/MediaInfo/codec_flac.png -------------------------------------------------------------------------------- /images/MediaInfo/codec_h264.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/MediaInfo/codec_h264.png -------------------------------------------------------------------------------- /images/MediaInfo/codec_h265.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/MediaInfo/codec_h265.png -------------------------------------------------------------------------------- /images/MediaInfo/codec_mp3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/MediaInfo/codec_mp3.png -------------------------------------------------------------------------------- /images/MediaInfo/codec_pcm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/MediaInfo/codec_pcm.png -------------------------------------------------------------------------------- /images/MediaInfo/codec_vc1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/MediaInfo/codec_vc1.png -------------------------------------------------------------------------------- /images/MediaInfo/codec_wma.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/MediaInfo/codec_wma.png -------------------------------------------------------------------------------- /images/MediaInfo/codec_xvid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/MediaInfo/codec_xvid.png -------------------------------------------------------------------------------- /images/MediaInfo/fullscreen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/MediaInfo/fullscreen.png -------------------------------------------------------------------------------- /images/MediaInfo/media_3d.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/MediaInfo/media_3d.png -------------------------------------------------------------------------------- /images/MediaInfo/media_SBS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/MediaInfo/media_SBS.png -------------------------------------------------------------------------------- /images/MediaInfo/media_TAB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/MediaInfo/media_TAB.png -------------------------------------------------------------------------------- /images/MediaInfo/media_dvd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/MediaInfo/media_dvd.png -------------------------------------------------------------------------------- /images/MediaInfo/media_m2ts.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/MediaInfo/media_m2ts.png -------------------------------------------------------------------------------- /images/MediaInfo/media_mp4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/MediaInfo/media_mp4.png -------------------------------------------------------------------------------- /images/MediaInfo/res_1080.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/MediaInfo/res_1080.png -------------------------------------------------------------------------------- /images/MediaInfo/widescreen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/MediaInfo/widescreen.png -------------------------------------------------------------------------------- /images/menu/AddToList-56x37.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/menu/AddToList-56x37.png -------------------------------------------------------------------------------- /images/menu/AddToList-60x37.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/menu/AddToList-60x37.png -------------------------------------------------------------------------------- /images/menu/Channels-46x37.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/menu/Channels-46x37.png -------------------------------------------------------------------------------- /images/menu/Live_TV-46x37.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/menu/Live_TV-46x37.png -------------------------------------------------------------------------------- /images/menu/Playlists-46x37.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/menu/Playlists-46x37.png -------------------------------------------------------------------------------- /images/menu/Settings-46x37.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/menu/Settings-46x37.png -------------------------------------------------------------------------------- /images/MediaInfo/codec_aac-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/MediaInfo/codec_aac-2.png -------------------------------------------------------------------------------- /images/MediaInfo/codec_dtses.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/MediaInfo/codec_dtses.png -------------------------------------------------------------------------------- /images/MediaInfo/codec_dtshra.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/MediaInfo/codec_dtshra.png -------------------------------------------------------------------------------- /images/MediaInfo/codec_dtsma.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/MediaInfo/codec_dtsma.png -------------------------------------------------------------------------------- /images/MediaInfo/codec_mpeg2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/MediaInfo/codec_mpeg2.png -------------------------------------------------------------------------------- /images/MediaInfo/codec_vorbis.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/MediaInfo/codec_vorbis.png -------------------------------------------------------------------------------- /images/MediaInfo/media_avi-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/MediaInfo/media_avi-2.png -------------------------------------------------------------------------------- /images/MediaInfo/media_bluray.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/MediaInfo/media_bluray.png -------------------------------------------------------------------------------- /images/MediaInfo/media_mkv-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/MediaInfo/media_mkv-2.png -------------------------------------------------------------------------------- /images/ShowPosterBlankSmaller.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/ShowPosterBlankSmaller.png -------------------------------------------------------------------------------- /images/menu/Collections-46x37.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/menu/Collections-46x37.png -------------------------------------------------------------------------------- /images/menu/Favourites-46x37.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/menu/Favourites-46x37.png -------------------------------------------------------------------------------- /images/menu/Home_Movies-46x37.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/menu/Home_Movies-46x37.png -------------------------------------------------------------------------------- /images/menu/Recordings-46x37.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/menu/Recordings-46x37.png -------------------------------------------------------------------------------- /images/musicplayer/play-29x37.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/musicplayer/play-29x37.png -------------------------------------------------------------------------------- /images/musicplayer/stop-37x37.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/musicplayer/stop-37x37.png -------------------------------------------------------------------------------- /images/MediaInfo/codec_ddtruehd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/MediaInfo/codec_ddtruehd.png -------------------------------------------------------------------------------- /images/menu/Media_Folders-46x37.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/menu/Media_Folders-46x37.png -------------------------------------------------------------------------------- /images/musicplayer/pause-32x37.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/musicplayer/pause-32x37.png -------------------------------------------------------------------------------- /images/MediaInfo/codec_mpeg4visual.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/MediaInfo/codec_mpeg4visual.png -------------------------------------------------------------------------------- /images/musicplayer/skip-next-36x37.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/musicplayer/skip-next-36x37.png -------------------------------------------------------------------------------- /images/musicplayer/fast-forward-53x37.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/musicplayer/fast-forward-53x37.png -------------------------------------------------------------------------------- /images/musicplayer/fast-rewind-54x37.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/musicplayer/fast-rewind-54x37.png -------------------------------------------------------------------------------- /images/musicplayer/pause-active-32x37.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/musicplayer/pause-active-32x37.png -------------------------------------------------------------------------------- /images/musicplayer/play-active-29x37.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/musicplayer/play-active-29x37.png -------------------------------------------------------------------------------- /images/musicplayer/stop-active-37x37.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/musicplayer/stop-active-37x37.png -------------------------------------------------------------------------------- /images/musicplayer/pause-selected-32x37.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/musicplayer/pause-selected-32x37.png -------------------------------------------------------------------------------- /images/musicplayer/play-selected-29x37.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/musicplayer/play-selected-29x37.png -------------------------------------------------------------------------------- /images/musicplayer/skip-previous-36x37.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/musicplayer/skip-previous-36x37.png -------------------------------------------------------------------------------- /images/musicplayer/stop-selected-37x37.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/musicplayer/stop-selected-37x37.png -------------------------------------------------------------------------------- /images/musicplayer/skip-next-active-36x37.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/musicplayer/skip-next-active-36x37.png -------------------------------------------------------------------------------- /images/musicplayer/skip-next-selected-36x37.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/musicplayer/skip-next-selected-36x37.png -------------------------------------------------------------------------------- /images/musicplayer/fast-forward-selected-53x37.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/musicplayer/fast-forward-selected-53x37.png -------------------------------------------------------------------------------- /images/musicplayer/fast-rewind-selected-54x37.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/musicplayer/fast-rewind-selected-54x37.png -------------------------------------------------------------------------------- /images/musicplayer/skip-previous-active-36x37.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/musicplayer/skip-previous-active-36x37.png -------------------------------------------------------------------------------- /images/musicplayer/skip-previous-selected-36x37.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jellyfin-archive/jellyfin-samsungtv/HEAD/images/musicplayer/skip-previous-selected-36x37.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SamsungSmartTV 2 | 3 | Warning: This app is a legacy program meant for older Samsung Smart TVs running Orsay (pre-2015), which has since been replaced by Tizen. It may be possible to use this app by side-loading, but it is considered unsupported (we are unable to help you with it). 4 | 5 | You may also wish to try a web browser with Jellyfin, wherever possible. 6 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | Emby 4 | 5 | 6 | 7 | 8 | 9 | 10 | org.eclipse.wst.jsdt.core.javascriptValidator 11 | 12 | 13 | 14 | 15 | 16 | org.eclipse.wst.jsdt.core.jsNature 17 | 18 | 19 | -------------------------------------------------------------------------------- /app/javascript/Support/polyfill.js: -------------------------------------------------------------------------------- 1 | if (!Array.prototype.findIndex) { 2 | Array.prototype.findIndex = function(predicate, thisArg) { 3 | if (typeof predicate !== 'function') { 4 | throw new TypeError('predicate must be a function'); 5 | } 6 | 7 | var lastIndex = -1; 8 | if (!Array.prototype.some.call(this, function(val, index, arr) { 9 | return predicate.call(thisArg, val, lastIndex = index, arr); 10 | })) { 11 | return -1; 12 | } 13 | return lastIndex; 14 | }; 15 | } 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Media Browser 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | icon/MB3_106_87.png 7 | icon/MB3_115_95.png 8 | icon/MB3_85_70.png 9 | icon/MB3_95_78.png 10 | Videos 11 | n 12 | 2.2.5b 13 | 14 | y 15 | user 16 | y 17 | n 18 | n 19 | n 20 | y 21 | Emby 22 | Emby for Samsung Smart TV 23 | 1920 24 | 1080 25 | 26 | ChessDragon136 27 | emby.media/community 28 | emby.media 29 | 30 | 31 | -------------------------------------------------------------------------------- /app/javascript/Support/ServerVersion.js: -------------------------------------------------------------------------------- 1 | var ServerVersion = { 2 | ServerInfo : null 3 | } 4 | 5 | ServerVersion.start = function() { 6 | document.getElementById("pageContent").innerHTML = "
\ 7 |

The Samsung app requires a later version of the Server - Please update it and restart the app

"; 8 | 9 | document.getElementById("ServerVersion").focus(); 10 | } 11 | 12 | ServerVersion.checkServerVersion = function() { 13 | var url = Server.getCustomURL("/System/Info/Public?format=json"); 14 | this.ServerInfo = Server.getContent(url); 15 | if (this.ServerInfo == null) { return; } 16 | 17 | var requiredServerVersion = Main.getRequiredServerVersion(); 18 | var currentServerVersion = this.ServerInfo.Version; 19 | 20 | if (currentServerVersion >= requiredServerVersion) { 21 | return true; 22 | } else { 23 | return false; 24 | } 25 | } 26 | 27 | ServerVersion.keyDown = function() { 28 | var keyCode = event.keyCode; 29 | alert("Key pressed: " + keyCode); 30 | 31 | if (document.getElementById("Notifications").style.visibility == "") { 32 | document.getElementById("Notifications").style.visibility = "hidden"; 33 | document.getElementById("NotificationText").innerHTML = ""; 34 | widgetAPI.blockNavigation(event); 35 | //Change keycode so it does nothing! 36 | keyCode = "VOID"; 37 | } 38 | 39 | switch(keyCode) { 40 | default: 41 | widgetAPI.sendExitEvent(); 42 | break; 43 | } 44 | } -------------------------------------------------------------------------------- /app/javascript/Support/GuiNotifications.js: -------------------------------------------------------------------------------- 1 | var GuiNotifications = { 2 | timeout : null 3 | } 4 | 5 | GuiNotifications.setNotification = function (Message, Title,alterHeight) { 6 | //Clear any existing message 7 | clearInterval(this.timeout); 8 | document.getElementById("Notifications").style.visibility = "hidden"; 9 | document.getElementById("NotificationText").innerHTML = ""; 10 | document.getElementById("NotificationText").className="notification highlight"+Main.highlightColour+"Boarder"; 11 | 12 | //Code to move based on screen (fix for GuiPage_IP) 13 | if (alterHeight == true) { 14 | document.getElementById("Notifications").style.top = "620px"; 15 | document.getElementById("Notifications").style.left = "430px"; 16 | } else { 17 | document.getElementById("Notifications").style.top = "390px"; 18 | document.getElementById("Notifications").style.left = "710px"; 19 | } 20 | 21 | /* if (Message.length > 30) { 22 | var brpoint = 30; 23 | newmessage = ""; 24 | while (brpoint < Message.length) { 25 | temphold = Message.substring((brpoint-30),brpoint+4); 26 | if (temphold.indexOf("
") == -1) { 27 | newmessage += Message.substring((brpoint-30),brpoint) + "
"; 28 | } else { 29 | newmessage += Message.substring((brpoint-30),brpoint); 30 | } 31 | alert(newmessage); 32 | brpoint = brpoint + 30; 33 | } 34 | newmessage += Message.substring((brpoint-30), Message.length); 35 | Message = newmessage; 36 | }*/ 37 | 38 | document.getElementById("NotificationText").innerHTML = "

" + Title + "


"+Message+"

"; 39 | document.getElementById("Notifications").style.visibility =""; 40 | 41 | if (Title != "Test Mode") { 42 | this.timeout = setTimeout(function(){ 43 | document.getElementById("Notifications").style.visibility = "hidden"; 44 | document.getElementById("NotificationText").innerHTML = ""; 45 | }, 5000); 46 | } 47 | } -------------------------------------------------------------------------------- /app/javascript/Support/FileLog.js: -------------------------------------------------------------------------------- 1 | var FileLog = { 2 | }; 3 | 4 | FileLog.deleteFile = function() { 5 | var fileSystemObj = new FileSystem(); 6 | fileSystemObj.deleteCommonFile(curWidget.id + '/MB3_Log.txt'); 7 | } 8 | 9 | FileLog.loadFile = function(returnContents) { 10 | var fileSystemObj = new FileSystem(); 11 | 12 | var bValid = fileSystemObj.isValidCommonPath(curWidget.id); 13 | if (!bValid) { 14 | fileSystemObj.createCommonDir(curWidget.id); 15 | var fileObj = fileSystemObj.openCommonFile(curWidget.id + '/MB3_Log.txt', 'a+'); 16 | fileSystemObj.closeCommonFile(fileObj); 17 | } 18 | 19 | var openRead = fileSystemObj.openCommonFile(curWidget.id + '/MB3_Log.txt', 'r'); 20 | if (!openRead) { 21 | fileSystemObj.createCommonDir(curWidget.id); 22 | var fileObj = fileSystemObj.openCommonFile(curWidget.id + '/MB3_Log.txt', 'a+'); 23 | fileSystemObj.closeCommonFile(fileObj); 24 | return null; 25 | } else { 26 | var strLine = ""; 27 | var arrayFile = new Array(); 28 | while ((strLine=openRead.readLine())) { 29 | arrayFile.push(strLine); 30 | } 31 | fileSystemObj.closeCommonFile(openRead); 32 | if (returnContents) { 33 | return arrayFile; 34 | } else { 35 | return null; 36 | } 37 | } 38 | }; 39 | 40 | FileLog.write = function (toWrite,noDate) { 41 | 42 | var writeDate = (noDate == undefined) ? true : false; 43 | toWrite = (writeDate == true) ? FileLog.getTimeStamp() + " " + toWrite : toWrite; 44 | alert(toWrite); 45 | var fileSystemObj = new FileSystem(); 46 | var openWrite = fileSystemObj.openCommonFile(curWidget.id + '/MB3_Log.txt', 'a+'); 47 | if (openWrite) { 48 | openWrite.writeLine(toWrite); 49 | fileSystemObj.closeCommonFile(openWrite); 50 | } 51 | } 52 | 53 | FileLog.empty = function () { 54 | var fileSystemObj = new FileSystem(); 55 | var openWrite = fileSystemObj.openCommonFile(curWidget.id + '/MB3_Log.txt', 'w'); 56 | if (openWrite) { 57 | fileSystemObj.closeCommonFile(openWrite); 58 | } 59 | } 60 | 61 | FileLog.getTimeStamp = function () { 62 | var date = new Date(); 63 | var day = (date.getDate() + 1 < 10) ? "0" + (date.getDate() + 1) : date.getDate() + 1; 64 | var month = (date.getMonth() + 1 < 10) ? "0" + (date.getMonth() + 1) : date.getMonth() + 1; 65 | var year = date.getFullYear(); 66 | 67 | var h=date.getHours(); 68 | var offset = File.getTVProperty("ClockOffset"); 69 | h = h+offset; 70 | if (h<0) {h = h + 24;}; 71 | if (h>23){h = h - 24;}; 72 | if (h<10) {h = "0" + h;}; 73 | var m=date.getMinutes(); 74 | if (m<10) {m = "0" + m;}; 75 | return day + "/" + month + "/" + year + " " + h+':'+m; 76 | } -------------------------------------------------------------------------------- /app/javascript/Support/srt-parser.js: -------------------------------------------------------------------------------- 1 | var parser = (function() { 2 | var pItems = {}; 3 | 4 | /** 5 | * Converts SubRip subtitles into array of objects 6 | * [{ 7 | * id: `Number of subtitle` 8 | * startTime: `Start time of subtitle` 9 | * endTime: `End time of subtitle 10 | * text: `Text of subtitle` 11 | * }] 12 | * 13 | * @param {String} data SubRip suntitles string 14 | * @param {Boolean} ms Optional: use milliseconds for startTime and endTime 15 | * @return {Array} 16 | */ 17 | pItems.fromSrt = function(data, ms) { 18 | var useMs = ms ? true : false; 19 | 20 | var regex = /(\d+)(\r?\n|\r)(\d{2}:\d{2}:\d{2},\d+) --> (\d{2}:\d{2}:\d{2},\d+)/g; 21 | data = data.split(regex); 22 | data.shift(); 23 | 24 | var items = []; 25 | for (var i = 0; i < data.length; i += 5) { 26 | items.push({ 27 | id: data[i], 28 | startTime: useMs ? timeMs(data[i + 2]) : data[i + 2], 29 | endTime: useMs ? timeMs(data[i + 3]) : data[i + 3], 30 | text: data[i + 4].replace(/\r?\n$|\r$/,'') 31 | }); 32 | } 33 | 34 | return items; 35 | }; 36 | 37 | /** 38 | * Converts Array of objects created by this module to SubRip subtitles 39 | * @param {Array} data 40 | * @return {String} SubRip subtitles string 41 | */ 42 | pItems.toSrt = function(data) { 43 | if (!data instanceof Array) return ''; 44 | var res = ''; 45 | 46 | for (var i = 0; i < data.length; i++) { 47 | var s = data[i]; 48 | 49 | if (!isNaN(s.startTime) && !isNaN(s.endTime)) { 50 | s.startTime = msTime(parseInt(s.startTime, 10)); 51 | s.endTime = msTime(parseInt(s.endTime, 10)); 52 | } 53 | 54 | res += s.id + '\r\n'; 55 | res += s.startTime + ' --> ' + s.endTime + '\r\n'; 56 | res += s.text.replace('\n', '\r\n') + '\r\n\r\n'; 57 | } 58 | 59 | return res; 60 | }; 61 | 62 | var timeMs = function(val) { 63 | var regex = /(\d+):(\d{2}):(\d{2}),(\d{3})/; 64 | var parts = regex.exec(val); 65 | 66 | if (parts === null) { 67 | return 0; 68 | } 69 | 70 | for (var i = 1; i < 5; i++) { 71 | parts[i] = parseInt(parts[i], 10); 72 | if (isNaN(parts[i])) parts[i] = 0; 73 | } 74 | 75 | // hours + minutes + seconds + ms 76 | return parts[1] * 3600000 + parts[2] * 60000 + parts[3] * 1000 + parts[4]; 77 | }; 78 | 79 | var msTime = function(val) { 80 | var measures = [ 3600000, 60000, 1000 ]; 81 | var time = []; 82 | 83 | for (var i in measures) { 84 | var res = (val / measures[i] >> 0).toString(); 85 | 86 | if (res.length < 2) res = '0' + res; 87 | val %= measures[i]; 88 | time.push(res); 89 | } 90 | 91 | var ms = val.toString(); 92 | if (ms.length < 3) { 93 | for (i = 0; i <= 3 - ms.length; i++) ms = '0' + ms; 94 | } 95 | 96 | return time.join(':') + ',' + ms; 97 | }; 98 | 99 | return pItems; 100 | })(); 101 | 102 | // ignore exports for browser 103 | if (typeof exports === 'object') { 104 | module.exports = parser; 105 | } -------------------------------------------------------------------------------- /app/javascript/Gui/GuiPage_Contributors.js: -------------------------------------------------------------------------------- 1 | var GuiPage_Contributors = { 2 | MainDevs : ["ChessDragon136","cmcg"], 3 | ContribDevs : ["Cragjagged","DrWatson","im85288","arcticwaters","SamES"], 4 | DonateSupport : ["c0m3r","Cbers","crashkelly","DaN","FrostByte","gbone8106","ginganinja","grimfandango","fc7","shorty1483","paulsalter","fluffykiwi","oleg","MongooseMan","SilentAssassin","gogreenpower","Ultroman","Spaceboy","JeremyG","strugglez"] 5 | } 6 | 7 | GuiPage_Contributors.onFocus = function() { 8 | GuiHelper.setControlButtons(null,null,null,GuiMusicPlayer.Status == "PLAYING" || GuiMusicPlayer.Status == "PAUSED" ? "Music" : null,"Return"); 9 | } 10 | 11 | GuiPage_Contributors.start = function() { 12 | alert("Page Enter : GuiPage_Contributors"); 13 | 14 | document.getElementById("Counter").innerHTML = Main.version; 15 | document.getElementById("guiReturnButton").style.visibility = ""; 16 | document.getElementById("guiReturnButton").innerHTML = "Return"; 17 | 18 | document.getElementById("pageContent").innerHTML = "
About:
"; 19 | 20 | var htmlToAdd = "Emby for Samsung Smart TVs is a free, opensource community project. A broad range of Smarthub devices are supported due to the generously donated time and efforts of, among others, the following people.
"; 21 | htmlToAdd += "Feedback on this and other Emby products is gratefully received at emby.media/community.

" 22 | htmlToAdd += "Main Developers"; 23 | for (var index = 0; index < this.MainDevs.length; index++) { 24 | if (index % 6 == 0) { 25 | htmlToAdd += ""; 26 | } 27 | htmlToAdd += ""; 28 | if (index+1 % 6 == 0) { 29 | htmlToAdd += ""; 30 | } 31 | } 32 | htmlToAdd += "
" + this.MainDevs[index] + "


"; 33 | htmlToAdd += "Contributing Developers"; 34 | for (var index = 0; index < this.ContribDevs.length; index++) { 35 | if (index % 6 == 0) { 36 | htmlToAdd += ""; 37 | } 38 | htmlToAdd += ""; 39 | if (index+1 % 6 == 0) { 40 | htmlToAdd += ""; 41 | } 42 | } 43 | htmlToAdd += "
" + this.ContribDevs[index] + "


"; 44 | htmlToAdd += "Donators, supporters and valued beta testers."; 45 | for (var index = 0; index < this.DonateSupport.length; index++) { 46 | if (index % 7 == 0) { 47 | htmlToAdd += ""; 48 | } 49 | htmlToAdd += ""; 50 | if (index+1 % 7 == 0) { 51 | htmlToAdd += ""; 52 | } 53 | } 54 | 55 | document.getElementById("ContentAbout").innerHTML = htmlToAdd + "
" + this.DonateSupport[index] + "
"; 56 | 57 | //Set Focus for Key Events 58 | document.getElementById("GuiPage_Contributors").focus(); 59 | } 60 | 61 | 62 | GuiPage_Contributors.keyDown = function() { 63 | var keyCode = event.keyCode; 64 | alert("Key pressed: " + keyCode); 65 | 66 | if (document.getElementById("Notifications").style.visibility == "") { 67 | document.getElementById("Notifications").style.visibility = "hidden"; 68 | document.getElementById("NotificationText").innerHTML = ""; 69 | widgetAPI.blockNavigation(event); 70 | //Change keycode so it does nothing! 71 | keyCode = "VOID"; 72 | } 73 | 74 | //Update Screensaver Timer 75 | Support.screensaver(); 76 | 77 | //If screensaver is running 78 | if (Main.getIsScreensaverRunning()) { 79 | //Update Main.js isScreensaverRunning - Sets to True 80 | Main.setIsScreensaverRunning(); 81 | 82 | //End Screensaver 83 | GuiImagePlayer_Screensaver.stopScreensaver(); 84 | 85 | //Change keycode so it does nothing! 86 | keyCode = "VOID"; 87 | } 88 | 89 | switch(keyCode) { 90 | case tvKey.KEY_LEFT: 91 | alert("LEFT"); 92 | this.openMenu(); 93 | break; 94 | case tvKey.KEY_RETURN: 95 | alert("RETURN"); 96 | widgetAPI.blockNavigation(event); 97 | Support.processReturnURLHistory(); 98 | break; 99 | case tvKey.KEY_BLUE: 100 | GuiMusicPlayer.showMusicPlayer("GuiPage_Contributors"); 101 | break; 102 | case tvKey.KEY_TOOLS: 103 | widgetAPI.blockNavigation(event); 104 | this.openMenu(); 105 | break; 106 | case tvKey.KEY_EXIT: 107 | alert ("EXIT KEY"); 108 | widgetAPI.sendExitEvent(); 109 | break; 110 | } 111 | } 112 | 113 | GuiPage_Contributors.openMenu = function() { 114 | Support.updateURLHistory("GuiPage_Contributors",null,null,null,null,null,null,null); 115 | GuiMainMenu.requested("GuiPage_Contributors",null); 116 | } -------------------------------------------------------------------------------- /app/javascript/Gui/GuiImagePlayer/GuiImagePlayer_Screensaver.js: -------------------------------------------------------------------------------- 1 | var GuiImagePlayer_Screensaver = { 2 | ImageViewer : null, 3 | newItemData : null, 4 | imagesToUse : "MetaData", 5 | 6 | Timeout : null, 7 | 8 | images : [], 9 | overlay : [], 10 | imageIdx : 0, // Image index 11 | effectIdx : 0, // Transition effect index 12 | effectNames : ['FADE1', 'FADE2', 'BLIND', 'SPIRAL','CHECKER', 'LINEAR', 'STAIRS', 'WIPE', 'RANDOM'], 13 | } 14 | 15 | GuiImagePlayer_Screensaver.kill = function() { 16 | if (this.ImageViewer != null) { 17 | this.ImageViewer.destroy(); 18 | } 19 | } 20 | 21 | GuiImagePlayer_Screensaver.start = function() { 22 | this.imagesToUse = File.getUserProperty("ScreensaverImages"); 23 | alert(this.imagesToUse); 24 | this.images = [] 25 | this.overlay = [] 26 | this.imageIdx = 0 27 | //alert("imagestouse - " + this.imagesToUse) 28 | //Update Main.js isScreensaverRunning - Sets to True 29 | Main.setIsScreensaverRunning(); 30 | 31 | //Hide helper page if shown 32 | GuiHelper.keyDown(); 33 | 34 | //Hide the trailer PiP window if shown 35 | if (Main.getModelYear() != "D") { 36 | sf.service.VideoPlayer.stop(); 37 | sf.service.VideoPlayer.hide(); 38 | } 39 | 40 | Support.styleSubtitles("GuiImagePlayer_ScreensaverOverlay") 41 | 42 | if (this.imagesToUse == "Media") { 43 | var randomImageURL = Server.getItemTypeURL("&SortBy=Random&MediaTypes=Photo&Recursive=true&CollapseBoxSetItems=false&Limit=1000"); 44 | var randomImageData = Server.getContent(randomImageURL); 45 | if (randomImageData == null) { return; } 46 | 47 | for (var index = 0; index < randomImageData.Items.length; index++) { 48 | //Only add images with higher res 49 | if (randomImageData.Items[index].Width >= 1920 && randomImageData.Items[index].Height >= 1080){ 50 | var imgsrc = Server.getScreenSaverImageURL(randomImageData.Items[index].Id,"Primary",1920,1080); 51 | this.images.push(imgsrc); 52 | if (randomImageData.Items[index].PremiereDate !== undefined) { 53 | this.overlay.push(Support.formatDateTime(randomImageData.Items[index].PremiereDate,1)) 54 | } else { 55 | this.overlay.push(""); //Need to push something to keep indexes matched up! 56 | } 57 | 58 | } 59 | } 60 | } else { 61 | var randomImageURL = Server.getItemTypeURL("&SortBy=Random&IncludeItemTypes=Series,Movie&Recursive=true&CollapseBoxSetItems=false&Limit=1000"); 62 | var randomImageData = Server.getContent(randomImageURL); 63 | if (randomImageData == null) { return; } 64 | 65 | for (var index = 0; index < randomImageData.Items.length; index++) { 66 | if (randomImageData.Items[index].BackdropImageTags.length > 0) { 67 | var imgsrc = Server.getScreenSaverImageURL(randomImageData.Items[index ].Id,"Backdrop",1920,1080); 68 | this.images.push(imgsrc); 69 | if (randomImageData.Items[index].Name !== undefined) { 70 | this.overlay.push(randomImageData.Items[index].Name) 71 | } else { 72 | this.overlay.push(""); //Need to push something to keep indexes matched up! 73 | } 74 | 75 | } 76 | } 77 | } 78 | 79 | //Hide Page Contents 80 | document.getElementById("everything").style.visibility="hidden"; 81 | 82 | //Initialte new instance, set Frame Area & Set Notifications 83 | this.ImageViewer = new CImageViewer('Common ImageViewer'); 84 | this.ImageViewer.setFrameArea(0, 0, Main.width, Main.height); 85 | 86 | this.ImageViewer.setOnNetworkError(function() { 87 | GuiNotifications.setNotification("Network Error"); 88 | }); 89 | 90 | this.ImageViewer.setOnRenderError(function() { 91 | GuiNotifications.setNotification("Render Error"); 92 | }); 93 | 94 | //Start Slide Show 95 | this.ImageViewer.show(); 96 | this.setSlideshowMode(); 97 | } 98 | 99 | // Set Slideshow mode 100 | // You can use Transtion effect 101 | GuiImagePlayer_Screensaver.setSlideshowMode = function() { 102 | this.ImageViewer.startSlideshow(); 103 | this.ImageViewer.setOnBufferingComplete(function(){ 104 | GuiImagePlayer_Screensaver.ImageViewer.showNow(); 105 | }); 106 | this.ImageViewer.setOnRenderingComplete(function(){ 107 | clearTimeout(GuiImagePlayer_Screensaver.Timeout); 108 | if (GuiImagePlayer_Screensaver.imagesToUse == "Media") { 109 | Support.setImagePlayerOverlay(GuiImagePlayer_Screensaver.overlay[GuiImagePlayer_Screensaver.imageIdx], GuiImagePlayer.overlayFormat); 110 | } else { 111 | Support.setImagePlayerOverlay(GuiImagePlayer_Screensaver.overlay[GuiImagePlayer_Screensaver.imageIdx], 2); 112 | } 113 | 114 | GuiImagePlayer_Screensaver.Timeout = setTimeout(function(){ 115 | GuiImagePlayer_Screensaver.imageIdx = GuiImagePlayer_Screensaver.imageIdx+1; 116 | if (GuiImagePlayer_Screensaver.imageIdx >= GuiImagePlayer_Screensaver.images.length ) { 117 | GuiImagePlayer_Screensaver.imageIdx = 0; 118 | } 119 | GuiImagePlayer_Screensaver.ImageViewer.prepareNext(GuiImagePlayer_Screensaver.images[GuiImagePlayer_Screensaver.imageIdx], GuiImagePlayer_Screensaver.ImageViewer.Effect.FADE1); 120 | }, File.getUserProperty("ScreensaverImageTime")); 121 | }); 122 | 123 | this.ImageViewer.stop(); 124 | this.playImage(); 125 | } 126 | 127 | // Play image - only called once in slideshow! 128 | //SS calls play -> BufferComplete, then the showNow will call RendComplete which starts timer for next image 129 | GuiImagePlayer_Screensaver.playImage = function() { 130 | var url = GuiImagePlayer_Screensaver.images[GuiImagePlayer_Screensaver.imageIdx]; 131 | GuiImagePlayer_Screensaver.ImageViewer.play(url, 1920, 1080); 132 | } 133 | 134 | GuiImagePlayer_Screensaver.stopScreensaver = function() { 135 | clearTimeout(this.Timeout); 136 | this.Timeout = null; 137 | this.images = []; 138 | this.ImageViewer.endSlideshow(); 139 | this.ImageViewer.hide(); 140 | widgetAPI.blockNavigation(event); 141 | GuiImagePlayer_Screensaver.kill(); 142 | document.getElementById("GuiImagePlayer_ScreensaverOverlay").innerHTML = ""; 143 | //Show Page Contents 144 | document.getElementById("everything").style.visibility=""; 145 | } -------------------------------------------------------------------------------- /app/javascript/Gui/GuiPage_Servers.js: -------------------------------------------------------------------------------- 1 | var GuiPage_Servers = { 2 | ServerData : null, 3 | 4 | selectedItem : 0, 5 | topLeftItem : 0, 6 | isAddButton : false, 7 | MAXCOLUMNCOUNT : 3, 8 | MAXROWCOUNT : 1 9 | } 10 | 11 | GuiPage_Servers.getMaxDisplay = function() { 12 | return this.MAXCOLUMNCOUNT * this.MAXROWCOUNT; 13 | } 14 | 15 | GuiPage_Servers.start = function(runAutoLogin) { 16 | alert("Page Enter : GuiPage_Servers"); 17 | GuiHelper.setControlButtons("Default ",null,null,"Delete","Exit"); 18 | 19 | //Reset Properties 20 | this.selectedItem = 0; 21 | this.topLeftItem = 0; 22 | this.isAddButton = false; 23 | 24 | //Load Data 25 | this.ServerData = JSON.parse(File.loadFile()); 26 | if (this.ServerData.Servers.length == 0) { 27 | //Should never happen - Redirect to 28 | GuiPage_NewServer.start(); 29 | } else { 30 | Support.removeSplashScreen(); 31 | 32 | //Change Display 33 | document.getElementById("pageContent").innerHTML = "
\ 34 |
" + 35 | "
Add a New Server
" + 36 | "
" + 37 | "

Use the RED button to set the selected server as the default auto connect server

" + 38 | "

Use the BLUE button to delete the selected server

"; 39 | 40 | this.updateDisplayedUsers(); 41 | this.updateSelectedUser(); 42 | 43 | //Set Backdrop 44 | Support.fadeImage("images/bg1.jpg"); 45 | 46 | //Set focus to element in Index that defines keydown method! This enables keys to work :D 47 | document.getElementById("GuiPage_Servers").focus(); 48 | } 49 | 50 | } 51 | 52 | GuiPage_Servers.updateDisplayedUsers = function() { 53 | var htmltoadd = ""; 54 | for (var index = this.topLeftItem; index < (Math.min(this.topLeftItem + this.getMaxDisplay(),this.ServerData.Servers.length)); index++) { 55 | htmltoadd += "
"; 56 | } 57 | 58 | //Set Content to Server Data 59 | document.getElementById("GuiPage_Servers_allusers").innerHTML = htmltoadd; 60 | } 61 | 62 | //Function sets CSS Properties so show which user is selected 63 | GuiPage_Servers.updateSelectedUser = function () { 64 | Support.updateSelectedNEW(this.ServerData.Servers,this.selectedItem,this.topLeftItem, 65 | Math.min(this.topLeftItem + GuiPage_Servers.getMaxDisplay(),this.ServerData.Servers.length),"User Selected highlight1Boarder","User",""); 66 | } 67 | 68 | //Function executes on the selection of a user - should log user in or generate error message on screen 69 | GuiPage_Servers.processSelectedUser = function () { 70 | if (this.isAddButton == true) { 71 | GuiPage_NewServer.start(); 72 | } else { 73 | File.setServerEntry(this.selectedItem); 74 | Server.testConnectionSettings(this.ServerData.Servers[this.selectedItem].Path,true); 75 | } 76 | } 77 | 78 | GuiPage_Servers.keyDown = function() 79 | { 80 | var keyCode = event.keyCode; 81 | alert("Key pressed: " + keyCode); 82 | 83 | if (document.getElementById("Notifications").style.visibility == "") { 84 | document.getElementById("Notifications").style.visibility = "hidden"; 85 | document.getElementById("NotificationText").innerHTML = ""; 86 | widgetAPI.blockNavigation(event); 87 | //Change keycode so it does nothing! 88 | keyCode = "VOID"; 89 | } 90 | 91 | switch(keyCode) 92 | { 93 | case tvKey.KEY_RETURN: 94 | alert("RETURN"); 95 | widgetAPI.sendReturnEvent(); 96 | break; 97 | case tvKey.KEY_LEFT: 98 | alert("LEFT"); 99 | this.selectedItem--; 100 | if (this.selectedItem < 0) { 101 | this.selectedItem = this.ServerData.Servers.length - 1; 102 | if(this.ServerData.Servers.length > this.MAXCOLUMNCOUNT) { 103 | this.topLeftItem = (this.selectedItem-2); 104 | this.updateDisplayedUsers(); 105 | } else { 106 | this.topLeftItem = 0; 107 | } 108 | } else { 109 | if (this.selectedItem < this.topLeftItem) { 110 | this.topLeftItem--; 111 | if (this.topLeftItem < 0) { 112 | this.topLeftItem = 0; 113 | } 114 | this.updateDisplayedUsers(); 115 | } 116 | } 117 | this.updateSelectedUser(); 118 | break; 119 | case tvKey.KEY_RIGHT: 120 | alert("RIGHT"); 121 | this.selectedItem++; 122 | if (this.selectedItem >= this.ServerData.Servers.length) { 123 | this.selectedItem = 0; 124 | this.topLeftItem = 0; 125 | this.updateDisplayedUsers(); 126 | } else { 127 | if (this.selectedItem >= this.topLeftItem+this.getMaxDisplay() ) { 128 | this.topLeftItem++; 129 | this.updateDisplayedUsers(); 130 | } 131 | } 132 | this.updateSelectedUser(); 133 | break; 134 | case tvKey.KEY_DOWN: 135 | this.isAddButton = true; 136 | document.getElementById(this.ServerData.Servers[this.selectedItem].Id).className = "User"; 137 | document.getElementById("GuiPage_Servers_addnew").style.border = "2px solid red"; 138 | break; 139 | case tvKey.KEY_UP: 140 | this.isAddButton = false; 141 | document.getElementById(this.ServerData.Servers[this.selectedItem].Id).className = "User Selected"; 142 | document.getElementById("GuiPage_Servers_addnew").style.border = "2px solid black"; 143 | break; 144 | case tvKey.KEY_ENTER: 145 | case tvKey.KEY_PANEL_ENTER: 146 | alert("ENTER"); 147 | GuiPage_Servers.processSelectedUser(); 148 | break; 149 | case tvKey.KEY_RED: 150 | File.setDefaultServer(this.selectedItem); 151 | break; 152 | case tvKey.KEY_YELLOW: 153 | File.deleteSettingsFile(); 154 | widgetAPI.sendExitEvent(); 155 | case tvKey.KEY_BLUE: 156 | File.deleteServer(this.selectedItem); 157 | break; 158 | case tvKey.KEY_EXIT: 159 | alert ("EXIT KEY"); 160 | widgetAPI.sendExitEvent(); 161 | break; 162 | default: 163 | alert("Unhandled key"); 164 | break; 165 | } 166 | }; -------------------------------------------------------------------------------- /app/javascript/Gui/GuiPage_NewServer.js: -------------------------------------------------------------------------------- 1 | var GuiPage_NewServer = { 2 | elementIds : [ "1","2","3","4","port","host"], 3 | inputs : [ null,null,null,null,null], 4 | ready : [ false,false,false,false,false], 5 | 6 | } 7 | 8 | GuiPage_NewServer.start = function() { 9 | alert("Page Enter : GuiPage_NewServer"); 10 | GuiHelper.setControlButtons(null,null,null,null,"Return"); 11 | 12 | //Insert html into page 13 | document.getElementById("pageContent").innerHTML = "
\ 14 |

Enter the IP address & port number of your Emby server.
(You can leave the port blank for 8096)

\ 15 |
. \ 16 | . \ 17 | . \ 18 | : \ 19 |
\ \ 20 |

OR

\ 21 |

Enter your server hostname here without http:// and
including : and port number.

\ 22 |
\ 23 |
"; 24 | 25 | //Set Backdrop 26 | Support.fadeImage("images/bg1.jpg"); 27 | Support.removeSplashScreen(); 28 | 29 | //Prepare all input elements for IME 30 | GuiPage_NewServer.createInputObjects(); 31 | pluginAPI.registIMEKey(); 32 | } 33 | 34 | //Prepare all input elements for IME on Load! 35 | GuiPage_NewServer.createInputObjects = function() { 36 | var previousIndex = 0; 37 | var nextIndex = 0; 38 | for (var index in this.elementIds) { 39 | previousIndex = index - 1; 40 | if (previousIndex < 0) { 41 | previousIndex = GuiPage_NewServer.inputs.length - 1; 42 | } 43 | 44 | nextIndex = (previousIndex + 2) % GuiPage_NewServer.inputs.length; 45 | GuiPage_NewServer.inputs[index] = new GuiPage_NewServer_Input(this.elementIds[index],this.elementIds[previousIndex], this.elementIds[nextIndex]); 46 | } 47 | } 48 | 49 | //Function to check if IME is ready, and when so sets focus on first element in array 50 | GuiPage_NewServer.ready = function(id) { 51 | var ready = true; 52 | 53 | for (var i in GuiPage_NewServer.elementIds) { 54 | if (GuiPage_NewServer.elementIds[i] == id) { 55 | GuiPage_NewServer.ready[i] = true; 56 | } 57 | 58 | if (GuiPage_NewServer.ready[i] == false) { 59 | ready = false; 60 | } 61 | } 62 | 63 | if (ready) { 64 | document.getElementById(GuiPage_NewServer.elementIds[0]).focus(); 65 | } 66 | } 67 | 68 | //Function to delete all the contents of the boxes 69 | GuiPage_NewServer.deleteAllBoxes = function(currentId) { 70 | for (var index = 0;index < GuiPage_NewServer.elementIds.length;index++) { 71 | document.getElementById(GuiPage_NewServer.elementIds[index]).value=""; 72 | } 73 | } 74 | 75 | //IME Key Handler 76 | var GuiPage_NewServer_Input = function(id,previousId, nextId) { 77 | var imeReady = function(imeObject) { 78 | installFocusKeyCallbacks(); 79 | GuiPage_NewServer.ready(id); 80 | } 81 | 82 | var ime = new IMEShell(id, imeReady,'en'); 83 | ime.setKeypadPos(1300,90); 84 | ime.setMode('_num'); 85 | 86 | var previousElement = document.getElementById(previousId); 87 | var nextElement = document.getElementById(nextId); 88 | 89 | var installFocusKeyCallbacks = function () { 90 | ime.setKeyFunc(tvKey.KEY_ENTER, function (keyCode) { 91 | alert("Enter key pressed"); 92 | 93 | GuiNotifications.setNotification("Please Wait","Checking Details",true); 94 | 95 | //Get content from 4 boxes 96 | var IP1 = document.getElementById('1').value; 97 | var IP2 = document.getElementById('2').value; 98 | var IP3 = document.getElementById('3').value; 99 | var IP4 = document.getElementById('4').value; 100 | 101 | var host = document.getElementById('host').value; 102 | 103 | if (IP1 == "" || IP2 == "" || IP3 == "" || IP4 == "" ) { 104 | //Check if host is empty 105 | if (host == "") { 106 | //not valid 107 | GuiNotifications.setNotification("Please re-enter your server details.","Incorrect Details",true); 108 | } else { 109 | document.getElementById("pageContent").focus(); 110 | //Timeout required to allow notification command above to be displayed 111 | setTimeout(function(){Server.testConnectionSettings(host,false);}, 1000); 112 | } 113 | } else { 114 | var Port = document.getElementById('port').value; 115 | if (Port == "") { 116 | Port = "8096"; 117 | } 118 | 119 | var ip = IP1 + '.' + IP2 + '.' + IP3 + '.' + IP4 + ':' + Port; 120 | document.getElementById("pageContent").focus(); 121 | //Timeout required to allow notification command above to be displayed 122 | setTimeout(function(){Server.testConnectionSettings(ip,false);}, 1000); 123 | 124 | } 125 | }); 126 | ime.setKeyFunc(tvKey.KEY_LEFT, function (keyCode) { 127 | previousElement.focus(); 128 | return false; 129 | }); 130 | ime.setKeyFunc(tvKey.KEY_RIGHT, function (keyCode) { 131 | nextElement.focus(); 132 | return false; 133 | }); 134 | ime.setKeyFunc(tvKey.KEY_UP, function (keyCode) { 135 | document.getElementById("1").focus(); 136 | return false; 137 | }); 138 | ime.setKeyFunc(tvKey.KEY_DOWN, function (keyCode) { 139 | document.getElementById("host").focus(); 140 | return false; 141 | }); 142 | ime.setKeyFunc(tvKey.KEY_BLUE, function (keyCode) { 143 | ime.setString(""); //Clears the currently focused Input - REQUIRED 144 | GuiPage_NewServer.deleteAllBoxes(); 145 | return false; 146 | }); 147 | ime.setKeyFunc(tvKey.KEY_RETURN, function (keyCode) { 148 | widgetAPI.blockNavigation(event); 149 | var fileJson = JSON.parse(File.loadFile()); 150 | if (fileJson.Servers.length > 0) { 151 | document.getElementById("pageContent").focus(); 152 | GuiPage_Servers.start(); 153 | } else { 154 | widgetAPI.sendReturnEvent(); 155 | } 156 | return false; 157 | }); 158 | ime.setKeyFunc(tvKey.KEY_EXIT, function (keyCode) { 159 | widgetAPI.sendExitEvent(); 160 | return false; 161 | }); 162 | } 163 | } -------------------------------------------------------------------------------- /app/javascript/Gui/GuiUsers_Manual.js: -------------------------------------------------------------------------------- 1 | var GuiUsers_Manual = { 2 | UserData : null, 3 | selectedItem : 0, //0 = User, 1 = Password 4 | rememberPassword : false 5 | } 6 | 7 | GuiUsers_Manual.start = function() { 8 | alert("Page Enter : GuiUsers_Manual"); 9 | GuiHelper.setControlButtons(null,null,null,null,"Return"); 10 | 11 | //Reset Properties 12 | this.selectedItem = 0; 13 | this.rememberPassword = false; 14 | 15 | document.getElementById("NotificationText").innerHTML = ""; 16 | document.getElementById("Notifications").style.visibility = "hidden"; 17 | 18 | //Load Data 19 | var url = Server.getServerAddr() + "/Users/Public?format=json"; 20 | this.UserData = Server.getContent(url); 21 | if (this.UserData == null) { return; } 22 | 23 | //Change Display 24 | document.getElementById("pageContent").innerHTML = "
\ 25 |

Username

\ 26 |
\ 27 |

Password

\ 28 |
\ 29 |
Remember Password : " + this.rememberPassword + " \ 30 |
"; 31 | 32 | new GuiUsers_Manual_Input("user"); 33 | } 34 | 35 | GuiUsers_Manual.IMEAuthenticate = function(user, password) { 36 | var authenticateSuccess = Server.Authenticate(null, user, password); 37 | if (authenticateSuccess) { 38 | document.getElementById("NoKeyInput").focus(); 39 | 40 | //Check if this user is already in the DB. 41 | var userInFile = false; 42 | var fileJson = JSON.parse(File.loadFile()); 43 | for (var index = 0; index < fileJson.Servers[File.getServerEntry()].Users.length; index++) { 44 | if (fileJson.Servers[File.getServerEntry()].Users[index].UserName == user) { 45 | userInFile = true; 46 | File.setUserEntry(index); 47 | } 48 | } 49 | 50 | //Otherwise add them. 51 | if (userInFile == false) { 52 | alert("Need to add the user to the DB"); 53 | //Add Username & Password to DB - Save password only if rememberPassword = true 54 | if (this.rememberPassword == true) { 55 | File.addUser(Server.UserID,user,password,this.rememberPassword); 56 | } else { 57 | File.addUser(Server.UserID,user,"",this.rememberPassword); 58 | } 59 | } 60 | 61 | //Change Focus and call function in GuiMain to initiate the page! 62 | GuiMainMenu.start(); 63 | } else { 64 | 65 | alert ("Authentication Failed"); 66 | document.getElementById("user").focus(); 67 | GuiNotifications.setNotification("Wrong username, bad password or network error.","Logon Error",true); 68 | } 69 | } 70 | 71 | ////////////////////////////////////////////////////////////////// 72 | // Input method for entering user password. // 73 | ////////////////////////////////////////////////////////////////// 74 | var GuiUsers_Manual_Input = function(id) { 75 | var imeReady = function(imeObject) { 76 | installFocusKeyCallbacks(); 77 | document.getElementById(id).focus(); 78 | } 79 | 80 | var ime = new IMEShell(id, imeReady,'en'); 81 | ime.setKeypadPos(1300,90); 82 | 83 | var installFocusKeyCallbacks = function () { 84 | ime.setKeyFunc(tvKey.KEY_ENTER, function (keyCode) { 85 | alert("Enter key pressed"); 86 | if (GuiUsers_Manual.selectedItem == 0) { 87 | //Set IME to Password field 88 | GuiUsers_Manual.selectedItem++; 89 | new GuiUsers_Manual_Input("pass"); 90 | document.getElementById("pass").focus; 91 | } else { 92 | //Process Login Here 93 | var usr = document.getElementById("user").value; 94 | var pwd = document.getElementById("pass").value; 95 | GuiUsers_Manual.IMEAuthenticate(usr,pwd); 96 | } 97 | }); 98 | 99 | ime.setKeyFunc(tvKey.KEY_DOWN, function (keyCode) { 100 | alert("Down key pressed"); 101 | if (GuiUsers_Manual.selectedItem == 0) { 102 | //Set IME to Password field 103 | GuiUsers_Manual.selectedItem++; 104 | new GuiUsers_Manual_Input("pass"); 105 | document.getElementById("pass").focus; 106 | } else { 107 | document.getElementById("guiUsers_rempwd").style.color = "red"; 108 | document.getElementById("GuiUsers_Manual_Pwd").focus(); 109 | } 110 | }); 111 | 112 | ime.setKeyFunc(tvKey.KEY_UP, function (keyCode) { 113 | alert("Up key pressed"); 114 | if (GuiUsers_Manual.selectedItem == 1) { 115 | //Set IME to Username field 116 | GuiUsers_Manual.selectedItem--; 117 | new GuiUsers_Manual_Input("user"); 118 | document.getElementById("user").focus; 119 | } 120 | }); 121 | 122 | //Keycode to abort login from password screen 123 | ime.setKeyFunc(tvKey.KEY_RETURN, function (keyCode) { 124 | widgetAPI.blockNavigation(event); 125 | var fileJson = JSON.parse(File.loadFile()); 126 | if (fileJson.Servers.length > 0) { 127 | document.getElementById("pageContent").focus(); 128 | GuiUsers.start(); 129 | } 130 | }); 131 | 132 | ime.setKeyFunc(tvKey.KEY_EXIT, function (keyCode) { 133 | document.getElementById("NoKeyInput").focus(); 134 | widgetAPI.sendExitEvent(); 135 | }); 136 | } 137 | }; 138 | 139 | GuiUsers_Manual.keyDownPassword = function() { 140 | var keyCode = event.keyCode; 141 | alert("Key pressed: " + keyCode); 142 | 143 | if (document.getElementById("Notifications").style.visibility == "") { 144 | document.getElementById("Notifications").style.visibility = "hidden"; 145 | document.getElementById("NotificationText").innerHTML = ""; 146 | widgetAPI.blockNavigation(event); 147 | //Change keycode so it does nothing! 148 | keyCode = "VOID"; 149 | } 150 | 151 | switch(keyCode) 152 | { 153 | case tvKey.KEY_RETURN: 154 | case tvKey.KEY_PANEL_RETURN: 155 | alert("RETURN"); 156 | widgetAPI.sendReturnEvent(); 157 | break; 158 | case tvKey.KEY_UP: 159 | if (document.getElementById("guiUsers_rempwd").style.color == "red") { 160 | document.getElementById("guiUsers_rempwd").style.color = "#f9f9f9"; 161 | document.getElementById("pass").focus(); 162 | } else { 163 | this.rememberPassword = (this.rememberPassword == false) ? true : false; 164 | document.getElementById("guiUsers_rempwdvalue").innerHTML = this.rememberPassword; 165 | } 166 | break; 167 | case tvKey.KEY_DOWN: 168 | if (document.getElementById("guiUsers_rempwdvalue").style.color == "red") { 169 | this.rememberPassword = (this.rememberPassword == false) ? true : false; 170 | document.getElementById("guiUsers_rempwdvalue").innerHTML = this.rememberPassword; 171 | } 172 | break; 173 | case tvKey.KEY_RIGHT: 174 | alert("RIGHT"); 175 | if (document.getElementById("guiUsers_rempwd").style.color == "red") { 176 | document.getElementById("guiUsers_rempwd").style.color = "green"; 177 | document.getElementById("guiUsers_rempwdvalue").style.color = "red"; 178 | } 179 | break; 180 | case tvKey.KEY_LEFT: 181 | alert("LEFT"); 182 | if (document.getElementById("guiUsers_rempwdvalue").style.color == "red") { 183 | document.getElementById("guiUsers_rempwd").style.color = "red"; 184 | document.getElementById("guiUsers_rempwdvalue").style.color = "#f9f9f9"; 185 | } 186 | break; 187 | case tvKey.KEY_ENTER: 188 | case tvKey.KEY_PANEL_ENTER: 189 | alert("ENTER"); 190 | if (document.getElementById("guiUsers_rempwdvalue").style.color == "red") { 191 | document.getElementById("guiUsers_rempwd").style.color = "red"; 192 | document.getElementById("guiUsers_rempwdvalue").style.color = "#f9f9f9"; 193 | } else { 194 | document.getElementById("guiUsers_rempwd").style.color = "green"; 195 | document.getElementById("guiUsers_rempwdvalue").style.color = "red"; 196 | } 197 | break; 198 | case tvKey.KEY_EXIT: 199 | alert ("EXIT KEY"); 200 | widgetAPI.sendExitEvent(); 201 | break; 202 | default: 203 | alert("Unhandled key"); 204 | break; 205 | } 206 | }; -------------------------------------------------------------------------------- /app/javascript/Gui/GuiPage_SettingsLog.js: -------------------------------------------------------------------------------- 1 | var GuiPage_SettingsLog = { 2 | logArray : null, 3 | selectedBannerItem : 0, 4 | topLeftItem : 0, 5 | 6 | MAXCOLUMNCOUNT : 1, 7 | MAXROWCOUNT : 20, 8 | 9 | bannerItems : ["User Settings","Server Settings","TV Settings","Log","About"], 10 | } 11 | 12 | GuiPage_SettingsLog.onFocus = function() { 13 | GuiHelper.setControlButtons("Clear Log",null,null,GuiMusicPlayer.Status == "PLAYING" || GuiMusicPlayer.Status == "PAUSED" ? "Music" : null,"Return"); 14 | } 15 | 16 | GuiPage_SettingsLog.getMaxDisplay = function() { 17 | return this.MAXCOLUMNCOUNT * this.MAXROWCOUNT; 18 | } 19 | 20 | GuiPage_SettingsLog.start = function() { 21 | alert("Page Enter : GuiPage_SettingsLog"); 22 | 23 | //Reset Vars 24 | this.selectedBannerItem = 3; //match Logs 25 | 26 | //Load Data 27 | this.logArray = FileLog.loadFile(true); 28 | this.topLeftItem = this.logArray.length - GuiPage_SettingsLog.getMaxDisplay(); 29 | this.topLeftItem = (this.topLeftItem < 0) ? 0 : this.topLeftItem; 30 | 31 | //Load Settings 32 | document.getElementById("pageContent").className = ""; 33 | document.getElementById("pageContent").innerHTML = "
Log
\ \ 34 |
";// + 35 | /*"
" + 36 | "
" + 37 | "
" + 38 | "
";*/ 39 | 40 | //Create Banner Items 41 | for (var index = 0; index < this.bannerItems.length; index++) { 42 | if (index != this.bannerItems.length-1) { 43 | document.getElementById("bannerSelection").innerHTML += "
"+this.bannerItems[index].replace(/_/g, ' ')+"
"; 44 | } else { 45 | document.getElementById("bannerSelection").innerHTML += "
"+this.bannerItems[index].replace(/_/g, ' ')+"
"; 46 | } 47 | } 48 | 49 | //Update Displayed 50 | //this.setText(); 51 | this.updateDisplayedItems(); 52 | this.updateSelectedBannerItems(); 53 | document.getElementById("GuiPage_SettingsLog").focus(); 54 | } 55 | 56 | GuiPage_SettingsLog.updateDisplayedItems = function() { 57 | var htmlToAdd = ""; 58 | for (var index = this.topLeftItem; index < Math.min(this.topLeftItem + this.getMaxDisplay(),this.logArray.length); index++) { 59 | htmlToAdd += ""; 60 | } 61 | document.getElementById("guiPage_Settings_Settings").innerHTML = htmlToAdd + "
" + this.logArray[index] + "
"; 62 | } 63 | 64 | GuiPage_SettingsLog.updateSelectedBannerItems = function() { 65 | for (var index = 0; index < this.bannerItems.length; index++) { 66 | if (index == this.selectedBannerItem) { 67 | if (index != this.bannerItems.length-1) { //Don't put padding on the last one. 68 | document.getElementById("bannerItem"+index).className = "bannerItem bannerItemPadding highlight"+Main.highlightColour+"Text"; 69 | } else { 70 | document.getElementById("bannerItem"+index).className = "bannerItem highlight"+Main.highlightColour+"Text"; 71 | } 72 | } else { 73 | if (index != this.bannerItems.length-1) { //Don't put padding on the last one. 74 | if (index == 3) { 75 | document.getElementById("bannerItem"+index).className = "bannerItem bannerItemPadding offWhite"; 76 | } else { 77 | document.getElementById("bannerItem"+index).className = "bannerItem bannerItemPadding"; 78 | } 79 | } else { 80 | if (index == 3) { 81 | document.getElementById("bannerItem"+index).className = "bannerItem offWhite"; 82 | } else { 83 | document.getElementById("bannerItem"+index).className = "bannerItem"; 84 | } 85 | } 86 | } 87 | } 88 | document.getElementById("Counter").innerHTML = (this.selectedBannerItem + 1) + "/" + (this.bannerItems.length); 89 | } 90 | 91 | GuiPage_SettingsLog.keyDown = function() { 92 | var keyCode = event.keyCode; 93 | alert("Key pressed: " + keyCode); 94 | 95 | if (document.getElementById("Notifications").style.visibility == "") { 96 | document.getElementById("Notifications").style.visibility = "hidden"; 97 | document.getElementById("NotificationText").innerHTML = ""; 98 | widgetAPI.blockNavigation(event); 99 | //Change keycode so it does nothing! 100 | keyCode = "VOID"; 101 | } 102 | 103 | //Update Screensaver Timer 104 | Support.screensaver(); 105 | 106 | //If screensaver is running 107 | if (Main.getIsScreensaverRunning()) { 108 | //Update Main.js isScreensaverRunning - Sets to True 109 | Main.setIsScreensaverRunning(); 110 | 111 | //End Screensaver 112 | GuiImagePlayer_Screensaver.stopScreensaver(); 113 | 114 | //Change keycode so it does nothing! 115 | keyCode = "VOID"; 116 | } 117 | 118 | switch(keyCode) { 119 | //Need Logout Key 120 | case tvKey.KEY_UP: 121 | this.processUpKey(); 122 | break; 123 | case tvKey.KEY_DOWN: 124 | this.processDownKey(); 125 | break; 126 | case tvKey.KEY_LEFT: 127 | this.processLeftKey(); 128 | break; 129 | case tvKey.KEY_RIGHT: 130 | this.processRightKey(); 131 | break; 132 | case tvKey.KEY_RETURN: 133 | widgetAPI.blockNavigation(event); 134 | Support.processReturnURLHistory(); 135 | break; 136 | case tvKey.KEY_ENTER: 137 | case tvKey.KEY_PANEL_ENTER: 138 | this.processSelectedItem(); 139 | break; 140 | case tvKey.KEY_RED: 141 | FileLog.empty(); 142 | FileLog.write("---------------------------------------------------------------------",true); 143 | FileLog.write("Log File Emptied by User") 144 | GuiPage_SettingsLog.start(); //relead 145 | break; 146 | case tvKey.KEY_BLUE: 147 | GuiMusicPlayer.showMusicPlayer("GuiPage_SettingsLog","bannerItem"+this.selectedBannerItem,"bannerItem bannerItemPadding highlight"+Main.highlightColour+"Text"); 148 | break; 149 | case tvKey.KEY_TOOLS: 150 | widgetAPI.blockNavigation(event); 151 | GuiMainMenu.requested("GuiPage_SettingsLog",null); 152 | break; 153 | case tvKey.KEY_EXIT: 154 | widgetAPI.sendExitEvent(); 155 | break; 156 | } 157 | } 158 | 159 | GuiPage_SettingsLog.processUpKey = function() { 160 | this.topLeftItem = this.topLeftItem - this.MAXCOLUMNCOUNT; 161 | if (this.topLeftItem == -1) { 162 | this.topLeftItem = 0; 163 | } else { 164 | this.updateDisplayedItems(); 165 | } 166 | } 167 | 168 | GuiPage_SettingsLog.processDownKey = function() { 169 | this.topLeftItem = this.topLeftItem + this.MAXCOLUMNCOUNT; 170 | if (this.topLeftItem > this.logArray.length - this.getMaxDisplay()) { 171 | this.topLeftItem = this.topLeftItem - this.MAXCOLUMNCOUNT; 172 | } else { 173 | this.updateDisplayedItems(); 174 | } 175 | } 176 | 177 | GuiPage_SettingsLog.processLeftKey = function() { 178 | this.selectedBannerItem--; 179 | if (this.selectedBannerItem < 0) { 180 | this.selectedBannerItem = 0; 181 | this.openMenu(); 182 | } else { 183 | this.updateSelectedBannerItems(); 184 | } 185 | } 186 | 187 | GuiPage_SettingsLog.openMenu = function() { 188 | document.getElementById("bannerItem0").className = "bannerItem bannerItemPadding"; 189 | GuiMainMenu.requested("GuiPage_SettingsLog","bannerItem0","bannerItem bannerItemPadding green"); 190 | } 191 | 192 | GuiPage_SettingsLog.processRightKey = function() { 193 | this.selectedBannerItem++; 194 | if (this.selectedBannerItem >= this.bannerItems.length) { 195 | this.selectedBannerItem--; 196 | } else { 197 | this.updateSelectedBannerItems(); 198 | } 199 | } 200 | 201 | GuiPage_SettingsLog.processSelectedItem = function() { 202 | if (this.bannerItems[this.selectedBannerItem] == "About") { 203 | Support.updateURLHistory("GuiPage_Settings",null,null,null,null,0,0,null); 204 | GuiPage_Contributors.start(); 205 | } else if (this.bannerItems[this.selectedBannerItem] != "Log") { 206 | GuiPage_Settings.start(this.bannerItems[this.selectedBannerItem]); 207 | } 208 | } 209 | 210 | GuiPage_SettingsLog.setText = function() { 211 | document.getElementById("guiPage_Settings_Overview_Title").innerHTML = "Log Viewer"; 212 | document.getElementById("guiPage_Settings_Overview_Content").innerHTML = "Press the up arrow to navigate to earlier entries in the log, and down to view later entries. The log opens at the last items in the log.

Press the red button to clear the log."; 213 | } 214 | 215 | -------------------------------------------------------------------------------- /app/javascript/Main.js: -------------------------------------------------------------------------------- 1 | var widgetAPI = new Common.API.Widget(); 2 | var pluginAPI = new Common.API.Plugin(); 3 | var tvKey = new Common.API.TVKeyValue(); 4 | 5 | var Main = 6 | { 7 | version : "v2.2.5b", 8 | requiredServerVersion : "10.3.2", 9 | requiredDevServerVersion : "3.0.5507.2131", 10 | 11 | //TV Series Version 12 | modelYear : null, 13 | width : 1920, 14 | height : 1080, 15 | backdropWidth : 1920, 16 | backdropHeight : 1080, 17 | posterWidth : 473, 18 | posterHeight : 267, 19 | seriesPosterWidth : 180, 20 | seriesPosterHeight : 270, 21 | seriesPosterLargeWidth : 235, 22 | seriesPosterLargeHeight : 350, 23 | 24 | forceDeleteSettings : false, 25 | highlightColour : 1, 26 | 27 | enableMusic : true, 28 | enableLiveTV : true, 29 | enableCollections : true, 30 | enableChannels : true, 31 | enableImageCache : true, 32 | 33 | enableScreensaver : true, 34 | isScreensaverRunning : false, 35 | }; 36 | 37 | Main.getModelYear = function() { 38 | return this.modelYear; 39 | }; 40 | 41 | Main.isMusicEnabled = function() { 42 | return this.enableMusic; 43 | }; 44 | 45 | Main.isLiveTVEnabled = function() { 46 | return this.enableLiveTV; 47 | }; 48 | 49 | Main.isCollectionsEnabled = function() { 50 | return this.enableCollections; 51 | }; 52 | 53 | Main.isChannelsEnabled = function() { 54 | return this.enableChannels; 55 | }; 56 | 57 | Main.isScreensaverEnabled = function() { 58 | return this.enableScreensaver; 59 | }; 60 | 61 | Main.isImageCaching = function() { 62 | return this.enableImageCache; 63 | }; 64 | 65 | Main.getRequiredServerVersion = function() { 66 | return this.requiredServerVersion; 67 | }; 68 | 69 | Main.getVersion = function() { 70 | return this.version; 71 | }; 72 | 73 | Main.getIsScreensaverRunning = function() { 74 | return this.isScreensaverRunning; 75 | }; 76 | 77 | Main.setIsScreensaverRunning = function() { 78 | if (this.isScreensaverRunning == false) { 79 | this.isScreensaverRunning = true; 80 | } else { 81 | this.isScreensaverRunning = false; 82 | } 83 | }; 84 | 85 | Main.onLoad = function() 86 | { 87 | //Support.removeSplashScreen(); 88 | //Setup Logging 89 | FileLog.loadFile(false); // doesn't return contents, done to ensure file exists 90 | FileLog.write("---------------------------------------------------------------------",true); 91 | FileLog.write("Emby Application Started"); 92 | 93 | if (Main.isImageCaching()) { 94 | var fileSystemObj = new FileSystem(); 95 | fileSystemObj.deleteCommonFile(curWidget.id + '/cache.json'); 96 | Support.imageCachejson = JSON.parse('{"Images":[]}'); 97 | } 98 | 99 | document.getElementById("splashscreen_version").innerHTML = Main.version; 100 | 101 | //Turn ON screensaver 102 | pluginAPI.setOnScreenSaver(); 103 | FileLog.write("Screensaver enabled."); 104 | Support.clock(); 105 | widgetAPI.sendReadyEvent(); 106 | window.onShow = Main.initKeys(); 107 | 108 | //Set DeviceID & Device Name 109 | var NNaviPlugin = document.getElementById("pluginObjectNNavi"); 110 | var pluginNetwork = document.getElementById("pluginObjectNetwork"); 111 | var pluginTV = document.getElementById("pluginObjectTV"); 112 | FileLog.write("Plugins initialised."); 113 | 114 | var ProductType = pluginNetwork.GetActiveType(); 115 | FileLog.write("Product type is "+ProductType); 116 | var phyConnection = pluginNetwork.CheckPhysicalConnection(ProductType); //returns -1 117 | FileLog.write("Check physical connection returned "+phyConnection); 118 | var http = pluginNetwork.CheckHTTP(ProductType); //returns -1 119 | FileLog.write("Check HTTP returned "+http); 120 | var gateway = pluginNetwork.CheckGateway(ProductType); //returns -1 121 | FileLog.write("Check gateway returned "+gateway); 122 | 123 | //Get the model year - Used for transcoding 124 | if (pluginTV.GetProductCode(0).substring(0,2) == "HT" || pluginTV.GetProductCode(0).substring(0,2) == "BD"){ 125 | this.modelYear = pluginTV.GetProductCode(0).substring(3,4); 126 | 127 | } else if (pluginTV.GetProductCode(0).substring(4,7) == "H52") { 128 | this.modelYear = "F"; 129 | } else if (pluginTV.GetProductCode(0).substring(4,7) == "J43") { 130 | this.modelYear = "F"; 131 | } else if (pluginTV.GetProductCode(0).substring(4,7) == "J52") { 132 | this.modelYear = "F"; 133 | } else if (pluginTV.GetProductCode(0).substring(4,7) == "J53") { 134 | this.modelYear = "F"; 135 | } else if (pluginTV.GetProductCode(0).substring(4,7) == "J62") { 136 | this.modelYear = "F"; 137 | } else if (pluginTV.GetProductCode(0).substring(4,7) == "J55") { 138 | this.modelYear = "H"; 139 | } else if (pluginTV.GetProductCode(0).substring(4,7) == "J63") { 140 | this.modelYear = "H"; 141 | } else if (pluginTV.GetProductCode(0).substring(4,7) == "J64") { 142 | this.modelYear = "H"; 143 | } else if (pluginTV.GetProductCode(0).substring(4,6) == "HU") { 144 | this.modelYear = "HU"; 145 | } else if (pluginTV.GetProductCode(0).substring(4,7) == "K85") { 146 | this.modelYear = "HU"; 147 | } else { 148 | this.modelYear = pluginTV.GetProductCode(0).substring(4,5); 149 | } 150 | FileLog.write("Model Year is " + this.modelYear); 151 | 152 | if (phyConnection && http && gateway) { 153 | var MAC = pluginNetwork.GetMAC(1); 154 | if (MAC == false || MAC == null) { //Set mac to fake 155 | MAC = "0123456789ab" ; 156 | } 157 | FileLog.write("MAC address is "+MAC); 158 | Server.setDevice ("Samsung " + pluginTV.GetProductCode(0)); 159 | Server.setDeviceID(NNaviPlugin.GetDUID(MAC)); 160 | 161 | //Load Settings File - Check if file needs to be deleted due to development 162 | var fileJson = JSON.parse(File.loadFile()); 163 | var version = File.checkVersion(fileJson); 164 | if (version == "Undefined" ) { 165 | //Delete Settings file and reload 166 | File.deleteSettingsFile(); 167 | fileJson = JSON.parse(File.loadFile()); 168 | } else if (version != this.version) { 169 | if (this.forceDeleteSettings == true) { 170 | //Delete Settings file and reload 171 | File.deleteSettingsFile(); 172 | fileJson = JSON.parse(File.loadFile()); 173 | } else { 174 | //Update version in settings file to current version 175 | fileJson.Version = this.version; 176 | } File.writeAll(fileJson); 177 | } 178 | 179 | //Allow Evo Kit owners to override the model year. 180 | if (fileJson.TV.ModelOverride != "None") { 181 | switch(fileJson.TV.ModelOverride){ 182 | case "SEK1000": 183 | this.modelYear = "F"; 184 | break; 185 | case "SEK2000": 186 | this.modelYear = "H"; 187 | break; 188 | case "SEK2500": 189 | this.modelYear = "H"; 190 | break; 191 | } 192 | FileLog.write("Model Year Override: " + this.modelYear); 193 | } 194 | 195 | //Check if Server exists 196 | if (fileJson.Servers.length > 1) { 197 | //If no default show user Servers page (Can set default on that page) 198 | var foundDefault = false; 199 | for (var index = 0; index < fileJson.Servers.length; index++) { 200 | if (fileJson.Servers[index].Default == true) { 201 | foundDefault = true; 202 | FileLog.write("Default server found."); 203 | File.setServerEntry(index); 204 | Server.testConnectionSettings(fileJson.Servers[index].Path,true); 205 | break; 206 | } 207 | } 208 | if (foundDefault == false) { 209 | FileLog.write("Multiple servers defined. Loading the select server page."); 210 | GuiPage_Servers.start(); 211 | } 212 | } else if (fileJson.Servers.length == 1) { 213 | //If 1 server auto login with that 214 | FileLog.write("Emby server name found in settings. Auto-connecting."); 215 | File.setServerEntry(0); 216 | Server.testConnectionSettings(fileJson.Servers[0].Path,true); 217 | } else { 218 | //No Server Defined - Load GuiPage_IP 219 | FileLog.write("No server defined. Loading the new server page."); 220 | GuiPage_NewServer.start(); 221 | } 222 | } else { 223 | document.getElementById("pageContent").innerHTML = "You have no network connectivity to the TV - Please check the settings on the TV"; 224 | } 225 | }; 226 | 227 | Main.initKeys = function() { 228 | pluginAPI.registKey(tvKey.KEY_TOOLS); 229 | pluginAPI.registKey(tvKey.KEY_3D); 230 | FileLog.write("Key handlers initialised."); 231 | }; 232 | 233 | Main.onUnload = function() 234 | { 235 | //Write Cache to disk 236 | ImageCache.writeAll(Support.imageCachejson); 237 | Support.screensaverOff(); 238 | GuiImagePlayer.kill(); 239 | GuiMusicPlayer.stopOnAppExit(); 240 | GuiPlayer.stopOnAppExit(); 241 | pluginAPI.unregistKey(tvKey.KEY_TOOLS); 242 | pluginAPI.unregistKey(tvKey.KEY_3D); 243 | }; 244 | -------------------------------------------------------------------------------- /app/javascript/Support/GuiHelper.js: -------------------------------------------------------------------------------- 1 | var GuiHelper = { 2 | helpPage : null 3 | } 4 | 5 | //------------------------------------------------------------------------------------------------ 6 | //GUIHelper isn't its own window, it just controls the help contents at the bottom of the screen 7 | //------------------------------------------------------------------------------------------------ 8 | GuiHelper.toggleHelp = function(helpPage) { 9 | this.helpPage = helpPage; 10 | if (document.getElementById("GuiImagePlayer_ScreensaverOverlay").style.visibility == ""){ 11 | document.getElementById("GuiImagePlayer_ScreensaverOverlay").style.visibility = "hidden"; 12 | } 13 | GuiHelper.setHelpPage(helpPage); 14 | 15 | //Unhide help window 16 | document.getElementById("Help").style.visibility = ""; 17 | 18 | //Set focus 19 | document.getElementById("GuiHelper").focus(); 20 | } 21 | 22 | GuiHelper.keyDown = function() { 23 | var keyCode; 24 | if (event) { 25 | keyCode = event.keyCode; 26 | } else { 27 | return; 28 | } 29 | 30 | switch(keyCode) { 31 | case tvKey.KEY_YELLOW: 32 | case tvKey.KEY_RETURN: 33 | 34 | //Stops Return causing the app to exit when closing help text. 35 | widgetAPI.blockNavigation(event); 36 | 37 | if (document.getElementById("GuiImagePlayer_ScreensaverOverlay").style.visibility == "hidden"){ 38 | document.getElementById("GuiImagePlayer_ScreensaverOverlay").style.visibility = ""; 39 | } 40 | 41 | //If required for Screensaver call in GuiImagePlayer_Screensaver 42 | if (document.getElementById("Help").style.visibility == "") { 43 | //Hide help window 44 | document.getElementById("Help").style.visibility = "hidden"; 45 | 46 | //Set focus back to original page 47 | document.getElementById(this.helpPage).focus(); 48 | } 49 | break; 50 | } 51 | } 52 | 53 | GuiHelper.setHelpPage = function(helpPage) { 54 | //switch (helpPage) { 55 | //case "GuiPage_IP": 56 | // document.getElementById("Help").innerHTML = "Welcome to a IP"; 57 | // break; 58 | //case "GuiUsers": 59 | // document.getElementById("Help").innerHTML = "Welcome to a User"; 60 | // break; 61 | //case "GuiDisplayOneItem": 62 | // document.getElementById("Help").innerHTML = this.generateDisplayOneItemHelp(); 63 | // break; 64 | //default: 65 | //document.getElementById("Help").innerHTML = "Welcome to a page with no help written!"; 66 | document.getElementById("HelpTitle").innerHTML = "Help Page"; 67 | document.getElementById("HelpContent").innerHTML = this.generateDisplayOneItemHelp(); 68 | // break; 69 | //} 70 | } 71 | 72 | GuiHelper.generateDisplayOneItemHelp = function() { 73 | if (this.helpPage == "GuiImagePlayer") { 74 | var htmlToAdd = "Return, Stop - Ends slideshow and returns the user to the previous screen.
" + 75 | "Left, Right - Move 1 image backwards or forwards.
" + 76 | "Pause - Pause slideshow.
" + 77 | "Play - Resume slideshow.
" + 78 | "Red - Mark photo as a favourite.
" + 79 | "Green - Toggle Date/Time overlay; None | Date | Date : Time
" + 80 | "Yellow - Show this help message.
" + 81 | "Blue - When music is playing, show the music player controls. "; 82 | } else { 83 | var htmlToAdd = "Tools - Show the main menu.
" + 84 | "Return - Returns the user to the previous screen.
" + 85 | "Up, Down, Left, Right - Navigation Control.
" + 86 | "Enter - Select the highlighted item.
" + 87 | "Red - Add or remove an item on the favourites page.
" + 88 | "Green - Mark a video item as watched or unwatched.
" + 89 | "Yellow - Show this help message.
" + 90 | "Blue - When music is playing, show the music player controls.
" + 91 | "Ch. Up/Down - Skips one page of content. "; 92 | } 93 | return htmlToAdd; 94 | 95 | } 96 | 97 | GuiHelper.setControlButtons = function(redText,greenText,yellowText,blueText,returnText) { 98 | //Displays the coloured remote control buttons on screen to indicate their current function. 99 | //Each parameter is the button text. A null value means the button is hidden, 0 means don't change it. 100 | //The position value is calculated to group the visible buttons on the right. 101 | //The offset allows for longer labels. 102 | 103 | //Get the current text if needed. 104 | if (redText == 0){ 105 | redText = document.getElementById("guiRedButton").innerHTML; 106 | if (redText == "") { 107 | redText = null; 108 | } 109 | } 110 | if (greenText == 0){ 111 | greenText = document.getElementById("guiGreenButton").innerHTML; 112 | if (greenText == "") { 113 | greenText = null; 114 | } 115 | } 116 | if (yellowText == 0){ 117 | yellowText = document.getElementById("guiYellowButton").innerHTML; 118 | if (yellowText == "") { 119 | yellowText = null; 120 | } 121 | } 122 | if (blueText == 0){ 123 | blueText = document.getElementById("guiBlueButton").innerHTML; 124 | if (blueText == "") { 125 | blueText = null; 126 | } 127 | } 128 | if (returnText == 0){ 129 | returnText = document.getElementById("guiReturnButton").innerHTML; 130 | if (returnText == "") { 131 | returnText = null; 132 | } 133 | } 134 | 135 | //Calculate an offset value if the label is longer than 5 characters. 136 | var redOffset = 0; 137 | if (redText != null){ 138 | redOffset = (redText.length > 5) ? (redText.length *6)+5 : 0; 139 | } 140 | 141 | var greenOffset = 0; 142 | if (greenText != null){ 143 | greenOffset = (greenText.length > 5) ? (greenText.length *6)+5 : 0; 144 | } 145 | 146 | var yellowOffset = 0; 147 | if (yellowText != null){ 148 | yellowOffset = (yellowText.length > 5) ? (yellowText.length *6)+5 : 0; 149 | } 150 | 151 | var blueOffset = 0; 152 | if (blueText != null){ 153 | blueOffset = (blueText.length > 5) ? (blueText.length *6)+5 : 0; 154 | } 155 | 156 | var returnOffset = 0; 157 | if (returnText != null){ 158 | returnOffset = (returnText.length > 5) ? (returnText.length *6)+5 : 0; 159 | } 160 | 161 | //Add the offset values to item's standard position. 162 | var redPos = (redText == null) ? 0 : 602; 163 | redPos = redPos + redOffset + greenOffset + yellowOffset + blueOffset + returnOffset; 164 | var greenPos = (greenText == null) ? 0 : 468; 165 | greenPos = greenPos + greenOffset + yellowOffset + blueOffset + returnOffset; 166 | var yellowPos = (yellowText == null) ? 0 : 322; 167 | yellowPos = yellowPos + yellowOffset + blueOffset + returnOffset; 168 | var bluePos = (blueText == null) ? 0 : 185; 169 | bluePos = bluePos + blueOffset + returnOffset; 170 | var returnPos = (returnText == null) ? 0 : 75; 171 | returnPos = returnPos + returnOffset; 172 | 173 | //This section moves the items right if some are not being displayed. 174 | if (returnText == null){ 175 | bluePos = bluePos -90; 176 | yellowPos = yellowPos -90; 177 | greenPos = greenPos -90; 178 | redPos = redPos -90; 179 | } 180 | if (blueText == null){ 181 | yellowPos = yellowPos -150; 182 | greenPos = greenPos -150; 183 | redPos = redPos -150; 184 | } 185 | if (yellowText == null){ 186 | greenPos = greenPos -130; 187 | redPos = redPos -130; 188 | } 189 | if (greenText == null){ 190 | redPos = redPos -150; 191 | } 192 | 193 | //Set control button visibility, inner text and position. 194 | if (redText == null){ 195 | document.getElementById("guiRedButton").style.visibility = "hidden"; 196 | document.getElementById("guiRedButton").innerHTML = null; 197 | } else { 198 | document.getElementById("guiRedButton").style.visibility = ""; 199 | document.getElementById("guiRedButton").innerHTML = redText; 200 | document.getElementById("guiRedButton").style.right = redPos + "px"; 201 | } 202 | if (greenText == null){ 203 | document.getElementById("guiGreenButton").style.visibility = "hidden"; 204 | document.getElementById("guiGreenButton").innerHTML = null; 205 | } else { 206 | document.getElementById("guiGreenButton").style.visibility = ""; 207 | document.getElementById("guiGreenButton").innerHTML = greenText; 208 | document.getElementById("guiGreenButton").style.right = greenPos + "px"; 209 | } 210 | if (yellowText == null){ 211 | document.getElementById("guiYellowButton").style.visibility = "hidden"; 212 | document.getElementById("guiYellowButton").innerHTML = null; 213 | } else { 214 | document.getElementById("guiYellowButton").style.visibility = ""; 215 | document.getElementById("guiYellowButton").innerHTML = yellowText; 216 | document.getElementById("guiYellowButton").style.right = yellowPos + "px"; 217 | } 218 | if (blueText == null){ 219 | document.getElementById("guiBlueButton").style.visibility = "hidden"; 220 | document.getElementById("guiBlueButton").innerHTML = null; 221 | } else { 222 | document.getElementById("guiBlueButton").style.visibility = ""; 223 | document.getElementById("guiBlueButton").innerHTML = blueText; 224 | document.getElementById("guiBlueButton").style.right = bluePos + "px"; 225 | } 226 | if (returnText == null){ 227 | document.getElementById("guiReturnButton").style.visibility = "hidden"; 228 | document.getElementById("guiReturnButton").innerHTML = null; 229 | } else { 230 | document.getElementById("guiReturnButton").style.visibility = ""; 231 | document.getElementById("guiReturnButton").innerHTML = returnText; 232 | document.getElementById("guiReturnButton").style.right = returnPos + "px"; 233 | } 234 | }; 235 | 236 | -------------------------------------------------------------------------------- /app/javascript/Gui/GuiImagePlayer/GuiImagePlayer.js: -------------------------------------------------------------------------------- 1 | var GuiImagePlayer = { 2 | ImageViewer : null, 3 | newItemData : null, 4 | 5 | Timeout : null, 6 | infoTimer : null, 7 | Paused : false, 8 | 9 | overlayFormat : 0, // 0 - date, 1 - date:time, 2 - off 10 | 11 | photos : [], 12 | 13 | images : [], 14 | overlay : [], 15 | imageIdx : 0, // Image index 16 | effectIdx : 0, // Transition effect index 17 | effectNames : ['FADE1', 'FADE2', 'BLIND', 'SPIRAL','CHECKER', 'LINEAR', 'STAIRS', 'WIPE', 'RANDOM'] 18 | } 19 | 20 | //ImageViewer.destroy doesn't work. Set it to null instead. 21 | GuiImagePlayer.kill = function() { 22 | if (this.ImageViewer != null) { 23 | this.ImageViewer = null; 24 | } 25 | } 26 | 27 | GuiImagePlayer.start = function(ItemData,selectedItem,isPhotoCollection) { 28 | alert("Page Enter : GuiImagePlayer"); 29 | 30 | //Show colour buttons on screen for a few seconds when a slideshow starts. 31 | document.getElementById("GuiImagePlayer_ScreensaverOverlay").style.visibility="hidden"; 32 | document.getElementById("guiButtonShade").style.visibility = ""; 33 | GuiHelper.setControlButtons("Favourite","Date/Time","Help",GuiMusicPlayer.Status == "PLAYING" || GuiMusicPlayer.Status == "PAUSED" ? "Music" : null,"Return"); 34 | this.infoTimer = setTimeout(function(){ 35 | GuiHelper.setControlButtons(null,null,null,null,null); 36 | document.getElementById("Clock").style.visibility = "hidden"; 37 | document.getElementById("guiButtonShade").style.visibility = "hidden"; 38 | document.getElementById("GuiImagePlayer_ScreensaverOverlay").style.visibility=""; 39 | }, 6000); 40 | 41 | //Turn off screensaver 42 | Support.screensaverOff(); 43 | 44 | var url = ""; 45 | if (isPhotoCollection) { 46 | url = Server.getChildItemsURL(ItemData.Items[selectedItem].Id,"&Recursive=true&SortBy=Random&SortOrder=Ascending&IncludeItemTypes=Photo&fields=SortName,Overview&Limit=2500"); 47 | } else { 48 | url = Server.getChildItemsURL(ItemData.Items[selectedItem].ParentId,"&SortBy=SortName&SortOrder=Ascending&IncludeItemTypes=Photo&fields=SortName,Overview&Limit=2500"); 49 | } 50 | 51 | var result = Server.getContent(url); 52 | if (result == null) { return; } 53 | this.newItemData = result; //Misleading I know! 54 | 55 | Support.styleSubtitles("GuiImagePlayer_ScreensaverOverlay") 56 | 57 | //Create ARRAY of all URL's! 58 | //Order from starting selectedItem! 59 | imageIdx = 0; 60 | for (var index = 0; index < result.Items.length; index++) { 61 | //Dont use server function here to prevent these large images caching! 62 | var temp = Server.getServerAddr() + "/Items/"+ this.newItemData.Items[index].Id +"/Images/Primary/0?maxwidth=1920&maxheight=1080&quality=90"; 63 | this.images.push(temp); 64 | 65 | if (this.newItemData.Items[index].PremiereDate !== undefined) { 66 | this.overlay.push(Support.formatDateTime(this.newItemData.Items[index].PremiereDate,1)) 67 | } else { 68 | this.overlay.push(""); //Need to push something to keep indexes matched up! 69 | } 70 | if (result.Items[index].Id == ItemData.Items[selectedItem].Id) { 71 | this.imageIdx = index; 72 | } 73 | } 74 | 75 | //Initialte new instance, set Frame Area & Set Notifications 76 | this.ImageViewer = new CImageViewer('Common ImageViewer'); 77 | this.ImageViewer.setFrameArea(0, 0, Main.width, Main.height); 78 | 79 | this.ImageViewer.setOnNetworkError(function() { 80 | GuiNotifications.setNotification("Network Error"); 81 | }); 82 | 83 | this.ImageViewer.setOnRenderError(function() { 84 | GuiNotifications.setNotification("Render Error"); 85 | }); 86 | 87 | 88 | //Set Focus for Key Events 89 | document.getElementById("GuiImagePlayer").focus(); 90 | 91 | //Start Slide Show 92 | this.ImageViewer.show(); 93 | this.setSlideshowMode(); 94 | //this.setNormalMode(); 95 | } 96 | 97 | // Set normal mode 98 | // You can play images on the area you set. 99 | GuiImagePlayer.setNormalMode = function() { 100 | 101 | sf.service.ImageViewer.setPosition({ 102 | left: 0, 103 | top: 0, 104 | width: 1920, 105 | height: 1080, 106 | }); 107 | 108 | sf.service.ImageViewer.show(); 109 | 110 | for (var i=0; i < this.newItemData.Items.length; i++){ 111 | //Dont use server function here to prevent these large images caching! 112 | var ImageUrl = Server.getServerAddr() + "/Items/"+ this.newItemData.Items[i].Id +"/Images/Primary/0?maxwidth=1920&maxheight=1080&quality=90"; 113 | this.photos[i] = { 114 | url: ImageUrl, 115 | width: 1920, 116 | height: 1080, 117 | filename: this.newItemData.Items[i].name, 118 | date: '2011/06/24' 119 | } 120 | } 121 | 122 | // Draw the image in the specified area defined by "setPosition" function. 123 | sf.service.ImageViewer.draw(this.photos[0]); 124 | 125 | 126 | //this.ImageViewer.endSlideshow(); 127 | //playImage(); 128 | } 129 | 130 | // Set Slideshow mode 131 | // You can use Transtion effect 132 | GuiImagePlayer.setSlideshowMode = function() { 133 | this.ImageViewer.startSlideshow(); 134 | this.ImageViewer.setOnBufferingComplete(function(){ 135 | GuiImagePlayer.ImageViewer.showNow(); 136 | }); 137 | this.ImageViewer.setOnRenderingComplete(function(){ 138 | clearTimeout(GuiImagePlayer.Timeout); 139 | Support.setImagePlayerOverlay(GuiImagePlayer.overlay[GuiImagePlayer.imageIdx], GuiImagePlayer.overlayFormat); 140 | GuiImagePlayer.Timeout = setTimeout(function(){ 141 | if (GuiImagePlayer.Paused == false) { 142 | GuiImagePlayer.imageIdx = GuiImagePlayer.imageIdx+1; 143 | if (GuiImagePlayer.imageIdx >= GuiImagePlayer.newItemData.Items.length ) { 144 | GuiImagePlayer.imageIdx = 0; 145 | } 146 | GuiImagePlayer.prepImage(GuiImagePlayer.imageIdx); 147 | } 148 | }, File.getUserProperty("ImagePlayerImageTime")); 149 | }); 150 | 151 | this.ImageViewer.stop(); 152 | this.playImage(); 153 | } 154 | 155 | //Prepare next image 156 | GuiImagePlayer.prepImage = function(imageIdx) { 157 | this.ImageViewer.prepareNext(GuiImagePlayer.images[imageIdx], this.ImageViewer.Effect.FADE1); 158 | } 159 | 160 | // Play image - only called once in slideshow! 161 | //SS calls play -> BufferComplete, then the showNow will call RendComplete which starts timer for next image 162 | GuiImagePlayer.playImage = function() { 163 | var url = GuiImagePlayer.images[GuiImagePlayer.imageIdx]; 164 | GuiImagePlayer.ImageViewer.play(url, 1920, 1080); 165 | } 166 | 167 | 168 | GuiImagePlayer.keyDown = function() { 169 | var keyCode = event.keyCode; 170 | alert("Key pressed: " + keyCode); 171 | 172 | if (document.getElementById("Notifications").style.visibility == "") { 173 | document.getElementById("Notifications").style.visibility = "hidden"; 174 | document.getElementById("NotificationText").innerHTML = ""; 175 | widgetAPI.blockNavigation(event); 176 | //Change keycode so it does nothing! 177 | keyCode = "VOID"; 178 | } 179 | 180 | switch(keyCode){ 181 | case tvKey.KEY_STOP: 182 | case tvKey.KEY_RETURN: 183 | alert("RETURN"); 184 | clearTimeout(this.infoTimer); 185 | clearTimeout(this.Timeout); 186 | this.Timeout = null; 187 | this.images = []; 188 | this.overlay = []; 189 | document.getElementById("GuiImagePlayer_ScreensaverOverlay").innerHTML = ""; 190 | document.getElementById("guiButtonShade").style.visibility = "hidden"; 191 | document.getElementById("Clock").style.visibility = ""; 192 | this.ImageViewer.endSlideshow(); 193 | this.ImageViewer.hide(); 194 | widgetAPI.blockNavigation(event); 195 | GuiImagePlayer.kill(); 196 | 197 | //Turn On Screensaver 198 | Support.screensaverOn(); 199 | Support.screensaver(); 200 | 201 | Support.processReturnURLHistory(); 202 | break; 203 | case tvKey.KEY_RIGHT: 204 | alert("RIGHT"); 205 | this.imageIdx++; 206 | if (this.imageIdx == this.images.length) { 207 | this.imageIdx = 0; 208 | } 209 | GuiImagePlayer.prepImage(GuiImagePlayer.imageIdx); 210 | break; 211 | case tvKey.KEY_LEFT: 212 | alert("LEFT"); 213 | this.imageIdx--; 214 | if (this.imageIdx < 0) { 215 | this.imageIdx = this.images.length-1; 216 | } 217 | GuiImagePlayer.prepImage(GuiImagePlayer.imageIdx); 218 | break; 219 | case tvKey.KEY_PAUSE: 220 | alert("PAUSE") 221 | this.Paused = true 222 | break; 223 | case tvKey.KEY_PLAY: 224 | alert("PLAY") 225 | this.Paused = false 226 | GuiImagePlayer.prepImage(GuiImagePlayer.imageIdx); 227 | break; 228 | case tvKey.KEY_RED: 229 | if (this.newItemData.Items[this.imageIdx].UserData.IsFavorite == true) { 230 | Server.deleteFavourite(this.newItemData.Items[this.imageIdx].Id); 231 | this.newItemData.Items[this.imageIdx].UserData.IsFavorite = false; 232 | GuiNotifications.setNotification ("Item has been removed from
favourites","Favourites"); 233 | } else { 234 | Server.setFavourite(this.newItemData.Items[this.imageIdx].Id); 235 | this.newItemData.Items[this.imageIdx].UserData.IsFavorite = true; 236 | GuiNotifications.setNotification ("Item has been added to
favourites","Favourites"); 237 | } 238 | break; 239 | case tvKey.KEY_GREEN: 240 | if (this.overlayFormat == 2) { 241 | this.overlayFormat = 0; 242 | } else { 243 | this.overlayFormat = this.overlayFormat + 1; 244 | } 245 | Support.setImagePlayerOverlay(this.overlay[this.imageIdx], this.overlayFormat); 246 | break; 247 | case tvKey.KEY_YELLOW: 248 | GuiHelper.toggleHelp("GuiImagePlayer"); 249 | break; 250 | case tvKey.KEY_BLUE: 251 | GuiMusicPlayer.showMusicPlayer("GuiImagePlayer"); 252 | break; 253 | } 254 | } 255 | 256 | -------------------------------------------------------------------------------- /app/javascript/Gui/GuiPlayer/GuiPlayer_Transcoding.js: -------------------------------------------------------------------------------- 1 | /* 2 | Render Error 1 : Unsupported container 3 | Render Error 2 : Unsupported video codec 4 | Render Error 3 : Unsupported audio codec 5 | Render Error 4 : Unsupported video resolution 6 | Render Error 6 : Corrupt Stream 7 | */ 8 | 9 | var GuiPlayer_Transcoding = { 10 | //File Information 11 | MediaSource : null, 12 | videoIndex : 0, 13 | audioIndex : 0, 14 | 15 | //Bitrate check 16 | bitRateToUse : null, 17 | 18 | //Boolean that conclude if all Video or All Audio elements will play without transcode 19 | isVideo : true, 20 | isAudio : true, 21 | 22 | //All Video Elements 23 | isCodec : null, 24 | isResolution : null, 25 | isContainer : null, 26 | isBitRate : null, 27 | isLevel : null, 28 | isFrameRate : null, 29 | isProfile : null, 30 | 31 | //All Audio elements 32 | isAudioCodec : null, 33 | isAudioContainer : null, 34 | isAudioChannel : null 35 | } 36 | 37 | //-------------------------------------------------------------------------------------- 38 | GuiPlayer_Transcoding.start = function(showId, MediaSource,MediaSourceIndex, videoIndex, audioIndex, isFirstAudioIndex, subtitleIndex) { 39 | //Set Class Vars 40 | this.MediaSource = MediaSource; 41 | this.videoIndex = videoIndex; 42 | this.audioIndex = audioIndex; 43 | 44 | //Check Video & Audio Compatibility 45 | this.checkCodec(videoIndex); 46 | this.checkAudioCodec(audioIndex); 47 | 48 | var streamparams = ""; 49 | var transcodeStatus = ""; 50 | 51 | //If audiocheck failed convert to AAC OR AC3 depending on setting 52 | //If audiocheck ok convert to AAC or dont convert & leave as original codec 53 | 54 | var fileAudioCodec = this.MediaSource.MediaStreams[this.audioIndex].Codec.toLowerCase(); 55 | var streamAudioCodec = "aac"; //Default, supported by all tv's (?) 56 | var convertAACtoDolby = false; 57 | if (File.getTVProperty("Dolby") && File.getTVProperty("AACtoDolby") && fileAudioCodec == "aac") { 58 | convertAACtoDolby = true; 59 | } 60 | if (this.isAudio == false) { 61 | streamAudioCodec = (File.getTVProperty("Dolby") && File.getTVProperty("AACtoDolby")) ? "ac3" : "aac"; 62 | } else { 63 | streamAudioCodec = (File.getTVProperty("Dolby") && File.getTVProperty("AACtoDolby") && fileAudioCodec == "aac") ? "ac3" : "aac"; 64 | } 65 | if (this.isVideo && this.isAudio && convertAACtoDolby == false) { 66 | if (isFirstAudioIndex == true) { 67 | transcodeStatus = "Direct Play"; 68 | streamparams = '/Stream.'+this.MediaSource.Container+'?static=true&MediaSourceId='+this.MediaSource.Id + '&api_key=' + Server.getAuthToken(); 69 | } else { 70 | transcodeStatus = "Stream Copy - Audio Not First Track"; 71 | streamparams = '/Stream.ts?VideoStreamIndex='+this.videoIndex+'&AudioStreamIndex='+this.audioIndex+'&VideoCodec=copy&AudioCodec='+ streamAudioCodec +'&MediaSourceId='+this.MediaSource.Id + '&api_key=' + Server.getAuthToken(); 72 | } 73 | } else if (this.isVideo == false) { 74 | transcodeStatus = "Transcoding Audio & Video"; 75 | streamparams = '/Stream.ts?VideoStreamIndex='+this.videoIndex+'&AudioStreamIndex='+this.audioIndex+'&VideoCodec=h264&Profile=high&Level=41&MaxVideoBitDepth=8&MaxWidth=1920&VideoBitrate='+this.bitRateToUse+'&AudioCodec=' + streamAudioCodec +'&AudioBitrate=360000&MaxAudioChannels=6&MediaSourceId='+this.MediaSource.Id + '&api_key=' + Server.getAuthToken(); 76 | } else if (this.isVideo == true && (this.isAudio == false || convertAACtoDolby == true)) { 77 | transcodeStatus = "Transcoding Audio"; 78 | streamparams = '/Stream.ts?VideoStreamIndex='+this.videoIndex+'&AudioStreamIndex='+this.audioIndex+'&VideoCodec=copy&AudioCodec='+ streamAudioCodec +'&audioBitrate=360000&MaxAudioChannels=6&MediaSourceId='+this.MediaSource.Id + '&api_key=' + Server.getAuthToken(); 79 | } 80 | var url = Server.getServerAddr() + '/Videos/' + showId + streamparams + '&DeviceId='+Server.getDeviceID(); 81 | FileLog.write("Video : Transcode Status : " + transcodeStatus); 82 | FileLog.write("Video : URL : " + url); 83 | 84 | //Return results to Versions 85 | //MediaSourceId,Url,transcodeStatus,videoIndex,audioIndex 86 | return [MediaSourceIndex,url,transcodeStatus,videoIndex,audioIndex,subtitleIndex]; 87 | } 88 | 89 | GuiPlayer_Transcoding.checkCodec = function() { 90 | var codec = this.MediaSource.MediaStreams[this.videoIndex].Codec.toLowerCase(); 91 | var codecParams = GuiPlayer_TranscodeParams.getParameters(codec,this.MediaSource.MediaStreams[this.videoIndex].Width); 92 | 93 | this.isCodec = codecParams[0]; 94 | this.isContainer = this.checkContainer(codecParams[1]); 95 | this.isResolution = this.checkResolution(codecParams[2]); 96 | this.isBitRate = this.checkBitRate(codecParams[3]); 97 | this.isFrameRate = this.checkFrameRate(codecParams[4]); 98 | this.isLevel = this.checkLevel(codecParams[5]); 99 | this.isProfile = this.checkProfile(codecParams[6]); 100 | 101 | //Results 102 | FileLog.write("Video : Video File Analysis Results"); 103 | FileLog.write("Video : Codec Compatibility: " + this.isCodec + " : " + this.MediaSource.MediaStreams[this.videoIndex].Codec); 104 | FileLog.write("Video : Container Compatibility: " + this.isContainer + " : " + this.MediaSource.Container); 105 | FileLog.write("Video : Resolution Compatibility: " + this.isResolution + " : " +this.MediaSource.MediaStreams[this.videoIndex].Width + "x" + this.MediaSource.MediaStreams[this.videoIndex].Height); 106 | FileLog.write("Video : BitRate Compatibility: " + this.isBitRate + " : " + this.MediaSource.MediaStreams[this.videoIndex].BitRate + " : " + this.bitRateToUse); 107 | FileLog.write("Video : FrameRate Compatibility: " + this.isFrameRate + " : " + this.MediaSource.MediaStreams[this.videoIndex].AverageFrameRate); 108 | FileLog.write("Video : Level Compatibility: " + this.isLevel + " : " + this.MediaSource.MediaStreams[this.videoIndex].Level); 109 | FileLog.write("Video : Profile Compatibility: " + this.isProfile + " : " + this.MediaSource.MediaStreams[this.videoIndex].Profile); 110 | 111 | //Put it all together 112 | if (this.isCodec && this.isContainer && this.isResolution && this.isBitRate && this.isFrameRate && this.isLevel && this.isProfile) { // 113 | this.isVideo = true; 114 | } else { 115 | this.isVideo = false; 116 | } 117 | } 118 | 119 | GuiPlayer_Transcoding.checkAudioCodec = function() { 120 | var audiocodec = this.MediaSource.MediaStreams[this.audioIndex].Codec.toLowerCase(); 121 | var audiocodecParams = GuiPlayer_TranscodeParams.getAudioParameters(audiocodec); 122 | 123 | this.isAudioCodec = audiocodecParams[0]; 124 | this.isAudioContainer = this.checkContainer(audiocodecParams[1]); 125 | this.isAudioChannel = this.checkAudioChannels(audiocodecParams[2]); 126 | 127 | //Results 128 | FileLog.write("Video : Audio File Analysis Results"); 129 | FileLog.write("Video : Codec Compatibility: " + this.isAudioCodec + " : " + this.MediaSource.MediaStreams[this.audioIndex].Codec); 130 | FileLog.write("Video : Container Compatibility: " + this.isAudioContainer + " : " + this.MediaSource.Container); 131 | FileLog.write("Video : Channel Compatibility: " + this.isAudioChannel + " : " + this.MediaSource.MediaStreams[this.audioIndex].Channels); 132 | 133 | //Put it all together 134 | if (this.isAudioCodec && this.isAudioChannel) { 135 | this.isAudio = true; 136 | } else { 137 | this.isAudio = false; 138 | } 139 | } 140 | 141 | GuiPlayer_Transcoding.checkAudioChannels = function(maxChannels) { 142 | if (maxChannels == null) { 143 | return false; 144 | } else { 145 | if (this.MediaSource.MediaStreams[this.audioIndex].Channels <= maxChannels) { 146 | return true; 147 | } else { 148 | return false; 149 | } 150 | } 151 | } 152 | 153 | GuiPlayer_Transcoding.checkResolution = function(maxResolution) { 154 | if (maxResolution == null) { 155 | return false; 156 | } else if (this.MediaSource.MediaStreams[this.videoIndex].Width <= maxResolution[0] && this.MediaSource.MediaStreams[this.videoIndex].Height <= maxResolution[1]) { 157 | return true; 158 | } else { 159 | return false; 160 | } 161 | } 162 | 163 | GuiPlayer_Transcoding.checkContainer = function(supportedContainers) { 164 | if (supportedContainers == null) { 165 | return false 166 | } else { 167 | var isContainer = false; 168 | for (var index = 0; index < supportedContainers.length; index++) { 169 | if (this.MediaSource.Container.toLowerCase() == supportedContainers[index]) { 170 | isContainer = true; 171 | break; 172 | } 173 | } 174 | return isContainer; 175 | } 176 | } 177 | 178 | GuiPlayer_Transcoding.checkBitRate = function(maxBitRate) { 179 | //Get Bitrate from Settings File 180 | var maxBitRateSetting = File.getTVProperty("Bitrate")*1024*1024; 181 | 182 | // MCB - Ignore bitrate in file 183 | this.bitRateToUse = maxBitRateSetting; 184 | 185 | if (this.MediaSource.MediaStreams[this.videoIndex].BitRate > maxBitRateSetting) { 186 | return false; 187 | } else { 188 | return true; 189 | } 190 | } 191 | 192 | GuiPlayer_Transcoding.checkFrameRate = function(maxFrameRate) { 193 | if (maxFrameRate == null) { 194 | return false; 195 | } else if (this.MediaSource.MediaStreams[this.videoIndex].AverageFrameRate <= maxFrameRate) { 196 | return true; 197 | } else { 198 | return false; 199 | } 200 | } 201 | 202 | GuiPlayer_Transcoding.checkLevel = function(maxLevel) { 203 | var level = this.MediaSource.MediaStreams[this.videoIndex].Level; 204 | if (maxLevel == null) { 205 | return false; 206 | } if (maxLevel == true) { 207 | return true; 208 | } else { 209 | var level = this.MediaSource.MediaStreams[this.videoIndex].Level; 210 | level = (level < 10) ? level * 10 : level; //If only 1 long, multiply by 10 to make it correct! 211 | if (level <= maxLevel && level >= 0) { 212 | return true; 213 | } else { 214 | return false; 215 | } 216 | } 217 | } 218 | 219 | GuiPlayer_Transcoding.checkProfile = function(supportedProfiles) { 220 | if (supportedProfiles == null) { 221 | return false; 222 | } if (supportedProfiles == true) { 223 | return true; 224 | } else { 225 | var profile = false; 226 | for (var index = 0; index < supportedProfiles.length; index++) { 227 | if (this.MediaSource.MediaStreams[this.videoIndex].Profile == supportedProfiles[index]) { 228 | profile = true; 229 | break; 230 | } 231 | } 232 | return profile; 233 | } 234 | } -------------------------------------------------------------------------------- /app/javascript/Gui/GuiPage_CastMember.js: -------------------------------------------------------------------------------- 1 | var GuiPage_CastMember = { 2 | CastData : null, 3 | ItemData : null, 4 | 5 | selectedItem : 0, 6 | topLeftItem : 0, 7 | MAXCOLUMNCOUNT : 9, 8 | MAXROWCOUNT : 1, 9 | } 10 | 11 | GuiPage_CastMember.getMaxDisplay = function() { 12 | return this.MAXCOLUMNCOUNT * this.MAXROWCOUNT; 13 | } 14 | 15 | GuiPage_CastMember.start = function(title,url,selectedItem,topLeftItem) { 16 | alert("Page Enter : GuiPage_CastMember"); 17 | GuiHelper.setControlButtons(null,null,null,GuiMusicPlayer.Status == "PLAYING" || GuiMusicPlayer.Status == "PAUSED" ? "Music" : null,"Return"); 18 | 19 | //Save Start Params 20 | this.startParams = [title,url]; 21 | 22 | //Reset Values 23 | this.selectedItem = selectedItem; 24 | this.topLeftItem = topLeftItem; 25 | 26 | //Load Data 27 | this.CastData = Server.getContent(url); 28 | if (this.CastData == null) { return; } 29 | var Itemurl = Server.getItemTypeURL("&SortBy=SortName&SortOrder=Ascending&Recursive=true&Limit=100&ExcludeLocationTypes=Virtual&fields=ParentId&Person=" + this.CastData.Name.replace(/ /g, '+')); 30 | this.ItemData = Server.getContent(Itemurl); 31 | if (this.ItemData == null) { Support.processReturnURLHistory(); } 32 | 33 | document.getElementById("pageContent").className = ""; 34 | document.getElementById("pageContent").innerHTML = "
\ 35 |
\ 36 |
\ 37 |
\ 38 |
"; 39 | document.getElementById("Counter").innerHTML = "1/1"; 40 | 41 | //Add cast member name and image. 42 | document.getElementById("GuiPage_CastMember_Name").innerHTML = this.CastData.Name; 43 | var imgsrc = Server.getImageURL(this.CastData.Id,"Primary",350,480,0,false,0); 44 | document.getElementById("GuiPage_CastMember_Poster").style.backgroundImage = "url("+imgsrc +")"; 45 | 46 | var detailsHtml = ""; 47 | if (this.CastData.PremiereDate && Main.getModelYear() != "D"){ 48 | var birthday = new Date(this.CastData.PremiereDate); 49 | detailsHtml += "Born: "+birthday.toDateString() + "

"; 50 | } 51 | if (this.CastData.ProductionLocations){ 52 | var birthPlace = this.CastData.ProductionLocations; 53 | if (birthPlace != ""){ 54 | detailsHtml += "Born in "+this.CastData.ProductionLocations + "

"; 55 | } 56 | } 57 | if (this.CastData.EndDate && Main.getModelYear() != "D"){ 58 | var deathday = new Date(this.CastData.EndDate); 59 | detailsHtml += "Died: "+deathday.toDateString() + "

"; 60 | } 61 | document.getElementById("GuiPage_CastMember_Details").innerHTML = detailsHtml; 62 | 63 | //Person bio 64 | var bio = ""; 65 | if (this.CastData.Overview){ 66 | bio += this.CastData.Overview; 67 | } 68 | document.getElementById("GuiPage_CastMember_Bio").innerHTML = bio; 69 | 70 | //Set Overview Scroller 71 | Support.scrollingText("GuiPage_CastMember_Bio"); 72 | 73 | if (this.ItemData.Items.length > 0) { 74 | //Display first 12 series 75 | this.updateDisplayedItems(); 76 | 77 | //Update Selected Collection CSS 78 | this.updateSelectedItems(); 79 | 80 | //Set Focus for Key Events 81 | document.getElementById("GuiPage_CastMember").focus(); 82 | } else { 83 | //Cannot happen as link can only be generated from a Cast member - thus at minimum it will return 1 result (itself) 84 | document.getElementById("GuiPage_CastMember").focus(); 85 | } 86 | } 87 | 88 | GuiPage_CastMember.updateDisplayedItems = function() { 89 | var htmlToAdd = ""; 90 | var htmlToAdd2 =""; 91 | for (var index = this.topLeftItem;index < Math.min(this.topLeftItem + this.getMaxDisplay(),this.ItemData.Items.length); index++) { 92 | var imgsrc = "images/menu/Play-46x37.png"; 93 | if (this.ItemData.Items[index].Type == "Episode"){ 94 | if (this.ItemData.Items[index].ImageTags.Primary) { 95 | imgsrc = Server.getImageURL(this.ItemData.Items[index].Id,"Primary",180,100,null,null,null,index); 96 | } 97 | } else { 98 | if (this.ItemData.Items[index].ImageTags.Thumb) { 99 | imgsrc = Server.getImageURL(this.ItemData.Items[index].Id,"Thumb",180,100,null,null,null,index); 100 | } else if (this.ItemData.Items[index].ImageTags.Primary) { 101 | imgsrc = Server.getImageURL(this.ItemData.Items[index].Id,"Primary",180,100,null,null,null,index); 102 | } 103 | } 104 | htmlToAdd += "
"+this.ItemData.Items[index].Name+"
"; 105 | } 106 | document.getElementById("GuiPage_CastMember_List").innerHTML = htmlToAdd; 107 | } 108 | 109 | //Function sets CSS Properties so show which user is selected 110 | GuiPage_CastMember.updateSelectedItems = function () { 111 | for (var index = this.topLeftItem; index < Math.min(this.topLeftItem + this.getMaxDisplay(),this.ItemData.Items.length); index++){ 112 | if (index == this.selectedItem) { 113 | document.getElementById(this.ItemData.Items[index].Id).className = "GuiPage_CastMember_ListSingle highlight"+Main.highlightColour+"Background"; 114 | //Set Background based on Type: 115 | switch (this.ItemData.Items[index].Type) { 116 | case "Episode": 117 | if (this.ItemData.Items[index].ParentBackdropItemId) { 118 | var imgsrc = Server.getBackgroundImageURL(this.ItemData.Items[index].ParentBackdropItemId,"Backdrop",Main.backdropWidth,Main.backdropHeight,0,false,0,this.ItemData.Items[index].ParentBackdropImageTags.length); 119 | Support.fadeImage(imgsrc); 120 | } 121 | break; 122 | case "Movie": 123 | case "Series": 124 | if (this.ItemData.Items[index].BackdropImageTags.length > 0) { 125 | var imgsrc = Server.getBackgroundImageURL(this.ItemData.Items[index].Id,"Backdrop",Main.backdropWidth,Main.backdropHeight,0,false,0,this.ItemData.Items[index].BackdropImageTags.length); 126 | Support.fadeImage(imgsrc); 127 | } 128 | break; 129 | case "Photo": 130 | if (this.ItemData.Items[index].ImageTags.Primary.length > 0) { 131 | var imgsrc = Server.getImageURL(this.ItemData.Items[index].Id,"Primary",Main.backdropWidth,Main.backdropHeight,0,false,0); 132 | Support.fadeImage(imgsrc); 133 | } 134 | break; 135 | default: 136 | break; 137 | } 138 | 139 | } else { 140 | document.getElementById(this.ItemData.Items[index].Id).className = "GuiPage_CastMember_ListSingle"; 141 | } 142 | } 143 | document.getElementById("Counter").innerHTML = (this.selectedItem + 1) + "/" + this.ItemData.Items.length; 144 | } 145 | 146 | GuiPage_CastMember.keyDown = function() 147 | { 148 | var keyCode = event.keyCode; 149 | alert("Key pressed: " + keyCode); 150 | 151 | if (document.getElementById("Notifications").style.visibility == "") { 152 | document.getElementById("Notifications").style.visibility = "hidden"; 153 | document.getElementById("NotificationText").innerHTML = ""; 154 | widgetAPI.blockNavigation(event); 155 | //Change keycode so it does nothing! 156 | keyCode = "VOID"; 157 | } 158 | 159 | //Update Screensaver Timer 160 | Support.screensaver(); 161 | 162 | //If screensaver is running 163 | if (Main.getIsScreensaverRunning()) { 164 | //Update Main.js isScreensaverRunning - Sets to True 165 | Main.setIsScreensaverRunning(); 166 | 167 | //End Screensaver 168 | GuiImagePlayer_Screensaver.stopScreensaver(); 169 | 170 | //Change keycode so it does nothing! 171 | keyCode = "VOID"; 172 | } 173 | 174 | switch(keyCode) 175 | { 176 | case tvKey.KEY_LEFT: 177 | alert("LEFT"); 178 | this.openMenu(); 179 | break; 180 | case tvKey.KEY_UP: 181 | alert("UP"); 182 | this.processUpKey(); 183 | break; 184 | case tvKey.KEY_DOWN: 185 | alert("RIGHT"); 186 | this.processDownKey(); 187 | break; 188 | case tvKey.KEY_RETURN: 189 | alert("RETURN"); 190 | widgetAPI.blockNavigation(event); 191 | Support.processReturnURLHistory(); 192 | break; 193 | case tvKey.KEY_ENTER: 194 | case tvKey.KEY_PANEL_ENTER: 195 | alert("ENTER"); 196 | this.processSelectedItem(); 197 | break; 198 | case tvKey.KEY_PLAY: 199 | this.playSelectedItem(); 200 | break; 201 | case tvKey.KEY_YELLOW: 202 | //Favourites 203 | break; 204 | case tvKey.KEY_BLUE: 205 | GuiMusicPlayer.showMusicPlayer("GuiPage_CastMember",this.ItemData.Items[this.selectedItem].Id,document.getElementById(this.ItemData.Items[this.selectedItem].Id).className); 206 | break; 207 | case tvKey.KEY_TOOLS: 208 | widgetAPI.blockNavigation(event); 209 | Support.updateURLHistory("GuiPage_CastMember",this.startParams[0],this.startParams[1],null,null,this.selectedItem,this.topLeftItem,null); 210 | document.getElementById(this.ItemData.Items[this.selectedItem].Id).className = "SeasonTitle"; 211 | GuiMainMenu.requested("GuiPage_CastMember",this.ItemData.Items[this.selectedItem].Id,"EpisodeListSingle highlight"+Main.highlightColour+"Background"); 212 | break; 213 | case tvKey.KEY_EXIT: 214 | alert ("EXIT KEY"); 215 | widgetAPI.sendExitEvent(); 216 | break; 217 | } 218 | } 219 | 220 | GuiPage_CastMember.openMenu = function() { 221 | Support.updateURLHistory("GuiPage_CastMember",null,null,null,null,null,null,null); 222 | GuiMainMenu.requested("GuiPage_CastMember",null); 223 | } 224 | 225 | GuiPage_CastMember.processSelectedItem = function() { 226 | Support.processSelectedItem("GuiPage_CastMember",this.ItemData,this.startParams,this.selectedItem,this.topLeftItem,null,null) 227 | } 228 | 229 | GuiPage_CastMember.playSelectedItem = function () { 230 | if (this.ItemData.Items[this.selectedItem].MediaType == "Video") { 231 | Support.updateURLHistory("GuiPage_CastMember",this.startParams[0],this.startParams[1],null,null,this.selectedItem,this.topLeftItem,null); 232 | var url = Server.getItemInfoURL(this.ItemData.Items[this.selectedItem].Id); 233 | GuiPlayer.start("PLAY",url,this.ItemData.Items[this.selectedItem].UserData.PlaybackPositionTicks / 10000); 234 | } 235 | } 236 | 237 | GuiPage_CastMember.processUpKey = function() { 238 | this.selectedItem--; 239 | if (this.selectedItem < 0) { 240 | this.selectedItem = 0; 241 | } else { 242 | if (this.selectedItem < this.topLeftItem) { 243 | this.topLeftItem = this.selectedItem; 244 | if (this.topLeftItem < 0) { 245 | this.topLeftItem = 0; 246 | } 247 | this.updateDisplayedItems(); 248 | } 249 | this.updateSelectedItems(); 250 | } 251 | 252 | } 253 | 254 | GuiPage_CastMember.processDownKey = function() { 255 | this.selectedItem++; 256 | if (this.selectedItem >= this.ItemData.Items.length) { 257 | this.selectedItem--; 258 | } else { 259 | if (this.selectedItem >= this.topLeftItem+this.getMaxDisplay() ) { 260 | this.topLeftItem++; 261 | this.updateDisplayedItems(); 262 | } 263 | } 264 | this.updateSelectedItems(); 265 | } 266 | 267 | GuiPage_CastMember.returnFromMusicPlayer = function() { 268 | this.selectedItem = 0; 269 | this.updateDisplayedItems(); 270 | this.updateSelectedItems(); 271 | } -------------------------------------------------------------------------------- /app/javascript/Gui/GuiPage_AddToPlaylist.js: -------------------------------------------------------------------------------- 1 | var GuiPage_AddToPlaylist = { 2 | ItemData : null, 3 | ItemData2 : null, 4 | 5 | hasItemInPlaylist : [], 6 | 7 | selectedItem : 0, 8 | topLeftItem : 0, 9 | 10 | itemId : "", 11 | playedFromPage : "", 12 | mediaType : "", 13 | 14 | MAXCOLUMNCOUNT : 1, 15 | MAXROWCOUNT : 5 16 | } 17 | 18 | GuiPage_AddToPlaylist.onFocus = function() { 19 | GuiHelper.setControlButtons(null,null,null,GuiMusicPlayer.Status == "PLAYING" || GuiMusicPlayer.Status == "PAUSED" ? "Music" : null,"Return"); 20 | } 21 | 22 | GuiPage_AddToPlaylist.getMaxDisplay = function() { 23 | return this.MAXCOLUMNCOUNT * this.MAXROWCOUNT; 24 | } 25 | 26 | GuiPage_AddToPlaylist.start=function(itemId, playedFromPage, mediaType) { 27 | alert("Page Enter : GuiPage_AddToPlaylist"); 28 | 29 | //Update page called from 30 | this.playedFromPage = playedFromPage; 31 | this.mediaType = mediaType; 32 | this.selectedItem = 0; 33 | this.topLeftItem = 0; 34 | this.itemId = itemId; 35 | 36 | //Get data from Server 37 | var url = Server.getItemTypeURL("/SortBy=SortName&SortOrder=Ascending&IncludeItemTypes=Playlist&Recursive=true&MediaTypes=" + mediaType); 38 | this.ItemData = Server.getContent(url); 39 | if (this.ItemData == null) { Support.processReturnURLHistory(); } 40 | 41 | //Set window size based on item count 42 | if (this.ItemData.Items.length < 6){ 43 | document.getElementById("guiPlayListContainer").style.height = (this.ItemData.Items.length*40)+400 +"px"; 44 | } else { 45 | document.getElementById("guiPlayListContainer").style.height = "560px"; 46 | } 47 | 48 | //Create IME - Send it the name of the thing to focus. 49 | new GuiPage_AddToPlaylist_Input("guiPlayListNew"); 50 | 51 | if (this.ItemData.Items.length == 0) { 52 | document.getElementById("guiPlayListExisting").innerHTML = "
You have no existing "+ this.mediaType.toLowerCase() +" playlists.
"; 53 | Support.screensaverOff(); // Must turn off as not possible to catch keys! 54 | } else { 55 | for (var index = 0; index < this.ItemData.Items.length; index++) { 56 | url2 = Server.getCustomURL("/Playlists/" + this.ItemData.Items[index].Id+"/Items?format=json&userId="+Server.getUserID()); 57 | this.ItemData2 = Server.getContent(url2); 58 | if (this.ItemData2 == null) { return; } 59 | 60 | this.hasItemInPlaylist[index] = false; 61 | for (var index2 = 0; index2 < this.ItemData2.Items.length; index2++) { 62 | if (this.ItemData2.Items[index2].Id == itemId) { 63 | this.hasItemInPlaylist[index] = true; 64 | break; 65 | } 66 | } 67 | } 68 | 69 | this.updateDisplayedItems(); 70 | this.updateSelectedItems(); 71 | } 72 | 73 | //Display Playlist Div 74 | document.getElementById("guiPlayListContainer").style.visibility = ""; 75 | } 76 | 77 | GuiPage_AddToPlaylist.updateDisplayedItems = function() { 78 | var htmlToAdd = ""; 79 | for (var index = this.topLeftItem; index < Math.min(this.topLeftItem + this.getMaxDisplay(),this.ItemData.Items.length);index++) { 80 | var existsInPlaylist = (this.hasItemInPlaylist[index] == true) ? "Yes" : "No"; 81 | htmlToAdd += ""; 82 | } 83 | document.getElementById("guiPlayListExisting").innerHTML = htmlToAdd + "
PlaylistExists in Playlist
"+ this.ItemData.Items[index].Name + ""+existsInPlaylist+"
"; 84 | } 85 | 86 | GuiPage_AddToPlaylist.updateSelectedItems = function() { 87 | for (var index = this.topLeftItem; index < Math.min(this.topLeftItem + this.getMaxDisplay(),this.ItemData.Items.length);index++) { 88 | if (index == this.selectedItem) { 89 | document.getElementById(this.ItemData.Items[index].Id).style.color = "#27a436"; 90 | } else { 91 | document.getElementById(this.ItemData.Items[index].Id).style.color = "#f9f9f9"; 92 | } 93 | } 94 | } 95 | 96 | GuiPage_AddToPlaylist.keyDown = function() { 97 | var keyCode = event.keyCode; 98 | alert("Key pressed: " + keyCode); 99 | 100 | if (document.getElementById("Notifications").style.visibility == "") { 101 | document.getElementById("Notifications").style.visibility = "hidden"; 102 | document.getElementById("NotificationText").innerHTML = ""; 103 | widgetAPI.blockNavigation(event); 104 | //Change keycode so it does nothing! 105 | keyCode = "VOID"; 106 | } 107 | 108 | //Update Screensaver Timer 109 | Support.screensaver(); 110 | 111 | //If screensaver is running 112 | if (Main.getIsScreensaverRunning()) { 113 | //Update Main.js isScreensaverRunning - Sets to True 114 | Main.setIsScreensaverRunning(); 115 | 116 | //End Screensaver 117 | GuiImagePlayer_Screensaver.stopScreensaver(); 118 | 119 | //Change keycode so it does nothing! 120 | keyCode = "VOID"; 121 | } 122 | 123 | switch(keyCode) { 124 | case tvKey.KEY_UP: 125 | this.processUpKey(); 126 | break; 127 | case tvKey.KEY_DOWN: 128 | this.processDownKey(); 129 | break; 130 | case tvKey.KEY_ENTER: 131 | case tvKey.KEY_PANEL_ENTER: 132 | this.processSelectedItem(); 133 | break; 134 | case tvKey.KEY_RETURN: 135 | alert("RETURN"); 136 | widgetAPI.blockNavigation(event); 137 | document.getElementById("guiPlayListContainer").style.visibility = "hidden"; 138 | document.getElementById(this.playedFromPage).focus(); 139 | break; 140 | case tvKey.KEY_EXIT: 141 | alert ("EXIT KEY"); 142 | widgetAPI.sendExitEvent(); 143 | break; 144 | default: 145 | break; 146 | } 147 | } 148 | 149 | GuiPage_AddToPlaylist.processSelectedItem = function() { 150 | if (this.hasItemInPlaylist[this.selectedItem] == false) { 151 | //Send update to server 152 | Server.addToPlaylist(this.ItemData.Items[this.selectedItem].Id,this.itemId); 153 | 154 | //Don't get a refresh from server, assumes communication works. 155 | this.hasItemInPlaylist[this.selectedItem] = true; 156 | this.updateDisplayedItems(); 157 | this.updateSelectedItems(); 158 | document.getElementById("guiPlayListResult").innerHTML = "
The "+ this.mediaType.toLowerCase() +" was added to the playlist.
"; 159 | } else { 160 | return; 161 | } 162 | //Close 163 | setTimeout(function(){ 164 | document.getElementById("guiPlayListContainer").style.visibility = "hidden"; 165 | document.getElementById("guiPlayListResult").innerHTML = ""; 166 | document.getElementById(GuiPage_AddToPlaylist.playedFromPage).focus(); 167 | }, 2000); 168 | } 169 | 170 | GuiPage_AddToPlaylist.processUpKey = function() { 171 | this.selectedItem = this.selectedItem - this.MAXCOLUMNCOUNT; 172 | if (this.selectedItem < 0) { 173 | this.selectedItem = 0; 174 | } else { 175 | if (this.selectedItem < this.topLeftItem) { 176 | if (this.topLeftItem - this.MAXCOLUMNCOUNT < 0) { 177 | this.topLeftItem = 0; 178 | } else { 179 | this.topLeftItem = this.topLeftItem - this.MAXCOLUMNCOUNT; 180 | } 181 | this.updateDisplayedItems(); 182 | } 183 | this.updateSelectedItems(); 184 | } 185 | } 186 | 187 | GuiPage_AddToPlaylist.processDownKey = function() { 188 | if (this.selectedItem == this.ItemData.Items.length - 1) { 189 | document.getElementById(this.ItemData.Items[this.selectedItem].Id).style.color = "#f9f9f9"; 190 | Support.screensaverOff(); // Must turn off as not possible to catch keys! 191 | document.getElementById("guiPlayListNew").focus(); 192 | } else { 193 | this.selectedItem = this.selectedItem + this.MAXCOLUMNCOUNT; 194 | if (this.selectedItem >= this.ItemData.Items.length) { 195 | this.selectedItem = (this.ItemData.Items.length-1); 196 | if (this.selectedItem >= (this.topLeftItem + this.getMaxDisplay())) { 197 | this.topLeftItem = this.topLeftItem + this.getMaxDisplay(); 198 | this.updateDisplayedItems(); 199 | } 200 | } else { 201 | if (this.selectedItem >= (this.topLeftItem + this.getMaxDisplay())) { 202 | this.topLeftItem = this.topLeftItem + this.MAXCOLUMNCOUNT; 203 | this.updateDisplayedItems(); 204 | } 205 | } 206 | this.updateSelectedItems(); 207 | } 208 | } 209 | 210 | 211 | ////////////////////////////////////////////////////////////////// 212 | // Input method for entering new playlist name. // 213 | ////////////////////////////////////////////////////////////////// 214 | var GuiPage_AddToPlaylist_Input = function(id) { 215 | var imeReady = function(imeObject) { 216 | installFocusKeyCallbacks(); 217 | document.getElementById(id).focus(); 218 | } 219 | 220 | var ime = new IMEShell("guiPlayListNew", imeReady,this); 221 | ime.setKeypadPos(1360,180); 222 | ime.setKeypadChangeFunc('qwerty',onSwitchToQwerty); 223 | ime.setKeypadChangeFunc('12key',onSwitchTo12key); 224 | 225 | function onSwitchToQwerty(arg){ 226 | alert("IME selected:"+arg); 227 | document.getElementById("guiPlayListContainer").className = "playlistContainerQwerty"; 228 | } 229 | 230 | function onSwitchTo12key(arg){ 231 | alert("IME selected:"+arg); 232 | document.getElementById("guiPlayListContainer").className = "playlistContainer12key"; 233 | } 234 | 235 | var installFocusKeyCallbacks = function () { 236 | ime.setKeyFunc(tvKey.KEY_ENTER, function (keyCode) { 237 | alert("Enter key pressed"); 238 | 239 | var playlist = document.getElementById("guiPlayListNew").value; 240 | if (playlist == "") { 241 | document.getElementById("guiPlayListResult").innerHTML = "
Enter a playlist name or press Return to cancel.
"; 242 | setTimeout(function(){ 243 | document.getElementById("guiPlayListResult").innerHTML = ""; 244 | }, 3000); 245 | return; 246 | } 247 | ime.setString(""); 248 | 249 | //Check playlist name doesnt already exist! 250 | 251 | //Sent Server Request 252 | Server.createPlaylist(playlist,GuiPage_AddToPlaylist.itemId, GuiPage_AddToPlaylist.mediaType); 253 | 254 | document.getElementById("guiPlayListResult").innerHTML = "
The playlist was created.
"; 255 | 256 | //Close 257 | setTimeout(function(){ 258 | document.getElementById("guiPlayListContainer").style.visibility = "hidden"; 259 | document.getElementById("guiPlayListResult").innerHTML = ""; 260 | document.getElementById(GuiPage_AddToPlaylist.playedFromPage).focus(); 261 | }, 2000); 262 | 263 | //Reload page! 264 | //GuiPage_AddToPlaylist.start(GuiPage_AddToPlaylist.itemId,GuiPage_AddToPlaylist.playedFromPage,GuiPage_AddToPlaylist.mediaType); 265 | 266 | }); 267 | 268 | ime.setKeyFunc(tvKey.KEY_UP, function (keyCode) { 269 | Support.screensaver(); 270 | 271 | if (GuiPage_AddToPlaylist.ItemData.Items.length > 0 ) { 272 | GuiPage_AddToPlaylist.updateSelectedItems(); 273 | document.getElementById("GuiPage_AddToPlaylist").focus(); 274 | } 275 | }); 276 | 277 | ime.setKeyFunc(tvKey.KEY_RETURN, function (keyCode) { 278 | widgetAPI.blockNavigation(event); 279 | //Handle Return 280 | Support.screensaver(); 281 | document.getElementById("guiPlayListContainer").style.visibility = "hidden"; 282 | document.getElementById(GuiPage_AddToPlaylist.playedFromPage).focus(); 283 | }); 284 | 285 | ime.setKeyFunc(tvKey.KEY_EXIT, function (keyCode) { 286 | widgetAPI.sendExitEvent(); 287 | }); 288 | } 289 | } -------------------------------------------------------------------------------- /app/javascript/Gui/GuiMainMenu.js: -------------------------------------------------------------------------------- 1 | var GuiMainMenu = { 2 | menuItems : [], 3 | menuItemsHomePages : [], 4 | 5 | pageSelected : "", 6 | selectedDivId : 0, 7 | selectedDivClass : "", 8 | 9 | testModeCount : 0, 10 | testModeTimeout : null, 11 | 12 | isMusicPlaying : false, 13 | 14 | clockVar : null 15 | } 16 | 17 | GuiMainMenu.getSelectedMainMenuItem = function() { 18 | return this.selectedMainMenuItem; 19 | } 20 | 21 | //Entry Point from User Menu - ONLY RUN ONCE PER USER LOGIN 22 | GuiMainMenu.start = function() { 23 | //Generate Menu based on whether there is any of (Folders, TV, Movies, .....) 24 | this.menuItems.length = 0; 25 | this.menuItemsHomePages.length = 0; 26 | 27 | //Generate main menu items 28 | this.menuItemsHomePages = Support.generateTopMenu(); 29 | this.menuItems = Support.generateMainMenu(); 30 | 31 | //Get user details. 32 | //document.getElementById("menuUserName").innerHTML = "
"+Server.getUserName()+"

"; 33 | var userURL = Server.getServerAddr() + "/Users/" + Server.getUserID() + "?format=json&Fields=PrimaryImageTag"; 34 | var UserData = Server.getContent(userURL); 35 | if (UserData == null) { return; } 36 | 37 | //User Image 38 | if (UserData.PrimaryImageTag) { 39 | var imgsrc = Server.getImageURL(UserData.Id,"UsersPrimary",70,70,0,false,0); 40 | document.getElementById("menuUserImage").style.backgroundImage = "url(" + imgsrc + ")"; 41 | } else { 42 | document.getElementById("menuUserImage").style.backgroundImage = "url(images/loginusernoimage.png)"; 43 | } 44 | 45 | //Add menu entries 46 | var htmlToAdd = ""; 47 | for (var index = 0; index < this.menuItems.length;index++) { 48 | htmlToAdd += ""; 49 | } 50 | document.getElementById("menuItems").innerHTML = htmlToAdd; 51 | 52 | //Add settings and logout 53 | htmlToAdd = ""; 54 | this.menuItems.push("Search"); 55 | htmlToAdd += ""; 56 | this.menuItems.push("Settings"); 57 | htmlToAdd += ""; 58 | this.menuItems.push("Log_Out"); 59 | htmlToAdd += ""; 60 | document.getElementById("menuItems").innerHTML += htmlToAdd; 61 | 62 | //Turn On Screensaver 63 | Support.screensaverOn(); 64 | Support.screensaver(); 65 | 66 | //Validate and update home page URL's 67 | //Convert views in http format to viewnames for settings in versions <=2.1.3 68 | var url1 = File.getUserProperty("View1"); 69 | if (url1.substring(0,4) == "http") { 70 | alert("Converting View1"); 71 | File.setUserProperty("View1","TVNextUp"); 72 | File.setUserProperty("View1Name","Next Up"); 73 | } 74 | 75 | var url2 = File.getUserProperty("View2"); 76 | if (url2) { 77 | if (url2.substring(0,4) == "http") { 78 | alert("Converting View2"); 79 | File.setUserProperty("View2","LatestMovies"); 80 | File.setUserProperty("View2Name","Latest Movies"); 81 | } 82 | } 83 | 84 | //Initialise view URL's 85 | Support.initViewUrls(); 86 | 87 | //Set the page highlight colour 88 | Main.highlightColour = File.getUserProperty("HighlightColour"); 89 | 90 | //Load Home Page 91 | Support.processHomePageMenu("Home"); 92 | } 93 | 94 | //Entry Point when called from any page displaying the menu 95 | GuiMainMenu.requested = function(pageSelected, selectedDivId, selectedDivClass) { 96 | //Reset Menus 97 | this.selectedMainMenuItem = 0; 98 | this.selectedSubMenuItem = 0; 99 | 100 | //UnSelect Selected Item on whatever page is loaded 101 | this.pageSelected = pageSelected; 102 | this.selectedDivId = selectedDivId; 103 | 104 | //Unhighlights the page's selected content 105 | if (this.selectedDivId != null) { 106 | if (selectedDivClass === undefined) { 107 | this.selectedDivClass = "UNDEFINED"; 108 | } else { 109 | this.selectedDivClass = selectedDivClass; 110 | } 111 | document.getElementById(selectedDivId).className = document.getElementById(selectedDivId).className.replace("GuiPage_Setting_Changing arrowUpDown",""); 112 | document.getElementById(selectedDivId).className = document.getElementById(selectedDivId).className.replace("highlight"+Main.highlightColour+"Background",""); 113 | document.getElementById(selectedDivId).className = document.getElementById(selectedDivId).className.replace("highlight"+Main.highlightColour+"Text",""); 114 | document.getElementById(selectedDivId).className = document.getElementById(selectedDivId).className.replace("seriesSelected",""); 115 | document.getElementById(selectedDivId).className = document.getElementById(selectedDivId).className.replace("Selected",""); 116 | } 117 | 118 | //Show Menu 119 | document.getElementById("menu").style.visibility = ""; 120 | document.getElementById("menu").style.left = "0px"; 121 | document.getElementById("page").style.left = "350px"; 122 | 123 | //Show submenu dependant on selectedMainMenuItem 124 | this.updateSelectedItems(); 125 | 126 | //Set Focus 127 | document.getElementById("GuiMainMenu").focus(); 128 | } 129 | 130 | GuiMainMenu.updateSelectedItems = function () { 131 | for (var index = 0; index < this.menuItems.length; index++){ 132 | if (index == this.selectedMainMenuItem) { 133 | document.getElementById(this.menuItems[index]).className = "menu-item highlight"+Main.highlightColour+"Background"; 134 | } else { 135 | document.getElementById(this.menuItems[index]).className = "menu-item"; 136 | } 137 | } 138 | } 139 | 140 | //------------------------------------------------------------- 141 | // Main Menu Key Handling 142 | //------------------------------------------------------------- 143 | GuiMainMenu.keyDown = function() 144 | { 145 | var keyCode = event.keyCode; 146 | alert("Key pressed: " + keyCode); 147 | 148 | if (document.getElementById("Notifications").style.visibility == "") { 149 | document.getElementById("Notifications").style.visibility = "hidden"; 150 | document.getElementById("NotificationText").innerHTML = ""; 151 | widgetAPI.blockNavigation(event); 152 | //Change keycode so it does nothing! 153 | keyCode = "VOID"; 154 | } 155 | 156 | //Update Screensaver Timer 157 | Support.screensaver(); 158 | 159 | //If screensaver is running 160 | if (Main.getIsScreensaverRunning()) { 161 | //Update Main.js isScreensaverRunning - Sets to True 162 | Main.setIsScreensaverRunning(); 163 | 164 | //End Screensaver 165 | GuiImagePlayer_Screensaver.stopScreensaver(); 166 | 167 | //Change keycode so it does nothing! 168 | keyCode = "VOID"; 169 | } 170 | 171 | switch(keyCode) 172 | { 173 | case tvKey.KEY_UP: 174 | alert("Up"); 175 | this.processUpKey(); 176 | break; 177 | case tvKey.KEY_DOWN: 178 | alert("DOWN"); 179 | this.processDownKey(); 180 | break; 181 | case tvKey.KEY_ENTER: 182 | case tvKey.KEY_PANEL_ENTER: 183 | alert("ENTER"); 184 | this.processSelectedItems(); 185 | break; 186 | case tvKey.KEY_PLAY: 187 | this.playSelectedItem(); 188 | break; 189 | case tvKey.KEY_RIGHT: 190 | case tvKey.KEY_RETURN: 191 | case tvKey.KEY_TOOLS: 192 | widgetAPI.blockNavigation(event); 193 | //Allows blocking of return from menu if page has no selectable items 194 | this.processReturnKey(); 195 | break; 196 | case tvKey.KEY_RED: 197 | //this.toggleTestMode(); 198 | break; 199 | case tvKey.KEY_EXIT: 200 | alert ("EXIT KEY"); 201 | widgetAPI.sendExitEvent(); 202 | break; 203 | } 204 | } 205 | 206 | GuiMainMenu.processSelectedItems = function() { 207 | 208 | //Selecting home when you came from home just closes the menu. 209 | if (this.menuItems[this.selectedMainMenuItem] == "Home" && 210 | (this.pageSelected == "GuiPage_HomeOneItem" || this.pageSelected == "GuiPage_HomeTwoItems")) { 211 | this.processReturnKey(); 212 | return; 213 | } 214 | 215 | //If a trailer was paused when we arrived in the menu, stop it now. 216 | if (GuiPage_ItemDetails.trailerState == sf.service.VideoPlayer.STATE_PAUSED) { 217 | sf.service.VideoPlayer.stop(); 218 | } 219 | 220 | //Close the menu 221 | document.getElementById("menu").style.visibility = "none"; 222 | document.getElementById("menu").style.left = "-350px"; 223 | document.getElementById("page").style.left = "0px"; 224 | 225 | setTimeout(function(){ 226 | Support.processHomePageMenu(GuiMainMenu.menuItems[GuiMainMenu.selectedMainMenuItem]); 227 | }, 200); 228 | } 229 | 230 | GuiMainMenu.playSelectedItem = function() { 231 | //Pressing play on Photos in the main menu plays a random slideshow. 232 | if (this.menuItems[this.selectedMainMenuItem] == "Photos") { 233 | 234 | //Close the menu 235 | document.getElementById("menu").style.visibility = "none"; 236 | document.getElementById("menu").style.left = "-350px"; 237 | document.getElementById("page").style.left = "0px"; 238 | 239 | var userViews = Server.getUserViews(); 240 | for (var i = 0; i < userViews.Items.length; i++){ 241 | if (userViews.Items[i].CollectionType == "photos"){ 242 | GuiImagePlayer.start(userViews,i,true); 243 | } 244 | } 245 | } 246 | } 247 | 248 | GuiMainMenu.processReturnKey = function() { 249 | if (this.pageSelected != null) { 250 | //As I don't want the settings page in the URL History I need to prevent popping it here (as its not added on leaving the settings page 251 | if (this.pageSelected != "GuiPage_Settings") { 252 | Support.removeLatestURL(); 253 | } 254 | 255 | //Cheap way to unhighlight all items! 256 | this.selectedMainMenuItem = -1; 257 | this.updateSelectedItems(); 258 | this.selectedMainMenuItem = 0; 259 | 260 | //Close the menu 261 | document.getElementById("menu").style.visibility = "none"; 262 | document.getElementById("menu").style.left = "-350px"; 263 | document.getElementById("page").style.left = "0px"; 264 | 265 | if (this.pageSelected == "GuiMusicPlayer") { 266 | GuiMusicPlayer.showMusicPlayer(this.selectedDivId); 267 | } 268 | 269 | //Set Page GUI elements Correct & Set Focus 270 | if (this.selectedDivId != null) { 271 | if (this.selectedDivClass == "UNDEFINED") { 272 | document.getElementById(this.selectedDivId).className = document.getElementById(this.selectedDivId).className + " Selected"; 273 | } else { 274 | document.getElementById(this.selectedDivId).className = this.selectedDivClass; 275 | } 276 | } 277 | 278 | //If a trailer was playing, set it going again. 279 | if (GuiPage_ItemDetails.trailerState == sf.service.VideoPlayer.STATE_PAUSED) { 280 | setTimeout(function(){ 281 | sf.service.VideoPlayer.show(); 282 | sf.service.VideoPlayer.resume(); 283 | }, 300); 284 | } 285 | 286 | document.getElementById(this.pageSelected).focus(); 287 | } 288 | } 289 | 290 | GuiMainMenu.processUpKey = function() { 291 | this.selectedMainMenuItem--; 292 | if (this.selectedMainMenuItem < 0) { 293 | this.selectedMainMenuItem = this.menuItems.length-1; 294 | } 295 | this.updateSelectedItems(); 296 | } 297 | 298 | GuiMainMenu.processDownKey = function() { 299 | this.selectedMainMenuItem++; 300 | if (this.selectedMainMenuItem >= this.menuItems.length) { 301 | this.selectedMainMenuItem = 0; 302 | } 303 | this.updateSelectedItems(); 304 | } 305 | 306 | GuiMainMenu.toggleTestMode = function() { 307 | if (this.testModeCount < 2) { 308 | this.testModeCount++; 309 | clearTimeout (this.testModeTimeout); 310 | this.testModeTimeout = setTimeout(function() { 311 | GuiMainMenu.testModeCount = 0; 312 | },3000) 313 | } else { 314 | clearTimeout (this.testModeTimeout); 315 | Main.setTestMode(); 316 | GuiNotifications.setNotification("Test mode is now: " + Main.getTestMode(),"Test Mode"); 317 | this.testModeCount = 0; 318 | } 319 | } -------------------------------------------------------------------------------- /app/javascript/Gui/GuiDisplayOneItem.js: -------------------------------------------------------------------------------- 1 | var GuiDisplayOneItem = { 2 | ItemData : null, 3 | ItemIndexData : null, 4 | 5 | selectedItem : 0, 6 | topLeftItem : 0, 7 | MAXCOLUMNCOUNT : 4, 8 | MAXROWCOUNT : 3, 9 | 10 | indexSeekPos : -1, 11 | isResume : false, 12 | genreType : "", 13 | 14 | startParams : [], 15 | isLatest : false, 16 | backdropTimeout : null 17 | } 18 | 19 | GuiDisplayOneItem.onFocus = function() { 20 | GuiHelper.setControlButtons(null,null,null,GuiMusicPlayer.Status == "PLAYING" || GuiMusicPlayer.Status == "PAUSED" ? "Music" : null,"Return"); 21 | } 22 | 23 | GuiDisplayOneItem.getMaxDisplay = function() { 24 | return this.MAXCOLUMNCOUNT * this.MAXROWCOUNT; 25 | } 26 | 27 | GuiDisplayOneItem.start = function(title,url,selectedItem,topLeftItem) { 28 | alert("Page Enter : GuiDisplayOneItem"); 29 | 30 | //Save Start Params 31 | this.startParams = [title,url]; 32 | 33 | //Reset Values 34 | this.indexSeekPos = -1; 35 | this.selectedItem = selectedItem; 36 | this.topLeftItem = topLeftItem; 37 | this.genreType = null; 38 | 39 | //Load Data 40 | this.ItemData = Server.getContent(url + "&Limit="+File.getTVProperty("ItemPaging")); 41 | if (this.ItemData == null) { Support.processReturnURLHistory(); } 42 | //Once we've browsed the channels down to a content folder we should display them using GuiDisplay_Series. 43 | if (this.ItemData.TotalRecordCount >0){ 44 | if (this.ItemData.Items[0].Type == "ChannelVideoItem" || 45 | this.ItemData.Items[0].Type == "ChannelAudioItem" || 46 | this.ItemData.Items[0].Type == "Trailer" || 47 | this.ItemData.Items[0].Type == "AudioPodcast") { 48 | GuiDisplay_Series.start("All "+this.ItemData.Items[0].Type,url,selectedItem,topLeftItem,this.ItemData); 49 | return; 50 | } 51 | } 52 | 53 | //Setup display width height based on title 54 | switch (title) { 55 | case "Collections": 56 | case "Channels": 57 | this.MAXCOLUMNCOUNT = 3; 58 | this.MAXROWCOUNT = 2; 59 | break; 60 | case "Music": 61 | case "Albums": 62 | case "Artists": 63 | this.MAXCOLUMNCOUNT = 6; 64 | this.MAXROWCOUNT = 3; 65 | break; 66 | default: 67 | this.MAXCOLUMNCOUNT = 4; 68 | this.MAXROWCOUNT = 3; 69 | break; 70 | } 71 | 72 | //Set Page Content 73 | document.getElementById("pageContent").innerHTML = "
"+title+"
" + 74 | "
"; 75 | 76 | //Set Top 77 | GuiDisplayOneItem.setPadding(title); 78 | 79 | if (this.ItemData.Items.length > 0) { 80 | //Set isResume based on title - used in UpdateDisplayedItems 81 | this.isResume = (title == "Resume") ? true : false; 82 | 83 | //Alter to only allow indexing on certain pages?? 84 | //this.ItemIndexData = Support.processIndexing(this.ItemData.Items); 85 | 86 | //Display first XX series 87 | this.updateDisplayedItems(); 88 | 89 | //Update Selected Collection CSS 90 | this.updateSelectedItems(); 91 | 92 | //Set Focus for Key Events 93 | document.getElementById("GuiDisplayOneItem").focus(); 94 | } else { 95 | //Set message to user 96 | document.getElementById("Counter").innerHTML = ""; 97 | document.getElementById("Content").style.fontSize="40px"; 98 | document.getElementById("Content").innerHTML = "Huh.. Looks like I have no content to show you in this view I'm afraid
Press return to get back to the previous screen"; 99 | 100 | document.getElementById("NoItems").focus(); 101 | } 102 | } 103 | 104 | GuiDisplayOneItem.updateDisplayedItems = function() { 105 | Support.updateDisplayedItems(this.ItemData.Items,this.selectedItem,this.topLeftItem, 106 | Math.min(this.topLeftItem + this.getMaxDisplay(),this.ItemData.Items.length),"Content","",this.isResume,this.genreType,true); 107 | } 108 | 109 | //Function sets CSS Properties so show which user is selected 110 | GuiDisplayOneItem.updateSelectedItems = function () { 111 | if (this.MAXCOLUMNCOUNT == 3) { 112 | //Add Collections Class to add more margin 113 | Support.updateSelectedNEW(this.ItemData.Items,this.selectedItem,this.topLeftItem, 114 | Math.min(this.topLeftItem + this.getMaxDisplay(),this.ItemData.Items.length),"Series Collection Selected highlight"+Main.highlightColour+"Boarder","Series Collection",""); 115 | } else { 116 | Support.updateSelectedNEW(this.ItemData.Items,this.selectedItem,this.topLeftItem, 117 | Math.min(this.topLeftItem + this.getMaxDisplay(),this.ItemData.Items.length),"Series Selected highlight"+Main.highlightColour+"Boarder","Series",""); 118 | } 119 | } 120 | 121 | GuiDisplayOneItem.keyDown = function() { 122 | var keyCode = event.keyCode; 123 | alert("GuiDisplayOneItem: Key pressed: " + keyCode); 124 | 125 | if (document.getElementById("Notifications").style.visibility == "") { 126 | document.getElementById("Notifications").style.visibility = "hidden"; 127 | document.getElementById("NotificationText").innerHTML = ""; 128 | widgetAPI.blockNavigation(event); 129 | //Change keycode so it does nothing! 130 | keyCode = "VOID"; 131 | } 132 | 133 | //Update Screensaver Timer 134 | Support.screensaver(); 135 | 136 | //If screensaver is running 137 | if (Main.getIsScreensaverRunning()) { 138 | //Update Main.js isScreensaverRunning - Sets to True 139 | Main.setIsScreensaverRunning(); 140 | 141 | //End Screensaver 142 | GuiImagePlayer_Screensaver.stopScreensaver(); 143 | 144 | //Change keycode so it does nothing! 145 | keyCode = "VOID"; 146 | } 147 | 148 | switch(keyCode) { 149 | //Need Logout Key 150 | case tvKey.KEY_LEFT: 151 | alert("LEFT"); 152 | this.processLeftKey(); 153 | break; 154 | case tvKey.KEY_RIGHT: 155 | alert("RIGHT"); 156 | this.processRightKey(); 157 | break; 158 | case tvKey.KEY_UP: 159 | alert("UP"); 160 | this.processUpKey(); 161 | break; 162 | case tvKey.KEY_DOWN: 163 | alert("DOWN"); 164 | this.processDownKey(); 165 | break; 166 | case tvKey.KEY_PANEL_CH_UP: 167 | case tvKey.KEY_CH_UP: 168 | this.processChannelUpKey(); 169 | break; 170 | case tvKey.KEY_PANEL_CH_DOWN: 171 | case tvKey.KEY_CH_DOWN: 172 | this.processChannelDownKey(); 173 | break; 174 | case tvKey.KEY_RETURN: 175 | alert("RETURN"); 176 | widgetAPI.blockNavigation(event); 177 | Support.processReturnURLHistory(); 178 | break; 179 | case tvKey.KEY_ENTER: 180 | case tvKey.KEY_PANEL_ENTER: 181 | alert("ENTER"); 182 | this.processSelectedItem(); 183 | break; 184 | case tvKey.KEY_PLAY: 185 | this.playSelectedItem(); 186 | break; 187 | case tvKey.KEY_GREEN: 188 | //Watched - May not be needed on this page 189 | break; 190 | case tvKey.KEY_YELLOW: 191 | //Favourites - May not be needed on this page 192 | break; 193 | case tvKey.KEY_BLUE: 194 | GuiMusicPlayer.showMusicPlayer("GuiDisplayOneItem",this.ItemData.Items[this.selectedItem].Id,document.getElementById(this.ItemData.Items[this.selectedItem].Id).className); 195 | break; 196 | case tvKey.KEY_TOOLS: 197 | widgetAPI.blockNavigation(event); 198 | this.openMenu(); 199 | break; 200 | case tvKey.KEY_EXIT: 201 | alert ("EXIT KEY"); 202 | widgetAPI.sendExitEvent(); 203 | break; 204 | } 205 | } 206 | 207 | GuiDisplayOneItem.processSelectedItem = function() { 208 | clearTimeout(this.backdropTimeout); 209 | Support.processSelectedItem("GuiDisplayOneItem",this.ItemData,this.startParams,this.selectedItem,this.topLeftItem,null,this.genreType,this.isLatest); 210 | } 211 | 212 | GuiDisplayOneItem.playSelectedItem = function () { 213 | clearTimeout(this.backdropTimeout); 214 | Support.playSelectedItem("GuiDisplayOneItem",this.ItemData,this.startParams,this.selectedItem,this.topLeftItem,null); 215 | } 216 | 217 | GuiDisplayOneItem.openMenu = function() { 218 | Support.updateURLHistory("GuiDisplayOneItem",this.startParams[0],this.startParams[1],null,null,this.selectedItem,this.topLeftItem,null); 219 | GuiMainMenu.requested("GuiDisplayOneItem",this.ItemData.Items[this.selectedItem].Id); 220 | } 221 | 222 | GuiDisplayOneItem.processLeftKey = function() { 223 | if (this.selectedItem % this.MAXCOLUMNCOUNT == 0){ 224 | this.openMenu(); //Going left from anywhere in the first column. 225 | } else { 226 | this.selectedItem--; 227 | if (this.selectedItem == -1) { 228 | this.selectedItem = 0; 229 | this.openMenu(); 230 | } else { 231 | if (this.selectedItem < this.topLeftItem) { 232 | this.topLeftItem = this.selectedItem - (this.getMaxDisplay() - 1); 233 | if (this.topLeftItem < 0) { 234 | this.topLeftItem = 0; 235 | } 236 | this.updateDisplayedItems(); 237 | } 238 | } 239 | this.updateSelectedItems(); 240 | } 241 | } 242 | 243 | GuiDisplayOneItem.processRightKey = function() { 244 | this.selectedItem++; 245 | if (this.selectedItem >= this.ItemData.Items.length) { 246 | this.selectedItem--; 247 | } else { 248 | if (this.selectedItem >= this.topLeftItem+this.getMaxDisplay() ) { 249 | this.topLeftItem = this.selectedItem; 250 | this.updateDisplayedItems(); 251 | } 252 | } 253 | this.updateSelectedItems(); 254 | } 255 | 256 | GuiDisplayOneItem.processUpKey = function() { 257 | this.selectedItem = this.selectedItem - this.MAXCOLUMNCOUNT; 258 | if (this.selectedItem < 0) { 259 | //Check User Setting 260 | this.selectedItem = this.selectedItem + this.MAXCOLUMNCOUNT; 261 | } else { 262 | if (this.selectedItem < this.topLeftItem) { 263 | if (this.topLeftItem - this.MAXCOLUMNCOUNT < 0) { 264 | this.topLeftItem = 0; 265 | } else { 266 | this.topLeftItem = this.topLeftItem - this.MAXCOLUMNCOUNT; 267 | } 268 | this.updateDisplayedItems(); 269 | } 270 | } 271 | this.updateSelectedItems(); 272 | } 273 | 274 | GuiDisplayOneItem.processDownKey = function() { 275 | this.selectedItem = this.selectedItem + this.MAXCOLUMNCOUNT; 276 | if (this.selectedItem >= this.ItemData.Items.length) { 277 | this.selectedItem = (this.ItemData.Items.length-1); 278 | if (this.selectedItem >= (this.topLeftItem + this.getMaxDisplay())) { 279 | this.topLeftItem = this.topLeftItem + this.getMaxDisplay(); 280 | this.updateDisplayedItems(); 281 | } 282 | } else { 283 | if (this.selectedItem >= (this.topLeftItem + this.getMaxDisplay())) { 284 | this.topLeftItem = this.topLeftItem + this.MAXCOLUMNCOUNT; 285 | this.updateDisplayedItems(); 286 | } 287 | } 288 | this.updateSelectedItems(); 289 | } 290 | 291 | GuiDisplayOneItem.processChannelUpKey = function() { 292 | this.selectedItem = this.selectedItem - this.getMaxDisplay(); 293 | if (this.selectedItem < 0) { 294 | this.selectedItem = 0; 295 | this.topLeftItem = 0; 296 | this.updateDisplayedItems(); 297 | } else { 298 | if (this.topLeftItem - this.getMaxDisplay() < 0) { 299 | this.topLeftItem = 0; 300 | } else { 301 | this.topLeftItem = this.topLeftItem - this.getMaxDisplay(); 302 | } 303 | this.updateDisplayedItems(); 304 | } 305 | this.updateSelectedItems(); 306 | } 307 | 308 | GuiDisplayOneItem.processChannelDownKey = function() { 309 | this.selectedItem = this.selectedItem + this.getMaxDisplay(); 310 | if (this.selectedItem >= this.ItemData.Items.length) { 311 | this.selectedItem = (this.ItemData.Items.length-1); 312 | if (this.selectedItem >= this.topLeftItem + this.getMaxDisplay()) { 313 | this.topLeftItem = this.topLeftItem + this.getMaxDisplay(); 314 | } 315 | this.updateDisplayedItems(); 316 | } else { 317 | this.topLeftItem = this.topLeftItem + this.getMaxDisplay(); 318 | this.updateDisplayedItems(); 319 | } 320 | this.updateSelectedItems(); 321 | } 322 | 323 | GuiDisplayOneItem.processIndexing = function() { 324 | var indexLetter = this.ItemIndexData[0]; 325 | var indexPos = this.ItemIndexData[1]; 326 | 327 | this.indexSeekPos++; 328 | if (this.indexSeekPos >= indexPos.length) { 329 | this.indexSeekPos = 0; 330 | this.topLeftItem = 0; 331 | } 332 | 333 | this.selectedItem = indexPos[this.indexSeekPos]; 334 | this.topLeftItem = this.selectedItem; 335 | 336 | this.updateDisplayedItems(); 337 | this.updateSelectedItems(); 338 | } 339 | 340 | GuiDisplayOneItem.setPadding = function(title) { 341 | switch (title) { 342 | case "Media Folders": 343 | case "Collections": 344 | if (this.ItemData.Items.length <= this.MAXCOLUMNCOUNT) { 345 | document.getElementById("Center").style.top = "220px"; 346 | } else { 347 | document.getElementById("Center").style.top = "180px"; 348 | } 349 | break; 350 | case "Music": 351 | case "Albums": 352 | case "Artists": 353 | break; 354 | default: 355 | if (this.ItemData.Items.length > this.MAXCOLUMNCOUNT * 2) { 356 | //3 Rows 357 | document.getElementById("Center").style.top = "120px"; 358 | } else if (this.ItemData.Items.length > this.MAXCOLUMNCOUNT) { 359 | //2 Rows 360 | document.getElementById("Center").style.top = "220px"; 361 | } else { 362 | //1 Row 363 | document.getElementById("Center").style.top = "180px"; 364 | } 365 | break; 366 | } 367 | } 368 | 369 | GuiDisplayOneItem.returnFromMusicPlayer = function() { 370 | this.selectedItem = 0; 371 | this.updateDisplayedItems(); 372 | this.updateSelectedItems(); 373 | } -------------------------------------------------------------------------------- /app/javascript/Support/File.js: -------------------------------------------------------------------------------- 1 | var File = { 2 | ServerEntry : null, 3 | UserEntry : null 4 | }; 5 | 6 | File.getServerEntry = function() { 7 | return this.ServerEntry; 8 | }; 9 | 10 | File.setServerEntry = function(serverEntry) { 11 | this.ServerEntry = serverEntry; 12 | }; 13 | 14 | File.getUserEntry = function() { 15 | return this.UserEntry; 16 | }; 17 | 18 | File.setUserEntry = function(userEntry) { 19 | this.UserEntry = userEntry; 20 | }; 21 | 22 | File.deleteOldSettingsFile = function() { 23 | var fileSystemObj = new FileSystem(); 24 | fileSystemObj.deleteCommonFile(curWidget.id + '/MB3_Settings.xml'); 25 | }; 26 | 27 | File.deleteSettingsFile = function() { 28 | var fileSystemObj = new FileSystem(); 29 | fileSystemObj.deleteCommonFile(curWidget.id + '/MB3_Settings.json'); 30 | }; 31 | 32 | File.loadFile = function() { 33 | var fileSystemObj = new FileSystem(); 34 | 35 | var bValid = fileSystemObj.isValidCommonPath(curWidget.id); 36 | if (!bValid) { 37 | fileSystemObj.createCommonDir(curWidget.id); 38 | var fileObj = fileSystemObj.openCommonFile(curWidget.id + '/MB3_Settings.json', 'w'); 39 | var contentToWrite = '{"Version":"'+Main.getVersion()+'","Servers":[],"TV":{}}'; 40 | fileObj.writeLine(contentToWrite); 41 | fileSystemObj.closeCommonFile(fileObj); 42 | } 43 | 44 | var openRead = fileSystemObj.openCommonFile(curWidget.id + '/MB3_Settings.json', 'r'); 45 | if (!openRead) { 46 | fileSystemObj.createCommonDir(curWidget.id); 47 | var fileObj = fileSystemObj.openCommonFile(curWidget.id + '/MB3_Settings.json', 'w'); 48 | var contentToWrite = '{"Version":"'+Main.getVersion()+'","Servers":[],"TV":{}}'; 49 | fileObj.writeLine(contentToWrite); 50 | fileSystemObj.closeCommonFile(fileObj); 51 | return contentToWrite; 52 | } else { 53 | var fileContents = openRead.readAll(); 54 | fileSystemObj.closeCommonFile(openRead); 55 | return fileContents; 56 | } 57 | }; 58 | 59 | File.checkVersion = function(fileContent) { 60 | if (fileContent.Version === undefined) { 61 | return "Undefined" 62 | } else { 63 | return fileContent.Version; 64 | } 65 | }; 66 | 67 | File.saveServerToFile = function(Id,Name,ServerIP) { 68 | var fileSystemObj = new FileSystem(); 69 | var openRead = fileSystemObj.openCommonFile(curWidget.id + '/MB3_Settings.json', 'r'); 70 | if (openRead) { 71 | var fileJson = JSON.parse(openRead.readLine()); //Read line as only 1 and skips line break! 72 | fileSystemObj.closeCommonFile(openRead); 73 | 74 | var serverExists = false; 75 | for (var index = 0; index < fileJson.Servers.length; index++) { 76 | if (Id == fileJson.Servers[index].Id) { 77 | this.ServerEntry = index; 78 | serverExists = true; 79 | alert ("Server already exists in file - not adding - Server Entry: " + this.ServerEntry); 80 | } 81 | } 82 | 83 | if (serverExists == false) { 84 | this.ServerEntry = fileJson.Servers.length 85 | fileJson.Servers[fileJson.Servers.length] = {"Id":Id,"Name":Name,"Path":ServerIP,"Default":false,"Users":[]}; 86 | var openWrite = fileSystemObj.openCommonFile(curWidget.id + '/MB3_Settings.json', 'w'); 87 | if (openWrite) { 88 | openWrite.writeLine(JSON.stringify(fileJson)); 89 | fileSystemObj.closeCommonFile(openWrite); 90 | alert ("Server added to file - Server Entry: " + this.ServerEntry); 91 | } 92 | } 93 | } 94 | }; 95 | 96 | File.setDefaultServer = function (defaultIndex) { 97 | var fileJson = JSON.parse(File.loadFile()); 98 | for (var index = 0; index < fileJson.Servers.length; index++) { 99 | if (fileJson.Servers[defaultIndex].Id == fileJson.Servers[index].Id ) { 100 | fileJson.Servers[index].Default = true; 101 | } else { 102 | fileJson.Servers[index].Default = false; 103 | } 104 | } 105 | 106 | var fileSystemObj = new FileSystem(); 107 | var openWrite = fileSystemObj.openCommonFile(curWidget.id + '/MB3_Settings.json', 'w'); 108 | if (openWrite) { 109 | openWrite.writeLine(JSON.stringify(fileJson)); 110 | fileSystemObj.closeCommonFile(openWrite); 111 | } 112 | GuiNotifications.setNotification(fileJson.Servers[defaultIndex].Name + " is now your default Server and will be logged in autiomatically from now on.","Default Server Changed",true); 113 | }; 114 | 115 | File.deleteServer = function (index) { 116 | var fileSystemObj = new FileSystem(); 117 | var openRead = fileSystemObj.openCommonFile(curWidget.id + '/MB3_Settings.json', 'r'); 118 | if (openRead) { 119 | var fileJson = JSON.parse(openRead.readLine()); //Read line as only 1 and skips line break! 120 | fileSystemObj.closeCommonFile(openRead); 121 | 122 | fileJson.Servers.splice(index); 123 | 124 | var openWrite = fileSystemObj.openCommonFile(curWidget.id + '/MB3_Settings.json', 'w'); 125 | if (openWrite) { 126 | openWrite.writeLine(JSON.stringify(fileJson)); 127 | fileSystemObj.closeCommonFile(openWrite); 128 | } 129 | 130 | if (fileJson.Servers.length == 0) { 131 | GuiPage_NewServer.start(); 132 | } else { 133 | GuiPage_Servers.start(); 134 | } 135 | } 136 | }; 137 | 138 | File.addUser = function (UserId, Name, Password, rememberPassword) { 139 | var fileSystemObj = new FileSystem(); 140 | var openRead = fileSystemObj.openCommonFile(curWidget.id + '/MB3_Settings.json', 'r'); 141 | if (openRead) { 142 | var fileJson = JSON.parse(openRead.readLine()); //Read line as only 1 and skips line break! 143 | fileSystemObj.closeCommonFile(openRead); 144 | 145 | //Check if user doesn't already exist - if does, alter password and save! 146 | var userFound = false; 147 | for (var index = 0; index < fileJson.Servers[this.ServerEntry].Users.length; index++) { 148 | if (fileJson.Servers[this.ServerEntry].Users[index].UserId == UserId) { 149 | userFound = true; 150 | this.UserEntry = index; 151 | fileJson.Servers[this.ServerEntry].Users[index].Password = Password; 152 | fileJson.Servers[this.ServerEntry].Users[index].RememberPassword = rememberPassword; 153 | break; 154 | } 155 | } 156 | if (userFound == false) { 157 | this.UserEntry = fileJson.Servers[this.ServerEntry].Users.length; 158 | //view1 = Server.getServerAddr() + "/Shows/NextUp?format=json&UserId="+Server.getUserID()+"&IncludeItemTypes=Episode&ExcludeLocationTypes=Virtual&Limit=24&Fields=PrimaryImageAspectRatio,SeriesInfo,DateCreated,SyncInfo,SortName&ImageTypeLimit=1&EnableImageTypes=Primary,Backdrop,Banner,Thumb"; 159 | //view2 = Server.getCustomURL("/Users/" + Server.getUserID() + "/Items/Latest?format=json&IncludeItemTypes=Movie"+Server.getMoviesViewQueryPart()+"&IsFolder=false&fields=ParentId,SortName,Overview,Genres,RunTimeTicks"); 160 | fileJson.Servers[this.ServerEntry].Users[this.UserEntry] = {"UserId":UserId,"UserName":Name.toLowerCase(),"Password":Password,"RememberPassword":rememberPassword,"Default":false,"HighlightColour":1,"ContinueWatching":true,"View1":"TVNextUp","View1Name":"Next Up","View2":"LatestMovies","View2Name":"Latest Movies"}; 161 | 162 | } 163 | 164 | var openWrite = fileSystemObj.openCommonFile(curWidget.id + '/MB3_Settings.json', 'w'); 165 | if (openWrite) { 166 | openWrite.writeLine(JSON.stringify(fileJson)); 167 | fileSystemObj.closeCommonFile(openWrite); 168 | } 169 | } 170 | }; 171 | 172 | File.deleteUser = function (index) { 173 | var fileSystemObj = new FileSystem(); 174 | var openRead = fileSystemObj.openCommonFile(curWidget.id + '/MB3_Settings.json', 'r'); 175 | if (openRead) { 176 | var fileJson = JSON.parse(openRead.readLine()); //Read line as only 1 and skips line break! 177 | fileSystemObj.closeCommonFile(openRead); 178 | 179 | fileJson.Servers[this.ServerEntry].Users.splice(index); 180 | 181 | var openWrite = fileSystemObj.openCommonFile(curWidget.id + '/MB3_Settings.json', 'w'); 182 | if (openWrite) { 183 | openWrite.writeLine(JSON.stringify(fileJson)); 184 | fileSystemObj.closeCommonFile(openWrite); 185 | } 186 | } 187 | }; 188 | 189 | File.deleteAllUsers = function (index) { 190 | var fileSystemObj = new FileSystem(); 191 | var openRead = fileSystemObj.openCommonFile(curWidget.id + '/MB3_Settings.json', 'r'); 192 | if (openRead) { 193 | var fileJson = JSON.parse(openRead.readLine()); //Read line as only 1 and skips line break! 194 | fileSystemObj.closeCommonFile(openRead); 195 | 196 | fileJson.Servers[this.ServerEntry].Users = []; 197 | 198 | var openWrite = fileSystemObj.openCommonFile(curWidget.id + '/MB3_Settings.json', 'w'); 199 | if (openWrite) { 200 | openWrite.writeLine(JSON.stringify(fileJson)); 201 | fileSystemObj.closeCommonFile(openWrite); 202 | } 203 | } 204 | }; 205 | 206 | File.deleteUserPasswords = function () { 207 | var fileSystemObj = new FileSystem(); 208 | var openRead = fileSystemObj.openCommonFile(curWidget.id + '/MB3_Settings.json', 'r'); 209 | if (openRead) { 210 | var fileJson = JSON.parse(openRead.readLine()); //Read line as only 1 and skips line break! 211 | fileSystemObj.closeCommonFile(openRead); 212 | 213 | for (var index = 0; index < fileJson.Servers[this.ServerEntry].Users.length; index++) { 214 | fileJson.Servers[this.ServerEntry].Users[index].Password = ""; // Do this so that users with no password are unaffected! 215 | } 216 | 217 | var openWrite = fileSystemObj.openCommonFile(curWidget.id + '/MB3_Settings.json', 'w'); 218 | if (openWrite) { 219 | openWrite.writeLine(JSON.stringify(fileJson)); 220 | fileSystemObj.closeCommonFile(openWrite); 221 | } 222 | } 223 | }; 224 | 225 | File.updateUserSettings = function (altered) { 226 | var fileSystemObj = new FileSystem(); 227 | var openRead = fileSystemObj.openCommonFile(curWidget.id + '/MB3_Settings.json', 'r'); 228 | if (openRead) { 229 | var fileJson = JSON.parse(openRead.readLine()); //Read line as only 1 and skips line break! 230 | fileSystemObj.closeCommonFile(openRead); 231 | 232 | fileJson.Servers[this.ServerEntry].Users[this.UserEntry] = altered; 233 | 234 | var openWrite = fileSystemObj.openCommonFile(curWidget.id + '/MB3_Settings.json', 'w'); 235 | if (openWrite) { 236 | openWrite.writeLine(JSON.stringify(fileJson)); 237 | fileSystemObj.closeCommonFile(openWrite); 238 | } 239 | } 240 | }; 241 | 242 | 243 | File.updateServerSettings = function (altered) { 244 | var fileSystemObj = new FileSystem(); 245 | var openRead = fileSystemObj.openCommonFile(curWidget.id + '/MB3_Settings.json', 'r'); 246 | if (openRead) { 247 | var fileJson = JSON.parse(openRead.readLine()); //Read line as only 1 and skips line break! 248 | fileSystemObj.closeCommonFile(openRead); 249 | 250 | fileJson.Servers[this.ServerEntry] = altered; 251 | 252 | var openWrite = fileSystemObj.openCommonFile(curWidget.id + '/MB3_Settings.json', 'w'); 253 | if (openWrite) { 254 | openWrite.writeLine(JSON.stringify(fileJson)); 255 | fileSystemObj.closeCommonFile(openWrite); 256 | } 257 | } 258 | }; 259 | 260 | File.writeAll = function (toWrite) { 261 | var fileSystemObj = new FileSystem(); 262 | var openWrite = fileSystemObj.openCommonFile(curWidget.id + '/MB3_Settings.json', 'w'); 263 | if (openWrite) { 264 | openWrite.writeLine(JSON.stringify(toWrite)); 265 | fileSystemObj.closeCommonFile(openWrite); 266 | } 267 | }; 268 | 269 | //--------------------------------------------------------------------------------------------------------------------------------- 270 | //- GET FUNCTIONS 271 | //--------------------------------------------------------------------------------------------------------------------------------- 272 | 273 | File.getUserProperty = function(property) { 274 | var fileSystemObj = new FileSystem(); 275 | var openRead = fileSystemObj.openCommonFile(curWidget.id + '/MB3_Settings.json', 'r'); 276 | if (openRead) { 277 | var fileJson = JSON.parse(openRead.readLine()); //Read line as only 1 and skips line break! 278 | fileSystemObj.closeCommonFile(openRead); 279 | if (!fileJson.Servers[this.ServerEntry].Users[this.UserEntry]) { //In case we're not logged in yet. 280 | return null; 281 | } 282 | if (fileJson.Servers[this.ServerEntry].Users[this.UserEntry][property] === undefined) { 283 | //Get System Default 284 | for (var index = 0; index < GuiPage_Settings.Settings.length; index++) { 285 | if (GuiPage_Settings.Settings[index] == property) { 286 | //Write setting here? 287 | fileJson.Servers[this.ServerEntry].Users[this.UserEntry][property] = GuiPage_Settings.SettingsDefaults[index]; 288 | File.writeAll(fileJson); 289 | break; 290 | } 291 | } 292 | } 293 | return fileJson.Servers[this.ServerEntry].Users[this.UserEntry][property]; 294 | } 295 | }; 296 | 297 | File.getTVProperty = function(property) { 298 | var fileSystemObj = new FileSystem(); 299 | var openRead = fileSystemObj.openCommonFile(curWidget.id + '/MB3_Settings.json', 'r'); 300 | if (openRead) { 301 | var fileJson = JSON.parse(openRead.readLine()); //Read line as only 1 and skips line break! 302 | fileSystemObj.closeCommonFile(openRead); 303 | 304 | if (fileJson.TV === undefined) { 305 | fileJson.TV = {}; 306 | File.writeAll (fileJson); 307 | } 308 | 309 | if (fileJson.TV[property] === undefined) { 310 | //Get System Default 311 | for (var index = 0; index < GuiPage_Settings.TVSettings.length; index++) { 312 | if (GuiPage_Settings.TVSettings[index] == property) { 313 | //Write setting here? 314 | fileJson.TV[property] = GuiPage_Settings.TVSettingsDefaults[index]; 315 | File.writeAll(fileJson); 316 | break; 317 | } 318 | } 319 | } 320 | return fileJson.TV[property]; 321 | } 322 | }; 323 | 324 | //--------------------------------------------------------------------------------------------------------------------------------- 325 | //- SET FUNCTIONS 326 | //--------------------------------------------------------------------------------------------------------------------------------- 327 | 328 | File.setUserProperty = function(property,value) { 329 | var fileSystemObj = new FileSystem(); 330 | var openRead = fileSystemObj.openCommonFile(curWidget.id + '/MB3_Settings.json', 'r'); 331 | if (openRead) { 332 | var fileJson = JSON.parse(openRead.readLine()); //Read line as only 1 and skips line break! 333 | fileSystemObj.closeCommonFile(openRead); 334 | 335 | if (fileJson.Servers[this.ServerEntry].Users[this.UserEntry][property] !== undefined) { 336 | fileJson.Servers[this.ServerEntry].Users[this.UserEntry][property] = value; 337 | File.writeAll(fileJson); 338 | } 339 | return 340 | } 341 | }; -------------------------------------------------------------------------------- /app/javascript/Gui/GuiPage_Music.js: -------------------------------------------------------------------------------- 1 | var GuiPage_Music = { 2 | AlbumData : null, 3 | 4 | selectedItem : 0, //Vertical 5 | topLeftItem : 0, 6 | 7 | selectedItem2 : 0, //Horizontal 8 | 9 | MAXCOLUMNCOUNT : 1, 10 | MAXROWCOUNT : 12, 11 | 12 | startParams : [], 13 | 14 | topMenuItems : ["PlayAll","QueueAll","ShuffleAll","InstantMix"], 15 | playItems : ["Play_","Queue_","Mix_"] 16 | } 17 | 18 | GuiPage_Music.onFocus = function() { 19 | this.updateSelectedItems(); 20 | GuiHelper.setControlButtons(null,null,null,GuiMusicPlayer.Status == "PLAYING" || GuiMusicPlayer.Status == "PAUSED" ? "Music" : null,"Return"); 21 | } 22 | 23 | GuiPage_Music.getMaxDisplay = function() { 24 | return this.MAXCOLUMNCOUNT * this.MAXROWCOUNT; 25 | } 26 | 27 | GuiPage_Music.start = function(title,url,type) { //Type is either MusicAlbum or MusicArtist 28 | alert("Page Enter : GuiPage_Music"); 29 | 30 | //Save Start Params 31 | this.startParams = [title,url]; 32 | 33 | //Reset Vars 34 | this.topLeftItem = 0; 35 | this.selectedItem = -1; 36 | this.selectedItem2 = 0; 37 | 38 | //Load Data 39 | this.AlbumData = Server.getContent(url); 40 | if (this.AlbumData == null) { return; } 41 | 42 | //Set PageContent 43 | document.getElementById("pageContent").innerHTML = "
\ 44 |
\ 45 |
\ 46 |
\ 47 |
Play All
\ 48 |
Queue All
\ 49 |
Shuffle
\ 50 |
Instant Mix
\ 51 |
\ 52 |
"; 53 | document.getElementById("Counter").innerHTML = "1/" + this.topMenuItems.length; 54 | 55 | //Get Episode Poster 56 | if (this.AlbumData.Items[0].AlbumPrimaryImageTag) { 57 | var imgsrc = Server.getImageURL(this.AlbumData.Items[0].AlbumId,"Primary",650,650,0,false,0); 58 | document.getElementById("guiMusic_Poster").style.backgroundImage = "url("+imgsrc + ")"; 59 | } else { 60 | document.getElementById("guiMusic_Poster").style.backgroundImage = "url(images/collection.png)"; 61 | } 62 | 63 | //Set Page Title 64 | if (type == "MusicAlbum") { 65 | if (this.AlbumData.Items[0].AlbumArtist){ 66 | document.getElementById("guiMusic_Title").innerHTML = this.AlbumData.Items[0].AlbumArtist; 67 | } 68 | if (this.AlbumData.Items[0].Album){ 69 | document.getElementById("guiMusic_Subtitle").innerHTML = this.AlbumData.Items[0].Album; 70 | } 71 | } else if (type == "MusicArtist") { 72 | if (this.AlbumData.Items[0].AlbumArtist){ 73 | document.getElementById("guiMusic_Title").innerHTML = this.AlbumData.Items[0].AlbumArtist; 74 | } 75 | } 76 | 77 | //Get Page Items 78 | this.updateDisplayedItems(); 79 | 80 | //Update Selected Item 81 | this.updateSelectedItems(); 82 | 83 | //Set Focus for Key Events 84 | document.getElementById("GuiPage_Music").focus(); 85 | } 86 | 87 | GuiPage_Music.updateDisplayedItems = function() { 88 | var htmlToAdd = ""; 89 | for (var index = this.topLeftItem; index < Math.min(this.topLeftItem + this.getMaxDisplay(),this.AlbumData.Items.length); index++){ 90 | if (this.AlbumData.Items[index].ParentIndexNumber && this.AlbumData.Items[index].IndexNumber) { 91 | TrackDetails = this.AlbumData.Items[index].ParentIndexNumber+"." + this.AlbumData.Items[index].IndexNumber; 92 | } else if (this.AlbumData.Items[index].IndexNumber) { 93 | TrackDetails = this.AlbumData.Items[index].IndexNumber; 94 | } else { 95 | TrackDetails = "?"; 96 | } 97 | 98 | //Truncate long song names. 99 | var songName = this.AlbumData.Items[index].Name; 100 | if (songName.length > 43){ 101 | songName = songName.substring(0,40) + "..."; 102 | } 103 | 104 | htmlToAdd += "" + 105 | "" + 106 | ""; 107 | } 108 | document.getElementById("GuiPage_Music_Options").innerHTML = htmlToAdd + "
PlayQueueMix"+TrackDetails+ "" + songName + ""+Support.convertTicksToTimeSingle(this.AlbumData.Items[index].RunTimeTicks/10000,true)+"
"; 109 | } 110 | 111 | //Function sets CSS Properties so show which user is selected 112 | GuiPage_Music.updateSelectedItems = function () { 113 | if (this.selectedItem == -1) { 114 | //Highlight the selected global item (PlayAll, Shuffle etc.) 115 | for (var index = 0; index < this.topMenuItems.length; index++) { 116 | if (index == this.selectedItem2) { 117 | document.getElementById(this.topMenuItems[index]).className = "guiMusic_Global highlight"+Main.highlightColour+"Background"; 118 | } else { 119 | document.getElementById(this.topMenuItems[index]).className = "guiMusic_Global"; 120 | } 121 | } 122 | } else { 123 | //Reset the global items. 124 | for (var index = 0; index < this.topMenuItems.length; index++) { 125 | document.getElementById(this.topMenuItems[index]).className = "guiMusic_Global"; 126 | } 127 | 128 | //Highlight the selected list item. 129 | for (var index = this.topLeftItem; index < Math.min(this.topLeftItem + this.getMaxDisplay(),this.AlbumData.Items.length); index++){ 130 | if (index == this.selectedItem) { 131 | for (var index2 = 0; index2 < this.playItems.length; index2++) { 132 | if (index2 == this.selectedItem2) { 133 | document.getElementById(this.playItems[index2]+this.AlbumData.Items[index].Id).className = "guiMusic_TableTd highlight"+Main.highlightColour+"Background"; 134 | } else { 135 | document.getElementById(this.playItems[index2]+this.AlbumData.Items[index].Id).className = "guiMusic_TableTd"; 136 | } 137 | } 138 | } else { 139 | document.getElementById(this.AlbumData.Items[index].Id).className = "guiMusic_TableTd"; 140 | for (var index2 = 0; index2 < this.playItems.length; index2++) { 141 | document.getElementById(this.playItems[index2]+this.AlbumData.Items[index].Id).className = "guiMusic_TableTd"; 142 | } 143 | } 144 | } 145 | } 146 | 147 | //Set Counter to be album count or x/3 for top part 148 | if (this.selectedItem == -1) { 149 | document.getElementById("Counter").innerHTML = (this.selectedItem2 + 1) + "/" + this.topMenuItems.length; 150 | } else { 151 | document.getElementById("Counter").innerHTML = (this.selectedItem + 1) + "/" + this.AlbumData.Items.length; 152 | } 153 | 154 | } 155 | 156 | GuiPage_Music.keyDown = function() { 157 | var keyCode = event.keyCode; 158 | alert("Key pressed: " + keyCode); 159 | 160 | //Update Screensaver Timer 161 | Support.screensaver(); 162 | 163 | //If screensaver is running 164 | if (Main.getIsScreensaverRunning()) { 165 | //Update Main.js isScreensaverRunning - Sets to True 166 | Main.setIsScreensaverRunning(); 167 | 168 | //End Screensaver 169 | GuiImagePlayer_Screensaver.stopScreensaver(); 170 | 171 | //Change keycode so it does nothing! 172 | keyCode = "VOID"; 173 | } 174 | 175 | switch(keyCode) { 176 | case tvKey.KEY_LEFT: 177 | this.processLeftKey(); 178 | break; 179 | case tvKey.KEY_RIGHT: 180 | this.processRightKey(); 181 | break; 182 | case tvKey.KEY_UP: 183 | this.processUpKey(); 184 | break; 185 | case tvKey.KEY_DOWN: 186 | this.processDownKey(); 187 | break; 188 | case tvKey.KEY_RETURN: 189 | alert("RETURN"); 190 | widgetAPI.blockNavigation(event); 191 | Support.processReturnURLHistory(); 192 | break; 193 | case tvKey.KEY_ENTER: 194 | case tvKey.KEY_PANEL_ENTER: 195 | alert("ENTER"); 196 | this.processSelectedItem(); 197 | break; 198 | case tvKey.KEY_TOOLS: 199 | widgetAPI.blockNavigation(event); 200 | this.openMenu(); 201 | break; 202 | case tvKey.KEY_YELLOW: 203 | //Favourites - May not be needed on this page 204 | break; 205 | case tvKey.KEY_BLUE: 206 | if (this.selectedItem == -1) { 207 | GuiMusicPlayer.showMusicPlayer("GuiPage_Music",this.topMenuItems[this.selectedItem2],"guiMusic_Global highlight"+Main.highlightColour+"Background"); 208 | } else { 209 | GuiMusicPlayer.showMusicPlayer("GuiPage_Music",this.playItems[this.selectedItem2]+this.AlbumData.Items[this.selectedItem].Id,"guiMusic_TableTd highlight"+Main.highlightColour+"Background"); 210 | } 211 | break; 212 | case tvKey.KEY_EXIT: 213 | alert ("EXIT KEY"); 214 | widgetAPI.sendExitEvent(); 215 | break; 216 | } 217 | } 218 | 219 | GuiPage_Music.openMenu = function() { 220 | Support.updateURLHistory("GuiPage_Music",this.startParams[0],this.startParams[1],null,null,this.selectedItem,this.topLeftItem,true); 221 | 222 | if (this.selectedItem == -1) { 223 | GuiMainMenu.requested("GuiPage_Music",this.topMenuItems[this.selectedItem2],"guiMusic_Global highlight"+Main.highlightColour+"Background"); 224 | } else { 225 | GuiMainMenu.requested("GuiPage_Music",this.playItems[this.selectedItem2]+this.AlbumData.Items[this.selectedItem].Id,"guiMusic_TableTd highlight"+Main.highlightColour+"Background"); 226 | } 227 | } 228 | 229 | GuiPage_Music.processUpKey = function() { 230 | this.selectedItem--; 231 | if (this.selectedItem < -1) { 232 | this.selectedItem = -1; 233 | } else { 234 | if (this.selectedItem == -1 && this.selectedItem2 >= 3) { 235 | this.selectedItem2 = 2; 236 | } 237 | if (this.selectedItem == -1) { 238 | document.getElementById(this.AlbumData.Items[0].Id).style.color = "white"; 239 | for (var index = 0; index < this.playItems.length; index++) { 240 | document.getElementById(this.playItems[index]+this.AlbumData.Items[0].Id).className = "guiMusic_TableTd"; 241 | } 242 | } 243 | if (this.selectedItem < this.topLeftItem) { 244 | if (this.topLeftItem - this.MAXCOLUMNCOUNT < 0) { 245 | this.topLeftItem = 0; 246 | } else { 247 | this.topLeftItem = this.topLeftItem - this.MAXCOLUMNCOUNT; 248 | } 249 | this.updateDisplayedItems(); 250 | } 251 | this.updateSelectedItems(); 252 | } 253 | } 254 | 255 | GuiPage_Music.processDownKey = function() { 256 | this.selectedItem++; 257 | if (this.selectedItem == 0) { 258 | this.selectedItem2 = 0; 259 | } 260 | if (this.selectedItem >= this.AlbumData.Items.length) { 261 | this.selectedItem--; 262 | if (this.selectedItem >= (this.topLeftItem + this.getMaxDisplay())) { 263 | this.topLeftItem = this.topLeftItem + this.getMaxDisplay(); 264 | this.updateDisplayedItems(); 265 | } 266 | } else { 267 | if (this.selectedItem >= (this.topLeftItem + this.getMaxDisplay())) { 268 | this.topLeftItem++; 269 | this.updateDisplayedItems(); 270 | } 271 | } 272 | this.updateSelectedItems(); 273 | } 274 | 275 | GuiPage_Music.processLeftKey = function() { 276 | this.selectedItem2--; 277 | if (this.selectedItem2 == -1) { 278 | this.selectedItem2 = 0; 279 | this.openMenu(); 280 | } else { 281 | this.updateSelectedItems(); 282 | } 283 | } 284 | 285 | GuiPage_Music.processRightKey = function() { 286 | this.selectedItem2++; 287 | if (this.selectedItem == -1) { 288 | if (this.selectedItem2 > this.topMenuItems.length-1) { 289 | this.selectedItem2--; 290 | } else { 291 | this.updateSelectedItems(); 292 | } 293 | } else { 294 | if (this.selectedItem2 > this.playItems.length-1) { 295 | this.selectedItem2--; 296 | } else { 297 | this.updateSelectedItems(); 298 | } 299 | } 300 | } 301 | 302 | GuiPage_Music.processSelectedItem = function() { 303 | if (this.selectedItem == -1) { 304 | //Is Top Menu Bar 305 | switch (this.selectedItem2) { 306 | case 0: 307 | //Play All 308 | document.getElementById(this.topMenuItems[this.selectedItem2]).className = document.getElementById(this.topMenuItems[this.selectedItem2]).className.replace("highlight"+Main.highlightColour+"Background",""); 309 | GuiMusicPlayer.start("Album",this.startParams[1] + "&Fields=MediaSources","GuiPage_Music",false); 310 | break; 311 | case 1: 312 | //Queue All 313 | GuiMusicPlayer.start("Album",this.startParams[1] + "&Fields=MediaSources","GuiPage_Music",true); 314 | break; 315 | case 2: 316 | //Shuffle 317 | document.getElementById(this.topMenuItems[this.selectedItem2]).className = document.getElementById(this.topMenuItems[this.selectedItem2]).className.replace("highlight"+Main.highlightColour+"Background",""); 318 | var url = this.startParams[1].replace("SortBy=SortName","SortBy=Random") 319 | GuiMusicPlayer.start("Album",url + "&Fields=MediaSources","GuiPage_Music",false); 320 | break; 321 | case 3: 322 | //Instant Mix 323 | document.getElementById(this.topMenuItems[this.selectedItem2]).className = document.getElementById(this.topMenuItems[this.selectedItem2]).className.replace("highlight"+Main.highlightColour+"Background",""); 324 | var url = Server.getCustomURL("/Albums/"+this.AlbumData.Items[0].AlbumId + "/InstantMix?format=json&Limit=50&UserId="+Server.getUserID()); 325 | GuiMusicPlayer.start("Album",url + "&Fields=MediaSources","GuiPage_Music",false); 326 | break; 327 | } 328 | } else { 329 | switch (this.selectedItem2) { 330 | case 0: 331 | //Play 332 | document.getElementById(this.playItems[this.selectedItem2]+this.AlbumData.Items[this.selectedItem].Id).className = document.getElementById(this.playItems[this.selectedItem2]+this.AlbumData.Items[this.selectedItem].Id).className.replace("highlight"+Main.highlightColour+"Background",""); 333 | var url = Server.getItemInfoURL(this.AlbumData.Items[this.selectedItem].Id); 334 | GuiMusicPlayer.start("Song",url,"GuiPage_Music",false); 335 | break; 336 | case 1: 337 | //Queue 338 | var url = Server.getItemInfoURL(this.AlbumData.Items[this.selectedItem].Id); 339 | GuiMusicPlayer.start("Song",url,"GuiPage_Music",true); 340 | break; 341 | case 2: 342 | //Mix 343 | document.getElementById(this.playItems[this.selectedItem2]+this.AlbumData.Items[this.selectedItem].Id).className = document.getElementById(this.playItems[this.selectedItem2]+this.AlbumData.Items[this.selectedItem].Id).className.replace("highlight"+Main.highlightColour+"Background",""); 344 | var url = Server.getCustomURL("/Songs/"+this.AlbumData.Items[this.selectedItem].Id + "/InstantMix?format=json&Limit=50&UserId="+Server.getUserID()); 345 | GuiMusicPlayer.start("Album",url + "&Fields=MediaSources","GuiPage_Music",false); 346 | break; 347 | } 348 | } 349 | 350 | //Genre Instant Mix 351 | //http://192.168.1.108:28067/emby/MusicGenres/Anime/InstantMix?UserId=4b4c128121aa642086bb225659a7d471&Fields=MediaSources%2CChapters&Limit=50 352 | //Artist Instant Mix 353 | //Artist/NameID/InstatnMix? 354 | } -------------------------------------------------------------------------------- /app/javascript/Gui/GuiPage_Search.js: -------------------------------------------------------------------------------- 1 | var GuiPage_Search = { 2 | ItemData : null, 3 | startParams : [], 4 | 5 | selectedItem : 0, 6 | selectedItem2 : 0, 7 | topLeftItem : 0, 8 | MAXCOLUMNCOUNT : 1, 9 | MAXROWCOUNT : 12, 10 | 11 | playItems : ["Play_","View_"] 12 | } 13 | 14 | GuiPage_Search.onFocus = function() { 15 | GuiHelper.setControlButtons(null,null,null,GuiMusicPlayer.Status == "PLAYING" || GuiMusicPlayer.Status == "PAUSED" ? "Music" : null,"Return"); 16 | } 17 | 18 | GuiPage_Search.getMaxDisplay = function() { 19 | return this.MAXCOLUMNCOUNT * this.MAXROWCOUNT; 20 | } 21 | 22 | GuiPage_Search.start = function(title, url) { 23 | alert("Page Enter : GuiPage_Search"); 24 | 25 | //Reset Properties 26 | this.ItemData = null; 27 | this.selectedItem = 0; 28 | this.selectedItem2 = 0; 29 | this.startParams = [], 30 | 31 | //Change Display 32 | document.getElementById("pageContent").innerHTML = "
Search
\ 33 |
\ 34 |
"; 35 | 36 | //Allows time for innerhtml to execute before creating ime 37 | setTimeout(function () { 38 | //Create IME 39 | new GuiPage_Search_Input(); 40 | 41 | if (title !== undefined && url !== undefined && title != null && url != null) { 42 | GuiPage_Search.ItemData = Server.getContent(url); 43 | if (GuiPage_Search.ItemData == null) { return; } 44 | 45 | document.getElementById("ResultsTitle").innerHTML = title; 46 | 47 | if (GuiPage_Search.ItemData.SearchHints.length > 0) { 48 | GuiPage_Search.startParams[0] = title; 49 | GuiPage_Search.startParams[1] = url; 50 | GuiPage_Search.updateDisplayedItems(); 51 | GuiPage_Search.updateSelectedItems(); 52 | document.getElementById("GuiPage_Search").focus(); 53 | } else { 54 | //Must turn off as cannot catch keys during IME! 55 | Support.screensaverOff(); 56 | document.getElementById("searchInput").focus(); 57 | } 58 | } else { 59 | //Must turn off as cannot catch keys during IME! 60 | Support.screensaverOff(); 61 | document.getElementById("searchInput").focus(); 62 | } 63 | }, 500); 64 | } 65 | 66 | GuiPage_Search.updateDisplayedItems = function() { 67 | htmlToAdd = ""; 68 | var epName = ""; 69 | for (var index = this.topLeftItem; index < Math.min(this.topLeftItem + this.getMaxDisplay(),this.ItemData.SearchHints.length); index++){ 70 | epName = (this.ItemData.SearchHints[index].Type == "Episode") ? Support.getNameFormat(null,this.ItemData.SearchHints[index].ParentIndexNumber,null,this.ItemData.SearchHints[index].IndexNumber) + " - " + this.ItemData.SearchHints[index].Name : this.ItemData.SearchHints[index].Name; 71 | htmlToAdd += "" + 72 | ""; 73 | } 74 | document.getElementById("Results").innerHTML = htmlToAdd + "
PlayView" + epName + "" + this.ItemData.SearchHints[index].Type + "
"; 75 | } 76 | 77 | //Function sets CSS Properties so show which user is selected 78 | GuiPage_Search.updateSelectedItems = function () { 79 | //Highlight the selected list item. 80 | for (var index = this.topLeftItem; index < Math.min(this.topLeftItem + this.getMaxDisplay(),this.ItemData.SearchHints.length); index++){ 81 | if (index == this.selectedItem) { 82 | for (var index2 = 0; index2 < this.playItems.length; index2++) { 83 | if (index2 == this.selectedItem2) { 84 | document.getElementById(this.playItems[index2]+this.ItemData.SearchHints[index].ItemId).className = "guiMusic_TableTd highlight"+Main.highlightColour+"Background"; 85 | } else { 86 | document.getElementById(this.playItems[index2]+this.ItemData.SearchHints[index].ItemId).className = "guiMusic_TableTd"; 87 | } 88 | } 89 | } else { 90 | document.getElementById(this.ItemData.SearchHints[index].ItemId).className = "guiMusic_TableTd"; 91 | for (var index2 = 0; index2 < this.playItems.length; index2++) { 92 | document.getElementById(this.playItems[index2]+this.ItemData.SearchHints[index].ItemId).className = "guiMusic_TableTd"; 93 | } 94 | } 95 | } 96 | 97 | //Set Counter to be album count or x/3 for top part 98 | document.getElementById("Counter").innerHTML = (this.selectedItem + 1) + "/" + this.ItemData.SearchHints.length; 99 | } 100 | 101 | GuiPage_Search.processSelectedItem = function() { 102 | Support.updateURLHistory("GuiPage_Search",this.startParams[0],this.startParams[1],null,null,0,0,null); 103 | switch (this.ItemData.SearchHints[this.selectedItem].Type) { 104 | case "Episode": 105 | case "Movie": 106 | if (this.playItems[this.selectedItem2] == "Play_") { 107 | //Play URL 108 | var url = Server.getItemInfoURL(this.ItemData.SearchHints[this.selectedItem].ItemId,"&ExcludeLocationTypes=Virtual"); 109 | GuiPlayer.start("PLAY",url,0,"GuiPage_Search"); 110 | } else if (this.playItems[this.selectedItem2] == "View_") { 111 | //Display Item Page 112 | var url = Server.getItemInfoURL(this.ItemData.SearchHints[this.selectedItem].ItemId,null); 113 | GuiPage_ItemDetails.start(this.ItemData.SearchHints[this.selectedItem].Name,url,0); 114 | } 115 | break; 116 | case "Series": 117 | if (this.playItems[this.selectedItem2] == "Play_") { 118 | //Play URL 119 | var url= Server.getChildItemsURL(this.ItemData.SearchHints[this.selectedItem].ItemId,"&ExcludeLocationTypes=Virtual&IncludeItemTypes=Episode&Recursive=true&SortBy=SortName&SortOrder=Ascending&Fields=ParentId,SortName,MediaSources") 120 | GuiPlayer.start("PlayAll",url,0,"GuiPage_Search"); 121 | } else if (this.playItems[this.selectedItem2] == "View_") { 122 | //Display Item Page 123 | var url = Server.getItemInfoURL(this.ItemData.SearchHints[this.selectedItem].ItemId,null); 124 | GuiTV_Show.start(this.ItemData.SearchHints[this.selectedItem].Name,url,0,0); 125 | } 126 | break; 127 | default: 128 | Support.removeLatestURL(); 129 | GuiNotifications.setNotification(this.ItemData.SearchHints[this.selectedItem].Type + " hasn't been implemented in search yet.", "To Be Done") 130 | } 131 | } 132 | 133 | ////////////////////////////////////////////////////////////////// 134 | //Input method for entering user password // 135 | ////////////////////////////////////////////////////////////////// 136 | var GuiPage_Search_Input = function() { 137 | var imeReady = function(imeObject) { 138 | installFocusKeyCallbacks(); 139 | } 140 | 141 | var ime = new IMEShell("searchInput", imeReady,'en'); 142 | ime.setKeypadPos(1300,90); 143 | 144 | var installFocusKeyCallbacks = function () { 145 | ime.setKeyFunc(tvKey.KEY_ENTER, function (keyCode) { 146 | alert("Enter key pressed"); 147 | var searchString = document.getElementById("searchInput").value; 148 | if (searchString != "") { 149 | //Load Data 150 | var url = Server.getSearchURL(searchString); 151 | GuiPage_Search.ItemData = Server.getContent(url); 152 | if (GuiPage_Search.ItemData == null) { return; } 153 | 154 | document.getElementById("ResultsTitle").innerHTML = GuiPage_Search.ItemData.TotalRecordCount + " Results for: " + searchString; 155 | ime.setString(""); 156 | 157 | if (GuiPage_Search.ItemData.SearchHints.length > 0) { 158 | 159 | //Turn On Screensaver 160 | Support.screensaverOn(); 161 | Support.screensaver(); 162 | 163 | GuiPage_Search.startParams[0] = document.getElementById("ResultsTitle").innerHTML; 164 | GuiPage_Search.startParams[1] = url; 165 | GuiPage_Search.selectedItem = 0; 166 | GuiPage_Search.updateDisplayedItems(); 167 | GuiPage_Search.updateSelectedItems(); 168 | document.getElementById("GuiPage_Search").focus(); 169 | } 170 | } 171 | }); 172 | 173 | ime.setKeyFunc(tvKey.KEY_DOWN, function (keyCode) { 174 | alert ("Down Key IME: " + GuiPage_Search.ItemData.TotalRecordCount); 175 | if (GuiPage_Search.ItemData.TotalRecordCount > 0) { 176 | //Turn On Screensaver 177 | Support.screensaverOn(); 178 | Support.screensaver(); 179 | 180 | GuiPage_Search.selectedItem = 0; 181 | GuiPage_Search.selectedItem2 = 0; 182 | GuiPage_Search.updateSelectedItems(); 183 | 184 | setTimeout(function () { 185 | document.getElementById("GuiPage_Search").focus(); 186 | },500) 187 | 188 | } 189 | }); 190 | 191 | ime.setKeyFunc(tvKey.KEY_INFO, function (keyCode) { 192 | GuiHelper.toggleHelp("GuiPage_Search"); 193 | }); 194 | 195 | ime.setKeyFunc(tvKey.KEY_RETURN, function (keyCode) { 196 | widgetAPI.blockNavigation(event); 197 | document.getElementById("NoKeyInput").focus(); 198 | Support.processReturnURLHistory(); 199 | }); 200 | 201 | ime.setKeyFunc(tvKey.KEY_EXIT, function (keyCode) { 202 | document.getElementById("NoKeyInput").focus(); 203 | widgetAPI.sendExitEvent(); 204 | }); 205 | } 206 | }; 207 | 208 | 209 | GuiPage_Search.keyDown = function() { 210 | var keyCode = event.keyCode; 211 | alert("Key pressed: " + keyCode); 212 | 213 | if (document.getElementById("Notifications").style.visibility == "") { 214 | document.getElementById("Notifications").style.visibility = "hidden"; 215 | document.getElementById("NotificationText").innerHTML = ""; 216 | widgetAPI.blockNavigation(event); 217 | //Change keycode so it does nothing! 218 | keyCode = "VOID"; 219 | } 220 | 221 | //Update Screensaver Timer 222 | Support.screensaver(); 223 | 224 | //If screensaver is running 225 | if (Main.getIsScreensaverRunning()) { 226 | //Update Main.js isScreensaverRunning - Sets to True 227 | Main.setIsScreensaverRunning(); 228 | 229 | //End Screensaver 230 | GuiImagePlayer_Screensaver.stopScreensaver(); 231 | 232 | //Change keycode so it does nothing! 233 | keyCode = "VOID"; 234 | } 235 | 236 | switch(keyCode) { 237 | case tvKey.KEY_LEFT: 238 | this.processLeftKey(); 239 | break; 240 | case tvKey.KEY_RIGHT: 241 | this.processRightKey(); 242 | break; 243 | case tvKey.KEY_UP: 244 | this.processUpKey(); 245 | break; 246 | case tvKey.KEY_DOWN: 247 | this.processDownKey(); 248 | break; 249 | case tvKey.KEY_PANEL_CH_UP: 250 | case tvKey.KEY_CH_UP: 251 | this.processChannelUpKey(); 252 | break; 253 | case tvKey.KEY_PANEL_CH_DOWN: 254 | case tvKey.KEY_CH_DOWN: 255 | this.processChannelDownKey(); 256 | break; 257 | case tvKey.KEY_RETURN: 258 | alert("RETURN"); 259 | widgetAPI.blockNavigation(event); 260 | Support.processReturnURLHistory(); 261 | break; 262 | case tvKey.KEY_ENTER: 263 | case tvKey.KEY_PANEL_ENTER: 264 | alert("ENTER"); 265 | this.processSelectedItem(); 266 | break; 267 | case tvKey.KEY_TOOLS: 268 | widgetAPI.blockNavigation(event); 269 | this.openMenu(true); 270 | break; 271 | case tvKey.KEY_YELLOW: 272 | //Favourites - May not be needed on this page 273 | break; 274 | case tvKey.KEY_BLUE: 275 | GuiMusicPlayer.showMusicPlayer("GuiPage_Search",this.playItems[this.selectedItem2]+this.ItemData.SearchHints[this.selectedItem].ItemId,"guiMusic_TableTd highlight"+Main.highlightColour+"Background"); 276 | break; 277 | case tvKey.KEY_EXIT: 278 | alert ("EXIT KEY"); 279 | widgetAPI.sendExitEvent(); 280 | break; 281 | } 282 | } 283 | 284 | GuiPage_Search.openMenu = function(hasData) { 285 | if (hasData) { 286 | Support.updateURLHistory("GuiPage_Search",this.startParams[0],this.startParams[1],null,null,0,0,null); 287 | 288 | for (var index = 0; index= this.ItemData.SearchHints.length) { 327 | this.selectedItem--; 328 | if (this.selectedItem >= (this.topLeftItem + this.getMaxDisplay())) { 329 | this.topLeftItem = this.topLeftItem + this.getMaxDisplay(); 330 | this.updateDisplayedItems(); 331 | } 332 | } else { 333 | if (this.selectedItem >= (this.topLeftItem + this.getMaxDisplay())) { 334 | this.topLeftItem++; 335 | this.updateDisplayedItems(); 336 | } 337 | } 338 | this.updateSelectedItems(); 339 | } 340 | 341 | GuiPage_Search.processLeftKey = function() { 342 | this.selectedItem2--; 343 | if (this.selectedItem2 == -1) { 344 | this.selectedItem2 = 0; 345 | this.openMenu(true); 346 | } else { 347 | this.updateSelectedItems(); 348 | } 349 | } 350 | 351 | GuiPage_Search.processRightKey = function() { 352 | this.selectedItem2++; 353 | if (this.selectedItem2 > this.playItems.length-1) { 354 | this.selectedItem2--; 355 | } else { 356 | this.updateSelectedItems(); 357 | } 358 | } 359 | 360 | GuiPage_Search.processChannelUpKey = function() { 361 | if (this.selectedItem > -1) { 362 | this.selectedItem = this.selectedItem - this.getMaxDisplay(); 363 | if (this.selectedItem < 0) { 364 | this.selectedItem = 0; 365 | this.topLeftItem = 0; 366 | this.updateDisplayedItems(); 367 | } else { 368 | if (this.topLeftItem - this.getMaxDisplay() < 0) { 369 | this.topLeftItem = 0; 370 | } else { 371 | this.topLeftItem = this.topLeftItem - this.getMaxDisplay(); 372 | } 373 | this.updateDisplayedItems(); 374 | } 375 | this.updateSelectedItems(); 376 | } 377 | } 378 | 379 | GuiPage_Search.processChannelDownKey = function() { 380 | if (this.selectedItem > -1) { 381 | this.selectedItem = this.selectedItem + this.getMaxDisplay(); 382 | if (this.selectedItem >= this.ItemData.SearchHints.length) { 383 | this.selectedItem = (this.ItemData.SearchHints.length-1); 384 | if (this.selectedItem >= this.topLeftItem + this.getMaxDisplay()) { 385 | this.topLeftItem = this.topLeftItem + this.getMaxDisplay(); 386 | } 387 | this.updateDisplayedItems(); 388 | } else { 389 | this.topLeftItem = this.topLeftItem + this.getMaxDisplay(); 390 | this.updateDisplayedItems(); 391 | } 392 | this.updateSelectedItems(); 393 | } 394 | } --------------------------------------------------------------------------------