Merge branch '0.7.x'
This commit is contained in:
26
INSTALL
26
INSTALL
@@ -25,22 +25,24 @@ it or regenerate `configure' using a newer version of `autoconf'.
|
|||||||
|
|
||||||
The simplest way to compile this package is:
|
The simplest way to compile this package is:
|
||||||
|
|
||||||
1. `cd' to the directory containing the package's source code and type
|
1. `cd' to the directory containing the package's source code.
|
||||||
`./configure' to configure the package for your system. If you're
|
|
||||||
using `csh' on an old version of System V, you might need to type
|
|
||||||
`sh ./configure' instead to prevent `csh' from trying to execute
|
|
||||||
`configure' itself.
|
|
||||||
|
|
||||||
Running `configure' takes a while. While running, it prints some
|
For the next two commands, `csh' users will need to prefix them with
|
||||||
messages telling which features it is checking for.
|
`sh '.
|
||||||
|
|
||||||
2. Type `make' to compile the package.
|
2. Run `./autogen.sh' to generate the `configure' script.
|
||||||
|
|
||||||
3. Type `make install' to install the programs and any data files and
|
3. Run `./configure' to configure the package for your system. This
|
||||||
documentation.
|
will take a while. While running, it prints some messages
|
||||||
|
telling which features it is checking for.
|
||||||
|
|
||||||
4. You can remove the program binaries and object files from the
|
4. Run `make' to compile the package.
|
||||||
source code directory by typing `make clean'.
|
|
||||||
|
5. Type `make install' to install the programs and any data files
|
||||||
|
and documentation.
|
||||||
|
|
||||||
|
6. You can remove the program binaries and object files from the
|
||||||
|
source code directory by typing `make clean'.
|
||||||
|
|
||||||
Compilers and Options
|
Compilers and Options
|
||||||
=====================
|
=====================
|
||||||
|
|||||||
9
NEWS
9
NEWS
@@ -2,6 +2,15 @@ ncmpcpp-0.8 (????-??-??)
|
|||||||
* Configuration variable 'execute_on_player_state_change' was added.
|
* Configuration variable 'execute_on_player_state_change' was added.
|
||||||
* Support for controlling whether ncmpcpp should display multiple tags as-is or make an effort to hide duplicate values (show_duplicate_tags configuration variable, enabled by default).
|
* Support for controlling whether ncmpcpp should display multiple tags as-is or make an effort to hide duplicate values (show_duplicate_tags configuration variable, enabled by default).
|
||||||
|
|
||||||
|
ncmpcpp-0.7.6 (2016-10-30)
|
||||||
|
* Fixed assertion failure on trying to search backwards in an empty list.
|
||||||
|
* Updated installation instructions in INSTALL file.
|
||||||
|
* Make sure that stream of random numbers is not deterministic.
|
||||||
|
* Opening playlist editor when there is no MPD playlists directory no longer freezes the application.
|
||||||
|
* Added info about behavior of MPD_HOST and MPD_PORT environment variables to man page.
|
||||||
|
* Tilde will now be expanded to home directory in visualizer_fifo_path, execute_on_song_change and external_editor configuration variables.
|
||||||
|
* Fixed lyricwiki and justsomelyrics fetchers.
|
||||||
|
|
||||||
ncmpcpp-0.7.5 (2016-08-17)
|
ncmpcpp-0.7.5 (2016-08-17)
|
||||||
* Action chains can be now used for seeking.
|
* Action chains can be now used for seeking.
|
||||||
* Fixed fetching artist info from last.fm.
|
* Fixed fetching artist info from last.fm.
|
||||||
|
|||||||
@@ -156,8 +156,3 @@ $AUTOMAKE --add-missing $AUTOMAKE_FLAGS || exit 1
|
|||||||
|
|
||||||
echo " $AUTOCONF"
|
echo " $AUTOCONF"
|
||||||
$AUTOCONF || exit 1
|
$AUTOCONF || exit 1
|
||||||
|
|
||||||
cd "$olddir"
|
|
||||||
if test x$NOCONFIGURE = x; then
|
|
||||||
"$srcdir"/configure "$@" || exit 1
|
|
||||||
fi
|
|
||||||
|
|||||||
@@ -59,10 +59,10 @@ Directory for storing ncmpcpp related files. Changing it is useful if you want t
|
|||||||
Directory for storing downloaded lyrics. It defaults to ~/.lyrics since other MPD clients (eg. ncmpc) also use that location.
|
Directory for storing downloaded lyrics. It defaults to ~/.lyrics since other MPD clients (eg. ncmpc) also use that location.
|
||||||
.TP
|
.TP
|
||||||
.B mpd_host = HOST
|
.B mpd_host = HOST
|
||||||
Connect to MPD running on specified host/unix socket. When HOST starts with a '/', it is assumed to be a unix socket.
|
Connect to MPD running on specified host/unix socket. When HOST starts with a '/', it is assumed to be a unix socket. Note: MPD_HOST environment variable overrides this setting.
|
||||||
.TP
|
.TP
|
||||||
.B mpd_port = PORT
|
.B mpd_port = PORT
|
||||||
Connect to MPD on the specified port.
|
Connect to MPD on the specified port. Note: MPD_PORT environment variable overrides this setting.
|
||||||
.TP
|
.TP
|
||||||
.B mpd_music_dir = PATH
|
.B mpd_music_dir = PATH
|
||||||
Search for files in specified directory. This is needed for tag editor to work.
|
Search for files in specified directory. This is needed for tag editor to work.
|
||||||
|
|||||||
@@ -2124,11 +2124,15 @@ void AddRandomItems::run()
|
|||||||
Statusbar::put() << "Number of random " << tag_type_str << "s: ";
|
Statusbar::put() << "Number of random " << tag_type_str << "s: ";
|
||||||
number = fromString<unsigned>(wFooter->prompt());
|
number = fromString<unsigned>(wFooter->prompt());
|
||||||
}
|
}
|
||||||
if (number && (rnd_type == 's' ? Mpd.AddRandomSongs(number) : Mpd.AddRandomTag(tag_type, number)))
|
if (number > 0)
|
||||||
{
|
{
|
||||||
Statusbar::printf("%1% random %2%%3% added to playlist",
|
bool success;
|
||||||
number, tag_type_str, number == 1 ? "" : "s"
|
if (rnd_type == 's')
|
||||||
);
|
success = Mpd.AddRandomSongs(number, Global::RNG);
|
||||||
|
else
|
||||||
|
success = Mpd.AddRandomTag(tag_type, number, Global::RNG);
|
||||||
|
if (success)
|
||||||
|
Statusbar::printf("%1% random %2%%3% added to playlist", number, tag_type_str, number == 1 ? "" : "s");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -38,4 +38,6 @@ bool SeekingInProgress = false;
|
|||||||
std::string VolumeState;
|
std::string VolumeState;
|
||||||
boost::posix_time::ptime Timer;
|
boost::posix_time::ptime Timer;
|
||||||
|
|
||||||
|
std::mt19937 RNG;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,8 @@
|
|||||||
#define NCMPCPP_GLOBAL_H
|
#define NCMPCPP_GLOBAL_H
|
||||||
|
|
||||||
#include <boost/date_time/posix_time/posix_time_types.hpp>
|
#include <boost/date_time/posix_time/posix_time_types.hpp>
|
||||||
|
#include <random>
|
||||||
|
|
||||||
#include "mpdpp.h"
|
#include "mpdpp.h"
|
||||||
#include "screen.h"
|
#include "screen.h"
|
||||||
|
|
||||||
@@ -58,6 +60,9 @@ extern std::string VolumeState;
|
|||||||
// global timer
|
// global timer
|
||||||
extern boost::posix_time::ptime Timer;
|
extern boost::posix_time::ptime Timer;
|
||||||
|
|
||||||
|
// global RNG
|
||||||
|
extern std::mt19937 RNG;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // NCMPCPP_GLOBAL_H
|
#endif // NCMPCPP_GLOBAL_H
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ MPD::SongIterator getDatabaseIterator(MPD::Connection &mpd)
|
|||||||
{
|
{
|
||||||
// If we can't get the database, display appropriate
|
// If we can't get the database, display appropriate
|
||||||
// error message and reconnect with the MPD server.
|
// error message and reconnect with the MPD server.
|
||||||
Statusbar::print("Unable to fetch the data, increase max_buffer_output_size in your MPD configuration file");
|
Statusbar::print("Unable to fetch the data, increase max_output_buffer_size in your MPD configuration file");
|
||||||
mpd.Disconnect();
|
mpd.Disconnect();
|
||||||
mpd.Connect();
|
mpd.Connect();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,9 @@
|
|||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <boost/algorithm/string/join.hpp>
|
||||||
#include <boost/algorithm/string/replace.hpp>
|
#include <boost/algorithm/string/replace.hpp>
|
||||||
|
#include <boost/algorithm/string/split.hpp>
|
||||||
#include <boost/algorithm/string/trim.hpp>
|
#include <boost/algorithm/string/trim.hpp>
|
||||||
#include <boost/regex.hpp>
|
#include <boost/regex.hpp>
|
||||||
|
|
||||||
@@ -105,6 +107,15 @@ std::vector<std::string> LyricsFetcher::getContent(const char *regex_, const std
|
|||||||
void LyricsFetcher::postProcess(std::string &data) const
|
void LyricsFetcher::postProcess(std::string &data) const
|
||||||
{
|
{
|
||||||
stripHtmlTags(data);
|
stripHtmlTags(data);
|
||||||
|
// Remove indentation from each line and collapse multiple newlines into one.
|
||||||
|
std::vector<std::string> lines;
|
||||||
|
boost::split(lines, data, boost::is_any_of("\r\n"));
|
||||||
|
for (auto &line : lines)
|
||||||
|
boost::trim(line);
|
||||||
|
std::unique(lines.begin(), lines.end(), [](std::string &a, std::string &b) {
|
||||||
|
return a.empty() && b.empty();
|
||||||
|
});
|
||||||
|
data = boost::algorithm::join(lines, "\n");
|
||||||
boost::trim(data);
|
boost::trim(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,7 +137,7 @@ LyricsFetcher::Result LyricwikiFetcher::fetch(const std::string &artist, const s
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto lyrics = getContent("<div class='lyricbox'>(.*?)<!--", data);
|
auto lyrics = getContent("<div class='lyricbox'>(.*?)</div>", data);
|
||||||
|
|
||||||
if (lyrics.empty())
|
if (lyrics.empty())
|
||||||
{
|
{
|
||||||
@@ -224,6 +235,14 @@ void Sing365Fetcher::postProcess(std::string &data) const
|
|||||||
|
|
||||||
/**********************************************************************/
|
/**********************************************************************/
|
||||||
|
|
||||||
|
void JustSomeLyricsFetcher::postProcess(std::string &data) const
|
||||||
|
{
|
||||||
|
data = unescapeHtmlUtf8(data);
|
||||||
|
LyricsFetcher::postProcess(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************************************************************/
|
||||||
|
|
||||||
void MetrolyricsFetcher::postProcess(std::string &data) const
|
void MetrolyricsFetcher::postProcess(std::string &data) const
|
||||||
{
|
{
|
||||||
// some of lyrics have both \n chars and <br />, html tags
|
// some of lyrics have both \n chars and <br />, html tags
|
||||||
|
|||||||
@@ -108,7 +108,9 @@ struct JustSomeLyricsFetcher : public GoogleLyricsFetcher
|
|||||||
virtual const char *name() const OVERRIDE { return "justsomelyrics.com"; }
|
virtual const char *name() const OVERRIDE { return "justsomelyrics.com"; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual const char *regex() const OVERRIDE { return "<div class=\"content.*?</div>(.*?)</div>"; }
|
virtual const char *regex() const OVERRIDE { return "<div class=\"content.*?</div>\\s*</div>(.*?)<div"; }
|
||||||
|
|
||||||
|
virtual void postProcess(std::string &data) const OVERRIDE;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AzLyricsFetcher : public GoogleLyricsFetcher
|
struct AzLyricsFetcher : public GoogleLyricsFetcher
|
||||||
|
|||||||
28
src/menu.h
28
src/menu.h
@@ -353,13 +353,33 @@ template <typename ItemT> struct Menu : Window, List
|
|||||||
|
|
||||||
Iterator current() { return Iterator(m_items.begin() + m_highlight); }
|
Iterator current() { return Iterator(m_items.begin() + m_highlight); }
|
||||||
ConstIterator current() const { return ConstIterator(m_items.begin() + m_highlight); }
|
ConstIterator current() const { return ConstIterator(m_items.begin() + m_highlight); }
|
||||||
ReverseIterator rcurrent() { return ReverseIterator(++current()); }
|
ReverseIterator rcurrent() {
|
||||||
ConstReverseIterator rcurrent() const { return ReverseIterator(++current()); }
|
if (empty())
|
||||||
|
return rend();
|
||||||
|
else
|
||||||
|
return ReverseIterator(++current());
|
||||||
|
}
|
||||||
|
ConstReverseIterator rcurrent() const {
|
||||||
|
if (empty())
|
||||||
|
return rend();
|
||||||
|
else
|
||||||
|
return ConstReverseIterator(++current());
|
||||||
|
}
|
||||||
|
|
||||||
ValueIterator currentV() { return ValueIterator(m_items.begin() + m_highlight); }
|
ValueIterator currentV() { return ValueIterator(m_items.begin() + m_highlight); }
|
||||||
ConstValueIterator currentV() const { return ConstValueIterator(m_items.begin() + m_highlight); }
|
ConstValueIterator currentV() const { return ConstValueIterator(m_items.begin() + m_highlight); }
|
||||||
ReverseValueIterator rcurrentV() { return ReverseValueIterator(++currentV()); }
|
ReverseValueIterator rcurrentV() {
|
||||||
ConstReverseValueIterator rcurrentV() const { return ConstReverseValueIterator(++currentV()); }
|
if (empty())
|
||||||
|
return rendV();
|
||||||
|
else
|
||||||
|
return ReverseValueIterator(++currentV());
|
||||||
|
}
|
||||||
|
ConstReverseValueIterator rcurrentV() const {
|
||||||
|
if (empty())
|
||||||
|
return rendV();
|
||||||
|
else
|
||||||
|
return ConstReverseValueIterator(++currentV());
|
||||||
|
}
|
||||||
|
|
||||||
Iterator begin() { return Iterator(m_items.begin()); }
|
Iterator begin() { return Iterator(m_items.begin()); }
|
||||||
ConstIterator begin() const { return ConstIterator(m_items.begin()); }
|
ConstIterator begin() const { return ConstIterator(m_items.begin()); }
|
||||||
|
|||||||
@@ -561,7 +561,7 @@ void Connection::Add(const std::string &path)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Connection::AddRandomTag(mpd_tag_type tag, size_t number)
|
bool Connection::AddRandomTag(mpd_tag_type tag, size_t number, std::mt19937 &rng)
|
||||||
{
|
{
|
||||||
std::vector<std::string> tags(
|
std::vector<std::string> tags(
|
||||||
std::make_move_iterator(GetList(tag)),
|
std::make_move_iterator(GetList(tag)),
|
||||||
@@ -570,7 +570,7 @@ bool Connection::AddRandomTag(mpd_tag_type tag, size_t number)
|
|||||||
if (number > tags.size())
|
if (number > tags.size())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
std::random_shuffle(tags.begin(), tags.end());
|
std::shuffle(tags.begin(), tags.end(), rng);
|
||||||
auto it = tags.begin();
|
auto it = tags.begin();
|
||||||
for (size_t i = 0; i < number && it != tags.end(); ++i)
|
for (size_t i = 0; i < number && it != tags.end(); ++i)
|
||||||
{
|
{
|
||||||
@@ -588,7 +588,7 @@ bool Connection::AddRandomTag(mpd_tag_type tag, size_t number)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Connection::AddRandomSongs(size_t number)
|
bool Connection::AddRandomSongs(size_t number, std::mt19937 &rng)
|
||||||
{
|
{
|
||||||
prechecksNoCommandsList();
|
prechecksNoCommandsList();
|
||||||
std::vector<std::string> files;
|
std::vector<std::string> files;
|
||||||
@@ -609,7 +609,7 @@ bool Connection::AddRandomSongs(size_t number)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::random_shuffle(files.begin(), files.end());
|
std::shuffle(files.begin(), files.end(), rng);
|
||||||
StartCommandsList();
|
StartCommandsList();
|
||||||
auto it = files.begin();
|
auto it = files.begin();
|
||||||
for (size_t i = 0; i < number && it != files.end(); ++i, ++it)
|
for (size_t i = 0; i < number && it != files.end(); ++i, ++it)
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <exception>
|
#include <exception>
|
||||||
|
#include <random>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@@ -524,8 +525,8 @@ struct Connection
|
|||||||
|
|
||||||
int AddSong(const std::string &, int = -1); // returns id of added song
|
int AddSong(const std::string &, int = -1); // returns id of added song
|
||||||
int AddSong(const Song &, int = -1); // returns id of added song
|
int AddSong(const Song &, int = -1); // returns id of added song
|
||||||
bool AddRandomTag(mpd_tag_type, size_t);
|
bool AddRandomTag(mpd_tag_type, size_t, std::mt19937 &rng);
|
||||||
bool AddRandomSongs(size_t);
|
bool AddRandomSongs(size_t number, std::mt19937 &rng);
|
||||||
void Add(const std::string &path);
|
void Add(const std::string &path);
|
||||||
void Delete(unsigned int pos);
|
void Delete(unsigned int pos);
|
||||||
void PlaylistDelete(const std::string &playlist, unsigned int pos);
|
void PlaylistDelete(const std::string &playlist, unsigned int pos);
|
||||||
|
|||||||
@@ -89,7 +89,6 @@ int main(int argc, char **argv)
|
|||||||
using Global::VolumeState;
|
using Global::VolumeState;
|
||||||
using Global::Timer;
|
using Global::Timer;
|
||||||
|
|
||||||
srand(time(nullptr));
|
|
||||||
std::setlocale(LC_ALL, "");
|
std::setlocale(LC_ALL, "");
|
||||||
std::locale::global(Charset::internalLocale());
|
std::locale::global(Charset::internalLocale());
|
||||||
|
|
||||||
@@ -131,6 +130,9 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
// initialize global timer
|
// initialize global timer
|
||||||
Timer = boost::posix_time::microsec_clock::local_time();
|
Timer = boost::posix_time::microsec_clock::local_time();
|
||||||
|
|
||||||
|
// initialize global random number generator
|
||||||
|
Global::RNG.seed(std::random_device()());
|
||||||
|
|
||||||
// initialize playlist
|
// initialize playlist
|
||||||
myPlaylist->switchTo();
|
myPlaylist->switchTo();
|
||||||
|
|||||||
@@ -147,13 +147,23 @@ void PlaylistEditor::update()
|
|||||||
{
|
{
|
||||||
m_playlists_update_requested = false;
|
m_playlists_update_requested = false;
|
||||||
size_t idx = 0;
|
size_t idx = 0;
|
||||||
for (MPD::PlaylistIterator it = Mpd.GetPlaylists(), end; it != end; ++it, ++idx)
|
try
|
||||||
{
|
{
|
||||||
if (idx < Playlists.size())
|
for (MPD::PlaylistIterator it = Mpd.GetPlaylists(), end; it != end; ++it, ++idx)
|
||||||
Playlists[idx].value() = std::move(*it);
|
{
|
||||||
|
if (idx < Playlists.size())
|
||||||
|
Playlists[idx].value() = std::move(*it);
|
||||||
|
else
|
||||||
|
Playlists.addItem(std::move(*it));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
catch (MPD::ServerError &e)
|
||||||
|
{
|
||||||
|
if (e.code() == MPD_SERVER_ERROR_SYSTEM) // no playlists directory
|
||||||
|
Statusbar::print(e.what());
|
||||||
else
|
else
|
||||||
Playlists.addItem(std::move(*it));
|
throw;
|
||||||
};
|
}
|
||||||
if (idx < Playlists.size())
|
if (idx < Playlists.size())
|
||||||
Playlists.resizeList(idx);
|
Playlists.resizeList(idx);
|
||||||
std::sort(Playlists.beginV(), Playlists.endV(),
|
std::sort(Playlists.beginV(), Playlists.endV(),
|
||||||
|
|||||||
@@ -160,6 +160,12 @@ std::string adjust_directory(std::string s)
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string adjust_path(std::string s)
|
||||||
|
{
|
||||||
|
expand_home(s);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
// parser worker for buffer
|
// parser worker for buffer
|
||||||
template <typename ValueT, typename TransformT>
|
template <typename ValueT, typename TransformT>
|
||||||
option_parser::worker buffer(NC::Buffer &arg, ValueT &&value, TransformT &&map)
|
option_parser::worker buffer(NC::Buffer &arg, ValueT &&value, TransformT &&map)
|
||||||
@@ -237,8 +243,8 @@ bool Configuration::read(const std::vector<std::string> &config_paths, bool igno
|
|||||||
p.add("mpd_crossfade_time", assign_default(
|
p.add("mpd_crossfade_time", assign_default(
|
||||||
crossfade_time, 5
|
crossfade_time, 5
|
||||||
));
|
));
|
||||||
p.add("visualizer_fifo_path", assign_default(
|
p.add("visualizer_fifo_path", assign_default<std::string>(
|
||||||
visualizer_fifo_path, "/tmp/mpd.fifo"
|
visualizer_fifo_path, "/tmp/mpd.fifo", adjust_path
|
||||||
));
|
));
|
||||||
p.add("visualizer_output_name", assign_default(
|
p.add("visualizer_output_name", assign_default(
|
||||||
visualizer_output_name, "Visualizer feed"
|
visualizer_output_name, "Visualizer feed"
|
||||||
@@ -372,8 +378,8 @@ bool Configuration::read(const std::vector<std::string> &config_paths, bool igno
|
|||||||
song_columns_mode_format = columns_to_format(columns);
|
song_columns_mode_format = columns_to_format(columns);
|
||||||
return v;
|
return v;
|
||||||
}));
|
}));
|
||||||
p.add("execute_on_song_change", assign_default(
|
p.add("execute_on_song_change", assign_default<std::string>(
|
||||||
execute_on_song_change, ""
|
execute_on_song_change, "", adjust_path
|
||||||
));
|
));
|
||||||
p.add("execute_on_player_state_change", assign_default(
|
p.add("execute_on_player_state_change", assign_default(
|
||||||
execute_on_player_state_change, ""
|
execute_on_player_state_change, ""
|
||||||
@@ -647,8 +653,8 @@ bool Configuration::read(const std::vector<std::string> &config_paths, bool igno
|
|||||||
boundsCheck(v, 1u, 3u);
|
boundsCheck(v, 1u, 3u);
|
||||||
return --v;
|
return --v;
|
||||||
}));
|
}));
|
||||||
p.add("external_editor", assign_default(
|
p.add("external_editor", assign_default<std::string>(
|
||||||
external_editor, "nano"
|
external_editor, "nano", adjust_path
|
||||||
));
|
));
|
||||||
p.add("use_console_editor", yes_no(
|
p.add("use_console_editor", yes_no(
|
||||||
use_console_editor, true
|
use_console_editor, true
|
||||||
|
|||||||
@@ -197,7 +197,7 @@ void SortPlaylistDialog::sort() const
|
|||||||
quick_sort = [this, &song_cmp, &quick_sort, &iter_swap](Iterator first, Iterator last) {
|
quick_sort = [this, &song_cmp, &quick_sort, &iter_swap](Iterator first, Iterator last) {
|
||||||
if (last-first > 1)
|
if (last-first > 1)
|
||||||
{
|
{
|
||||||
Iterator pivot = first+rand()%(last-first);
|
Iterator pivot = first+Global::RNG()%(last-first);
|
||||||
iter_swap(pivot, last-1);
|
iter_swap(pivot, last-1);
|
||||||
pivot = last-1;
|
pivot = last-1;
|
||||||
|
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ void stripHtmlTags(std::string &s)
|
|||||||
for (size_t i = s.find("<"); i != std::string::npos; i = s.find("<"))
|
for (size_t i = s.find("<"); i != std::string::npos; i = s.find("<"))
|
||||||
{
|
{
|
||||||
size_t j = s.find(">", i)+1;
|
size_t j = s.find(">", i)+1;
|
||||||
if (s.compare(i, j-i, "<p>") == 0 || s.compare(i, j-i, "</p>") == 0)
|
if (s.compare(i, std::min(3ul, j-i), "<p ") == 0 || s.compare(i, j-i, "</p>") == 0)
|
||||||
s.replace(i, j-i, "\n");
|
s.replace(i, j-i, "\n");
|
||||||
else
|
else
|
||||||
s.replace(i, j-i, "");
|
s.replace(i, j-i, "");
|
||||||
@@ -87,4 +87,4 @@ void stripHtmlTags(std::string &s)
|
|||||||
else if (s[i] == '\t')
|
else if (s[i] == '\t')
|
||||||
s[i] = ' ';
|
s[i] = ' ';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user