diff options
Diffstat (limited to 'import/src/plugins/media_info.rs')
| -rw-r--r-- | import/src/plugins/media_info.rs | 166 |
1 files changed, 104 insertions, 62 deletions
diff --git a/import/src/plugins/media_info.rs b/import/src/plugins/media_info.rs index da445a3..250e417 100644 --- a/import/src/plugins/media_info.rs +++ b/import/src/plugins/media_info.rs @@ -5,10 +5,25 @@ */ use crate::plugins::{ImportContext, ImportPlugin, PluginInfo}; -use anyhow::{Result, anyhow}; -use jellyremuxer::matroska::Segment; +use anyhow::Result; +use jellycommon::{ + jellyobject::{Object, ObjectBuffer, Tag}, + *, +}; +use jellydb::table::RowNum; +use jellyremuxer::matroska::{Segment, TrackType}; use std::path::Path; +fn lang_str_to_tag(s: &str) -> Tag { + use jellycommon::*; + match s { + "eng" => LANG_ENG.0, + "deu" => LANG_DEU.0, + "jpn" => LANG_JPN.0, + _ => LANG_UND.0, + } +} + pub struct MediaInfo; impl ImportPlugin for MediaInfo { fn info(&self) -> PluginInfo { @@ -18,71 +33,98 @@ impl ImportPlugin for MediaInfo { ..Default::default() } } - fn media(&self, ct: &ImportContext, node: NodeID, path: &Path, seg: &Segment) -> Result<()> { - let tracks = seg - .tracks - .as_ref() - .ok_or(anyhow!("no tracks"))? - .entries - .iter() - .map(|track| SourceTrack { - codec: track.codec_id.clone(), - language: track.language.clone(), - name: track.name.clone().unwrap_or_default(), - federated: Vec::new(), - kind: if let Some(video) = &track.video { - SourceTrackKind::Video { - width: video.pixel_width, - height: video.pixel_height, - fps: video.frame_rate, - } - } else if let Some(audio) = &track.audio { - SourceTrackKind::Audio { - channels: audio.channels as usize, - sample_rate: audio.sampling_frequency, - bit_depth: audio.bit_depth.map(|r| r as usize), - } - } else { - SourceTrackKind::Subtitle - }, - source: TrackSource::Local(path.to_owned(), track.track_number), - }) - .collect::<Vec<_>>(); - + fn media(&self, ct: &ImportContext, row: RowNum, path: &Path, seg: &Segment) -> Result<()> { let size = path.metadata()?.len(); - - ct.db.update_node_init(node, |node| { - node.storage_size = size; - node.media = Some(jellycommon::MediaInfo { - chapters: seg - .chapters - .clone() - .map(|c| { - let mut chaps = Vec::new(); - if let Some(ee) = c.edition_entries.first() { - for ca in &ee.chapter_atoms { - let mut labels = Vec::new(); - for cd in &ca.displays { - for lang in &cd.languages { - labels.push((lang.to_owned(), cd.string.clone())) - } - } - chaps.push(Chapter { - labels, - time_start: Some(ca.time_start as f64 * 1e-9), - time_end: ca.time_end.map(|ts| ts as f64 * 1e-9), - }) + ct.dba.db.write_transaction(&mut |txn| { + let mut node = ct.dba.nodes.get(txn, row)?.unwrap(); + if let Some(tracks) = &seg.tracks { + node = node.as_object().extend_object( + NO_TRACK, + TR_SOURCE.0, + tracks.entries.iter().map(|t| { + let mut track = ObjectBuffer::empty(); + track = track.as_object().insert(TR_CODEC, &t.codec_id); + track = track + .as_object() + .insert(TR_LANGUAGE, lang_str_to_tag(&t.language)); + if let Some(name) = &t.name { + track = track.as_object().insert(TR_NAME, name); + } + track = track.as_object().insert( + TR_KIND, + match t.track_type { + TrackType::Audio => TRKIND_AUDIO, + TrackType::Video => TRKIND_VIDEO, + TrackType::Subtitle => TRKIND_TEXT, + _ => TRKIND_UNKNOWN, + }, + ); + if let Some(v) = &t.video { + track = track + .as_object() + .insert(TR_PIXEL_WIDTH, v.pixel_width as u32); + track = track + .as_object() + .insert(TR_PIXEL_HEIGHT, v.pixel_height as u32); + if let Some(fr) = v.frame_rate { + track = track.as_object().insert(TR_RATE, fr); + } + } + if let Some(a) = &t.audio { + track = track.as_object().insert(TR_CHANNELS, a.channels as u32); + track = track.as_object().insert(TR_RATE, a.sampling_frequency); + if let Some(d) = a.bit_depth { + track = track.as_object().insert(TR_BIT_DEPTH, d as u32); } } - chaps - }) - .unwrap_or_default(), - duration: fix_invalid_runtime( + + let source = Object::EMPTY + .insert(TRSOURCE_LOCAL_PATH, &path.to_string_lossy()) + .as_object() + .insert(TRSOURCE_LOCAL_TRACKNUM, t.track_number); + track = track.as_object().insert(TR_SOURCE, source.as_object()); + + track + }), + ); + } + + if let Some(chapters) = &seg.chapters { + node = node.as_object().extend_object( + NO_CHAPTER, + CH_NAME.0, + chapters + .edition_entries + .iter() + .flat_map(|e| &e.chapter_atoms) + .map(|cha| { + let mut chapter = ObjectBuffer::empty(); + chapter = chapter + .as_object() + .insert(CH_START, cha.time_start as f64 * 1e-9); + if let Some(end) = cha.time_end { + chapter = chapter.as_object().insert(CH_END, end as f64 * 1e-9); + } + if let Some(display) = cha.displays.iter().next() { + chapter = chapter.as_object().insert(CH_NAME, &display.string); + } + chapter + }), + ); + } + + node = node.as_object().insert( + NO_DURATION, + fix_invalid_runtime( seg.info.duration.unwrap_or_default() * seg.info.timestamp_scale as f64 * 1e-9, ), - tracks, - }); - })?; + ); + node = node.as_object().insert(NO_STORAGE_SIZE, size); + + ct.dba.nodes.update(txn, row, node); + + Ok(()) + }); Ok(()) } |