/// <summary> /// 재생목록 중 해당경로에 따른 단건을 조회한다. /// </summary> /// <param name="path"></param> /// <returns></returns> private MediaInfo GetPlayList(string query, string path) { MediaInfo mi = null; using (var stmt = conn.Prepare(query)) { stmt.Bind("@PATH", path); if (stmt.Step() == SQLiteResult.ROW) { mi = GetRowDataForPlayList(stmt); if (stmt.GetText("HAS_SUBTITLE") == "Y") { using (var stmt2 = conn.Prepare(DML_SELECT_SUBTITLE)) { stmt2.Bind("@OWNER_PATH", mi.Path); while (stmt2.Step() == SQLiteResult.ROW) { mi.AddSubtitle(new SubtitleInfo { Path = stmt2.GetText("PATH"), Owner = stmt2.GetText("OWNER_PATH"), FalToken = stmt2.GetText2("FAL_TOKEN") }); } } } } } return(mi); }
/// <summary> /// 모든 비디오을 검색한다. /// </summary> /// <param name="allVideoList">로딩될 리스트</param> public void SearchAllVideoList(ICollection <MediaInfo> allVideoList, string searchWord) { //보호되는 폴더 목록 List <FolderInfo> pFiList = GetProtectedFolderList(); using (var stmt = conn.Prepare(DML_SELECT_MEDIA.Replace("@WHERE", "WHERE LOWER(NAME) LIKE '%' || @NAME || '%'"))) { stmt.Bind("@NAME", searchWord); string prevItemName = string.Empty; while (stmt.Step() == SQLiteResult.ROW) { MediaInfo fi = new MediaInfo() { Path = stmt.GetText("PATH"), Name = stmt.GetText("NAME"), FalToken = stmt.GetText2("FAL_TOKEN"), }; if (!pFiList.Any(x => fi.Path.Contains(x.Path))) { if (stmt.GetText("HAS_SUBTITLE") == "Y") { using (var stmt2 = conn.Prepare(DML_SELECT_SUBTITLE)) { stmt2.Bind("@OWNER_PATH", fi.Path); while (stmt2.Step() == SQLiteResult.ROW) { fi.AddSubtitle(new SubtitleInfo { Path = stmt2.GetText("PATH"), Owner = stmt2.GetText("OWNER_PATH"), FalToken = stmt2.GetText2("FAL_TOKEN") }); } } } //이름이 중복되는 경우 루트 경로를 표시 if (prevItemName == fi.Name) { fi.Name = string.Format("{0} ({1})", fi.Name, Path.GetPathRoot(fi.Path)); } allVideoList.Add(fi); prevItemName = fi.Name; } } } }
/// <summary> /// 재생 목록을 로딩한다. /// </summary> /// <param name="allVideoList">로딩될 리스트</param> public void LoadPlayList(ICollection <MediaInfo> playList, int count, int skip, bool loadSubtitle) { var query = new StringBuilder(DML_SELECT_PLAYLIST) .Replace("${INLINE_VIEW}", "PLAY_LIST") .AppendLine() .AppendLine("ORDER BY P.ADDED_DATETIME DESC, P.ORDER_NO DESC, M.NAME") .AppendLine("LIMIT @COUNT OFFSET @SKIP"); using (var stmt = conn.Prepare(query.ToString())) { string prevItemName = string.Empty; stmt.Bind("@COUNT", count); stmt.Bind("@SKIP", skip); while (stmt.Step() == SQLiteResult.ROW) { MediaInfo mi = GetRowDataForPlayList(stmt); if (loadSubtitle && stmt.GetText("HAS_SUBTITLE") == "Y") { using (var stmt2 = conn.Prepare(DML_SELECT_SUBTITLE)) { stmt2.Bind("@OWNER_PATH", mi.Path); while (stmt2.Step() == SQLiteResult.ROW) { mi.AddSubtitle(new SubtitleInfo { Path = stmt2.GetText("PATH"), Owner = stmt2.GetText("OWNER_PATH"), FalToken = stmt2.GetText2("FAL_TOKEN") }); } } } //이름이 중복되는 경우 루트 경로를 표시 if (prevItemName == mi.Name) { mi.Name = string.Format("{0} ({1})", mi.Name, Path.GetPathRoot(mi.Path)); } playList.Add(mi); prevItemName = mi.Name; } } }
public void AddAllVideoJumpList(IEnumerable <StorageFile> fileList) { var mediaFiles = fileList.Where(x => x.IsVideoFile());//.OrderBy(x => x.DateCreated); if (mediaFiles.Any()) { var mediaInfoList = new List <MediaInfo>(); var subtitleFiles = fileList.Where(x => x.IsSubtitleFile()).ToList(); foreach (var file in mediaFiles) { var mi = new MediaInfo(file); //비동기 모드로 자막 정보 로드 var asyncAction = ThreadPool.RunAsync((handler) => { //재생목록 추가여부 표시 mi.IsAddedPlaylist = playlist.Any(x => x.Path == mi.Path); var fileName = file.Path.Remove(mi.Path.Length - Path.GetExtension(mi.Path).Length).ToUpper(); foreach (var ext in CCPlayerConstant.SUBTITLE_FILE_SUFFIX) { StorageFile subtitleFile = null; try { //System.InvalidOperationException를 방지하기 위해서 새롭게 리스트를 생성 subtitleFile = new List <StorageFile>(subtitleFiles).FirstOrDefault( x => x.Path.Length > ext.Length && Path.GetExtension(x.Path).ToUpper() == ext.ToUpper() && x.Path.Remove(x.Path.Length - ext.Length).ToUpper().Contains(fileName)); } catch (Exception) { } if (subtitleFile != null) { subtitleFiles.Remove(subtitleFile); //자막을 미디어 파일에 연결 mi.AddSubtitle(new SubtitleInfo(subtitleFile)); } } if (mi.SubtitleFileList != null) { //미디어에 연결된 자막목록을 DB에 등록한다. fileDAO.InsertSubtitles(mi); } }); //미디어 파일을 그룹으로 생성할 리스트에 추가 mediaInfoList.Add(mi); } //DB 등록 fileDAO.InsertMedia(mediaInfoList); //그룹 변환 var ng = mediaInfoList.ToAlphaGroups(x => x.Name); //그룹 변환 포인터로 부터 데이터 복사 var group = new ObservableCollection <JumpListGroup <MediaInfo> >(ng); foreach (var jg in group) { DispatcherHelper.CheckBeginInvokeOnUI(() => { var curGrp = AllVideoSource.FirstOrDefault(x => (string)x.Key == (string)jg.Key); if (curGrp == null) { AllVideoSource.Add(jg); } else { if (jg.Count > 0) { foreach (var fi in jg) { //동일한 파일이 존재하면 추가하지 않음. if (curGrp.Any(x => x.Path.ToUpper() == fi.Path.ToUpper() && x.Name.ToUpper() == fi.Name.ToUpper())) { continue; } //삽입할 위치를 검색하여 해당 위치에 새로운 파일을 추가한다. int idx = curGrp.IndexOf(curGrp.FirstOrDefault(x => string.Compare(fi.Name, x.Name) < 0)); if (idx == -1) { curGrp.Add(fi); } else { if (curGrp.Any(x => x.Name == fi.Name)) { fi.Name = string.Format("{0} ({1})", fi.Name, Path.GetPathRoot(fi.Path)); } curGrp.Insert(idx, fi); } } } } }); } if (mediaInfoList.Count > 0) { DispatcherHelper.CheckBeginInvokeOnUI(() => { EnableButtons(true); }); } } }
public RawFile(Entities.VideoLocal vl, int level) { if (vl != null) { id = vl.VideoLocalID; crc32 = vl.CRC32; ed2khash = vl.ED2KHash; md5 = vl.MD5; sha1 = vl.SHA1; created = vl.DateTimeCreated; updated = vl.DateTimeUpdated; duration = vl.Duration; filename = vl.FileName; size = vl.FileSize; hash = vl.Hash; hash_source = vl.HashSource; is_ignored = vl.IsIgnored; if (vl.Media != null && ( level > 1 || level == 0)) { media = new MediaInfo(); // TODO APIV2: replace 1 with userid or rewrite file server url = APIHelper.ConstructVideoLocalStream(1, vl.Media.Id, "file." + vl.Media.Container, false); MediaInfo new_media = new MediaInfo(); new_media.AddGeneral(MediaInfo.General.format, vl.Media.Container); new_media.AddGeneral(MediaInfo.General.duration, vl.Media.Duration); new_media.AddGeneral(MediaInfo.General.id, vl.Media.Id); new_media.AddGeneral(MediaInfo.General.overallbitrate, vl.Media.Bitrate); if (vl.Media.Parts != null) { new_media.AddGeneral(MediaInfo.General.size, vl.Media.Parts[0].Size); foreach (JMMContracts.PlexAndKodi.Stream p in vl.Media.Parts[0].Streams) { switch (p.StreamType) { //video case "1": new_media.AddVideo(p); break; //audio case "2": new_media.AddAudio(p); break; //subtitle case "3": new_media.AddSubtitle(p); break; //menu case "4": Dictionary<string, string> mdict = new Dictionary<string, string>(); //TODO APIv2: menu object could be usefull for external players new_media.AddMenu(mdict); break; } } } media = new_media; } } }
public RawFile(NancyContext ctx, SVR_VideoLocal vl, int level, int uid) { if (vl != null) { id = vl.VideoLocalID; crc32 = vl.CRC32; ed2khash = vl.ED2KHash; md5 = vl.MD5; sha1 = vl.SHA1; created = vl.DateTimeCreated; updated = vl.DateTimeUpdated; duration = vl.Duration; if (vl.ReleaseGroup != null) { group_full = vl.ReleaseGroup.GroupName; group_short = vl.ReleaseGroup.GroupNameShort; group_id = vl.ReleaseGroup.AniDB_ReleaseGroupID; } size = vl.FileSize; hash = vl.Hash; hash_source = vl.HashSource; is_ignored = vl.IsIgnored; VideoLocal_User vl_user = vl.GetUserRecord(uid); if (vl_user != null) { offset = vl_user.ResumePosition; } else { offset = 0; } VideoLocal_Place place = vl.GetBestVideoLocalPlace(); if (place != null) { filename = place.FilePath; videolocal_place_id = place.VideoLocal_Place_ID; import_folder_id = place.ImportFolderID; } if (vl.EpisodeCrossRefs.Count == 0) { recognized = false; } else { recognized = true; } if (vl.Media != null && (level > 1 || level == 0)) { media = new MediaInfo(); url = APIHelper.ConstructVideoLocalStream(ctx, uid, vl.Media.Id, "file." + vl.Media.Container, false); MediaInfo new_media = new MediaInfo(); new_media.AddGeneral(MediaInfo.General.format, vl.Media.Container); new_media.AddGeneral(MediaInfo.General.duration, vl.Media.Duration); new_media.AddGeneral(MediaInfo.General.id, vl.Media.Id); new_media.AddGeneral(MediaInfo.General.overallbitrate, vl.Media.Bitrate); if (vl.Media.Parts != null) { new_media.AddGeneral(MediaInfo.General.size, vl.Media.Parts[0].Size); foreach (Shoko.Models.PlexAndKodi.Stream p in vl.Media.Parts[0].Streams) { switch (p.StreamType) { //video case "1": new_media.AddVideo(p); break; //audio case "2": new_media.AddAudio(p); break; //subtitle case "3": new_media.AddSubtitle(p); break; //menu case "4": Dictionary <string, string> mdict = new Dictionary <string, string>(); //TODO APIv2: menu object could be usefull for external players new_media.AddMenu(mdict); break; } } } media = new_media; } } }
public RawFile(Entities.VideoLocal vl, int level, int uid) { if (vl != null) { id = vl.VideoLocalID; crc32 = vl.CRC32; ed2khash = vl.ED2KHash; md5 = vl.MD5; sha1 = vl.SHA1; created = vl.DateTimeCreated; updated = vl.DateTimeUpdated; duration = vl.Duration; size = vl.FileSize; hash = vl.Hash; hash_source = vl.HashSource; is_ignored = vl.IsIgnored; if (vl.Places != null && vl.Places.Count >= 0) { filename = vl.Places[0].FilePath; videolocal_place_id = vl.Places[0].VideoLocal_Place_ID; import_folder_id = vl.Places[0].ImportFolderID; } if (vl.EpisodeCrossRefs.Count == 0) { recognized = false; } else { recognized = true; } if (vl.Media != null && (level > 1 || level == 0)) { media = new MediaInfo(); url = APIHelper.ConstructVideoLocalStream(uid, vl.Media.Id, "file." + vl.Media.Container, false); MediaInfo new_media = new MediaInfo(); new_media.AddGeneral(MediaInfo.General.format, vl.Media.Container); new_media.AddGeneral(MediaInfo.General.duration, vl.Media.Duration); new_media.AddGeneral(MediaInfo.General.id, vl.Media.Id); new_media.AddGeneral(MediaInfo.General.overallbitrate, vl.Media.Bitrate); if (vl.Media.Parts != null) { new_media.AddGeneral(MediaInfo.General.size, vl.Media.Parts[0].Size); foreach (JMMContracts.PlexAndKodi.Stream p in vl.Media.Parts[0].Streams) { switch (p.StreamType) { //video case "1": new_media.AddVideo(p); break; //audio case "2": new_media.AddAudio(p); break; //subtitle case "3": new_media.AddSubtitle(p); break; //menu case "4": Dictionary <string, string> mdict = new Dictionary <string, string>(); //TODO APIv2: menu object could be usefull for external players new_media.AddMenu(mdict); break; } } } media = new_media; } } }
public RawFile(HttpContext ctx, SVR_VideoLocal vl, int level, int uid, AnimeEpisode e = null) { if (vl == null) { return; } id = vl.VideoLocalID; crc32 = vl.CRC32; ed2khash = vl.ED2KHash; md5 = vl.MD5; sha1 = vl.SHA1; created = vl.DateTimeCreated; updated = vl.DateTimeUpdated; duration = vl.Duration; var releaseGroup = vl.ReleaseGroup; if (releaseGroup != null) { group_full = releaseGroup.GroupName; group_short = releaseGroup.GroupNameShort; group_id = releaseGroup.AniDB_ReleaseGroupID; } size = vl.FileSize; hash = vl.Hash; hash_source = vl.HashSource; is_ignored = vl.IsIgnored; var vl_user = vl.GetUserRecord(uid); offset = vl_user?.ResumePosition ?? 0; var place = vl.GetBestVideoLocalPlace(); if (place != null) { filename = place.FilePath; server_path = place.FullServerPath; videolocal_place_id = place.VideoLocal_Place_ID; import_folder_id = place.ImportFolderID; } url = APIV2Helper.ConstructVideoLocalStream(ctx, uid, vl.VideoLocalID.ToString(), "file" + Path.GetExtension(filename), false); recognized = e != null || vl.EpisodeCrossRefs.Count != 0; if (vl.Media == null || level < 0) { return; } MediaInfo new_media = new MediaInfo(); new_media.AddGeneral(MediaInfo.General.format, vl.Media.Container); new_media.AddGeneral(MediaInfo.General.duration, vl.Media.Duration); new_media.AddGeneral(MediaInfo.General.id, vl.Media.Id); new_media.AddGeneral(MediaInfo.General.overallbitrate, vl.Media.Bitrate); if (vl.Media.Parts != null) { new_media.AddGeneral(MediaInfo.General.size, vl.Media.Parts[0].Size); foreach (Stream p in vl.Media.Parts[0].Streams) { switch (p.StreamType) { //video case 1: new_media.AddVideo(p); break; //audio case 2: new_media.AddAudio(p); break; //subtitle case 3: new_media.AddSubtitle(p); break; //menu case 4: Dictionary <string, string> mdict = new Dictionary <string, string>(); //TODO APIv2: menu object could be usefull for external players new_media.AddMenu(mdict); break; } } } media = new_media; }
/// <summary> /// 다른 뷰모델들로 부터 수신된 메세지를 처리한다. /// </summary> private void RegisterMessages() { //재생목록 메세지 수신 MessengerInstance.Register <Message>(this, NAME, (msg) => { switch (msg.Key) { case "Activated": if (loadingModel != LoadingMode.None) { PlaylistSource.Clear(); LoadFiles(); } break; case "MoveToSection": //재생목록 섹션으로 이동 MoveToSection(msg.GetValue <HubSection>()); break; case "BackPressed": msg.GetValue <BackPressedEventArgs>().Handled = true; if (SelectionMode != ListViewSelectionMode.None) { //선택 모드 변경 SelectionMode = ListViewSelectionMode.None; MainButtonGroupVisible = true; CheckListButtonGroupVisible = false; ReorderButtonGroupVisible = false; } else { //종료 확인 MessengerInstance.Send <Message>(new Message("ConfirmTermination", null), MainViewModel.NAME); } break; case "FolderDeleted": //허브섹션을 반대 방향으로 들어오는 경우, 모든 비디오 DB가 초기화 되어 있지 않으면 초기화를 시킨다. MessengerInstance.Send <Message>(new Message("CheckFolderSyncForPlaylist", null), AllVideoViewModel.NAME); //탐색기에서 삭제된 폴더 삭제 Trigger //재생 목록 생성전 모든 비디오 파일과 재생 목록을 동기화하여 존재하지 않는 파일을 재생목록에서 제거 fileDAO.CleanPlayList(); //로딩 요청 상태 변경 loadingModel = LoadingMode.Caching; break; case "PlayItem": PlayItem(msg.GetValue <MediaInfo>()); break; case "PlayList": loadingModel = LoadingMode.Caching; var list = msg.GetValue <IEnumerable <MediaInfo> >(); MessengerInstance.Send <Message>(new Message("MoveToPlaylistSection", list.Count() > 1), CCPlayerViewModel.NAME); //재생 목록 생성전 모든 비디오 파일과 재생 목록을 동기화하여 존재하지 않는 파일을 재생목록에서 제거 fileDAO.CleanPlayList(); //재생 목록 생성 MakePlaylist(list); break; case "UpdatePausedTime": var source = msg.GetValue <MediaInfo>(); fileDAO.UpdatePlayList(new MediaInfo[] { source }); //화면 업데이트 처리 var item = PlaylistSource.FirstOrDefault(x => x.Path == source.Path); if (item != null) { item.RunningTime = source.RunningTime; item.PausedTime = source.PausedTime; } // System.Diagnostics.Debug.WriteLine(string.Format("재생시간 업데이트 : {0}", TimeSpan.FromSeconds(source.PausedTime))); break; case "FileAssociation": var value = msg.GetValue <FileActivatedEventArgs>(); if (value.Files != null && value.Files.Count > 0) { var file = value.Files.FirstOrDefault(); if (file != null && file.IsOfType(Windows.Storage.StorageItemTypes.File)) { var mi = new MediaInfo((StorageFile)file); //로딩 패널 표시 var loader = ResourceLoader.GetForCurrentView(); var loadingMsg = string.Format(loader.GetString("Loading"), loader.GetString("Video")); MessengerInstance.Send(new Message("ShowLoadingPanel", new KeyValuePair <string, bool>(loadingMsg, true)), MainViewModel.NAME); DispatcherHelper.CheckBeginInvokeOnUI(async() => { try { StorageFolder folder = await StorageFolder.GetFolderFromPathAsync(mi.ParentFolderPath); IReadOnlyList <StorageFile> fileStorageList = await folder.GetFilesAsync(); List <StorageFile> subtitleList = fileStorageList.Where(x => x.IsSubtitleFile()).ToList(); var pathName = mi.Path.Remove(mi.Path.Length - Path.GetExtension(mi.Path).Length); //자막 검색 foreach (var ext in CCPlayerConstant.SUBTITLE_FILE_SUFFIX) { StorageFile subtitleFile = null; try { subtitleFile = new List <StorageFile>(subtitleList).FirstOrDefault(x => Path.GetExtension(x.Path).ToUpper() == ext.ToUpper() && x.Path.Length > ext.Length && x.Path.Remove(x.Path.Length - ext.Length).ToUpper().Contains(pathName.ToUpper())); } catch (Exception) { } if (subtitleFile != null) { subtitleList.Remove(subtitleFile); //자막을 미디어 파일에 연결 mi.AddSubtitle(new SubtitleInfo(subtitleFile)); } } } catch (System.UnauthorizedAccessException) { } //재생 처리 MessengerInstance.Send <Message>(new Message("Play", mi), CCPlayerViewModel.NAME); }); } } break; case "ShowErrorFile": if (PlaylistSource.Any()) { var kv = msg.GetValue <KeyValuePair <string, MediaInfo> >(); var mi = PlaylistSource.FirstOrDefault(f => f.Path == kv.Value.Path); if (mi != null) { mi.OccuredError = kv.Key + "\n"; } } break; case "RemovePlayList": OnRemovePlayList(msg.GetValue <MediaInfo>()); break; } }); }
private async Task AddExplorerList(IEnumerable <StorageFile> storageFile, List <StorageFile> subtitleList, FolderInfo parentFolder, CancellationToken token) { var prevFolderName = string.Empty; //재생목록 로드 List <MediaInfo> playlist = null; foreach (var item in storageFile) { var mi = new MediaInfo(item); if (subtitleList != null) { //비동기 모드로 파일의 기본 정보(사이즈, 생성일자) 로드 var asyncAction = ThreadPool.RunAsync((handler) => { if (playlist == null) { playlist = new List <MediaInfo>(); fileDAO.LoadPlayList(playlist, 100, 0, false); } //재생목록 존재여부 체크 mi.IsAddedPlaylist = playlist.Any(x => x.Path == mi.Path); var pathName = mi.Path.Remove(mi.Path.Length - Path.GetExtension(mi.Path).Length); //자막 검색 foreach (var ext in CCPlayerConstant.SUBTITLE_FILE_SUFFIX) { StorageFile subtitleFile = null; try { subtitleFile = new List <StorageFile>(subtitleList).FirstOrDefault(x => Path.GetExtension(x.Path).ToUpper() == ext.ToUpper() && x.Path.Length > ext.Length && x.Path.Remove(x.Path.Length - ext.Length).ToUpper().Contains(pathName.ToUpper())); } catch (Exception) { } if (subtitleFile != null) { subtitleList.Remove(subtitleFile); //자막을 미디어 파일에 연결 mi.AddSubtitle(new SubtitleInfo(subtitleFile)); } } }, WorkItemPriority.Low); } else { if (prevFolderName == item.Name) { mi.Name = string.Format("{0} ({1})", mi.Name, Path.GetPathRoot(mi.Path)); } prevFolderName = item.Name; } token.ThrowIfCancellationRequested(); await DispatcherHelper.RunAsync(() => { //if (token == cancelTokenSource.Token) if (currentFolderInfo.Path == mi.ParentFolderPath) { ExplorerFileSource.Add(mi); } }); } }
public RawFile(Entities.VideoLocal vl, int level, int uid) { if (vl != null) { id = vl.VideoLocalID; crc32 = vl.CRC32; ed2khash = vl.ED2KHash; md5 = vl.MD5; sha1 = vl.SHA1; created = vl.DateTimeCreated; updated = vl.DateTimeUpdated; duration = vl.Duration; size = vl.FileSize; hash = vl.Hash; hash_source = vl.HashSource; is_ignored = vl.IsIgnored; if (vl.Places != null && vl.Places.Count >= 0) { filename = vl.Places[0].FilePath; videolocal_place_id = vl.Places[0].VideoLocal_Place_ID; import_folder_id = vl.Places[0].ImportFolderID; } if (vl.EpisodeCrossRefs.Count == 0) { recognized = false; } else { recognized = true; } if (vl.Media != null && ( level > 1 || level == 0)) { media = new MediaInfo(); url = APIHelper.ConstructVideoLocalStream(uid, vl.Media.Id, "file." + vl.Media.Container, false); MediaInfo new_media = new MediaInfo(); new_media.AddGeneral(MediaInfo.General.format, vl.Media.Container); new_media.AddGeneral(MediaInfo.General.duration, vl.Media.Duration); new_media.AddGeneral(MediaInfo.General.id, vl.Media.Id); new_media.AddGeneral(MediaInfo.General.overallbitrate, vl.Media.Bitrate); if (vl.Media.Parts != null) { new_media.AddGeneral(MediaInfo.General.size, vl.Media.Parts[0].Size); foreach (JMMContracts.PlexAndKodi.Stream p in vl.Media.Parts[0].Streams) { switch (p.StreamType) { //video case "1": new_media.AddVideo(p); break; //audio case "2": new_media.AddAudio(p); break; //subtitle case "3": new_media.AddSubtitle(p); break; //menu case "4": Dictionary<string, string> mdict = new Dictionary<string, string>(); //TODO APIv2: menu object could be usefull for external players new_media.AddMenu(mdict); break; } } } media = new_media; } } }