package shakuhachi

  1. Overview
  2. Docs
A music collection manager

Install

dune-project
 Dependency

Authors

Maintainers

Sources

0.2.0.tar.gz
sha256=966fc8667c2aa9830e64950d2de74bd564a65d60e1f50cfd3dc1e99ef106dc47
sha512=6423ce04d784ba521a7f49fabdafbe036e2dd80cd08ca999fdc6767262d7f12aa4e5002d65efd4c568b343eaabf4d680191c88334d629e1ca0156084531e9e0b

doc/src/shakuhachi.query/queryMusic.ml.html

Source file queryMusic.ml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
(*****************************************************************************)
(*                                                                           *)
(*  Copyright (C) 2026 Yves Ndiaye                                           *)
(*                                                                           *)
(* This Source Code Form is subject to the terms of the Mozilla Public       *)
(* License, v. 2.0. If a copy of the MPL was not distributed with this       *)
(* file, You can obtain one at https://mozilla.org/MPL/2.0/.                 *)
(*                                                                           *)
(*****************************************************************************)

module Metadata = SkhcMetadata.Metadata
module Ids = SkhcDb.Ids
module Roles = SkhcDb.Roles
include QueryUtil

let matches_node subfields (music_file, album, participants, properties) node =
  let metadata = SkhcMetadata.Metadata.init None [||] properties in
  let album_name = SkhcDb.Album.name album in
  let id = SkhcDb.MusicFile.id music_file in
  let path = SkhcDb.MusicFile.path music_file in
  let extension = Filename.extension path in
  let size = SkhcDb.MusicFile.size music_file in
  let play_count = SkhcDb.MusicFile.play_count music_file in
  let flag = SkhcDb.MusicFile.flag music_file in
  let rating = SkhcDb.MusicFile.rating music_file in
  let duration = SkhcDb.MusicFile.duration music_file in
  let has_cover = SkhcDb.MusicFile.has_cover music_file in
  let title = Metadata.title metadata in
  let sort_name = Metadata.title_sort metadata in
  let track_number = Metadata.track metadata in
  let disc_number = Metadata.disc metadata in
  let year = Metadata.year metadata in
  let genre = Metadata.genre metadata in

  match node with
  | Node.Substring s ->
      let fields = match_participants participants in
      let fields =
        Substring.(
          SubFields.(
            fields
            |> add_field_if_some STitle title
            |> add_field_if_some SSortName sort_name
            |> add SAlbum album_name
            |> add_field_if_some SGenre genre
            |> filter (fun key _ -> List.mem key subfields)
            |> bindings |> List.map snd
          )
        )
      in
      List.exists (matches ~insensible:true false s) fields
  | Field (FString s) -> (
      let regex = Field.String.regex s in
      let insensible = Field.String.insensible s in
      let field = Field.String.field s in
      match field with
      | Title ftitle ->
          omatches ~insensible regex ftitle title
      | SortName fsort_name ->
          omatches ~insensible regex fsort_name sort_name
      | Artist fartist ->
          Ids.Map.exists
            (fun _ (artist_name, roles) ->
              Roles.mem Artist roles
              && matches ~insensible regex fartist artist_name
            )
            participants
      | Album falbum ->
          matches ~insensible regex falbum album_name
      | AlbumArtist falbum_artist ->
          Ids.Map.exists
            (fun _ (artist_name, roles) ->
              Roles.mem AlbumArtist roles
              && matches ~insensible regex falbum_artist artist_name
            )
            participants
      | Composer fcomposer ->
          Ids.Map.exists
            (fun _ (artist_name, roles) ->
              Roles.mem Composer roles
              && matches ~insensible regex fcomposer artist_name
            )
            participants
      | Genre fgenre ->
          omatches ~insensible regex fgenre genre
      | Path fpath ->
          matches ~insensible regex fpath path
      | FileExtension fextension ->
          matches ~insensible regex fextension extension
    )
  | Field (FBool b) -> (
      match b with Art b -> b = has_cover | Flag b -> flag = b
    )
  | Field (FInt i) -> (
      match i with
      | Id fid ->
          Range.matches fid id
      | Size fsize ->
          Range.matches fsize (Int64.of_int size)
      | Track ftrack ->
          track_number
          |> Option.map (Range.matches ftrack)
          |> Option.value ~default:false
      | Year fyear ->
          year
          |> Option.map (Range.matches fyear)
          |> Option.value ~default:false
      | Disc fdisc ->
          Option.fold ~none:false ~some:(Range.matches fdisc) disc_number
      | Plays fcount ->
          Range.matches fcount play_count
      | Length flength ->
          Range.matches flength duration
      | Rating frating ->
          rating
          |> Option.map (Range.matches frating)
          |> Option.value ~default:false
      | AlbumCount fcount ->
          Range.matches fcount 1
    )
  | Field (FFloat f) -> (
      match f with
      | AvgDuration favg_duration ->
          Range.matches favg_duration (Float.of_int duration)
      | AvgRating favg_rating ->
          rating
          |> Option.map (fun rating ->
              let rating = Float.of_int rating in
              Range.matches favg_rating rating
          )
          |> Option.value ~default:false
      | AvgSize favg_size ->
          Range.matches favg_size (Int.to_float size)
    )