diff options
-rw-r--r-- | common/src/lib.rs | 2 | ||||
-rw-r--r-- | import/src/lib.rs | 84 |
2 files changed, 76 insertions, 10 deletions
diff --git a/common/src/lib.rs b/common/src/lib.rs index e61bdb9..c836b95 100644 --- a/common/src/lib.rs +++ b/common/src/lib.rs @@ -221,7 +221,7 @@ pub enum Rating { Trakt, } -#[derive(Debug, Clone, Deserialize, Serialize, Encode, Decode)] +#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, Encode, Decode)] #[serde(rename_all = "snake_case")] pub enum SourceTrackKind { Video { diff --git a/import/src/lib.rs b/import/src/lib.rs index 547179c..678d065 100644 --- a/import/src/lib.rs +++ b/import/src/lib.rs @@ -21,7 +21,7 @@ use jellybase::{ use jellyclient::Session; use jellycommon::{ AssetLocation, AssetRole, ExtendedNode, ImportOptions, ImportSource, MediaInfo, Node, NodeKind, - NodePrivate, NodePublic, PeopleGroup, Rating, TrackSource, + NodePrivate, NodePublic, PeopleGroup, Rating, SourceTrack, TrackSource, }; use jellymatroska::read::EbmlReader; use jellyremuxer::import::import_metadata; @@ -109,7 +109,7 @@ pub fn merge_nodes(db: &DataAcid) -> anyhow::Result<()> { let mut node = nodes .into_iter() .map(|(_, x)| x) - .reduce(|x, y| merge_node(x, y)) + .reduce(|x, y| merge_node(x, y).unwrap()) .unwrap(); node.public.id = Some(id.value().to_owned()); @@ -174,9 +174,9 @@ pub fn generate_node_paths(db: &DataAcid) -> anyhow::Result<()> { fn compare_index_path(x: &[usize], y: &[usize]) -> Ordering { if x.is_empty() { - Ordering::Greater - } else if y.is_empty() { Ordering::Less + } else if y.is_empty() { + Ordering::Greater } else { match x[0].cmp(&y[0]) { o @ (Ordering::Less | Ordering::Greater) => o, @@ -592,8 +592,23 @@ pub fn infer_id_from_path(path: &Path) -> anyhow::Result<String> { Ok(fsan) } -fn merge_node(x: Node, y: Node) -> Node { - Node { +fn merge_node(x: Node, y: Node) -> anyhow::Result<Node> { + let (media, source) = match ( + x.public.media, + y.public.media, + x.private.source, + y.private.source, + ) { + (Some(x), Some(y), Some(sx), Some(sy)) => { + let k = merge_media(x, y, sx, sy); + (Some(k.0), Some(k.1)) + } + (Some(x), None, Some(sx), None) => (Some(x), Some(sx)), + (None, Some(y), None, Some(sy)) => (Some(y), Some(sy)), + (None, None, None, None) => (None, None), + _ => bail!("invalid node. source and media dont agree."), + }; + Ok(Node { public: NodePublic { kind: x.public.kind.or(y.public.kind), title: x.public.title.or(y.public.title), @@ -604,7 +619,7 @@ fn merge_node(x: Node, y: Node) -> Node { description: x.public.description.or(y.public.description), release_date: x.public.release_date.or(y.public.release_date), index: x.public.index.or(y.public.index), - media: x.public.media.or(y.public.media), // TODO proper media merging + media, ratings: x .public .ratings @@ -617,9 +632,9 @@ fn merge_node(x: Node, y: Node) -> Node { id: x.private.id.or(y.private.id), poster: x.private.poster.or(y.private.poster), backdrop: x.private.backdrop.or(y.private.backdrop), - source: x.private.source.or(y.private.source), // TODO here too + source, }, - } + }) } fn merge_children(mut a: Vec<String>, b: Vec<String>) -> Vec<String> { @@ -631,6 +646,57 @@ fn merge_children(mut a: Vec<String>, b: Vec<String>) -> Vec<String> { } a } +fn merge_media( + x: MediaInfo, + y: MediaInfo, + sx: Vec<TrackSource>, + sy: Vec<TrackSource>, +) -> (MediaInfo, Vec<TrackSource>) { + let mut tracks: Vec<SourceTrack> = Vec::new(); + let mut source: Vec<TrackSource> = Vec::new(); + for (t, s) in x + .tracks + .into_iter() + .zip(sx.into_iter()) + .chain(y.tracks.into_iter().zip(sy.into_iter())) + { + let mut remove = None; + let mut skip = false; + for (i, ot) in tracks.iter().enumerate() { + if t.name == ot.name + && t.kind == ot.kind + && t.language == ot.language + && t.codec == ot.codec + { + if t.federated.len() < ot.federated.len() { + remove = Some(i); + } else { + skip = true; + } + } + } + if let Some(r) = remove { + tracks.swap_remove(r); + source.swap_remove(r); + } + if !skip { + tracks.push(t); + source.push(s); + } + } + ( + MediaInfo { + duration: x.duration * 0.5 + y.duration * 0.5, + tracks, + chapters: if x.chapters.len() > y.chapters.len() { + x.chapters + } else { + y.chapters + }, + }, + source, + ) +} static SEM_REMOTE_IMPORT: Semaphore = Semaphore::const_new(16); |