Hello community,
here is the log from the commit of package pianobar for openSUSE:Factory checked in at 2019-02-15 10:02:33
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/pianobar (Old)
and /work/SRC/openSUSE:Factory/.pianobar.new.28833 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "pianobar"
Fri Feb 15 10:02:33 2019 rev:4 rq:674972 version:2019.02.14
Changes:
--------
--- /work/SRC/openSUSE:Factory/pianobar/pianobar.changes 2018-07-09 13:31:22.602486273 +0200
+++ /work/SRC/openSUSE:Factory/.pianobar.new.28833/pianobar.changes 2019-02-15 10:02:36.247621842 +0100
@@ -1,0 +2,9 @@
+Thu Feb 14 12:53:46 UTC 2019 - Luigi Baldoni
+
+- Update to version 2019.02.14
+ * Fix MP3 playback (affects premium subscribers with audio
+ quality “high”)
+ version 2019.01.25
+ * Implement audio buffering
+
+-------------------------------------------------------------------
Old:
----
pianobar-2018.06.22.tar.gz
New:
----
pianobar-2019.02.14.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ pianobar.spec ++++++
--- /var/tmp/diff_new_pack.yeL8zR/_old 2019-02-15 10:02:37.935621298 +0100
+++ /var/tmp/diff_new_pack.yeL8zR/_new 2019-02-15 10:02:37.979621284 +0100
@@ -1,7 +1,7 @@
#
# spec file for package pianobar
#
-# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany.
# Copyright (c) 2016 Packman team: http://packman.links2linux.org/
#
# All modifications and additions to the file contributed by third parties
@@ -13,17 +13,17 @@
# license that conforms to the Open Source Definition (Version 1.9)
# published by the Open Source Initiative.
-# Please submit bugfixes or comments via http://bugs.opensuse.org/
+# Please submit bugfixes or comments via https://bugs.opensuse.org/
#
Name: pianobar
-Version: 2018.06.22
+Version: 2019.02.14
Release: 0
Summary: Pandora Player
License: MIT
Group: Productivity/Multimedia/Sound/Utilities
-Url: https://6xq.net/pianobar
+URL: https://6xq.net/pianobar
Source0: https://github.com/PromyLOPh/pianobar/archive/%{version}.tar.gz#/%{name}-%{version}.tar.gz
BuildRequires: libgcrypt-devel
BuildRequires: pkgconfig
++++++ pianobar-2018.06.22.tar.gz -> pianobar-2019.02.14.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pianobar-2018.06.22/.github/issue_template.md new/pianobar-2019.02.14/.github/issue_template.md
--- old/pianobar-2018.06.22/.github/issue_template.md 1970-01-01 01:00:00.000000000 +0100
+++ new/pianobar-2019.02.14/.github/issue_template.md 2019-02-14 09:37:03.000000000 +0100
@@ -0,0 +1,19 @@
+### Subject of the issue
+Briefly describe your issue here.
+
+### Your environment
+* version of pianobar
+* your Linux distribution and release version
+* ffmpeg/libav version and the flags it was compiled with (if you compiled yourself)
+* your config file
+
+### Steps to reproduce
+Tell us how to reproduce this issue.
+
+### Expected behaviour
+Tell us what should happen.
+
+### Actual behaviour
+Tell us what happens instead, including a copy of all error messages.
+
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pianobar-2018.06.22/ChangeLog new/pianobar-2019.02.14/ChangeLog
--- old/pianobar-2018.06.22/ChangeLog 2018-06-22 08:57:26.000000000 +0200
+++ new/pianobar-2019.02.14/ChangeLog 2019-02-14 09:37:03.000000000 +0100
@@ -1,3 +1,11 @@
+Release 2019.02.14
+
+- Fix MP3 playback (affects premium subscribers with audio quality “high”)
+
+Release 2019.01.25
+
+- Implement audio buffering
+
Release 2018.06.22
- Happy 10th birthday pianobar!
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pianobar-2018.06.22/README.md new/pianobar-2019.02.14/README.md
--- old/pianobar-2018.06.22/README.md 2018-06-22 08:57:26.000000000 +0200
+++ new/pianobar-2019.02.14/README.md 2019-02-14 09:37:03.000000000 +0100
@@ -1,6 +1,6 @@
# pianobar
-pianobar is a console client for the personalized web radio [Pandora](http://www.pandora.com).
+pianobar is a console client for the personalized web radio [Pandora](https://www.pandora.com).
### Features
@@ -13,9 +13,9 @@
### Source Code
-The source code can be downloaded at [github.com](http://github.com/PromyLOPh/pianobar/)
-or [6xq.net](http://6xq.net/projects/pianobar/).
+The source code can be downloaded at [github.com](https://github.com/PromyLOPh/pianobar)
+or [6xq.net](https://6xq.net/pianobar/).
### Download/Installation
-There are community provided packages available for most Linux distributions (see your distribution’s package manager), Mac OS X ([MacPorts](http://trac.macports.org/browser/trunk/dports/audio/pianobar/Portfile) or [homebrew](http://brew.sh/)) and *BSD as well as a [native Windows port](https://github.com/thedmd/pianobar-windows).
+There are community provided packages available for most Linux distributions (see your distribution’s package manager), macOS ([MacPorts](https://www.macports.org) or [Homebrew](https://brew.sh)) and *BSD as well as a [native Windows port](https://github.com/thedmd/pianobar-windows).
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pianobar-2018.06.22/contrib/pianobar.1 new/pianobar-2019.02.14/contrib/pianobar.1
--- old/pianobar-2018.06.22/contrib/pianobar.1 2018-06-22 08:57:26.000000000 +0200
+++ new/pianobar-2019.02.14/contrib/pianobar.1 2019-02-14 09:37:03.000000000 +0100
@@ -209,6 +209,10 @@
.B route-nopull.
.TP
+.B buffer_seconds = 5
+Audio buffer size in seconds.
+
+.TP
.B ca_bundle = /etc/ssl/certs/ca-certificates.crt
Path to CA certifiate bundle, containing the root and intermediate certificates
required to validate Pandora's SSL certificate.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pianobar-2018.06.22/src/config.h new/pianobar-2019.02.14/src/config.h
--- old/pianobar-2018.06.22/src/config.h 2018-06-22 08:57:26.000000000 +0200
+++ new/pianobar-2019.02.14/src/config.h 2019-02-14 09:37:03.000000000 +0100
@@ -3,7 +3,7 @@
/* package name */
#define PACKAGE "pianobar"
-#define VERSION "2018.06.22"
+#define VERSION "2019.02.14"
/* glibc feature test macros, define _before_ including other files */
#define _POSIX_C_SOURCE 200809L
@@ -12,10 +12,33 @@
* ffmpeg’s micro versions always start at 100, that’s how we can distinguish
* ffmpeg and libav */
#include
+#include
/* does graph_send_command exist (ffmpeg >=2.2) */
-#if LIBAVFILTER_VERSION_MAJOR >= 4 && \
+#if !defined(HAVE_AVFILTER_GRAPH_SEND_COMMAND) && \
+ LIBAVFILTER_VERSION_MAJOR >= 4 && \
LIBAVFILTER_VERSION_MICRO >= 100
#define HAVE_AVFILTER_GRAPH_SEND_COMMAND
#endif
+/* explicit init is optional for ffmpeg>=4.0 */
+#if !defined(HAVE_AVFORMAT_NETWORK_INIT) && \
+ LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(58, 5, 100) && \
+ LIBAVFORMAT_VERSION_MICRO >= 100
+#define HAVE_AVFORMAT_NETWORK_INIT
+#endif
+
+/* dito */
+#if !defined(HAVE_AVFILTER_REGISTER_ALL) && \
+ LIBAVFILTER_VERSION_INT < AV_VERSION_INT(7, 14, 100) && \
+ LIBAVFILTER_VERSION_MICRO >= 100
+#define HAVE_AVFILTER_REGISTER_ALL
+#endif
+
+/* dito */
+#if !defined(HAVE_AV_REGISTER_ALL) && \
+ LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(58, 9, 100) && \
+ LIBAVFORMAT_VERSION_MICRO >= 100
+#define HAVE_AV_REGISTER_ALL
+#endif
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pianobar-2018.06.22/src/player.c new/pianobar-2019.02.14/src/player.c
--- old/pianobar-2018.06.22/src/player.c 2018-06-22 08:57:26.000000000 +0200
+++ new/pianobar-2019.02.14/src/player.c 2019-02-14 09:37:03.000000000 +0100
@@ -21,7 +21,16 @@
THE SOFTWARE.
*/
-/* receive/play audio stream */
+/* receive/play audio stream.
+ *
+ * There are two threads involved here:
+ * BarPlayerThread
+ * Sets up the stream and fetches the data into a ffmpeg buffersrc
+ * BarAoPlayThread
+ * Reads data from the filter chain’s sink and hands it over to libao for
+ * playback.
+ *
+ */
#include "config.h"
@@ -61,19 +70,24 @@
}
/* global initialization
- *
- * XXX: in theory we can select the filters/formats we want to support, but
- * this does not work in practise.
*/
void BarPlayerInit (player_t * const p, const BarSettings_t * const settings) {
ao_initialize ();
av_log_set_level (AV_LOG_FATAL);
+#ifdef HAVE_AV_REGISTER_ALL
av_register_all ();
+#endif
+#ifdef HAVE_AVFILTER_REGISTER_ALL
avfilter_register_all ();
+#endif
+#ifdef HAVE_AVFORMAT_NETWORK_INIT
avformat_network_init ();
+#endif
pthread_mutex_init (&p->lock, NULL);
pthread_cond_init (&p->cond, NULL);
+ pthread_mutex_init (&p->aoplayLock, NULL);
+ pthread_cond_init (&p->aoplayCond, NULL);
BarPlayerReset (p);
p->settings = settings;
}
@@ -81,8 +95,12 @@
void BarPlayerDestroy (player_t * const p) {
pthread_cond_destroy (&p->cond);
pthread_mutex_destroy (&p->lock);
+ pthread_cond_destroy (&p->aoplayCond);
+ pthread_mutex_destroy (&p->aoplayLock);
+#ifdef HAVE_AVFORMAT_NETWORK_INIT
avformat_network_deinit ();
+#endif
ao_shutdown ();
}
@@ -257,14 +275,14 @@
av_get_sample_fmt_name (player->cctx->sample_fmt),
cp->channel_layout);
if ((ret = avfilter_graph_create_filter (&player->fabuf,
- avfilter_get_by_name ("abuffer"), NULL, strbuf, NULL,
+ avfilter_get_by_name ("abuffer"), "source", strbuf, NULL,
player->fgraph)) < 0) {
softfail ("create_filter abuffer");
}
/* volume */
if ((ret = avfilter_graph_create_filter (&player->fvolume,
- avfilter_get_by_name ("volume"), NULL, "0dB", NULL,
+ avfilter_get_by_name ("volume"), "volume", "0dB", NULL,
player->fgraph)) < 0) {
softfail ("create_filter volume");
}
@@ -274,14 +292,14 @@
snprintf (strbuf, sizeof (strbuf), "sample_fmts=%s",
av_get_sample_fmt_name (avformat));
if ((ret = avfilter_graph_create_filter (&fafmt,
- avfilter_get_by_name ("aformat"), NULL, strbuf, NULL,
+ avfilter_get_by_name ("aformat"), "format", strbuf, NULL,
player->fgraph)) < 0) {
softfail ("create_filter aformat");
}
/* abuffersink */
if ((ret = avfilter_graph_create_filter (&player->fbufsink,
- avfilter_get_by_name ("abuffersink"), NULL, NULL, NULL,
+ avfilter_get_by_name ("abuffersink"), "sink", NULL, NULL,
player->fgraph)) < 0) {
softfail ("create_filter abuffersink");
}
@@ -349,6 +367,7 @@
*/
static int play (player_t * const player) {
assert (player != NULL);
+ const int64_t minBufferHealth = player->settings->bufferSecs;
AVPacket pkt;
AVCodecContext * const cctx = player->cctx;
@@ -356,14 +375,14 @@
pkt.data = NULL;
pkt.size = 0;
- AVFrame *frame = NULL, *filteredFrame = NULL;
+ AVFrame *frame = NULL;
frame = av_frame_alloc ();
assert (frame != NULL);
- filteredFrame = av_frame_alloc ();
- assert (filteredFrame != NULL);
-
+ pthread_t aoplaythread;
+ pthread_create (&aoplaythread, NULL, BarAoPlayThread, player);
enum { FILL, DRAIN, DONE } drainMode = FILL;
int ret = 0;
+ const double timeBase = av_q2d (player->st->time_base);
while (!shouldQuit (player) && drainMode != DONE) {
if (drainMode == FILL) {
ret = av_read_frame (player->fctx, &pkt);
@@ -377,6 +396,12 @@
continue;
} else if (ret < 0) {
/* error, abort */
+ /* mark the EOF, so that BarAoPlayThread can quit*/
+ pthread_mutex_lock (&player->aoplayLock);
+ const int rt = av_buffersrc_add_frame (player->fabuf, NULL);
+ assert (rt == 0);
+ pthread_cond_broadcast (&player->aoplayCond);
+ pthread_mutex_unlock (&player->aoplayLock);
break;
} else {
/* fill buffer */
@@ -384,22 +409,17 @@
}
}
- /* pausing */
- pthread_mutex_lock (&player->lock);
- if (player->doPause) {
- av_read_pause (player->fctx);
- do {
- pthread_cond_wait (&player->cond, &player->lock);
- } while (player->doPause);
- av_read_play (player->fctx);
- }
- pthread_mutex_unlock (&player->lock);
-
while (!shouldQuit (player)) {
ret = avcodec_receive_frame (cctx, frame);
if (ret == AVERROR_EOF) {
/* done draining */
drainMode = DONE;
+ /* mark the EOF*/
+ pthread_mutex_lock (&player->aoplayLock);
+ const int rt = av_buffersrc_add_frame (player->fabuf, NULL);
+ assert (rt == 0);
+ pthread_cond_broadcast (&player->aoplayCond);
+ pthread_mutex_unlock (&player->aoplayLock);
break;
} else if (ret != 0) {
/* no more output */
@@ -410,36 +430,29 @@
if (frame->pts == (int64_t) AV_NOPTS_VALUE) {
frame->pts = 0;
}
+ pthread_mutex_lock (&player->aoplayLock);
ret = av_buffersrc_write_frame (player->fabuf, frame);
assert (ret >= 0);
-
- while (true) {
- if (av_buffersink_get_frame (player->fbufsink, filteredFrame) < 0) {
- /* try again next frame */
- break;
+ pthread_mutex_unlock (&player->aoplayLock);
+
+ int64_t bufferHealth = 0;
+ do {
+ pthread_mutex_lock (&player->aoplayLock);
+ bufferHealth = timeBase * (double) (frame->pts - player->lastTimestamp);
+ if (bufferHealth > minBufferHealth) {
+ /* Buffer get healthy, resume */
+ pthread_cond_broadcast (&player->aoplayCond);
+ /* Buffer is healthy enough, wait */
+ pthread_cond_wait (&player->aoplayCond, &player->aoplayLock);
}
-
- const int numChannels = av_get_channel_layout_nb_channels (
- filteredFrame->channel_layout);
- const int bps = av_get_bytes_per_sample(filteredFrame->format);
- ao_play (player->aoDev, (char *) filteredFrame->data[0],
- filteredFrame->nb_samples * numChannels * bps);
-
- av_frame_unref (filteredFrame);
- }
+ pthread_mutex_unlock (&player->aoplayLock);
+ } while (bufferHealth > minBufferHealth);
}
- const unsigned int songPlayed = av_q2d (player->st->time_base) * (double) pkt.pts;
- pthread_mutex_lock (&player->lock);
- player->songPlayed = songPlayed;
- pthread_mutex_unlock (&player->lock);
- player->lastTimestamp = pkt.pts;
-
av_packet_unref (&pkt);
}
-
- av_frame_free (&filteredFrame);
av_frame_free (&frame);
+ pthread_join (aoplaythread, NULL);
return ret;
}
@@ -496,3 +509,65 @@
return (void *) pret;
}
+void *BarAoPlayThread (void *data) {
+ assert (data != NULL);
+
+ player_t * const player = data;
+
+ AVFrame *filteredFrame = NULL;
+ filteredFrame = av_frame_alloc ();
+ assert (filteredFrame != NULL);
+
+ int ret;
+ const double timeBase = av_q2d (av_buffersink_get_time_base (player->fbufsink)),
+ timeBaseSt = av_q2d (player->st->time_base);
+ while (!shouldQuit(player)) {
+ pthread_mutex_lock (&player->aoplayLock);
+ ret = av_buffersink_get_frame (player->fbufsink, filteredFrame);
+ if (ret == AVERROR_EOF || shouldQuit (player)) {
+ /* we are done here */
+ pthread_mutex_unlock (&player->aoplayLock);
+ break;
+ } else if (ret < 0) {
+ /* wait for more frames */
+ pthread_cond_broadcast (&player->aoplayCond);
+ pthread_cond_wait (&player->aoplayCond, &player->aoplayLock);
+ pthread_mutex_unlock (&player->aoplayLock);
+ continue;
+ }
+ pthread_mutex_unlock (&player->aoplayLock);
+
+ const int numChannels = av_get_channel_layout_nb_channels (
+ filteredFrame->channel_layout);
+ const int bps = av_get_bytes_per_sample (filteredFrame->format);
+ ao_play (player->aoDev, (char *) filteredFrame->data[0],
+ filteredFrame->nb_samples * numChannels * bps);
+
+ const double timestamp = (double) filteredFrame->pts * timeBase;
+ const unsigned int songPlayed = timestamp;
+
+ pthread_mutex_lock (&player->lock);
+ player->songPlayed = songPlayed;
+ /* pausing */
+ if (player->doPause) {
+ do {
+ pthread_cond_wait (&player->cond, &player->lock);
+ } while (player->doPause);
+ }
+ pthread_mutex_unlock (&player->lock);
+
+ /* lastTimestamp must be the last pts, but expressed in terms of
+ * st->time_base, not the sink’s time_base. */
+ const int64_t lastTimestamp = timestamp/timeBaseSt;
+ /* notify download thread, we might need more data */
+ pthread_mutex_lock (&player->aoplayLock);
+ player->lastTimestamp = lastTimestamp;
+ pthread_cond_broadcast (&player->aoplayCond);
+ pthread_mutex_unlock (&player->aoplayLock);
+
+ av_frame_unref (filteredFrame);
+ }
+ av_frame_free (&filteredFrame);
+
+ return (void *) 0;
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pianobar-2018.06.22/src/player.h new/pianobar-2019.02.14/src/player.h
--- old/pianobar-2018.06.22/src/player.h 2018-06-22 08:57:26.000000000 +0200
+++ new/pianobar-2019.02.14/src/player.h 2019-02-14 09:37:03.000000000 +0100
@@ -51,9 +51,8 @@
typedef struct {
/* public attributes protected by mutex */
- pthread_mutex_t lock;
- pthread_cond_t cond; /* broadcast changes to doPause */
-
+ pthread_mutex_t lock, aoplayLock;
+ pthread_cond_t cond, aoplayCond; /* broadcast changes to doPause */
bool doQuit, doPause;
/* measured in seconds */
@@ -86,6 +85,7 @@
enum {PLAYER_RET_OK = 0, PLAYER_RET_HARDFAIL = 1, PLAYER_RET_SOFTFAIL = 2};
void *BarPlayerThread (void *data);
+void *BarAoPlayThread (void *data);
void BarPlayerSetVolume (player_t * const player);
void BarPlayerInit (player_t * const p, const BarSettings_t * const settings);
void BarPlayerReset (player_t * const p);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pianobar-2018.06.22/src/settings.c new/pianobar-2019.02.14/src/settings.c
--- old/pianobar-2018.06.22/src/settings.c 2018-06-22 08:57:26.000000000 +0200
+++ new/pianobar-2019.02.14/src/settings.c 2019-02-14 09:37:03.000000000 +0100
@@ -163,7 +163,9 @@
settings->volume = 0;
settings->timeout = 30; /* seconds */
settings->gainMul = 1.0;
- settings->maxRetry = 3;
+ /* should be > 4, otherwise expired audio urls (403) can stop playback */
+ settings->maxRetry = 5;
+ settings->bufferSecs = 5;
settings->sortOrder = BAR_SORT_NAME_AZ;
settings->loveIcon = strdup (" <3");
settings->banIcon = strdup (" 3");
@@ -342,6 +344,8 @@
settings->maxRetry = atoi (val);
} else if (streq ("timeout", key)) {
settings->timeout = atoi (val);
+ } else if (streq ("buffer_seconds", key)) {
+ settings->bufferSecs = atoi (val);
} else if (streq ("sort", key)) {
size_t i;
static const char *mapping[] = {"name_az",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pianobar-2018.06.22/src/settings.h new/pianobar-2019.02.14/src/settings.h
--- old/pianobar-2018.06.22/src/settings.h 2018-06-22 08:57:26.000000000 +0200
+++ new/pianobar-2019.02.14/src/settings.h 2019-02-14 09:37:03.000000000 +0100
@@ -84,7 +84,7 @@
typedef struct {
bool autoselect;
- unsigned int history, maxRetry, timeout;
+ unsigned int history, maxRetry, timeout, bufferSecs;
int volume;
float gainMul;
BarStationSorting_t sortOrder;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pianobar-2018.06.22/src/ui.c new/pianobar-2019.02.14/src/ui.c
--- old/pianobar-2018.06.22/src/ui.c 2018-06-22 08:57:26.000000000 +0200
+++ new/pianobar-2019.02.14/src/ui.c 2019-02-14 09:37:03.000000000 +0100
@@ -250,7 +250,7 @@
free (buffer.data);
buffer.data = NULL;
buffer.pos = 0;
- if (retry > settings->maxRetry) {
+ if (retry >= settings->maxRetry) {
break;
}
} else {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pianobar-2018.06.22/src/ui_act.c new/pianobar-2019.02.14/src/ui_act.c
--- old/pianobar-2018.06.22/src/ui_act.c 2018-06-22 08:57:26.000000000 +0200
+++ new/pianobar-2019.02.14/src/ui_act.c 2019-02-14 09:37:03.000000000 +0100
@@ -57,6 +57,9 @@
player->doPause = false;
pthread_cond_broadcast (&player->cond);
pthread_mutex_unlock (&player->lock);
+ pthread_mutex_lock (&player->aoplayLock);
+ pthread_cond_broadcast (&player->aoplayCond);
+ pthread_mutex_unlock (&player->aoplayLock);
}
/* transform station if necessary to allow changes like rename, rate, ...
@@ -561,15 +564,15 @@
if (selStation->isQuickMix) {
PianoStation_t *toggleStation;
while ((toggleStation = BarUiSelectStation (app, app->ph.stations,
- "Toggle quickmix for station: ",
+ "Toggle QuickMix for station: ",
BarUiActQuickmixCallback, false)) != NULL) {
toggleStation->useQuickMix = !toggleStation->useQuickMix;
}
- BarUiMsg (&app->settings, MSG_INFO, "Setting quickmix stations... ");
+ BarUiMsg (&app->settings, MSG_INFO, "Setting QuickMix stations... ");
BarUiActDefaultPianoCall (PIANO_REQUEST_SET_QUICKMIX, NULL);
BarUiActDefaultEventcmd ("stationquickmixtoggle");
} else {
- BarUiMsg (&app->settings, MSG_ERR, "Not a QuickMix station.\n");
+ BarUiMsg (&app->settings, MSG_ERR, "Please select a QuickMix station first.\n");
}
}
@@ -881,4 +884,3 @@
PianoDestroyStationInfo (&reqData.info);
}
-