1 /*
2  * Copyright 2003-2021 The Music Player Daemon Project
3  * http://www.musicpd.org
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  */
19 
20 #ifndef MPD_DATABASE_INTERFACE_HXX
21 #define MPD_DATABASE_INTERFACE_HXX
22 
23 #include "Visitor.hxx"
24 #include "tag/Type.h"
25 
26 #include <chrono>
27 #include <string>
28 
29 struct DatabasePlugin;
30 struct DatabaseStats;
31 struct DatabaseSelection;
32 struct LightSong;
33 template<typename Key> class RecursiveMap;
34 template<typename T> struct ConstBuffer;
35 
36 class Database {
37 	const DatabasePlugin &plugin;
38 
39 protected:
Database(const DatabasePlugin & _plugin)40 	Database(const DatabasePlugin &_plugin) noexcept
41 		:plugin(_plugin) {}
42 
43 public:
44 	/**
45 	 * Free instance data.
46          */
47 	virtual ~Database() noexcept = default;
48 
GetPlugin() const49 	const DatabasePlugin &GetPlugin() const noexcept {
50 		return plugin;
51 	}
52 
53 	/**
54          * Open the database.  Read it into memory if applicable.
55 	 *
56 	 * Throws on error (e.g. #DatabaseError).
57 	 */
Open()58 	virtual void Open() {
59 	}
60 
61 	/**
62          * Close the database, free allocated memory.
63 	 */
Close()64 	virtual void Close() noexcept {}
65 
66 	/**
67          * Look up a song (including tag data) in the database.  When
68          * you don't need this anymore, call ReturnSong().
69 	 *
70 	 * Throws on error.  "Not found" is an error that throws
71 	 * DatabaseErrorCode::NOT_FOUND.
72 	 *
73 	 * @param uri_utf8 the URI of the song within the music
74 	 * directory (UTF-8)
75 	 * @return a pointer that must be released with ReturnSong()
76 	 */
77 	virtual const LightSong *GetSong(std::string_view uri_utf8) const = 0;
78 
79 	/**
80 	 * Mark the song object as "unused".  Call this on objects
81 	 * returned by GetSong().
82 	 */
83 	virtual void ReturnSong(const LightSong *song) const noexcept = 0;
84 
85 	/**
86 	 * Visit the selected entities.
87 	 *
88 	 * Throws on error.
89 	 */
90 	virtual void Visit(const DatabaseSelection &selection,
91 			   VisitDirectory visit_directory,
92 			   VisitSong visit_song,
93 			   VisitPlaylist visit_playlist) const = 0;
94 
Visit(const DatabaseSelection & selection,VisitDirectory visit_directory,VisitSong visit_song) const95 	void Visit(const DatabaseSelection &selection,
96 		   VisitDirectory visit_directory,
97 		   VisitSong visit_song) const {
98 		Visit(selection, visit_directory, visit_song, VisitPlaylist());
99 	}
100 
Visit(const DatabaseSelection & selection,VisitSong visit_song) const101 	void Visit(const DatabaseSelection &selection,
102 		   VisitSong visit_song) const {
103 		return Visit(selection, VisitDirectory(), visit_song);
104 	}
105 
106 	/**
107 	 * Collect unique values of the given tag types.  Each item in
108 	 * the #tag_types parameter results in one nesting level in
109 	 * the return value.
110 	 *
111 	 * Throws on error.
112 	 */
113 	virtual RecursiveMap<std::string> CollectUniqueTags(const DatabaseSelection &selection,
114 							    ConstBuffer<TagType> tag_types) const = 0;
115 
116 	/**
117 	 * Throws on error.
118 	 */
119 	virtual DatabaseStats GetStats(const DatabaseSelection &selection) const = 0;
120 
121 	/**
122 	 * Update the database.
123 	 *
124 	 * Throws on error.
125 	 *
126 	 * @return the job id or 0 if not implemented
127 	 */
Update(const char * uri_utf8,bool discard)128 	virtual unsigned Update([[maybe_unused]] const char *uri_utf8,
129 				[[maybe_unused]] bool discard) {
130 		/* not implemented: return 0 */
131 		return 0;
132 	}
133 
134 	/**
135 	 * Returns the time stamp of the last database update.
136 	 * Returns a negative value if that is not not known/available.
137 	 */
138 	[[gnu::pure]]
139 	virtual std::chrono::system_clock::time_point GetUpdateStamp() const noexcept = 0;
140 };
141 
142 #endif
143