public ICollection <Share> CreateDefaultShares() { List <Share> result = new List <Share>(); Guid localFsResourceProviderId = LocalFsResourceProviderBase.LOCAL_FS_RESOURCE_PROVIDER_ID; if (LocalResourceProviders.ContainsKey(localFsResourceProviderId)) { string folderPath; if (WindowsAPI.GetSpecialFolder(WindowsAPI.SpecialFolder.MyMusic, out folderPath)) { folderPath = LocalFsResourceProviderBase.ToProviderPath(folderPath); string[] mediaCategories = new[] { DefaultMediaCategories.Audio.ToString() }; Share sd = Share.CreateNewLocalShare(ResourcePath.BuildBaseProviderPath(localFsResourceProviderId, folderPath), MY_MUSIC_SHARE_NAME_RESOURE, mediaCategories); result.Add(sd); } if (WindowsAPI.GetSpecialFolder(WindowsAPI.SpecialFolder.MyVideos, out folderPath)) { folderPath = LocalFsResourceProviderBase.ToProviderPath(folderPath); string[] mediaCategories = new[] { DefaultMediaCategories.Video.ToString() }; Share sd = Share.CreateNewLocalShare(ResourcePath.BuildBaseProviderPath(localFsResourceProviderId, folderPath), MY_VIDEOS_SHARE_NAME_RESOURCE, mediaCategories); result.Add(sd); } if (WindowsAPI.GetSpecialFolder(WindowsAPI.SpecialFolder.MyPictures, out folderPath)) { folderPath = LocalFsResourceProviderBase.ToProviderPath(folderPath); string[] mediaCategories = new[] { DefaultMediaCategories.Image.ToString() }; Share sd = Share.CreateNewLocalShare(ResourcePath.BuildBaseProviderPath(localFsResourceProviderId, folderPath), MY_PICTURES_SHARE_NAME_RESOURCE, mediaCategories); result.Add(sd); } } if (result.Count > 0) { return(result); } // Fallback: If no share was added for the defaults above, use the provider's root folders result.AddRange(LocalBaseResourceProviders.Select(resourceProvider => resourceProvider.Metadata).Select( metadata => Share.CreateNewLocalShare(ResourcePath.BuildBaseProviderPath(metadata.ResourceProviderId, "/"), metadata.Name, null))); return(result); }
/// <summary> /// Helper method to create a valid <see cref="ResourcePath"/> from the given path. This method supports both local and UNC paths and will use the right ResourceProviderId. /// </summary> /// <param name="path">Path or file name</param> /// <returns></returns> protected static ResourcePath BuildResourcePath(string path) { Guid providerId; if (path.StartsWith("\\\\")) { // NetworkNeighborhoodResourceProvider providerId = new Guid("{03DD2DA6-4DA8-4D3E-9E55-80E3165729A3}"); // Cut-off the first \ path = path.Substring(1); } else { providerId = LocalFsResourceProviderBase.LOCAL_FS_RESOURCE_PROVIDER_ID; } string folderPath = LocalFsResourceProviderBase.ToProviderPath(path); var resourcePath = ResourcePath.BuildBaseProviderPath(providerId, folderPath); return(resourcePath); }
public ICollection <Share> CreateDefaultShares() { List <Share> result = new List <Share>(); Guid localFsResourceProviderId = LocalFsResourceProviderBase.LOCAL_FS_RESOURCE_PROVIDER_ID; if (LocalResourceProviders.ContainsKey(localFsResourceProviderId)) { string folderPath; if (WindowsAPI.GetSpecialFolder(Environment.SpecialFolder.MyMusic, out folderPath)) { folderPath = LocalFsResourceProviderBase.ToProviderPath(folderPath); string[] mediaCategories = new[] { DefaultMediaCategories.Audio.ToString() }; Share sd = Share.CreateNewLocalShare(ResourcePath.BuildBaseProviderPath(localFsResourceProviderId, folderPath), MY_MUSIC_SHARE_NAME_RESOURE, true, mediaCategories); result.Add(sd); } if (WindowsAPI.GetSpecialFolder(Environment.SpecialFolder.MyVideos, out folderPath)) { folderPath = LocalFsResourceProviderBase.ToProviderPath(folderPath); string[] mediaCategories = new[] { DefaultMediaCategories.Video.ToString() }; Share sd = Share.CreateNewLocalShare(ResourcePath.BuildBaseProviderPath(localFsResourceProviderId, folderPath), MY_VIDEOS_SHARE_NAME_RESOURCE, true, mediaCategories); result.Add(sd); } if (WindowsAPI.GetSpecialFolder(Environment.SpecialFolder.MyPictures, out folderPath)) { folderPath = LocalFsResourceProviderBase.ToProviderPath(folderPath); string[] mediaCategories = new[] { DefaultMediaCategories.Image.ToString() }; Share sd = Share.CreateNewLocalShare(ResourcePath.BuildBaseProviderPath(localFsResourceProviderId, folderPath), MY_PICTURES_SHARE_NAME_RESOURCE, true, mediaCategories); result.Add(sd); } } return(result); }
public ResourcePath ExpandResourcePathFromString(string pathStr) { if (string.IsNullOrEmpty(pathStr)) { return(null); } // The input string is given by the user. We can cope with three formats: // 1) A resource provider path which can be interpreted by the choosen resource provider itself (i.e. a path without the // starting resource provider GUID) // 2) A resource path in the resource path syntax (i.e. {[Base-Provider-Id]}://[Base-Provider-Path]) // 3) A dos path if (IsResource(pathStr)) { return(new ResourcePath(new ProviderPathSegment[] { new ProviderPathSegment(_metadata.ResourceProviderId, pathStr, true), })); } string providerPath = LocalFsResourceProviderBase.ToProviderPath(pathStr); if (IsResource(providerPath)) { return(new ResourcePath(new ProviderPathSegment[] { new ProviderPathSegment(_metadata.ResourceProviderId, providerPath, true), })); } try { return(ResourcePath.Deserialize(pathStr)); } catch (ArgumentException) { return(null); } }
protected int FindExternalSubtitles(ILocalFsResourceAccessor lfsra, IDictionary <Guid, IList <MediaItemAspect> > extractedAspectData) { int subtitleCount = 0; try { IList <MultipleMediaItemAspect> providerResourceAspects; if (!MediaItemAspect.TryGetAspects(extractedAspectData, ProviderResourceAspect.Metadata, out providerResourceAspects)) { return(0); } int newResourceIndex = -1; foreach (MultipleMediaItemAspect providerResourceAspect in providerResourceAspects) { int resouceIndex = providerResourceAspect.GetAttributeValue <int>(ProviderResourceAspect.ATTR_RESOURCE_INDEX); if (newResourceIndex < resouceIndex) { newResourceIndex = resouceIndex; } } newResourceIndex++; using (lfsra.EnsureLocalFileSystemAccess()) { foreach (MultipleMediaItemAspect mmia in providerResourceAspects) { string accessorPath = (string)mmia.GetAttributeValue(ProviderResourceAspect.ATTR_RESOURCE_ACCESSOR_PATH); ResourcePath resourcePath = ResourcePath.Deserialize(accessorPath); if (mmia.GetAttributeValue <int>(ProviderResourceAspect.ATTR_TYPE) != ProviderResourceAspect.TYPE_PRIMARY) { continue; } string filePath = LocalFsResourceProviderBase.ToDosPath(resourcePath); if (string.IsNullOrEmpty(filePath)) { continue; } List <string> subs = new List <string>(); int videoResouceIndex = (int)mmia.GetAttributeValue(ProviderResourceAspect.ATTR_RESOURCE_INDEX); string[] subFiles = Directory.GetFiles(Path.GetDirectoryName(filePath), Path.GetFileNameWithoutExtension(filePath) + "*.*"); if (subFiles != null) { subs.AddRange(subFiles); } foreach (string folder in SUBTITLE_FOLDERS) { if (string.IsNullOrEmpty(Path.GetPathRoot(folder)) && Directory.Exists(Path.Combine(Path.GetDirectoryName(filePath), folder))) //Is relative path { subFiles = Directory.GetFiles(Path.Combine(Path.GetDirectoryName(filePath), folder), Path.GetFileNameWithoutExtension(filePath) + "*.*"); } else if (Directory.Exists(folder)) //Is absolute path { subFiles = Directory.GetFiles(folder, Path.GetFileNameWithoutExtension(filePath) + "*.*"); } if (subFiles != null) { subs.AddRange(subFiles); } } foreach (string subFile in subFiles) { if (!HasSubtitleExtension(subFile)) { continue; } LocalFsResourceAccessor fsra = new LocalFsResourceAccessor((LocalFsResourceProvider)lfsra.ParentProvider, LocalFsResourceProviderBase.ToProviderPath(subFile)); //Check if already exists bool exists = false; foreach (MultipleMediaItemAspect providerResourceAspect in providerResourceAspects) { string subAccessorPath = (string)providerResourceAspect.GetAttributeValue(ProviderResourceAspect.ATTR_RESOURCE_ACCESSOR_PATH); ResourcePath subResourcePath = ResourcePath.Deserialize(subAccessorPath); if (subResourcePath.Equals(fsra.CanonicalLocalResourcePath)) { //Already exists exists = true; break; } } if (exists) { continue; } string subFormat = GetSubtitleFormat(subFile); if (!string.IsNullOrEmpty(subFormat)) { MultipleMediaItemAspect providerResourceAspect = MediaItemAspect.CreateAspect(extractedAspectData, ProviderResourceAspect.Metadata); providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_RESOURCE_INDEX, newResourceIndex); providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_TYPE, ProviderResourceAspect.TYPE_SECONDARY); providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_MIME_TYPE, GetSubtitleMime(subFormat)); providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_SIZE, fsra.Size); providerResourceAspect.SetAttribute(ProviderResourceAspect.ATTR_RESOURCE_ACCESSOR_PATH, fsra.CanonicalLocalResourcePath.Serialize()); MultipleMediaItemAspect subtitleResourceAspect = MediaItemAspect.CreateAspect(extractedAspectData, SubtitleAspect.Metadata); subtitleResourceAspect.SetAttribute(SubtitleAspect.ATTR_RESOURCE_INDEX, newResourceIndex); subtitleResourceAspect.SetAttribute(SubtitleAspect.ATTR_VIDEO_RESOURCE_INDEX, videoResouceIndex); subtitleResourceAspect.SetAttribute(SubtitleAspect.ATTR_STREAM_INDEX, -1); //External subtitle subtitleResourceAspect.SetAttribute(SubtitleAspect.ATTR_SUBTITLE_FORMAT, subFormat); subtitleResourceAspect.SetAttribute(SubtitleAspect.ATTR_INTERNAL, false); subtitleResourceAspect.SetAttribute(SubtitleAspect.ATTR_DEFAULT, subFile.ToLowerInvariant().Contains(".default.")); subtitleResourceAspect.SetAttribute(SubtitleAspect.ATTR_FORCED, subFile.ToLowerInvariant().Contains(".forced.")); bool imageBased = IsImageBasedSubtitle(subFormat); string language = GetSubtitleLanguage(subFile, imageBased); if (language != null) { subtitleResourceAspect.SetAttribute(SubtitleAspect.ATTR_SUBTITLE_LANGUAGE, language); } if (imageBased == false) { string encoding = GetSubtitleEncoding(subFile, language); if (encoding != null) { subtitleResourceAspect.SetAttribute(SubtitleAspect.ATTR_SUBTITLE_ENCODING, encoding); } } else { subtitleResourceAspect.SetAttribute(SubtitleAspect.ATTR_SUBTITLE_ENCODING, SubtitleAspect.BINARY_ENCODING); } newResourceIndex++; subtitleCount++; } } } } } catch (Exception e) { ServiceRegistration.Get <ILogger>().Info("SubtitleMetadataExtractor: Exception finding external subtitles for resource '{0}' (Text: '{1}')", e, lfsra.CanonicalLocalResourcePath, e.Message); } return(subtitleCount); }
protected void PrepareMediaSources() { Dictionary <string, ICollection <MediaCategory> > checkFolders = new Dictionary <string, ICollection <MediaCategory> >(); List <string> recordingFolders; string singlePattern; string seriesPattern; if (!GetRecordingConfiguration(out recordingFolders, out singlePattern, out seriesPattern)) { ServiceRegistration.Get <ILogger>().Warn("SlimTvService: Unable to configure MediaSource for recordings, probably TV configuration wasn't run yet."); return; } string movieSubfolder = GetFixedFolderPart(singlePattern); string seriesSubfolder = GetFixedFolderPart(seriesPattern); foreach (var recordingFolder in recordingFolders) { if (!string.IsNullOrEmpty(movieSubfolder) && !string.IsNullOrEmpty(seriesSubfolder)) { // If there are different target folders defined, register the media sources with specialized Series/Movie types checkFolders.Add(FileUtils.CheckTrailingPathDelimiter(Path.Combine(recordingFolder, movieSubfolder)), new HashSet <MediaCategory> { DefaultMediaCategories.Video, Movie }); checkFolders.Add(FileUtils.CheckTrailingPathDelimiter(Path.Combine(recordingFolder, seriesSubfolder)), new HashSet <MediaCategory> { DefaultMediaCategories.Video, Series }); } else { checkFolders.Add(FileUtils.CheckTrailingPathDelimiter(recordingFolder), new HashSet <MediaCategory> { DefaultMediaCategories.Video }); } } IMediaLibrary mediaLibrary = ServiceRegistration.Get <IMediaLibrary>(); int cnt = 1; foreach (var folderTypes in checkFolders) { try { List <Share> shares; // Check if there are already share(s) for the folder if (GetSharesForPath(folderTypes.Key, out shares)) { continue; } var folderPath = LocalFsResourceProviderBase.ToProviderPath(folderTypes.Key); var mediaCategories = folderTypes.Value.Select(mc => mc.CategoryName); Share sd = Share.CreateNewLocalShare(ResourcePath.BuildBaseProviderPath(LocalFsResourceProviderBase.LOCAL_FS_RESOURCE_PROVIDER_ID, folderPath), string.Format("Recordings ({0})", cnt), mediaCategories); mediaLibrary.RegisterShare(sd); cnt++; } catch (Exception ex) { ServiceRegistration.Get <ILogger>().Error("SlimTvService: Error registering new MediaSource.", ex); } } }
protected override async Task <bool> ConvertSubtitleFileAsync(string clientId, VideoTranscoding video, double timeStart, string transcodingFile, SubtitleStream sourceSubtitle, SubtitleStream res) { SubtitleCodec targetCodec = video.TargetSubtitleCodec; if (targetCodec == SubtitleCodec.Unknown) { targetCodec = sourceSubtitle.Codec; } string tempFile = null; FFMpegTranscodeData data = new FFMpegTranscodeData(_cachePath) { TranscodeId = video.TranscodeId + "_sub", ClientId = clientId }; if (string.IsNullOrEmpty(video.TranscoderBinPath) == false) { data.TranscoderBinPath = video.TranscoderBinPath; } if (string.IsNullOrEmpty(video.TranscoderArguments) == false) { // TODO: not sure if this is working data.TranscoderArguments = video.TranscoderArguments; data.InputMediaFilePaths.Add(0, res.SourcePath); data.InputArguments.Add(0, new List <string>()); } else { tempFile = transcodingFile + ".tmp"; res = await ConvertSubtitleEncodingAsync(res, tempFile, video.TargetSubtitleCharacterEncoding).ConfigureAwait(false); // TODO: not sure if this is working _ffMpegCommandline.InitTranscodingParameters(false, new Dictionary <int, string> { { 0, res.SourcePath } }, ref data); data.InputArguments[0].Add(string.Format("-f {0}", FFMpegGetSubtitleContainer.GetSubtitleContainer(sourceSubtitle.Codec))); if (timeStart > 0) { data.OutputArguments.Add(string.Format(CultureInfo.InvariantCulture, "-ss {0:0.0}", timeStart)); } res.Codec = targetCodec; string subtitleEncoder = "copy"; if (res.Codec == SubtitleCodec.Unknown) { res.Codec = SubtitleCodec.Ass; } if (sourceSubtitle.Codec != res.Codec) { subtitleEncoder = FFMpegGetSubtitleContainer.GetSubtitleContainer(res.Codec); } string subtitleFormat = FFMpegGetSubtitleContainer.GetSubtitleContainer(res.Codec); data.OutputArguments.Add("-vn"); data.OutputArguments.Add("-an"); data.OutputArguments.Add(string.Format("-c:s {0}", subtitleEncoder)); data.OutputArguments.Add(string.Format("-f {0}", subtitleFormat)); } data.OutputFilePath = transcodingFile; _logger.Debug("FFMpegMediaConverter: Invoking transcoder to transcode subtitle file '{0}' for transcode '{1}'", res.SourcePath, data.TranscodeId); bool success = false; var path = ResourcePath.Deserialize(res.SourcePath); if (path.TryCreateLocalResourceAccessor(out var subRes)) { using (var rah = new LocalFsResourceAccessorHelper(subRes)) using (var access = rah.LocalFsResourceAccessor.EnsureLocalFileSystemAccess()) { var result = await FFMpegBinary.FFMpegExecuteWithResourceAccessAsync(rah.LocalFsResourceAccessor, data.TranscoderArguments, ProcessPriorityClass.Normal, _transcoderTimeout).ConfigureAwait(false); success = result.Success; } } if (success && File.Exists(transcodingFile) == true) { if (tempFile != null && File.Exists(tempFile)) { File.Delete(tempFile); } res.SourcePath = LocalFsResourceProviderBase.ToProviderPath(transcodingFile); return(true); } return(false); }