internal VolumeItem(VolumeDatabase database, VolumeItemType itemType) : base(tableName, primarykeyFields) { this.volumeID = 0L; this.itemID = 0L; //this.rootID = 0L; this.parentID = 0L; this.name = null; this.mimeType = null; this.metaData = MetadataStore.Empty; this.note = null; this.keywords = null; //this.ownerVolume = null; this.database = database; this.itemType = itemType; }
private static void ImportFile(IDataReader reader, long volumeID, long minFileID, string rootPath, MetadataStore metaData, VolumeDatabase db, BufferedVolumeItemWriter writer, long[] counters) { FileSystemVolumeItem item; if ((string)reader["type"] == "directory") { item = new DirectoryVolumeItem(db); counters[TOTAL_DIRS]++; } else { item = new FileVolumeItem(db); long size = (long)reader["size"]; ((FileVolumeItem)item).SetFileVolumeItemFields(size, null); counters[TOTAL_FILES]++; counters[TOTAL_SIZE] += size; } string path = (string)reader["path"]; Debug.Assert(path.StartsWith("file://"), "path starts with 'file://'"); string name = (string)reader["name"]; string location = DecoderUtility.UrlDecode(path); location = location.Substring(rootPath.Length); location = location.Substring(0, location.Length - name.Length - 1); if (location.Length == 0) location = "/"; long itemID = 2 + (long)reader["id"] - minFileID; // id 1 is the root item long parentID = Math.Max(1, 2 + (long)reader["idparent"] - minFileID); item.SetFileSystemVolumeItemFields(location, DateTime.MinValue, VolumeDatabase.ID_NONE); item.SetVolumeItemFields(volumeID, itemID, parentID, name, Util.ReplaceDBNull<string>(reader["mime"], null), metaData, Util.ReplaceDBNull<string>(reader["comment"], null), null); writer.Write(item); }
/// <summary> /// <para>Required by internal factory methods like AbstractVolumeScanner.GetNewVolumeItem<TVolumeItem>()</para> /// <para>Purpose :</para> /// <para> /// - guarantee that _all_ fields of this type are initialized by the caller /// (in contrast to property initialization, which easily makes you miss a property [in particular if a new one was added..]) /// </para> /// <para> /// - seperate fields of a type from fields of its base type (e.g. GetNewVolumeItem<TVolumeItem>() initializes all fields of a the VolumeItem base type. /// Caller code only needs to initialize fields of the derived <TMediaItem> type) /// </para> /// </summary> internal void SetVolumeItemFields( long volumeID, long itemID, //long rootID, long parentID, string name, string mimeType, MetadataStore metaData, string note, string keywords /*Volume ownerVolume*/ ) { this.volumeID = volumeID; this.itemID = itemID; //this.m_rootID = rootID; this.parentID = parentID; this.name = name; this.mimeType = mimeType; this.metaData = metaData; this.note = note; this.keywords = keywords; //this.ownerVolume = ownerVolume; }
internal override void ReadFromVolumeDBRecord(IRecordData recordData) { volumeID = (long) recordData["VolumeID"]; itemID = (long) recordData["ItemID"]; //rootID = (long) recordData["RootID"]; parentID = (long) recordData["ParentID"]; name = Util.ReplaceDBNull<string>( recordData["Name"], null); mimeType = Util.ReplaceDBNull<string>( recordData["MimeType"], null); metaData = new MetadataStore(Util.ReplaceDBNull<string>( recordData["MetaData"], null)); note = Util.ReplaceDBNull<string>( recordData["Note"], null); keywords = Util.ReplaceDBNull<string>( recordData["Keywords"], null); }
private void RecursiveDump(XmlNode node, long volumeID, long parentID, ref string comment, ref string borrow, ref MetadataStore metadata) { long dirID = 0L; string b = null, c = null; MetadataStore md = MetadataStore.Empty; CheckForCancellationRequest(); switch (node.Name) { case "catalog": mediaCounter = 0; totalMedia = GetMediaCount(node); break; case "media": volumeID = targetDb.GetNextVolumeID(); dirID = 1L; // root item idCounter = 2L; // id 1 is the root item //path.Clear(); for (int i = 0; i < counters.Length; i++) counters[i] = 0L; break; case "directory": dirID = idCounter++; path.Push(node.Attributes["name"].Value); break; } foreach (XmlNode n in node) RecursiveDump(n, volumeID, dirID, ref c, ref b, ref md); switch (node.Name) { case "media": ImportMedia(node, b, c, volumeID); PostProgressUpdate((++mediaCounter * 100.0) / totalMedia); break; case "directory": path.Pop(); ImportFile(node, c, volumeID, parentID, dirID, path, /* ignore weird CdCat directory metadata */ MetadataStore.Empty); break; case "file": ImportFile(node, c, volumeID, parentID, idCounter++, path, md); break; case "comment": if (!ConvertMetaData(node, ref metadata)) comment = node.InnerText.Trim(); break; case "borrow": borrow = node.InnerText.Trim(); break; case "mp3tag": ConvertMetaData(node, ref metadata); break; case "datafile": if (float.Parse(node.Attributes["version"].Value, ci.NumberFormat) > MAX_SUPPORTED_VERSION) throw new ImportException("Unsupported catalog version"); break; } }
private void ImportFile(XmlNode node, string comment, long volumeID, long parentID, long itemID, Stack<string> path, MetadataStore metaData) { FileSystemVolumeItem item; string location = "/" + string.Join("/", path.Reverse()); string name = node.Attributes["name"].Value; string mimeType; DateTime lastWriteTime; if (node.Name == "directory") { item = new DirectoryVolumeItem(targetDb); mimeType = VolumeScanner.FilesystemVolumeScanner.MIME_TYPE_DIRECTORY; counters[TOTAL_DIRS]++; } else { item = new FileVolumeItem(targetDb); // prepend a non-existing path to ensure the file doesn't actually exist // in the current environment directory mimeType = MimeType.GetMimeTypeForFile(mimePathPrefix + name); long size = ConvertSize(node.Attributes["size"].Value); ((FileVolumeItem)item).SetFileVolumeItemFields(size, null); counters[TOTAL_FILES]++; counters[TOTAL_SIZE] += size; } if (!DateTime.TryParseExact(node.Attributes["time"].Value, DATETIME_FORMAT, ci.DateTimeFormat, DateTimeStyles.None, out lastWriteTime)) lastWriteTime = DateTime.MinValue; item.SetFileSystemVolumeItemFields(location, lastWriteTime, VolumeDatabase.ID_NONE); item.SetVolumeItemFields(volumeID, itemID, parentID, name, mimeType, metaData, comment, null); writer.Write(item); }
private bool ConvertMetaData(XmlNode node, ref MetadataStore metadata) { List<MetadataItem> convertedData; StringSplitOptions opts = StringSplitOptions.RemoveEmptyEntries; Debug.Assert((node.Name == "mp3tag") || (node.Name == "comment"), string.Format("Expected 'mp3tag' or 'comment' node but got '{0}' node", node.Name)); try { string tmp; switch (node.Name) { case "mp3tag": convertedData = new List<MetadataItem>(); foreach (var pair in metadataMapping) { tmp = node.Attributes[pair.Key].Value.Trim(); if (tmp.Length > 0) convertedData.Add(new MetadataItem(pair.Value, tmp)); } string comment = node.InnerText.Trim(); if (comment.Length > 0) convertedData.Add(new MetadataItem(MetadataType.COMMENT, comment)); if (convertedData.Count > 0) metadata = new MetadataStore(convertedData); break; case "comment": string match; tmp = node.InnerText.Trim(); // try to parse Video/Audio info from comments, // e. g. "Video:#XVID MPEG-4#Gesamtzeit = 1:16:09#Framerate = 23.976 f/s#Aufloesung = 640x272##Audio:#ISO/MPEG Layer-3 // #Kanaele = 2 #Sample/s = 48.0kHz #Bitrate = 123 kBit" if (tmp.StartsWith("Video:#")) { convertedData = new List<MetadataItem>(); string[] streams = tmp.Split(new string[] { "##" }, opts); // // parse video info // string videoFormat = null; string framerate = null; if (Match(streams[0], @"([\d\.]+) f/s", out match)) { // framerate float fps; if (float.TryParse(match, NumberStyles.AllowDecimalPoint, ci.NumberFormat, out fps)) framerate = string.Format(ci.NumberFormat, "{0:F2} fps", fps); } if (Match(streams[0], @"^Video:#([#/\w\.\-\+\(\)\$\s]+)#", out match)) { // videoformat videoFormat = match; if (framerate != null) videoFormat += ", " + framerate; } if (Match(streams[0], @"(\d+:\d+:\d+)", out match)) { // duration TimeSpan duration = TimeSpan.Parse(match); convertedData.Add(new MetadataItem(MetadataType.DURATION, MetadataUtils.SecsToMetadataDuration(duration.TotalSeconds))); } if (Match(streams[0], @"(\d+x\d+)", out match)) { // size (NxM) convertedData.Add(new MetadataItem(MetadataType.SIZE, match)); } if (videoFormat != null) { string format; // // audio stream info available? // if ((streams.Length > 1) && (streams[1].StartsWith("Audio:#"))) { string audioFormat; List<string> fmt = new List<string>(); if (Match(streams[1], @"([\w\.\s]+)kHz", out match)) { // frequency int freq = ((int)float.Parse(match, ci.NumberFormat)) * 1000; fmt.Add(freq.ToString() + " Hz"); } if (Match(streams[1], @"(\d+) kBit", out match)) { // bitrate fmt.Add(match + " kb/s"); } if (Match(streams[1], @"^Audio:#([#/\w\.\-\+\(\)\$\s]+)#", out match)) { // audioformat audioFormat = match; if (fmt.Count > 0) audioFormat += ", " + string.Join(", ", fmt); format = string.Format("Video: {0}; Audio: {1}", videoFormat, audioFormat); } else { format = videoFormat; } } else { format = videoFormat; } convertedData.Add(new MetadataItem(MetadataType.FORMAT, format)); } if (convertedData.Count > 0) metadata = new MetadataStore(convertedData); // try to parse audio only info // e. g. "0:7, 192 kbps#44100Hz, Simple stereo" // (try to parse duration only) } else if (Match(tmp, @"^(\d+:\d{1,2}), \d+ kbps", out match)) { // don't use DateTime.ParseExact() since minutes may be > 59 string[] time = match.Split(new char[] { ':' }, opts); int mins = int.Parse(time[0]); int secs = int.Parse(time[1]); double duration = (mins * 60.0) + secs; metadata = new MetadataStore(new MetadataItem[] { new MetadataItem(MetadataType.DURATION, MetadataUtils.SecsToMetadataDuration(duration)) }); // try to parse audio only info // e. g. "VBR,44100Hz#Joint stereo" (didn't encounter ABR or CBR yet) } else if (Regex.IsMatch(tmp, @"^(VBR|ABR|CBR){1},\d+Hz")) { // ignored // "Encoder: Lavf52.77.0 // Video tracks: // Track 1: , 640x480 @ 25.0 fps, 1:59:23.5 // Audio tracks: // Track 2: MPEG-4 (AAC), 128 kbps, 44100 Hz, Channels: 2, 1:59:23.5" } else if (Regex.IsMatch(tmp, @"Video tracks:\nTrack \d+:")) { convertedData = new List<MetadataItem>(); if (Match(tmp, @"(\d+x\d+)", out match)) { // size (NxM) convertedData.Add(new MetadataItem(MetadataType.SIZE, match)); } if (Match(tmp, @"(\d+:\d+:\d+)", out match)) { TimeSpan duration = TimeSpan.Parse(match); convertedData.Add(new MetadataItem(MetadataType.DURATION, MetadataUtils.SecsToMetadataDuration(duration.TotalSeconds))); } else if (Match(tmp, @"(\d+:\d+) min", out match)) { string[] time = match.Split(new char[] { ':' }, opts); int mins = int.Parse(time[0]); int secs = int.Parse(time[1]); double duration = (mins * 60.0) + secs; convertedData.Add(new MetadataItem(MetadataType.DURATION, MetadataUtils.SecsToMetadataDuration(duration))); } if (convertedData.Count > 0) metadata = new MetadataStore(convertedData); // "foo text // Windows Media Audio 9 // 32 kbps, 32 kHz, stereo (A/V) 1-pass CBR" } else if (Regex.IsMatch(tmp, @"Windows Media Audio \d+( Professional)?\n\d+ kbps")) { // ignored, audio only info for a wmv file // "640 x 340, 25,000 fps, 765,8 kbit/s (2:19:29) // XviD MPEG-4 codec // MPEG-1 Layer 3 (MP3), 128,0 kbit/s, 48000 Hz, stereo // --- // Software: VirtualDubMod 1.5.10.2 (build 2542/release)" } else if (Match(tmp, @"^""(\d+ x \d+), \d+[,\.]{1}\d+ fps", out match)) { convertedData = new List<MetadataItem>(); convertedData.Add(new MetadataItem(MetadataType.SIZE, match.Replace(" ", ""))); if (Match(tmp, @"(\d+:\d+:\d+)", out match)) { TimeSpan duration = TimeSpan.Parse(match); convertedData.Add(new MetadataItem(MetadataType.DURATION, MetadataUtils.SecsToMetadataDuration(duration.TotalSeconds))); } metadata = new MetadataStore(convertedData); // try to parse image info, e.g.: // "751 x 500, 16.7 million colors (24 bit) // --- // Firmware Version: Adobe Photoshop CS3 Windows // 300 x 300 DPI" } else if (Match(tmp, @"^""?(\d+ x \d+), ([\w\.\s]+ colors|Black and White){1}", out match)) { metadata = new MetadataStore(new MetadataItem[] { new MetadataItem(MetadataType.SIZE, match.Replace(" ", "")) }); } else { return false; } break; default: return false; } // switch (node.Name) } catch (Exception ex) { Debug.WriteLine("Caught exception in ConvertMetaData():\n" + ex.ToString()); return false; } return true; }