Merge branch 'added_time' of https://github.com/jcorporation/MPD
This commit is contained in:
commit
ac25f3456a
2
NEWS
2
NEWS
|
@ -10,7 +10,9 @@ ver 0.24 (not yet released)
|
|||
- show PCRE support in "config" response
|
||||
- apply Unicode normalization to case-insensitive filter expressions
|
||||
- stickers on playlists and some tag types
|
||||
- new command "stickernames"
|
||||
* database
|
||||
- attribute "added" shows when each song was added to the database
|
||||
- proxy: require MPD 0.21 or later
|
||||
- proxy: require libmpdclient 2.15 or later
|
||||
* archive
|
||||
|
|
|
@ -77,6 +77,9 @@ song_print_info(Response &r, const LightSong &song, bool base) noexcept
|
|||
if (!IsNegative(song.mtime))
|
||||
time_print(r, "Last-Modified", song.mtime);
|
||||
|
||||
if (!IsNegative(song.added))
|
||||
time_print(r, "Added", song.added);
|
||||
|
||||
if (song.audio_format.IsDefined())
|
||||
r.Fmt(FMT_STRING("Format: {}\n"), song.audio_format);
|
||||
|
||||
|
@ -100,6 +103,9 @@ song_print_info(Response &r, const DetachedSong &song, bool base) noexcept
|
|||
if (!IsNegative(song.GetLastModified()))
|
||||
time_print(r, "Last-Modified", song.GetLastModified());
|
||||
|
||||
if (!IsNegative(song.GetAdded()))
|
||||
time_print(r, "Added", song.GetAdded());
|
||||
|
||||
if (const auto &f = song.GetAudioFormat(); f.IsDefined())
|
||||
r.Fmt(FMT_STRING("Format: {}\n"), f);
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <stdlib.h>
|
||||
|
||||
#define SONG_MTIME "mtime"
|
||||
#define SONG_ADDED "added"
|
||||
#define SONG_END "song_end"
|
||||
|
||||
static void
|
||||
|
@ -54,6 +55,10 @@ song_save(BufferedOutputStream &os, const Song &song)
|
|||
if (!IsNegative(song.mtime))
|
||||
os.Fmt(FMT_STRING(SONG_MTIME ": {}\n"),
|
||||
std::chrono::system_clock::to_time_t(song.mtime));
|
||||
|
||||
if (!IsNegative(song.added))
|
||||
os.Fmt(FMT_STRING(SONG_ADDED ": {}\n"),
|
||||
std::chrono::system_clock::to_time_t(song.added));
|
||||
os.Write(SONG_END "\n");
|
||||
}
|
||||
|
||||
|
@ -69,6 +74,10 @@ song_save(BufferedOutputStream &os, const DetachedSong &song)
|
|||
if (!IsNegative(song.GetLastModified()))
|
||||
os.Fmt(FMT_STRING(SONG_MTIME ": {}\n"),
|
||||
std::chrono::system_clock::to_time_t(song.GetLastModified()));
|
||||
|
||||
if (!IsNegative(song.GetAdded()))
|
||||
os.Fmt(FMT_STRING(SONG_ADDED ": {}\n"),
|
||||
std::chrono::system_clock::to_time_t(song.GetAdded()));
|
||||
os.Write(SONG_END "\n");
|
||||
}
|
||||
|
||||
|
@ -109,6 +118,8 @@ song_load(LineReader &file, const char *uri,
|
|||
tag.SetHasPlaylist(StringIsEqual(value, "yes"));
|
||||
} else if (StringIsEqual(line, SONG_MTIME)) {
|
||||
song.SetLastModified(std::chrono::system_clock::from_time_t(atoi(value)));
|
||||
} else if (StringIsEqual(line, SONG_ADDED)) {
|
||||
song.SetAdded(std::chrono::system_clock::from_time_t(atoi(value)));
|
||||
} else if (StringIsEqual(line, "Range")) {
|
||||
char *endptr;
|
||||
|
||||
|
|
|
@ -51,6 +51,9 @@ ParseSortTag(const char *s)
|
|||
if (StringIsEqualIgnoreCase(s, "Last-Modified"))
|
||||
return TagType(SORT_TAG_LAST_MODIFIED);
|
||||
|
||||
if (StringIsEqualIgnoreCase(s, "Added"))
|
||||
return TagType(SORT_TAG_ADDED);
|
||||
|
||||
TagType tag = tag_name_parse_i(s);
|
||||
if (tag == TAG_NUM_OF_ITEM_TYPES)
|
||||
throw ProtocolError(ACK_ERROR_ARG, "Unknown sort tag");
|
||||
|
|
|
@ -276,6 +276,9 @@ ParseSortTag(const char *s)
|
|||
if (StringIsEqualIgnoreCase(s, "Last-Modified"))
|
||||
return TagType(SORT_TAG_LAST_MODIFIED);
|
||||
|
||||
if (StringIsEqualIgnoreCase(s, "Added"))
|
||||
return TagType(SORT_TAG_ADDED);
|
||||
|
||||
if (StringIsEqualIgnoreCase(s, "prio"))
|
||||
return TagType(SORT_TAG_PRIO);
|
||||
|
||||
|
|
|
@ -60,6 +60,13 @@ DatabaseVisitorHelper::Commit()
|
|||
? a.GetLastModified() > b.GetLastModified()
|
||||
: a.GetLastModified() < b.GetLastModified();
|
||||
});
|
||||
else if (sort == TagType(SORT_TAG_ADDED))
|
||||
std::stable_sort(songs.begin(), songs.end(),
|
||||
[descending](const DetachedSong &a, const DetachedSong &b){
|
||||
return descending
|
||||
? a.GetAdded() > b.GetAdded()
|
||||
: a.GetAdded() < b.GetAdded();
|
||||
});
|
||||
else
|
||||
std::stable_sort(songs.begin(), songs.end(),
|
||||
[sort, descending](const DetachedSong &a,
|
||||
|
|
|
@ -19,6 +19,7 @@ Song::Song(DetachedSong &&other, Directory &_parent) noexcept
|
|||
filename(other.GetURI()),
|
||||
tag(std::move(other.WritableTag())),
|
||||
mtime(other.GetLastModified()),
|
||||
added(other.GetAdded()),
|
||||
start_time(other.GetStartTime()),
|
||||
end_time(other.GetEndTime()),
|
||||
audio_format(other.GetAudioFormat())
|
||||
|
@ -117,6 +118,9 @@ Song::Export() const noexcept
|
|||
dest.mtime = IsNegative(mtime) && target_song != nullptr
|
||||
? target_song->mtime
|
||||
: mtime;
|
||||
dest.added = IsNegative(added) && target_song != nullptr
|
||||
? target_song->added
|
||||
: added;
|
||||
dest.start_time = start_time.IsZero() && target_song != nullptr
|
||||
? target_song->start_time
|
||||
: start_time;
|
||||
|
|
|
@ -56,6 +56,13 @@ struct Song : IntrusiveListHook<> {
|
|||
std::chrono::system_clock::time_point mtime =
|
||||
std::chrono::system_clock::time_point::min();
|
||||
|
||||
/**
|
||||
* The time stamp when the file was added. A negative
|
||||
* value means that this is unknown/unavailable.
|
||||
*/
|
||||
std::chrono::system_clock::time_point added =
|
||||
std::chrono::system_clock::time_point::min();
|
||||
|
||||
/**
|
||||
* Start of this sub-song within the file.
|
||||
*/
|
||||
|
|
|
@ -50,6 +50,7 @@ try {
|
|||
}
|
||||
|
||||
new_song->mark = true;
|
||||
new_song->added = std::chrono::system_clock::now();
|
||||
|
||||
{
|
||||
const ScopeDatabaseLock protect;
|
||||
|
|
|
@ -25,6 +25,7 @@ merge_song_metadata(DetachedSong &add, const DetachedSong &base) noexcept
|
|||
}
|
||||
|
||||
add.SetLastModified(base.GetLastModified());
|
||||
add.SetAdded(base.GetAdded());
|
||||
|
||||
if (add.GetStartTime().IsZero()) {
|
||||
add.SetStartTime(base.GetStartTime());
|
||||
|
|
|
@ -33,6 +33,7 @@ UpdatePlaylistSong(const Database &db, DetachedSong &song)
|
|||
}
|
||||
|
||||
song.SetLastModified(original->mtime);
|
||||
song.SetAdded(original->added);
|
||||
song.SetTag(original->tag);
|
||||
|
||||
db.ReturnSong(original);
|
||||
|
|
|
@ -127,6 +127,17 @@ PrintSortedQueue(Response &r, const Queue &queue,
|
|||
|
||||
return a.GetLastModified() < b.GetLastModified();
|
||||
});
|
||||
else if (sort == TagType(SORT_TAG_ADDED))
|
||||
std::stable_sort(v.begin(), v.end(),
|
||||
[&queue, descending](unsigned a_pos, unsigned b_pos){
|
||||
if (descending)
|
||||
std::swap(a_pos, b_pos);
|
||||
|
||||
const auto &a = queue.Get(a_pos);
|
||||
const auto &b = queue.Get(b_pos);
|
||||
|
||||
return a.GetAdded() < b.GetAdded();
|
||||
});
|
||||
else if (sort == TagType(SORT_TAG_PRIO))
|
||||
std::stable_sort(v.begin(), v.end(),
|
||||
[&queue, descending](unsigned a_pos, unsigned b_pos){
|
||||
|
|
|
@ -11,6 +11,7 @@ DetachedSong::DetachedSong(const LightSong &other) noexcept
|
|||
real_uri(other.real_uri != nullptr ? other.real_uri : ""),
|
||||
tag(other.tag),
|
||||
mtime(other.mtime),
|
||||
added(other.added),
|
||||
start_time(other.start_time),
|
||||
end_time(other.end_time),
|
||||
audio_format(other.audio_format) {}
|
||||
|
@ -21,6 +22,7 @@ DetachedSong::operator LightSong() const noexcept
|
|||
result.directory = nullptr;
|
||||
result.real_uri = real_uri.empty() ? nullptr : real_uri.c_str();
|
||||
result.mtime = mtime;
|
||||
result.added = added;
|
||||
result.start_time = start_time;
|
||||
result.end_time = end_time;
|
||||
return result;
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "tag/Tag.hxx"
|
||||
#include "pcm/AudioFormat.hxx"
|
||||
#include "Chrono.hxx"
|
||||
#include "time/ChronoUtil.hxx"
|
||||
|
||||
#include <chrono>
|
||||
#include <string>
|
||||
|
@ -58,6 +59,13 @@ class DetachedSong {
|
|||
std::chrono::system_clock::time_point mtime =
|
||||
std::chrono::system_clock::time_point::min();
|
||||
|
||||
/**
|
||||
* The time stamp when the file was added to db. A negative
|
||||
* value means that this is unknown/unavailable.
|
||||
*/
|
||||
std::chrono::system_clock::time_point added =
|
||||
std::chrono::system_clock::time_point::min();
|
||||
|
||||
/**
|
||||
* Start of this sub-song within the file.
|
||||
*/
|
||||
|
@ -212,6 +220,16 @@ public:
|
|||
mtime = _value;
|
||||
}
|
||||
|
||||
std::chrono::system_clock::time_point GetAdded() const noexcept {
|
||||
return IsNegative(added)
|
||||
? mtime
|
||||
: added;
|
||||
}
|
||||
|
||||
void SetAdded(std::chrono::system_clock::time_point _value) noexcept {
|
||||
added = _value;
|
||||
}
|
||||
|
||||
SongTime GetStartTime() const noexcept {
|
||||
return start_time;
|
||||
}
|
||||
|
|
|
@ -21,6 +21,11 @@
|
|||
*/
|
||||
#define SORT_TAG_PRIO (TAG_NUM_OF_ITEM_TYPES + 4)
|
||||
|
||||
/**
|
||||
* Special value for the db_selection_print() sort parameter.
|
||||
*/
|
||||
#define SORT_TAG_ADDED (TAG_NUM_OF_ITEM_TYPES + 5)
|
||||
|
||||
enum TagType : uint8_t;
|
||||
struct LightSong;
|
||||
|
||||
|
|
|
@ -51,6 +51,12 @@ struct LightSong {
|
|||
*/
|
||||
std::chrono::system_clock::time_point mtime = std::chrono::system_clock::time_point::min();
|
||||
|
||||
/**
|
||||
* The time stamp when the file was added. A negative
|
||||
* value means that this is unknown/unavailable.
|
||||
*/
|
||||
std::chrono::system_clock::time_point added = std::chrono::system_clock::time_point::min();
|
||||
|
||||
/**
|
||||
* Start of this sub-song within the file.
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue