aboutsummaryrefslogtreecommitdiffstats
path: root/src/DetachedSong.hxx
blob: b2f5196fff5e899457e6c3d3da502226c0897ed3 (plain) (blame)
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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
/*
 * Copyright (C) 2003-2014 The Music Player Daemon Project
 * http://www.musicpd.org
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#ifndef MPD_DETACHED_SONG_HXX
#define MPD_DETACHED_SONG_HXX

#include "check.h"
#include "tag/Tag.hxx"
#include "Compiler.h"

#include <string>
#include <utility>

#include <time.h>

struct LightSong;

class DetachedSong {
	friend DetachedSong map_song_detach(const LightSong &song);

	/**
	 * An UTF-8-encoded URI referring to the song file.  This can
	 * be one of:
	 *
	 * - an absolute URL with a scheme
	 *   (e.g. "http://example.com/foo.mp3")
	 *
	 * - an absolute file name
	 *
	 * - a file name relative to the music directory
	 */
	std::string uri;

	/**
	 * The "real" URI, the one to be used for opening the
	 * resource.  If this attribute is empty, then #uri shall be
	 * used.
	 *
	 * This attribute is used for songs from the database which
	 * have a relative URI.
	 */
	std::string real_uri;

	Tag tag;

	time_t mtime;

	/**
	 * Start of this sub-song within the file in milliseconds.
	 */
	unsigned start_ms;

	/**
	 * End of this sub-song within the file in milliseconds.
	 * Unused if zero.
	 */
	unsigned end_ms;

	explicit DetachedSong(const LightSong &other);

public:
	explicit DetachedSong(const DetachedSong &) = default;

	explicit DetachedSong(const char *_uri)
		:uri(_uri),
		 mtime(0), start_ms(0), end_ms(0) {}

	explicit DetachedSong(const std::string &_uri)
		:uri(_uri),
		 mtime(0), start_ms(0), end_ms(0) {}

	explicit DetachedSong(std::string &&_uri)
		:uri(std::move(_uri)),
		 mtime(0), start_ms(0), end_ms(0) {}

	template<typename U>
	DetachedSong(U &&_uri, Tag &&_tag)
		:uri(std::forward<U>(_uri)),
		 tag(std::move(_tag)),
		 mtime(0), start_ms(0), end_ms(0) {}

	DetachedSong(DetachedSong &&) = default;

	gcc_pure
	const char *GetURI() const {
		return uri.c_str();
	}

	template<typename T>
	void SetURI(T &&_uri) {
		uri = std::forward<T>(_uri);
	}

	/**
	 * Does this object have a "real" URI different from the
	 * displayed URI?
	 */
	gcc_pure
	bool HasRealURI() const {
		return !real_uri.empty();
	}

	/**
	 * Returns "real" URI (#real_uri) and falls back to just
	 * GetURI().
	 */
	gcc_pure
	const char *GetRealURI() const {
		return (HasRealURI() ? real_uri : uri).c_str();
	}

	template<typename T>
	void SetRealURI(T &&_uri) {
		real_uri = std::forward<T>(_uri);
	}

	/**
	 * Returns true if both objects refer to the same physical
	 * song.
	 */
	gcc_pure
	bool IsSame(const DetachedSong &other) const {
		return uri == other.uri;
	}

	gcc_pure gcc_nonnull_all
	bool IsURI(const char *other_uri) const {
		return uri == other_uri;
	}

	gcc_pure
	bool IsRemote() const;

	gcc_pure
	bool IsFile() const {
		return !IsRemote();
	}

	gcc_pure
	bool IsAbsoluteFile() const;

	gcc_pure
	bool IsInDatabase() const;

	const Tag &GetTag() const {
		return tag;
	}

	Tag &WritableTag() {
		return tag;
	}

	void SetTag(const Tag &_tag) {
		tag = Tag(_tag);
	}

	void SetTag(Tag &&_tag) {
		tag = std::move(_tag);
	}

	void MoveTagFrom(DetachedSong &&other) {
		tag = std::move(other.tag);
	}

	time_t GetLastModified() const {
		return mtime;
	}

	void SetLastModified(time_t _value) {
		mtime = _value;
	}

	unsigned GetStartMS() const {
		return start_ms;
	}

	void SetStartMS(unsigned _value) {
		start_ms = _value;
	}

	unsigned GetEndMS() const {
		return end_ms;
	}

	void SetEndMS(unsigned _value) {
		end_ms = _value;
	}

	gcc_pure
	double GetDuration() const;

	/**
	 * Update the #tag and #mtime.
	 *
	 * @return true on success
	 */
	bool Update();
};

#endif