1 /**
2 * Copyright © Underground Rekordz 2019
3 * License: MIT (https://github.com/UndergroundRekordz/Musicpulator/blob/master/LICENSE)
4 * Author: Jacob Jensen (bausshf)
5 */
6 module musicpulator.song;
7 
8 import std.string : format;
9 
10 import musicpulator.songpart;
11 import musicpulator.musicalscale;
12 import musicpulator.musicalprogression;
13 
14 /// Wrapper around a song.
15 final class Song
16 {
17   private:
18   /// The name.
19   string _name;
20 
21   /// The parts of the song.
22   SongPart[SongPartTitle] _parts;
23 
24   public:
25   final:
26   /// Creates a new song.
27   this(string name)
28   {
29     _name = name;
30   }
31 
32   @property
33   {
34     /// Gets the parts of a song.
35     auto parts() { return _parts.values; }
36   }
37 
38   /**
39   * Adds a part to the song.
40   * Params:
41   *   part = The part.
42   */
43   void addPart(SongPart part)
44   {
45     if (!part)
46     {
47       return;
48     }
49 
50     _parts[part.title] = part;
51   }
52 
53   /**
54   * Gets a part from the song.
55   * Params:
56   *   title = The title of the part to get.
57   * Returns:
58   *   The part if existing, null otherwise.
59   */
60   SongPart getPart(SongPartTitle title)
61   {
62     return _parts ? _parts.get(title, null) : null;
63   }
64 
65   /// Converts the song to string. Calls toJson().
66   override string toString()
67   {
68     return toJson();
69   }
70 
71   /// Converts the song to json.
72   string toJson()
73   {
74     auto partsJson = "[";
75 
76     if (_parts && _parts.length)
77     {
78       foreach (k,v; _parts)
79       {
80         partsJson ~= v.toJson() ~ ",";
81       }
82 
83       partsJson.length -= 1;
84     }
85 
86     partsJson ~= "]";
87 
88     return `{"name":"%s","parts": %s}`
89       .format(_name ? _name : "", partsJson);
90   }
91 
92   /// Converts the song to xml.
93   string toXml()
94   {
95     auto partsXml = "";
96 
97     if (_parts && _parts.length)
98     {
99       foreach (k,v; _parts)
100       {
101         partsXml ~= v.toXml();
102       }
103     }
104 
105     return `<Song name="%s">%s</Song>`
106       .format(_name, partsXml);
107   }
108 }