summaryrefslogtreecommitdiff
path: root/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'plugins')
-rw-r--r--plugins/aac/COPYING25
-rw-r--r--plugins/aac/Makefile.am2
-rw-r--r--plugins/aac/aac.c31
-rw-r--r--plugins/adplug/COPYING40
-rw-r--r--plugins/adplug/adplug-db.cpp34
-rw-r--r--plugins/adplug/plugin.c93
-rw-r--r--plugins/alac/COPYING68
-rw-r--r--plugins/alac/alac_plugin.c1
-rw-r--r--plugins/alsa/COPYING17
-rw-r--r--plugins/ao/COPYING (renamed from plugins/ao/license.txt)19
-rw-r--r--plugins/ao/Makefile.am2
-rw-r--r--plugins/artwork/COPYING20
-rw-r--r--plugins/artwork/Makefile.am12
-rw-r--r--plugins/artwork/albumartorg.c34
-rw-r--r--plugins/artwork/albumartorg.h34
-rw-r--r--plugins/artwork/artwork.c180
-rw-r--r--plugins/artwork/artwork.h26
-rw-r--r--plugins/artwork/lastfm.c38
-rw-r--r--plugins/artwork/lastfm.h33
-rw-r--r--plugins/cdda/COPYING55
-rw-r--r--plugins/converter/COPYING17
-rw-r--r--plugins/converter/Makefile.am14
-rw-r--r--plugins/converter/converter.c20
-rw-r--r--plugins/converter/presets/ALAC.txt10
-rw-r--r--plugins/coreaudio/COPYING17
-rw-r--r--plugins/dca/COPYING359
-rw-r--r--plugins/dsp_libsrc/COPYING20
-rw-r--r--plugins/dumb/COPYING89
-rw-r--r--plugins/dumb/cdumb.c61
-rw-r--r--plugins/ffap/COPYING18
-rw-r--r--plugins/ffmpeg/COPYING18
-rw-r--r--plugins/ffmpeg/ffmpeg.c5
-rw-r--r--plugins/flac/COPYING93
-rw-r--r--plugins/flac/Makefile.am2
-rw-r--r--plugins/flac/flac.c77
-rw-r--r--plugins/gme/COPYING40
-rw-r--r--plugins/gme/cgme.c114
-rw-r--r--plugins/gtkui/COPYING16
-rw-r--r--plugins/gtkui/Makefile.am19
-rw-r--r--plugins/gtkui/callbacks.c18
-rw-r--r--plugins/gtkui/callbacks.h8
-rw-r--r--plugins/gtkui/coverart.c2
-rw-r--r--plugins/gtkui/ddblistview.c2
-rw-r--r--plugins/gtkui/ddbseekbar.c69
-rw-r--r--plugins/gtkui/ddbseekbar.h10
-rw-r--r--plugins/gtkui/ddbvolumebar.c61
-rw-r--r--plugins/gtkui/ddbvolumebar.h3
-rw-r--r--plugins/gtkui/deadbeef.glade218
-rw-r--r--plugins/gtkui/gtkui.c144
-rw-r--r--plugins/gtkui/gtkui.h14
-rw-r--r--plugins/gtkui/gtkui_api.h5
-rw-r--r--plugins/gtkui/hotkeys.c1
-rw-r--r--plugins/gtkui/interface.c133
-rw-r--r--plugins/gtkui/mainplaylist.c2
-rw-r--r--plugins/gtkui/plcommon.c35
-rw-r--r--plugins/gtkui/prefwin.c14
-rw-r--r--plugins/gtkui/trkproperties.c14
-rw-r--r--plugins/gtkui/widgets.c304
-rw-r--r--plugins/gtkui/widgets.h12
-rw-r--r--plugins/hotkeys/COPYING22
-rw-r--r--plugins/hotkeys/Makefile.am2
-rw-r--r--plugins/hotkeys/hotkeys.c48
-rw-r--r--plugins/hotkeys/hotkeys.h34
-rw-r--r--plugins/lastfm/lastfm.c32
-rw-r--r--plugins/mpgmad/Makefile.am2
-rw-r--r--plugins/mpgmad/mpgmad.c29
-rw-r--r--plugins/pltbrowser/Makefile.am11
-rw-r--r--plugins/shellexec/shellexec.c18
-rw-r--r--plugins/shellexecui/Makefile.am11
-rw-r--r--plugins/sid/csid.cpp67
-rw-r--r--plugins/sndfile/Makefile.am2
-rw-r--r--plugins/vfs_curl/vfs_curl.c40
-rw-r--r--plugins/vfs_zip/Makefile.am2
-rw-r--r--plugins/vfs_zip/vfs_zip.c64
-rw-r--r--plugins/vorbis/COPYING55
-rw-r--r--plugins/vorbis/i18n.h18
-rw-r--r--plugins/vorbis/vcedit.c1065
-rw-r--r--plugins/vorbis/vcedit.h82
-rw-r--r--plugins/vorbis/vceditaux.h9
-rw-r--r--plugins/vorbis/vorbis.c401
-rw-r--r--plugins/wavpack/Makefile.am2
-rw-r--r--plugins/wma/asfheader.c3
82 files changed, 2596 insertions, 2265 deletions
diff --git a/plugins/aac/COPYING b/plugins/aac/COPYING
new file mode 100644
index 00000000..a23602c3
--- /dev/null
+++ b/plugins/aac/COPYING
@@ -0,0 +1,25 @@
+AAC DeaDBeeF Player Plugin
+Copyright (c) 2009-2014 Alexey Yakovenko <waker@users.sourceforge.net>
+
+libmp4ff (modified)
+Code from MP4FF is copyright (c) Nero AG, www.nero.com
+deadbeef-related modifications (c) 2009-2014 Alexey Yakovenko
+
+Relies on libfaad2
+Code from FAAD2 is copyright (c) Nero AG, www.nero.com
+
+
+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.
+
diff --git a/plugins/aac/Makefile.am b/plugins/aac/Makefile.am
index ffd7b76e..1669db2f 100644
--- a/plugins/aac/Makefile.am
+++ b/plugins/aac/Makefile.am
@@ -6,6 +6,6 @@ aac_la_SOURCES = aac.c aac_parser.c aac_parser.h
aac_la_LDFLAGS = -module -avoid-version
aac_la_LIBADD = $(LDADD) $(FAAD2_LIBS) ../libmp4ff/libmp4ff.a
-AM_CFLAGS = $(CFLAGS) -std=c99 -DUSE_MP4FF -DUSE_TAGGING -I@top_srcdir@/plugins/libmp4ff
+AM_CFLAGS = -I@top_srcdir@/plugins/libmp4ff $(CFLAGS) $(FAAD2_CFLAGS) -std=c99 -DUSE_MP4FF -DUSE_TAGGING
endif
diff --git a/plugins/aac/aac.c b/plugins/aac/aac.c
index a711621b..8796da83 100644
--- a/plugins/aac/aac.c
+++ b/plugins/aac/aac.c
@@ -482,6 +482,10 @@ aac_init (DB_fileinfo_t *_info, DB_playItem_t *it) {
info->endsample = totalsamples-1;
}
}
+ if (_info->fmt.channels == 7) {
+ _info->fmt.channels = 8;
+ }
+
trace ("totalsamples: %d, endsample: %d, samples-from-duration: %d, samplerate %d, channels %d\n", totalsamples-1, info->endsample, (int)deadbeef->pl_get_item_duration (it)*44100, _info->fmt.samplerate, _info->fmt.channels);
for (int i = 0; i < _info->fmt.channels; i++) {
@@ -555,44 +559,45 @@ aac_read (DB_fileinfo_t *_info, char *bytes, int size) {
int i, j;
if (info->remap[0] == -1) {
// build remap mtx
+ memset (info->remap, -1, sizeof (info->remap));
// FIXME: should build channelmask 1st; then remap based on channelmask
for (i = 0; i < _info->fmt.channels; i++) {
switch (info->frame_info.channel_position[i]) {
case FRONT_CHANNEL_CENTER:
- trace ("FC->%d\n", i);
+ trace ("FC->%d %d\n", i, 2);
info->remap[2] = i;
break;
case FRONT_CHANNEL_LEFT:
- trace ("FL->%d\n", i);
+ trace ("FL->%d %d\n", i, 0);
info->remap[0] = i;
break;
case FRONT_CHANNEL_RIGHT:
- trace ("FR->%d\n", i);
+ trace ("FR->%d %d\n", i, 1);
info->remap[1] = i;
break;
case SIDE_CHANNEL_LEFT:
- trace ("SL->%d\n", i);
+ trace ("SL->%d %d\n", i, 6);
info->remap[6] = i;
break;
case SIDE_CHANNEL_RIGHT:
- trace ("SR->%d\n", i);
+ trace ("SR->%d %d\n", i, 7);
info->remap[7] = i;
break;
case BACK_CHANNEL_LEFT:
- trace ("RL->%d\n", i);
+ trace ("RL->%d %d\n", i, 4);
info->remap[4] = i;
break;
case BACK_CHANNEL_RIGHT:
- trace ("RR->%d\n", i);
+ trace ("RR->%d %d\n", i, 5);
info->remap[5] = i;
break;
case BACK_CHANNEL_CENTER:
- trace ("BC->%d\n", i);
+ trace ("BC->%d %d\n", i, 8);
info->remap[8] = i;
break;
case LFE_CHANNEL:
- trace ("LFE->%d\n", i);
+ trace ("LFE->%d %d\n", i, 3);
info->remap[3] = i;
break;
default:
@@ -615,7 +620,12 @@ aac_read (DB_fileinfo_t *_info, char *bytes, int size) {
for (i = 0; i < n; i++) {
for (j = 0; j < _info->fmt.channels; j++) {
- ((int16_t *)bytes)[j] = ((int16_t *)src)[info->remap[j]];
+ if (info->remap[j] == -1) {
+ ((int16_t *)bytes)[j] = 0;
+ }
+ else {
+ ((int16_t *)bytes)[j] = ((int16_t *)src)[info->remap[j]];
+ }
}
src += samplesize;
bytes += samplesize;
@@ -842,6 +852,7 @@ static const char *metainfo[] = {
"copyright", "copyright",
"totaltracks", "numtracks",
"tool", "tool",
+ "MusicBrainz Track Id", "musicbrainz_trackid",
NULL
};
diff --git a/plugins/adplug/COPYING b/plugins/adplug/COPYING
new file mode 100644
index 00000000..8dcb9556
--- /dev/null
+++ b/plugins/adplug/COPYING
@@ -0,0 +1,40 @@
+ADPLUG DeaDBeeF Player Plugin
+Copyright (C) 2009-2014 Alexey Yakovenko <waker@users.sourceforge.net>
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any damages
+arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source distribution.
+
+
+
+adplug (modified)
+Copyright (C) 1999 - 2006 Simon Peter, <dn.tlp@gmx.net>, et al.
+deadbeef-related modifications (c) 2009-2014 Alexey Yakovenko
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
diff --git a/plugins/adplug/adplug-db.cpp b/plugins/adplug/adplug-db.cpp
index 45cc6421..4561b217 100644
--- a/plugins/adplug/adplug-db.cpp
+++ b/plugins/adplug/adplug-db.cpp
@@ -1,20 +1,24 @@
/*
- DeaDBeeF - ultimate music player for GNU/Linux systems with X11
- Copyright (C) 2009-2013 Alexey Yakovenko <waker@users.sourceforge.net>
+ DeaDBeeF ADPLUG plugin
+ Copyright (C) 2009-2014 Alexey Yakovenko <waker@users.sourceforge.net>
- 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.
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+
+ 3. This notice may not be removed or altered from any source distribution.
*/
#include <stdio.h>
diff --git a/plugins/adplug/plugin.c b/plugins/adplug/plugin.c
index 5ad940a4..61143d5f 100644
--- a/plugins/adplug/plugin.c
+++ b/plugins/adplug/plugin.c
@@ -1,20 +1,24 @@
/*
- DeaDBeeF - ultimate music player for GNU/Linux systems with X11
- Copyright (C) 2009-2013 Alexey Yakovenko <waker@users.sourceforge.net>
+ DeaDBeeF ADPLUG plugin
+ Copyright (C) 2009-2014 Alexey Yakovenko <waker@users.sourceforge.net>
- 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.
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+
+ 3. This notice may not be removed or altered from any source distribution.
*/
// this is a decoder plugin skeleton
@@ -59,25 +63,46 @@ DB_decoder_t adplug_plugin = {
.plugin.name = "Adplug player",
.plugin.descr = "Adplug player (ADLIB OPL2/OPL3 emulator)",
.plugin.copyright =
- "Copyright (C) 2009-2013 Alexey Yakovenko <waker@users.sourceforge.net>\n"
- "\n"
- "Uses modified AdPlug library\n"
- "Copyright (C) 1999 - 2010 Simon Peter, et al.\n"
- "http://adplug.sourceforge.net/\n"
- "\n"
- "This program is free software; you can redistribute it and/or\n"
- "modify it under the terms of the GNU General Public License\n"
- "as published by the Free Software Foundation; either version 2\n"
- "of the License, or (at your option) any later version.\n"
- "\n"
- "This program is distributed in the hope that it will be useful,\n"
- "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
- "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
- "GNU General Public License for more details.\n"
- "\n"
- "You should have received a copy of the GNU General Public License\n"
- "along with this program; if not, write to the Free Software\n"
- "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n"
+ "ADPLUG DeaDBeeF Player Plugin\n"
+ "Copyright (C) 2009-2014 Alexey Yakovenko <waker@users.sourceforge.net>\n"
+ "\n"
+ "This software is provided 'as-is', without any express or implied\n"
+ "warranty. In no event will the authors be held liable for any damages\n"
+ "arising from the use of this software.\n"
+ "\n"
+ "Permission is granted to anyone to use this software for any purpose,\n"
+ "including commercial applications, and to alter it and redistribute it\n"
+ "freely, subject to the following restrictions:\n"
+ "\n"
+ "1. The origin of this software must not be misrepresented; you must not\n"
+ " claim that you wrote the original software. If you use this software\n"
+ " in a product, an acknowledgment in the product documentation would be\n"
+ " appreciated but is not required.\n"
+ "\n"
+ "2. Altered source versions must be plainly marked as such, and must not be\n"
+ " misrepresented as being the original software.\n"
+ "\n"
+ "3. This notice may not be removed or altered from any source distribution.\n"
+ "\n"
+ "\n"
+ "\n"
+ "adplug (modified)\n"
+ "Copyright (C) 1999 - 2006 Simon Peter, <dn.tlp@gmx.net>, et al.\n"
+ "deadbeef-related modifications (c) 2009-2014 Alexey Yakovenko\n"
+ "\n"
+ "This library is free software; you can redistribute it and/or\n"
+ "modify it under the terms of the GNU Lesser General Public\n"
+ "License as published by the Free Software Foundation; either\n"
+ "version 2.1 of the License, or (at your option) any later version.\n"
+ "\n"
+ "This library is distributed in the hope that it will be useful,\n"
+ "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
+ "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n"
+ "Lesser General Public License for more details.\n"
+ "\n"
+ "You should have received a copy of the GNU Lesser General Public\n"
+ "License along with this library; if not, write to the Free Software\n"
+ "Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n"
,
.plugin.website = "http://deadbeef.sf.net",
.plugin.start = adplug_start,
diff --git a/plugins/alac/COPYING b/plugins/alac/COPYING
new file mode 100644
index 00000000..ed09298c
--- /dev/null
+++ b/plugins/alac/COPYING
@@ -0,0 +1,68 @@
+ALAC plugin for deadbeef
+Copyright (C) 2012-2013 Alexey Yakovenko <waker@users.sourceforge.net>
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or
+sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+
+
+ALAC (Apple Lossless Audio Codec) decoder
+Copyright (c) 2005 David Hammerton
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or
+sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+
+
+libmp4ff (modified)
+Code from MP4FF is copyright (c) Nero AG, www.nero.com
+deadbeef-related modifications (c) 2009-2014 Alexey Yakovenko
+
+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.
diff --git a/plugins/alac/alac_plugin.c b/plugins/alac/alac_plugin.c
index 160821f2..4291099f 100644
--- a/plugins/alac/alac_plugin.c
+++ b/plugins/alac/alac_plugin.c
@@ -357,6 +357,7 @@ static const char *metainfo[] = {
"copyright", "copyright",
"totaltracks", "numtracks",
"tool", "tool",
+ "MusicBrainz Track Id", "musicbrainz_trackid",
NULL
};
diff --git a/plugins/alsa/COPYING b/plugins/alsa/COPYING
new file mode 100644
index 00000000..8317a4be
--- /dev/null
+++ b/plugins/alsa/COPYING
@@ -0,0 +1,17 @@
+DeaDBeeF ALSA plugin
+Copyright (C) 2009-2014 Alexey Yakovenko et al.
+
+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.
+
diff --git a/plugins/ao/license.txt b/plugins/ao/COPYING
index b700befa..070fb661 100644
--- a/plugins/ao/license.txt
+++ b/plugins/ao/COPYING
@@ -1,3 +1,22 @@
+AudioOverload DeaDBeeF plugin
+Copyright (C) 2009-2014 Alexey Yakovenko <waker@users.sourceforge.net>
+
+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.
+
+
+
Here is a list of the licenses each file in this package are under, and their text.
The upshot is this: if you create anything from this SDK and include any MAME licensed components
diff --git a/plugins/ao/Makefile.am b/plugins/ao/Makefile.am
index 55638c11..2d124b27 100644
--- a/plugins/ao/Makefile.am
+++ b/plugins/ao/Makefile.am
@@ -22,6 +22,6 @@ ddb_ao_la_LDFLAGS = -module -avoid-version $(ZLIB_LIBS)
EXTRA_DIST=eng_psf/peops/reverb.c eng_psf/peops/adsr.c eng_psf/peops/registers.c eng_psf/peops/dma.c eng_psf/peops2/spu2.c eng_psf/peops2/reverb2.c eng_psf/peops2/adsr2.c eng_dsf/arm7memil.c eng_dsf/aicalfo.c eng_ssf/scsplfo.c
ddb_ao_la_LIBADD = $(LDADD)
-AM_CFLAGS = $(CFLAGS) -Wall -DPATH_MAX=1024 -DHAS_PSXCPU=1 -I.. -Ieng_ssf -Ieng_qsf -Ieng_dsf -lm -fPIC
+AM_CFLAGS = $(CFLAGS) $(ZLIB_CFLAGS) -Wall -DPATH_MAX=1024 -DHAS_PSXCPU=1 -I.. -Ieng_ssf -Ieng_qsf -Ieng_dsf -lm -fPIC
endif
diff --git a/plugins/artwork/COPYING b/plugins/artwork/COPYING
new file mode 100644
index 00000000..f88ac121
--- /dev/null
+++ b/plugins/artwork/COPYING
@@ -0,0 +1,20 @@
+DeaDBeeF Album Art plugin
+Copyright (C) 2009-2014 Viktor Semykin, Alexey Yakovenko et al.
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any damages
+arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source distribution.
diff --git a/plugins/artwork/Makefile.am b/plugins/artwork/Makefile.am
index 5948af9b..9fb8bea8 100644
--- a/plugins/artwork/Makefile.am
+++ b/plugins/artwork/Makefile.am
@@ -1,7 +1,13 @@
if HAVE_ARTWORK
artworkdir = $(libdir)/$(PACKAGE)
pkglib_LTLIBRARIES = artwork.la
-artwork_la_SOURCES = artwork.c artwork.h albumartorg.c albumartorg.h lastfm.c lastfm.h wos.c wos.h escape.c escape.h
+
+if ARTWORK_USE_VFS_CURL
+artwork_net_cflags = -DUSE_VFS_CURL
+artwork_net_sources = albumartorg.c albumartorg.h lastfm.c lastfm.h wos.c wos.h escape.c escape.h
+endif
+
+artwork_la_SOURCES = artwork.c artwork.h $(artwork_net_sources)
artwork_la_LDFLAGS = -module -avoid-version
@@ -15,9 +21,9 @@ endif
if HAVE_FLAC
FLAC_DEPS=$(FLAC_LIBS)
-FLAC_CFLAGS=-DUSE_METAFLAC
+flac_clags=-DUSE_METAFLAC $(FLAC_CFLAGS)
endif
-AM_CFLAGS = $(CFLAGS) $(ARTWORK_CFLAGS) $(FLAC_CFLAGS) -std=c99
+AM_CFLAGS = $(CFLAGS) $(ARTWORK_CFLAGS) $(flac_cflags) $(artwork_net_cflags) -std=c99
artwork_la_LIBADD = $(LDADD) $(ARTWORK_DEPS) $(FLAC_DEPS)
endif
diff --git a/plugins/artwork/albumartorg.c b/plugins/artwork/albumartorg.c
index 1b21f3f0..c15a17ad 100644
--- a/plugins/artwork/albumartorg.c
+++ b/plugins/artwork/albumartorg.c
@@ -1,21 +1,27 @@
/*
- DeaDBeeF - ultimate music player for GNU/Linux systems with X11
+ Album Art plugin for DeaDBeeF
+ Copyright (C) 2009-2011 Viktor Semykin <thesame.ml@gmail.com>
Copyright (C) 2009-2013 Alexey Yakovenko <waker@users.sourceforge.net>
- 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.
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+
+ 3. This notice may not be removed or altered from any source distribution.
*/
+
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
diff --git a/plugins/artwork/albumartorg.h b/plugins/artwork/albumartorg.h
index 46ade53f..dc062541 100644
--- a/plugins/artwork/albumartorg.h
+++ b/plugins/artwork/albumartorg.h
@@ -1,21 +1,27 @@
/*
- DeaDBeeF - ultimate music player for GNU/Linux systems with X11
+ Album Art plugin for DeaDBeeF
+ Copyright (C) 2009-2011 Viktor Semykin <thesame.ml@gmail.com>
Copyright (C) 2009-2013 Alexey Yakovenko <waker@users.sourceforge.net>
- 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.
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+
+ 3. This notice may not be removed or altered from any source distribution.
*/
+
#ifndef __ALBUMARTORG_H
#define __ALBUMARTORG_H
diff --git a/plugins/artwork/artwork.c b/plugins/artwork/artwork.c
index 44aa68dc..fa1a3f3b 100644
--- a/plugins/artwork/artwork.c
+++ b/plugins/artwork/artwork.c
@@ -1,3 +1,27 @@
+/*
+ Album Art plugin for DeaDBeeF
+ Copyright (C) 2009-2011 Viktor Semykin <thesame.ml@gmail.com>
+ Copyright (C) 2009-2013 Alexey Yakovenko <waker@users.sourceforge.net>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
#ifdef HAVE_CONFIG_H
# include "../../config.h"
#endif
@@ -22,9 +46,11 @@
#include <assert.h>
#include "../../deadbeef.h"
#include "artwork.h"
+#ifdef USE_VFS_CURL
#include "lastfm.h"
#include "albumartorg.h"
#include "wos.h"
+#endif
#ifdef USE_IMLIB2
#include <Imlib2.h>
@@ -85,18 +111,42 @@ static intptr_t tid;
static int artwork_enable_embedded;
static int artwork_enable_local;
+#ifdef USE_VFS_CURL
static int artwork_enable_lfm;
static int artwork_enable_aao;
static int artwork_enable_wos;
+#endif
static time_t artwork_reset_time;
static char artwork_filemask[200];
static const char *get_default_cover (void) {
- return default_cover;
+return default_cover;
+}
+
+static int
+esc_char (char c) {
+ if (c < 1
+ || (c >= 'a' && c <= 'z')
+ || (c >= 'A' && c <= 'Z')
+ || (c >= '0' && c <= '9')
+ || c == ' '
+ || c == '_'
+ || c == '-') {
+ return c;
+ }
+ return '_';
}
int
make_cache_dir_path (char *path, int size, const char *artist, int img_size) {
+ char esc_artist[PATH_MAX];
+ int i;
+
+ for (i = 0; artist[i]; i++) {
+ esc_artist[i] = esc_char (artist[i]);
+ }
+ esc_artist[i] = 0;
+
const char *cache = getenv ("XDG_CACHE_HOME");
int sz;
@@ -108,7 +158,7 @@ make_cache_dir_path (char *path, int size, const char *artist, int img_size) {
}
path += sz;
- sz += snprintf (path, size-sz, "%s", artist);
+ sz += snprintf (path, size-sz, "%s", esc_artist);
for (char *p = path; *p; p++) {
if (*p == '/') {
*p = '_';
@@ -117,13 +167,50 @@ make_cache_dir_path (char *path, int size, const char *artist, int img_size) {
return sz;
}
-void
-make_cache_path (char *path, int size, const char *album, const char *artist, int img_size) {
+int
+make_cache_path2 (char *path, int size, const char *fname, const char *album, const char *artist, int img_size) {
+ if (!album) {
+ album = "";
+ }
+ if (!artist) {
+ artist = "";
+ }
+
+ if (*album && !(*artist)) {
+ artist = album;
+ }
+
+ if (!*artist || !*album)
+ {
+ if (fname) {
+ // album=escape(path), artist=uknown
+ artist = "Unknown artist";
+ album = fname;
+ }
+ else {
+ trace ("artist or album is empty, give up\n");
+ *path = 0;
+ return -1;
+ }
+ }
+
char *p = path;
+ char esc_album[PATH_MAX];
+ const char *palbum = album;
+ size_t l = strlen (album);
+ if (l > 200) {
+ palbum = album + l - 200;
+ }
+ int i;
+ for (i = 0; palbum[i]; i++) {
+ esc_album[i] = esc_char (palbum[i]);
+ }
+ esc_album[i] = 0;
+
int sz = make_cache_dir_path (path, size, artist, img_size);
size -= sz;
path += sz;
- sz = snprintf (path, size, "/%s.jpg", album);
+ sz = snprintf (path, size, "/%s.jpg", esc_album);
for (char *p = path+1; *p; p++) {
if (*p == '/') {
*p = '_';
@@ -132,6 +219,11 @@ make_cache_path (char *path, int size, const char *album, const char *artist, in
}
void
+make_cache_path (char *path, int size, const char *album, const char *artist, int img_size) {
+ make_cache_path2 (path, size, NULL, album, artist, img_size);
+}
+
+void
queue_add (const char *fname, const char *artist, const char *album, int img_size, artwork_callback callback, void *user_data) {
if (!artist) {
artist = "";
@@ -849,7 +941,7 @@ fetcher_thread (void *none)
trace ("fetching cover for %s %s\n", param->album, param->artist);
char cache_path[1024];
- make_cache_path (cache_path, sizeof (cache_path), param->album, param->artist, -1);
+ make_cache_path2 (cache_path, sizeof (cache_path), param->fname, param->album, param->artist, -1);
int got_pic = 0;
if (deadbeef->is_local_file (param->fname)) {
@@ -884,7 +976,7 @@ fetcher_thread (void *none)
trace ("artwork: corrupted id3v2 APIC frame\n");
continue;
}
- if (strcasecmp (data, "image/jpeg") && strcasecmp (data, "image/png")) {
+ if (strcasecmp (data, "image/jpeg") && strcasecmp (data, "image/png") && strcasecmp (data, "image/gif")) {
trace ("artwork: unsupported mime type: %s\n", data);
continue;
}
@@ -973,7 +1065,7 @@ fetcher_thread (void *none)
trace ("found apev2 cover art of %d bytes (%s)\n", sz, ext);
char tmp_path[1024];
char cache_path[1024];
- make_cache_path (cache_path, sizeof (cache_path), param->album, param->artist, -1);
+ make_cache_path2 (cache_path, sizeof (cache_path), param->fname, param->album, param->artist, -1);
trace ("will write apev2 cover art into %s\n", cache_path);
snprintf (tmp_path, sizeof (tmp_path), "%s.part", cache_path);
FILE *out = fopen (tmp_path, "w+b");
@@ -1042,7 +1134,7 @@ fetcher_thread (void *none)
trace ("found flac cover art of %d bytes (%s)\n", pic->data_length, pic->description);
char tmp_path[1024];
char cache_path[1024];
- make_cache_path (cache_path, sizeof (cache_path), param->album, param->artist, -1);
+ make_cache_path2 (cache_path, sizeof (cache_path), param->fname, param->album, param->artist, -1);
trace ("will write flac cover art into %s\n", cache_path);
snprintf (tmp_path, sizeof (tmp_path), "%s.part", cache_path);
FILE *out = fopen (tmp_path, "w+b");
@@ -1118,7 +1210,7 @@ fetcher_thread (void *none)
strcat (path, files[0]->d_name);
char cache_path[1024];
char tmp_path[1024];
- make_cache_path (cache_path, sizeof (cache_path), param->album, param->artist, -1);
+ make_cache_path2 (cache_path, sizeof (cache_path), param->fname, param->album, param->artist, -1);
snprintf (tmp_path, sizeof (tmp_path), "%s.part", cache_path);
copy_file (path, tmp_path, -1);
int err = rename (tmp_path, cache_path);
@@ -1136,6 +1228,7 @@ fetcher_thread (void *none)
}
}
+#ifdef USE_VFS_CURL
if (!got_pic) {
if (artwork_enable_wos) {
@@ -1164,6 +1257,7 @@ fetcher_thread (void *none)
got_pic = 1;
}
}
+#endif
if (got_pic) {
trace ("downloaded art for %s %s\n", param->album, param->artist);
@@ -1176,7 +1270,7 @@ fetcher_thread (void *none)
continue;
}
char scaled_path[1024];
- make_cache_path (scaled_path, sizeof (scaled_path), param->album, param->artist, param->size);
+ make_cache_path2 (scaled_path, sizeof (scaled_path), param->fname, param->album, param->artist, param->size);
copy_file (cache_path, scaled_path, param->size);
}
for (int i = 0; i < param->numcb; i++) {
@@ -1227,23 +1321,6 @@ get_album_art (const char *fname, const char *artist, const char *album, int siz
{
char path [1024];
- if (!album) {
- album = "";
- }
- if (!artist) {
- artist = "";
- }
-
- if (!*artist || !*album)
- {
- trace ("artist or album is empty, give up\n");
- //give up
- if (callback) {
- callback (NULL, NULL, NULL, user_data);
- }
- return NULL;
- }
-
if (!deadbeef->is_local_file (fname)) {
if (callback) {
callback (NULL, NULL, NULL, user_data);
@@ -1251,7 +1328,7 @@ get_album_art (const char *fname, const char *artist, const char *album, int siz
return NULL;
}
- make_cache_path (path, sizeof (path), album, artist, size);
+ make_cache_path2 (path, sizeof (path), fname, album, artist, size);
char *p = find_image (path);
if (p) {
if (callback) {
@@ -1263,7 +1340,7 @@ get_album_art (const char *fname, const char *artist, const char *album, int siz
if (size != -1) {
// check if we have unscaled image
char unscaled_path[1024];
- make_cache_path (unscaled_path, sizeof (unscaled_path), album, artist, -1);
+ make_cache_path2 (unscaled_path, sizeof (unscaled_path), fname, album, artist, -1);
p = find_image (unscaled_path);
if (p) {
free (p);
@@ -1358,25 +1435,31 @@ static int
artwork_configchanged (void) {
int new_artwork_enable_embedded = deadbeef->conf_get_int ("artwork.enable_embedded", 1);
int new_artwork_enable_local = deadbeef->conf_get_int ("artwork.enable_localfolder", 1);
+#ifdef USE_VFS_CURL
int new_artwork_enable_lfm = deadbeef->conf_get_int ("artwork.enable_lastfm", 0);
int new_artwork_enable_aao = deadbeef->conf_get_int ("artwork.enable_albumartorg", 0);
int new_artwork_enable_wos = deadbeef->conf_get_int ("artwork.enable_wos", 0);
+#endif
char new_artwork_filemask[200];
deadbeef->conf_get_str ("artwork.filemask", DEFAULT_FILEMASK, new_artwork_filemask, sizeof (new_artwork_filemask));
if (new_artwork_enable_embedded != artwork_enable_embedded
|| new_artwork_enable_local != artwork_enable_local
+#ifdef USE_VFS_CURL
|| new_artwork_enable_lfm != artwork_enable_lfm
|| new_artwork_enable_aao != artwork_enable_aao
|| new_artwork_enable_wos != artwork_enable_wos
+#endif
|| strcmp (new_artwork_filemask, artwork_filemask)) {
trace ("artwork config changed, invalidating cache...\n");
artwork_enable_embedded = new_artwork_enable_embedded;
artwork_enable_local = new_artwork_enable_local;
+#ifdef USE_VFS_CURL
artwork_enable_lfm = new_artwork_enable_lfm;
artwork_enable_aao = new_artwork_enable_aao;
artwork_enable_wos = new_artwork_enable_wos;
+#endif
artwork_reset_time = time (NULL);
strcpy (artwork_filemask, new_artwork_filemask);
deadbeef->conf_set_int64 ("artwork.cache_reset_time", artwork_reset_time);
@@ -1413,8 +1496,11 @@ artwork_plugin_start (void)
artwork_enable_embedded = deadbeef->conf_get_int ("artwork.enable_embedded", 1);
artwork_enable_local = deadbeef->conf_get_int ("artwork.enable_localfolder", 1);
+#ifdef USE_VFS_CURL
artwork_enable_lfm = deadbeef->conf_get_int ("artwork.enable_lastfm", 0);
artwork_enable_aao = deadbeef->conf_get_int ("artwork.enable_albumartorg", 0);
+ artwork_enable_wos = deadbeef->conf_get_int ("artwork.enable_wos", 0);
+#endif
artwork_reset_time = deadbeef->conf_get_int64 ("artwork.cache_reset_time", 0);
deadbeef->conf_get_str ("artwork.filemask", DEFAULT_FILEMASK, artwork_filemask, sizeof (artwork_filemask));
@@ -1471,9 +1557,11 @@ static const char settings_dlg[] =
"property \"Fetch from embedded tags\" checkbox artwork.enable_embedded 1;\n"
"property \"Fetch from local folder\" checkbox artwork.enable_localfolder 1;\n"
"property \"Local cover file mask\" entry artwork.filemask \"" DEFAULT_FILEMASK "\";\n"
+#ifdef USE_VFS_CURL
"property \"Fetch from last.fm\" checkbox artwork.enable_lastfm 0;\n"
"property \"Fetch from albumart.org\" checkbox artwork.enable_albumartorg 0;\n"
"property \"Fetch from worldofspectrum.org (AY only)\" checkbox artwork.enable_wos 0;\n"
+#endif
"property \"Scale artwork towards longer side\" checkbox artwork.scale_towards_longer 1;\n"
;
@@ -1482,28 +1570,33 @@ static DB_artwork_plugin_t plugin = {
.plugin.plugin.api_vmajor = 1,
.plugin.plugin.api_vminor = 0,
.plugin.plugin.version_major = 1,
- .plugin.plugin.version_minor = 1,
+ .plugin.plugin.version_minor = 2,
.plugin.plugin.type = DB_PLUGIN_MISC,
.plugin.plugin.id = "artwork",
.plugin.plugin.name = "Album Artwork",
.plugin.plugin.descr = "Loads album artwork either from local directories or from internet",
.plugin.plugin.copyright =
- "Copyright (C) 2009-2013 Alexey Yakovenko <waker@users.sourceforge.net>\n"
+ "Album Art plugin for DeaDBeeF\n"
"Copyright (C) 2009-2011 Viktor Semykin <thesame.ml@gmail.com>\n"
+ "Copyright (C) 2009-2013 Alexey Yakovenko <waker@users.sourceforge.net>\n"
+ "\n"
+ "This software is provided 'as-is', without any express or implied\n"
+ "warranty. In no event will the authors be held liable for any damages\n"
+ "arising from the use of this software.\n"
+ "\n"
+ "Permission is granted to anyone to use this software for any purpose,\n"
+ "including commercial applications, and to alter it and redistribute it\n"
+ "freely, subject to the following restrictions:\n"
"\n"
- "This program is free software; you can redistribute it and/or\n"
- "modify it under the terms of the GNU General Public License\n"
- "as published by the Free Software Foundation; either version 2\n"
- "of the License, or (at your option) any later version.\n"
+ "1. The origin of this software must not be misrepresented; you must not\n"
+ " claim that you wrote the original software. If you use this software\n"
+ " in a product, an acknowledgment in the product documentation would be\n"
+ " appreciated but is not required.\n"
"\n"
- "This program is distributed in the hope that it will be useful,\n"
- "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
- "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
- "GNU General Public License for more details.\n"
+ "2. Altered source versions must be plainly marked as such, and must not be\n"
+ " misrepresented as being the original software.\n"
"\n"
- "You should have received a copy of the GNU General Public License\n"
- "along with this program; if not, write to the Free Software\n"
- "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n"
+ "3. This notice may not be removed or altered from any source distribution.\n"
,
.plugin.plugin.website = "http://deadbeef.sf.net",
.plugin.plugin.start = artwork_plugin_start,
@@ -1515,4 +1608,5 @@ static DB_artwork_plugin_t plugin = {
.get_default_cover = get_default_cover,
.get_album_art_sync = get_album_art_sync,
.make_cache_path = make_cache_path,
+ .make_cache_path2 = make_cache_path2,
};
diff --git a/plugins/artwork/artwork.h b/plugins/artwork/artwork.h
index 9d8a2a7d..850937e1 100644
--- a/plugins/artwork/artwork.h
+++ b/plugins/artwork/artwork.h
@@ -1,3 +1,26 @@
+/*
+ Album Art plugin for DeaDBeeF
+ Copyright (C) 2009-2011 Viktor Semykin <thesame.ml@gmail.com>
+ Copyright (C) 2009-2013 Alexey Yakovenko <waker@users.sourceforge.net>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+
+ 3. This notice may not be removed or altered from any source distribution.
+*/
#ifndef __ARTWORK_H
#define __ARTWORK_H
@@ -24,6 +47,9 @@ typedef struct {
// creates full path string for cache storage
void (*make_cache_path) (char *path, int size, const char *album, const char *artist, int img_size);
+
+ // creates full path string for cache storage
+ int (*make_cache_path2) (char *path, int size, const char *fname, const char *album, const char *artist, int img_size);
} DB_artwork_plugin_t;
#endif /*__ARTWORK_H*/
diff --git a/plugins/artwork/lastfm.c b/plugins/artwork/lastfm.c
index 5b5cedd4..83bda9cb 100644
--- a/plugins/artwork/lastfm.c
+++ b/plugins/artwork/lastfm.c
@@ -1,3 +1,26 @@
+/*
+ Album Art plugin for DeaDBeeF
+ Copyright (C) 2009-2011 Viktor Semykin <thesame.ml@gmail.com>
+ Copyright (C) 2009-2013 Alexey Yakovenko <waker@users.sourceforge.net>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+
+ 3. This notice may not be removed or altered from any source distribution.
+*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
@@ -22,11 +45,17 @@ int
fetch_from_lastfm (const char *artist, const char *album, const char *dest)
{
char url [1024];
- char *artist_url = uri_escape (artist, 0);
- char *album_url = uri_escape (album, 0);
+ char *artist_url = NULL;
+ char *album_url = NULL;
+
+retry:
+ artist_url = uri_escape (artist, 0);
+ album_url = uri_escape (album, 0);
snprintf (url, sizeof (url), BASE_URL "?method=album.getinfo&api_key=" API_KEY "&artist=%s&album=%s", artist_url, album_url);
free (artist_url);
+ artist_url = NULL;
free (album_url);
+ album_url = NULL;
DB_FILE *fp = deadbeef->fopen (url);
if (!fp) {
@@ -55,6 +84,11 @@ fetch_from_lastfm (const char *artist, const char *album, const char *dest)
char *end = strstr (img, "</image>");
if (!end || end == img) {
+ if (artist != album) {
+ artist = album;
+ goto retry;
+ }
+
trace ("fetch_from_lastfm: bad xml (or image not found) from %s\n", url);
return -1;
}
diff --git a/plugins/artwork/lastfm.h b/plugins/artwork/lastfm.h
index b11ca370..e6fc82ba 100644
--- a/plugins/artwork/lastfm.h
+++ b/plugins/artwork/lastfm.h
@@ -1,20 +1,25 @@
/*
- DeaDBeeF - ultimate music player for GNU/Linux systems with X11
+ Album Art plugin for DeaDBeeF
+ Copyright (C) 2009-2011 Viktor Semykin <thesame.ml@gmail.com>
Copyright (C) 2009-2013 Alexey Yakovenko <waker@users.sourceforge.net>
- 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.
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+
+ 3. This notice may not be removed or altered from any source distribution.
*/
#ifndef __LASTFM_H
#define __LASTFM_H
diff --git a/plugins/cdda/COPYING b/plugins/cdda/COPYING
new file mode 100644
index 00000000..cf6220be
--- /dev/null
+++ b/plugins/cdda/COPYING
@@ -0,0 +1,55 @@
+CD audio plugin for DeaDBeeF
+Copyright (C) 2009-2014 Alexey Yakovenko, Viktor Semykin
+
+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, see <http://www.gnu.org/licenses/>.
+
+
+libcddb
+Copyright (C) 2003, 2004, 2005 Kris Verbeeck <airborne@advalvas.be>
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this library; if not, write to the
+Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+
+
+
+libcdio
+Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009 Rocky Bernstein <rocky@gnu.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 3 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, see <http://www.gnu.org/licenses/>.
+
+
+
diff --git a/plugins/converter/COPYING b/plugins/converter/COPYING
new file mode 100644
index 00000000..0950706e
--- /dev/null
+++ b/plugins/converter/COPYING
@@ -0,0 +1,17 @@
+Converter plugin for DeaDBeeF Player
+
+Copyright (C) 2009-2013 Alexey Yakovenko <waker@users.sourceforge.net>
+
+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.
diff --git a/plugins/converter/Makefile.am b/plugins/converter/Makefile.am
index f34ec5fc..cc379437 100644
--- a/plugins/converter/Makefile.am
+++ b/plugins/converter/Makefile.am
@@ -22,7 +22,8 @@ convdata_DATA = \
presets/MusePack.txt\
presets/Ogg_Vorbis_(-q_5).txt\
presets/TTA.txt\
- presets/WavPack.txt
+ presets/WavPack.txt\
+ presets/ALAC.txt
EXTRA_DIST = $(convdata_DATA) converter.glade
@@ -37,7 +38,7 @@ converter_gtk2_la_LDFLAGS = -module -avoid-version
if STATICLINK
GTK_ROOT=@top_srcdir@/$(LIB)/gtk-2.12.12/usr
-converter_gtk2_la_LIBADD = $(LDADD) -L$(GTK_ROOT)/lib $(GTK_ROOT)/lib/libgtk-x11-2.0.la $(GTK_ROOT)/lib/libgdk-x11-2.0.la $(GTK_ROOT)/lib/libpangoft2-1.0.la $(GTK_ROOT)/lib/libpangocairo-1.0.la $(GTK_ROOT)/lib/libgdk_pixbuf-2.0.la -lm $(GTK_ROOT)/lib/libcairo.la $(GTK_ROOT)/lib/libpango-1.0.la $(GTK_ROOT)/lib/libgobject-2.0.la $(GTK_ROOT)/lib/libgmodule-2.0.la $(GTK_ROOT)/lib/libgthread-2.0.la -lrt $(GTK_ROOT)/lib/libglib-2.0.la
+converter_gtk2_la_LIBADD = $(LDADD) -L$(GTK_ROOT)/lib -lgtk-x11-2.0 -lgdk-x11-2.0 -latk-1.0 -lgdk_pixbuf-2.0 -lm -lpangocairo-1.0 -lpango-1.0 -lcairo -lgobject-2.0 -lgmodule-2.0 -ldl -lglib-2.0 -lrt
converter_gtk2_la_CFLAGS = -std=c99 -I $(GTK_ROOT)/include -I $(GTK_ROOT)/lib/gtk-2.0/include -I $(GTK_ROOT)/include/glib-2.0 -I $(GTK_ROOT)/include/gtk-2.0 -I $(GTK_ROOT)/include/cairo -I $(GTK_ROOT)/lib/glib-2.0/include/ -I $(GTK_ROOT)/include/pango-1.0 -I $(GTK_ROOT)/include/atk-1.0 -DULTRA_COMPATIBLE=1
else
@@ -49,17 +50,8 @@ endif
if HAVE_GTK3
converter_gtk3_la_SOURCES = convgui.c interface.c support.c callbacks.h converter.h interface.h support.h
converter_gtk3_la_LDFLAGS = -module -avoid-version
-if STATICLINK
-GTK_ROOT_300=@top_srcdir@/$(LIB)/gtk-3.0.0
-
-converter_gtk3_la_LIBADD = $(LDADD) -L$(GTK_ROOT_300)/lib -lgtk-3 -lgdk-3 -latk-1.0 -lgio-2.0 -lpangocairo-1.0 -lgdk_pixbuf-2.0 -lcairo-gobject -lpango-1.0 -lcairo -lgobject-2.0 -lglib-2.0 -lfreetype $(SM_LIBADD)
-
-converter_gtk3_la_CFLAGS = -std=c99 -I$(GTK_ROOT_300)/include/gtk-3.0 -I$(GTK_ROOT_300)/include/pango-1.0 -I$(GTK_ROOT_300)/include/gio-unix-2.0/ -I$(GTK_ROOT_300)/include/atk-1.0 -I$(GTK_ROOT_300)/include/cairo -I$(GTK_ROOT_300)/include/gdk-pixbuf-2.0 -I$(GTK_ROOT_300)/include/freetype2 -I$(GTK_ROOT_300)/include/glib-2.0 -I$(GTK_ROOT_300)/lib/glib-2.0/include $(SM_CFLAGS)
-
-else
converter_gtk3_la_LIBADD = $(LDADD) $(GTK3_DEPS_LIBS)
converter_gtk3_la_CFLAGS = -std=c99 $(GTK3_DEPS_CFLAGS)
endif
-endif
endif
diff --git a/plugins/converter/converter.c b/plugins/converter/converter.c
index 17be3036..04faaae3 100644
--- a/plugins/converter/converter.c
+++ b/plugins/converter/converter.c
@@ -1158,20 +1158,18 @@ error:
if (encoder_preset->tag_oggvorbis) {
// find flac decoder plugin
DB_decoder_t **plugs = deadbeef->plug_get_decoder_list ();
- DB_decoder_t *ogg = NULL;
+ int res = -1;
for (int i = 0; plugs[i]; i++) {
- if (!strcmp (plugs[i]->plugin.id, "stdogg")) {
- ogg = plugs[i];
- break;
+ if (!strcmp (plugs[i]->plugin.id, "stdogg")
+ || !strcmp (plugs[i]->plugin.id, "stdopus")) {
+ res = plugs[i]->write_metadata (out_it);
+ if (!res) {
+ break;
+ }
}
}
- if (!ogg) {
- fprintf (stderr, "converter: ogg plugin not found, cannot write ogg metadata\n");
- }
- else {
- if (0 != ogg->write_metadata (out_it)) {
- fprintf (stderr, "converter: failed to write ogg metadata, not an ogg file?\n");
- }
+ if (res) {
+ fprintf (stderr, "converter: failed to write ogg metadata, not an ogg file?\n");
}
}
if (out_it) {
diff --git a/plugins/converter/presets/ALAC.txt b/plugins/converter/presets/ALAC.txt
new file mode 100644
index 00000000..3ede71f3
--- /dev/null
+++ b/plugins/converter/presets/ALAC.txt
@@ -0,0 +1,10 @@
+title ALAC
+ext m4a
+encoder ffmpeg -i %i -acodec alac %o
+method 1
+id3v2_version 0
+tag_id3v2 0
+tag_id3v1 0
+tag_apev2 0
+tag_flac 0
+tag_oggvorbis 0
diff --git a/plugins/coreaudio/COPYING b/plugins/coreaudio/COPYING
new file mode 100644
index 00000000..fb7c6b6c
--- /dev/null
+++ b/plugins/coreaudio/COPYING
@@ -0,0 +1,17 @@
+CoreAudio Output Deadbeef Plugin
+Copyright (c) 2011-2013 Carlos Nunes <carloslnunes@gmail.com>
+
+This plugin is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This plugin 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
diff --git a/plugins/dca/COPYING b/plugins/dca/COPYING
index d511905c..77d7529a 100644
--- a/plugins/dca/COPYING
+++ b/plugins/dca/COPYING
@@ -1,339 +1,20 @@
- GNU GENERAL PUBLIC LICENSE
- Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users. This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it. (Some other Free Software Foundation software is covered by
-the GNU Lesser General Public License instead.) You can apply it to
-your programs, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
- To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
- For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have. You must make sure that they, too, receive or can get the
-source code. And you must show them these terms so they know their
-rights.
-
- We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
- Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software. If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
- Finally, any free program is threatened constantly by software
-patents. We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary. To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
- The precise terms and conditions for copying, distribution and
-modification follow.
-
- GNU GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License. The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language. (Hereinafter, translation is included without limitation in
-the term "modification".) Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
- 1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
- 2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) You must cause the modified files to carry prominent notices
- stating that you changed the files and the date of any change.
-
- b) You must cause any work that you distribute or publish, that in
- whole or in part contains or is derived from the Program or any
- part thereof, to be licensed as a whole at no charge to all third
- parties under the terms of this License.
-
- c) If the modified program normally reads commands interactively
- when run, you must cause it, when started running for such
- interactive use in the most ordinary way, to print or display an
- announcement including an appropriate copyright notice and a
- notice that there is no warranty (or else, saying that you provide
- a warranty) and that users may redistribute the program under
- these conditions, and telling the user how to view a copy of this
- License. (Exception: if the Program itself is interactive but
- does not normally print such an announcement, your work based on
- the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
- a) Accompany it with the complete corresponding machine-readable
- source code, which must be distributed under the terms of Sections
- 1 and 2 above on a medium customarily used for software interchange; or,
-
- b) Accompany it with a written offer, valid for at least three
- years, to give any third party, for a charge no more than your
- cost of physically performing source distribution, a complete
- machine-readable copy of the corresponding source code, to be
- distributed under the terms of Sections 1 and 2 above on a medium
- customarily used for software interchange; or,
-
- c) Accompany it with the information you received as to the offer
- to distribute corresponding source code. (This alternative is
- allowed only for noncommercial distribution and only if you
- received the program in object code or executable form with such
- an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it. For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable. However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License. Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
- 5. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Program or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
- 6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
- 7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all. For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded. In such case, this License incorporates
-the limitation as if written in the body of this License.
-
- 9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time. Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation. If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
- 10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission. For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this. Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
- NO WARRANTY
-
- 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
- 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Programs
-
- If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
- To do so, attach the following notices to the program. It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
- <one line to give the program's name and a brief idea of what it does.>
- Copyright (C) <year> <name of author>
-
- 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.
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
- Gnomovision version 69, Copyright (C) year name of author
- Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
- This is free software, and you are welcome to redistribute it
- under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License. Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary. Here is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the program
- `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
- <signature of Ty Coon>, 1 April 1989
- Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs. If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library. If this is what you want to do, use the GNU Lesser General
-Public License instead of this License.
+DCA Plugin for DeaDBeeF Player
+Copyright (C) 2009-2014 Alexey Yakovenko <waker@users.sourceforge.net>
+
+libdca (C) Gildas Bazin et al.
+deadbeef-related modifications (C) Alexey Yakovenko
+see AUTHORS for more details
+
+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.
diff --git a/plugins/dsp_libsrc/COPYING b/plugins/dsp_libsrc/COPYING
new file mode 100644
index 00000000..641f9446
--- /dev/null
+++ b/plugins/dsp_libsrc/COPYING
@@ -0,0 +1,20 @@
+resampling plugin for DeaDBeeF Player
+Copyright (C) 2009-2014 Alexey Yakovenko <waker@users.sourceforge.net>
+
+libsamplerate
+Copyright (C) 2002-2008 Erik de Castro Lopo <erikd@mega-nerd.com>
+
+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.
+
diff --git a/plugins/dumb/COPYING b/plugins/dumb/COPYING
new file mode 100644
index 00000000..3621ccac
--- /dev/null
+++ b/plugins/dumb/COPYING
@@ -0,0 +1,89 @@
+DUMB plugin for DeaDBeeF Player
+Copyright (C) 2009-2014 Alexey Yakovenko <waker@users.sourceforge.net>
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any damages
+arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source distribution.
+
+
+
+modified DUMB 0.9.3
+Dynamic Universal Music Bibliotheque, Version 0.9.3
+
+Copyright (C) 2001-2005 Ben Davis, Robert J Ohannessian and Julien Cugniere
+
+This software is provided 'as-is', without any express or implied warranty.
+In no event shall the authors be held liable for any damages arising from the
+use of this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not claim
+ that you wrote the original software. If you use this software in a
+ product, you are requested to acknowledge its use in the product
+ documentation, along with details on where to get an unmodified version of
+ this software, but this is not a strict requirement.
+
+ [Note that the above point asks for a link to DUMB, not just a mention.
+ Googling for DUMB doesn't help much! The URL is "http://dumb.sf.net/".]
+
+ [The link was originally strictly required. This was changed for two
+ reasons. Firstly, if many projects request an acknowledgement, the list of
+ acknowledgements can become quite unmanageable. Secondly, DUMB was placing
+ a restriction on the code using it, preventing people from using the GNU
+ General Public Licence which disallows any such restrictions. See
+ http://www.gnu.org/philosophy/bsd.html for more information on this
+ subject. However, if DUMB plays a significant part in your project, we do
+ urge you to acknowledge its use.]
+
+2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+
+3. This notice may not be removed from or altered in any source distribution.
+
+4. If you are using the Program in someone else's bedroom on any Monday at
+ 3:05 pm, you are not allowed to modify the Program for ten minutes. [This
+ clause provided by Inphernic; every licence should contain at least one
+ clause, the reasoning behind which is far from obvious.]
+
+5. Users who wish to use DUMB for the specific purpose of playing music are
+ required to feed their dog on every full moon (if deemed appropriate).
+ [This clause provided by Allefant, who couldn't remember what Inphernic's
+ clause was.]
+
+6. No clause in this licence shall prevent this software from being depended
+ upon by a product licensed under the GNU General Public Licence. If such a
+ clause is deemed to exist, Debian, then it shall be respected in spirit as
+ far as possible and all other clauses shall continue to apply in full
+ force.
+
+We regret that we cannot provide any warranty, not even the implied warranty
+of merchantability or fitness for a particular purpose.
+
+Some files generated or copied by automake, autoconf and friends are
+available in an extra download. These fall under separate licences but are
+all free to distribute. Please check their licences as necessary.
+
+
+
+Uses code from kode54's foobar2000 plugin, http://kode54.foobar2000.org/
+
+
+
+deadbeef-related modifications (C) Alexey Yakovenko
diff --git a/plugins/dumb/cdumb.c b/plugins/dumb/cdumb.c
index dfd9ec50..017b850b 100644
--- a/plugins/dumb/cdumb.c
+++ b/plugins/dumb/cdumb.c
@@ -1,19 +1,24 @@
/*
- DeaDBeeF - ultimate music player for GNU/Linux systems with X11
- Copyright (C) 2009-2013 Alexey Yakovenko <waker@users.sourceforge.net>
+ DUMB Plugin for DeaDBeeF Player
+ Copyright (C) 2009-2014 Alexey Yakovenko <waker@users.sourceforge.net>
- 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 software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
- 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.
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+
+ 3. This notice may not be removed or altered from any source distribution.
*/
// based on fb2k dumb plugin from http://kode54.foobar2000.org
@@ -121,6 +126,8 @@ cdumb_startrenderer (DB_fileinfo_t *_info) {
dumb_it_set_resampling_quality (itsr, q);
dumb_it_set_xm_speed_zero_callback (itsr, &dumb_it_callback_terminate, NULL);
dumb_it_set_global_volume_zero_callback (itsr, &dumb_it_callback_terminate, NULL);
+
+ dumb_it_sr_set_global_volume (itsr, deadbeef->conf_get_int ("dumb.globalvolume", 64));
return 0;
}
@@ -884,6 +891,7 @@ cgme_stop (void) {
static const char settings_dlg[] =
"property \"Resampling quality (0..2, higher is better)\" entry dumb.resampling_quality 2;\n"
"property \"8-bit output (default is 16)\" checkbox dumb.8bitoutput 0;\n"
+ "property \"Internal DUMB volume (0..128)\" spinbtn[0,128,16] dumb.globalvolume 64;\n"
;
// define plugin interface
@@ -897,25 +905,30 @@ static DB_decoder_t plugin = {
.plugin.name = "DUMB module player",
.plugin.descr = "module player based on DUMB library",
.plugin.copyright =
- "Copyright (C) 2009-2013 Alexey Yakovenko <waker@users.sourceforge.net>\n"
+ "DUMB Plugin for DeaDBeeF Player\n"
+ "Copyright (C) 2009-2014 Alexey Yakovenko <waker@users.sourceforge.net>\n"
"\n"
"Uses a fork of DUMB (Dynamic Universal Music Bibliotheque), Version 0.9.3\n"
"Copyright (C) 2001-2005 Ben Davis, Robert J Ohannessian and Julien Cugniere\n"
"Uses code from kode54's foobar2000 plugin, http://kode54.foobar2000.org/\n"
"\n"
- "This program is free software; you can redistribute it and/or\n"
- "modify it under the terms of the GNU General Public License\n"
- "as published by the Free Software Foundation; either version 2\n"
- "of the License, or (at your option) any later version.\n"
+ "This software is provided 'as-is', without any express or implied\n"
+ "warranty. In no event will the authors be held liable for any damages\n"
+ "arising from the use of this software.\n"
+ "\n"
+ "Permission is granted to anyone to use this software for any purpose,\n"
+ "including commercial applications, and to alter it and redistribute it\n"
+ "freely, subject to the following restrictions:\n"
+ "\n"
+ "1. The origin of this software must not be misrepresented; you must not\n"
+ " claim that you wrote the original software. If you use this software\n"
+ " in a product, an acknowledgment in the product documentation would be\n"
+ " appreciated but is not required.\n"
"\n"
- "This program is distributed in the hope that it will be useful,\n"
- "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
- "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
- "GNU General Public License for more details.\n"
+ "2. Altered source versions must be plainly marked as such, and must not be\n"
+ " misrepresented as being the original software.\n"
"\n"
- "You should have received a copy of the GNU General Public License\n"
- "along with this program; if not, write to the Free Software\n"
- "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n"
+ "3. This notice may not be removed or altered from any source distribution.\n"
,
.plugin.website = "http://deadbeef.sf.net",
.plugin.start = cgme_start,
diff --git a/plugins/ffap/COPYING b/plugins/ffap/COPYING
new file mode 100644
index 00000000..a85ee5d0
--- /dev/null
+++ b/plugins/ffap/COPYING
@@ -0,0 +1,18 @@
+APE / Monkey's Audio plugin for DeaDBeeF
+Copyright (C) 2009-2014 Alexey Yakovenko <waker@users.sourceforge.net>
+based on apedec from FFMpeg Copyright (c) 2007 Benjamin Zores <ben@geexbox.org>
+based upon libdemac from Dave Chapman.
+
+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.
diff --git a/plugins/ffmpeg/COPYING b/plugins/ffmpeg/COPYING
new file mode 100644
index 00000000..c07664c4
--- /dev/null
+++ b/plugins/ffmpeg/COPYING
@@ -0,0 +1,18 @@
+FFMPEG plugin for DeaDBeeF
+Copyright (C) 2009-2014 Alexey Yakovenko et al.
+Copyright (C) FFMPEG Developers
+
+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.
+
diff --git a/plugins/ffmpeg/ffmpeg.c b/plugins/ffmpeg/ffmpeg.c
index efedb7bd..1cc6564a 100644
--- a/plugins/ffmpeg/ffmpeg.c
+++ b/plugins/ffmpeg/ffmpeg.c
@@ -442,10 +442,9 @@ ffmpeg_read (DB_fileinfo_t *_info, char *bytes, int size) {
if (info->pkt.duration > 0) {
AVRational *time_base = &info->fctx->streams[info->stream_id]->time_base;
float sec = (float)info->pkt.duration * time_base->num / time_base->den;
- int bitrate = info->pkt.size/sec;
+ int bitrate = info->pkt.size * 8 / sec;
if (bitrate > 0) {
- // FIXME: seems like duration translation is wrong
- deadbeef->streamer_set_bitrate (bitrate / 100);
+ deadbeef->streamer_set_bitrate (bitrate / 1000);
}
}
diff --git a/plugins/flac/COPYING b/plugins/flac/COPYING
new file mode 100644
index 00000000..b8147af8
--- /dev/null
+++ b/plugins/flac/COPYING
@@ -0,0 +1,93 @@
+FLAC plugin for DeaDBeeF
+Copyright (C) 2009-2014 Alexey Yakovenko et al.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+- Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+
+- Neither the name of the DeaDBeeF Player nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+
+libFLAC - Free Lossless Audio Codec library
+Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007 Josh Coalson
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+- Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+
+- Neither the name of the Xiph.org Foundation nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+
+libogg
+Copyright (c) 2002, Xiph.org Foundation
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+- Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+
+- Neither the name of the Xiph.org Foundation nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION
+OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/plugins/flac/Makefile.am b/plugins/flac/Makefile.am
index 51efb662..49eecb7f 100644
--- a/plugins/flac/Makefile.am
+++ b/plugins/flac/Makefile.am
@@ -5,5 +5,5 @@ flac_la_SOURCES = flac.c
flac_la_LDFLAGS = -module -avoid-version
flac_la_LIBADD = $(LDADD) $(FLAC_LIBS)
-AM_CFLAGS = $(CFLAGS) -std=c99
+AM_CFLAGS = $(CFLAGS) $(FLAC_CFLAGS) -std=c99
endif
diff --git a/plugins/flac/flac.c b/plugins/flac/flac.c
index 96d89b8f..9a823b9e 100644
--- a/plugins/flac/flac.c
+++ b/plugins/flac/flac.c
@@ -2,18 +2,32 @@
DeaDBeeF - ultimate music player for GNU/Linux systems with X11
Copyright (C) 2009-2013 Alexey Yakovenko <waker@users.sourceforge.net>
- 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, see <http://www.gnu.org/licenses/>.
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ - Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ - Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ - Neither the name of the DeaDBeeF Player nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <string.h>
#include <stdio.h>
@@ -1141,21 +1155,36 @@ static DB_decoder_t plugin = {
.plugin.name = "FLAC decoder",
.plugin.descr = "FLAC decoder using libFLAC",
.plugin.copyright =
- "Copyright (C) 2009-2013 Alexey Yakovenko <waker@users.sourceforge.net>\n"
+ "Copyright (C) 2009-2013 Alexey Yakovenko et al.\n"
+ "Uses libFLAC (C) Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007 Josh Coalson\n"
+ "Uses libogg Copyright (c) 2002, Xiph.org Foundation\n"
"\n"
- "This program is free software; you can redistribute it and/or\n"
- "modify it under the terms of the GNU General Public License\n"
- "as published by the Free Software Foundation; either version 2\n"
- "of the License, or (at your option) any later version.\n"
+ "Redistribution and use in source and binary forms, with or without\n"
+ "modification, are permitted provided that the following conditions\n"
+ "are met:\n"
"\n"
- "This program is distributed in the hope that it will be useful,\n"
- "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
- "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
- "GNU General Public License for more details.\n"
+ "- Redistributions of source code must retain the above copyright\n"
+ "notice, this list of conditions and the following disclaimer.\n"
"\n"
- "You should have received a copy of the GNU General Public License\n"
- "along with this program; if not, write to the Free Software\n"
- "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n"
+ "- Redistributions in binary form must reproduce the above copyright\n"
+ "notice, this list of conditions and the following disclaimer in the\n"
+ "documentation and/or other materials provided with the distribution.\n"
+ "\n"
+ "- Neither the name of the DeaDBeeF Player nor the names of its\n"
+ "contributors may be used to endorse or promote products derived from\n"
+ "this software without specific prior written permission.\n"
+ "\n"
+ "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
+ "``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
+ "LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
+ "A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR\n"
+ "CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n"
+ "EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n"
+ "PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n"
+ "PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\n"
+ "LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\n"
+ "NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n"
+ "SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
,
.plugin.website = "http://deadbeef.sf.net",
.open = cflac_open,
diff --git a/plugins/gme/COPYING b/plugins/gme/COPYING
new file mode 100644
index 00000000..445d1b98
--- /dev/null
+++ b/plugins/gme/COPYING
@@ -0,0 +1,40 @@
+Game_Music_Emu plugin for DeaDBeeF
+Copyright (C) 2009-2014 Alexey Yakovenko <waker@users.sourceforge.net>
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any damages
+arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source distribution.
+
+
+
+Game_Music_Emu (modified)
+Copyright (C) 2003-2009 Shay Green.
+DeaDBeeF-related modifications (C) Alexey Yakovenko.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
diff --git a/plugins/gme/cgme.c b/plugins/gme/cgme.c
index a6452034..557ec13f 100644
--- a/plugins/gme/cgme.c
+++ b/plugins/gme/cgme.c
@@ -1,20 +1,29 @@
/*
- DeaDBeeF - ultimate music player for GNU/Linux systems with X11
- Copyright (C) 2009-2013 Alexey Yakovenko <waker@users.sourceforge.net>
+ GameMusicEmu plugin for DeaDBeeF
+ Copyright (C) 2009-2014 Alexey Yakovenko <waker@users.sourceforge.net>
- 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 software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
- 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.
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+
+ 3. This notice may not be removed or altered from any source distribution.
*/
+
+#ifdef HAVE_CONFIG_H
+# include "../../config.h"
+#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -22,20 +31,30 @@
#include "gme/gme.h"
#include <zlib.h>
#include "../../deadbeef.h"
+#if HAVE_SYS_CDEFS_H
+#include <sys/cdefs.h>
+#endif
+#if HAVE_SYS_SYSLIMITS_H
+#include <sys/syslimits.h>
+#endif
//#define trace(...) { fprintf(stderr, __VA_ARGS__); }
#define trace(fmt,...)
+// how big vgz can be?
+#define MAX_REMOTE_GZ_FILE 0x100000
+
static DB_decoder_t plugin;
static DB_functions_t *deadbeef;
static int conf_fadeout = 10;
static int conf_loopcount = 2;
+static int chip_voices = 0xff;
+static int chip_voices_changed = 0;
typedef struct {
DB_fileinfo_t info;
Music_Emu *emu;
int reallength;
- uint32_t cgme_voicemask;
float duration; // of current song
} gme_fileinfo_t;
@@ -48,14 +67,38 @@ cgme_open (uint32_t hint) {
static int
read_gzfile (const char *fname, char **buffer, int *size) {
- FILE *fp = fopen (fname, "rb");
+ int fd = -1;
+ DB_FILE *fp = deadbeef->fopen (fname);
if (!fp) {
- trace ("failed to fopen %s\n", fname);
+ trace ("gme read_gzfile: failed to fopen %s\n", fname);
return -1;
}
- fseek (fp, 0, SEEK_END);
- size_t sz = ftell (fp);
- fclose (fp);
+
+ int64_t sz = deadbeef->fgetlength (fp);
+ if (fp->vfs && fp->vfs->plugin.id && strcmp (fp->vfs->plugin.id, "vfs_stdio") && sz > 0 && sz <= MAX_REMOTE_GZ_FILE) {
+ trace ("gme read_gzfile: reading %s of size %lld and writing to temp file\n", fname, sz);
+ char buffer[sz];
+ if (sz == deadbeef->fread (buffer, 1, sz, fp)) {
+ const char *tmp = getenv ("TMPDIR");
+ if (!tmp) {
+ tmp = "/tmp";
+ }
+ char nm[PATH_MAX];
+ snprintf (nm, sizeof (nm), "%s/ddbgmeXXXXXX.vgz", tmp);
+ fd = mkstemps (nm, 4);
+ if (fd == -1 || sz != write (fd, buffer, sz)) {
+ trace ("gme read_gzfile: failed to write temp file\n");
+ if (fd != -1) {
+ close (fd);
+ }
+ }
+ if (fd != -1) {
+ lseek (fd, 0, SEEK_SET);
+ }
+ }
+ }
+
+ deadbeef->fclose (fp);
sz *= 2;
int readsize = sz;
@@ -64,7 +107,7 @@ read_gzfile (const char *fname, char **buffer, int *size) {
return -1;
}
- gzFile gz = gzopen (fname, "rb");
+ gzFile gz = fd == -1 ? gzopen (fname, "rb") : gzdopen (fd, "r");
if (!gz) {
trace ("failed to gzopen %s\n", fname);
return -1;
@@ -77,6 +120,7 @@ read_gzfile (const char *fname, char **buffer, int *size) {
if (nb < 0) {
free (*buffer);
trace ("failed to gzread from %s\n", fname);
+ gzclose (gz);
return -1;
}
if (nb > 0) {
@@ -150,7 +194,8 @@ cgme_init (DB_fileinfo_t *_info, DB_playItem_t *it) {
trace ("failed with error %d\n", res);
return -1;
}
- gme_mute_voices (info->emu, info->cgme_voicemask);
+ chip_voices = deadbeef->conf_get_int ("chip.voices", 0xff);
+ gme_mute_voices (info->emu, chip_voices^0xff);
gme_start_track (info->emu, deadbeef->pl_find_meta_int (it, ":TRACKNUM", 0));
#ifdef GME_VERSION_055
@@ -194,6 +239,13 @@ cgme_read (DB_fileinfo_t *_info, char *bytes, int size) {
// DON'T ajust size, buffer must always be po2
//size = t * (float)info->samplerate * 4;
}
+
+ if (chip_voices_changed) {
+ chip_voices = deadbeef->conf_get_int ("chip.voices", 0xff);
+ chip_voices_changed = 0;
+ gme_mute_voices (info->emu, chip_voices^0xff);
+ }
+
if (gme_play (info->emu, size/2, (short*)bytes)) {
return 0;
}
@@ -406,25 +458,6 @@ static const char * exts[]=
"ay","gbs","gym","hes","kss","nsf","nsfe","sap","spc","vgm","vgz",NULL
};
-#if 0
-static int
-cgme_numvoices (void) {
- if (!emu) {
- return 0;
- }
- return gme_voice_count (emu);
-}
-
-static void
-cgme_mutevoice (int voice, int mute) {
- cgme_voicemask &= ~ (1<<voice);
- cgme_voicemask |= ((mute ? 1 : 0) << voice);
- if (emu) {
- gme_mute_voices (emu, cgme_voicemask);
- }
-}
-#endif
-
static int
cgme_start (void) {
conf_fadeout = deadbeef->conf_get_int ("gme.fadeout", 10);
@@ -443,6 +476,9 @@ cgme_message (uint32_t id, uintptr_t ctx, uint32_t p1, uint32_t p2) {
case DB_EV_CONFIGCHANGED:
conf_fadeout = deadbeef->conf_get_int ("gme.fadeout", 10);
conf_loopcount = deadbeef->conf_get_int ("gme.loopcount", 2);
+ if (chip_voices != deadbeef->conf_get_int ("chip.voices", 0xff)) {
+ chip_voices_changed = 1;
+ }
break;
}
return 0;
diff --git a/plugins/gtkui/COPYING b/plugins/gtkui/COPYING
new file mode 100644
index 00000000..5e62520a
--- /dev/null
+++ b/plugins/gtkui/COPYING
@@ -0,0 +1,16 @@
+GTK2/3 UI plugin for DeaDBeeF player
+Copyright (C) 2009-2014 Alexey Yakovenko <waker@users.sourceforge.net>
+
+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, see <http://www.gnu.org/licenses/>.
+
diff --git a/plugins/gtkui/Makefile.am b/plugins/gtkui/Makefile.am
index f7fb1203..d7f6fcc9 100644
--- a/plugins/gtkui/Makefile.am
+++ b/plugins/gtkui/Makefile.am
@@ -154,17 +154,9 @@ GTKUI_SOURCES_GTK2 = $(GTKUI_SOURCES)
ddb_gui_GTK2_la_SOURCES = $(GTKUI_SOURCES_GTK2)
ddb_gui_GTK2_la_LDFLAGS = -module -avoid-version
-if STATICLINK
-GTK_ROOT_216=@top_srcdir@/$(LIB)/gtk-2.16.0
-
-ddb_gui_GTK2_la_LIBADD = $(LDADD) -L$(GTK_ROOT_216)/lib -lgtk-x11-2.0 -lgdk-x11-2.0 -latk-1.0 -lgio-2.0 -lpangoft2-1.0 -lgdk_pixbuf-2.0 -lpangocairo-1.0 -lcairo -lpango-1.0 -lfreetype -lgobject-2.0 -lgmodule-2.0 -lgthread-2.0 -lrt -lglib-2.0 $(SM_LIBADD) ../libparser/libparser.a $(GTKGLEXT2_LIBS)
-
-ddb_gui_GTK2_la_CFLAGS = -std=c99 -I$(GTK_ROOT_216)/include/gtk-2.0 -I$(GTK_ROOT_216)/lib/gtk-2.0/include -I$(GTK_ROOT_216)/include/atk-1.0 -I$(GTK_ROOT_216)/include/cairo -I$(GTK_ROOT_216)/include/pango-1.0 -I$(GTK_ROOT_216)/include -I$(GTK_ROOT_216)/include/glib-2.0 -I$(GTK_ROOT_216)/lib/glib-2.0/include $(SM_CFLAGS) $(GTKGLEXT_CFLAGS_GTK2)
-else
ddb_gui_GTK2_la_LIBADD = $(LDADD) $(GTK2_DEPS_LIBS) $(SM_LIBADD) ../libparser/libparser.a $(GTKGLEXT2_LIBS)
ddb_gui_GTK2_la_CFLAGS = -std=c99 $(GTK2_DEPS_CFLAGS) $(SM_CFLAGS) $(GTKGLEXT_CFLAGS_GTK2) -DDDB_WARN_DEPRECATED=1
-endif
endif
@@ -233,21 +225,12 @@ GTKGLEXT_CFLAGS_GTK3 = -I@top_srcdir@/plugins/gtkui/gtkglext-gtk3 -I@top_srcdir@
ddb_gui_GTK3_la_LDFLAGS = -module -avoid-version
-if STATICLINK
-ddb_gui_GTK3_la_SOURCES = $(GTKUI_SOURCES_GTK3)
-GTK_ROOT_300=@top_srcdir@/$(LIB)/gtk-3.0.0
-
-ddb_gui_GTK3_la_LIBADD = $(LDADD) -L$(GTK_ROOT_300)/lib -lgtk-3 -lgdk-3 -latk-1.0 -lgio-2.0 -lpangocairo-1.0 -lgdk_pixbuf-2.0 -lcairo-gobject -lpango-1.0 -lcairo -lgobject-2.0 -lgthread-2.0 -lglib-2.0 -lfreetype $(SM_LIBADD) ../libparser/libparser.a $(GTKGLEXT3_LIBS)
-
-ddb_gui_GTK3_la_CFLAGS = -std=c99 -I$(GTK_ROOT_300)/include/gtk-3.0 -I$(GTK_ROOT_300)/include/pango-1.0 -I$(GTK_ROOT_300)/include/gio-unix-2.0/ -I$(GTK_ROOT_300)/include/atk-1.0 -I$(GTK_ROOT_300)/include/cairo -I$(GTK_ROOT_300)/include/gdk-pixbuf-2.0 -I$(GTK_ROOT_300)/include/freetype2 -I$(GTK_ROOT_300)/include/glib-2.0 -I$(GTK_ROOT_300)/lib/glib-2.0/include $(SM_CFLAGS) $(GTKGLEXT_CFLAGS_GTK3)
-else
ddb_gui_GTK3_la_SOURCES = $(GTKUI_SOURCES_GTK3)
ddb_gui_GTK3_la_LIBADD = $(LDADD) $(GTK3_DEPS_LIBS) $(SM_LIBADD) ../libparser/libparser.a $(GTKGLEXT3_LIBS)
ddb_gui_GTK3_la_CFLAGS = -std=c99 $(GTK3_DEPS_CFLAGS) $(SM_CFLAGS) $(GTKGLEXT_CFLAGS_GTK3)
ddb_gui_GTK3_la_OBJCFLAGS = $(GTK3_DEPS_CFLAGS) $(SM_CFLAGS) $(GTKGLEXT_CFLAGS_GTK3)
endif
-endif
# fallback lib
if STATICLINK
@@ -256,7 +239,7 @@ GTK_ROOT=@top_srcdir@/$(LIB)/gtk-2.12.12/usr
ddb_gui_GTK2_fallback_la_SOURCES = $(GTKUI_SOURCES_GTK2)
ddb_gui_GTK2_fallback_la_LDFLAGS = -module -avoid-version
-ddb_gui_GTK2_fallback_la_LIBADD = $(LDADD) -L$(GTK_ROOT)/lib $(GTK_ROOT)/lib/libgtk-x11-2.0.la $(GTK_ROOT)/lib/libgdk-x11-2.0.la $(GTK_ROOT)/lib/libpangoft2-1.0.la $(GTK_ROOT)/lib/libpangocairo-1.0.la $(GTK_ROOT)/lib/libgdk_pixbuf-2.0.la -lm $(GTK_ROOT)/lib/libcairo.la $(GTK_ROOT)/lib/libpango-1.0.la $(GTK_ROOT)/lib/libgobject-2.0.la $(GTK_ROOT)/lib/libgmodule-2.0.la $(GTK_ROOT)/lib/libgthread-2.0.la -lrt $(GTK_ROOT)/lib/libglib-2.0.la $(SM_LIBADD) ../libparser/libparser.a $(GTKGLEXT2_LIBS)
+ddb_gui_GTK2_fallback_la_LIBADD = $(LDADD) -L$(GTK_ROOT)/lib -lgtk-x11-2.0 -lgdk-x11-2.0 -latk-1.0 -lgdk_pixbuf-2.0 -lm -lpangocairo-1.0 -lpango-1.0 -lcairo -lgobject-2.0 -lgmodule-2.0 -ldl -lglib-2.0 -lgthread-2.0 -lrt -lglib-2.0 $(SM_LIBADD) ../libparser/libparser.a $(GTKGLEXT2_LIBS)
ddb_gui_GTK2_fallback_la_CFLAGS = -std=c99 -I $(GTK_ROOT)/include -I $(GTK_ROOT)/lib/gtk-2.0/include -I $(GTK_ROOT)/include/glib-2.0 -I $(GTK_ROOT)/include/gtk-2.0 -I $(GTK_ROOT)/include/cairo -I $(GTK_ROOT)/lib/glib-2.0/include/ -I $(GTK_ROOT)/include/pango-1.0 -I $(GTK_ROOT)/include/atk-1.0 $(SM_CFLAGS) $(GTKGLEXT_CFLAGS_GTK2)
diff --git a/plugins/gtkui/callbacks.c b/plugins/gtkui/callbacks.c
index 5a696bc9..51de7a9d 100644
--- a/plugins/gtkui/callbacks.c
+++ b/plugins/gtkui/callbacks.c
@@ -257,6 +257,7 @@ on_loop_all_activate (GtkMenuItem *menuitem,
gpointer user_data)
{
deadbeef->conf_set_int ("playback.loop", 0);
+ deadbeef->sendmessage (DB_EV_CONFIGCHANGED, 0, 0, 0);
}
@@ -265,6 +266,7 @@ on_loop_single_activate (GtkMenuItem *menuitem,
gpointer user_data)
{
deadbeef->conf_set_int ("playback.loop", 2);
+ deadbeef->sendmessage (DB_EV_CONFIGCHANGED, 0, 0, 0);
}
@@ -273,6 +275,7 @@ on_loop_disable_activate (GtkMenuItem *menuitem,
gpointer user_data)
{
deadbeef->conf_set_int ("playback.loop", 1);
+ deadbeef->sendmessage (DB_EV_CONFIGCHANGED, 0, 0, 0);
}
void
@@ -311,6 +314,7 @@ on_scroll_follows_playback_activate (GtkMenuItem *menuitem,
gpointer user_data)
{
deadbeef->conf_set_int ("playlist.scroll.followplayback", gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (menuitem)));
+ deadbeef->sendmessage (DB_EV_CONFIGCHANGED, 0, 0, 0);
}
@@ -454,7 +458,7 @@ on_toggle_status_bar_activate (GtkMenuItem *menuitem,
gtk_widget_show (sb);
}
}
- deadbeef->conf_save ();
+ deadbeef->sendmessage (DB_EV_CONFIGCHANGED, 0, 0, 0);
}
void
@@ -462,6 +466,15 @@ on_stop_after_current_activate (GtkMenuItem *menuitem,
gpointer user_data)
{
deadbeef->conf_set_int ("playlist.stop_after_current", gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (menuitem)));
+ deadbeef->sendmessage (DB_EV_CONFIGCHANGED, 0, 0, 0);
+}
+
+void
+on_stop_after_album_activate (GtkMenuItem *menuitem,
+ gpointer user_data)
+{
+ deadbeef->conf_set_int ("playlist.stop_after_album", gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (menuitem)));
+ deadbeef->sendmessage (DB_EV_CONFIGCHANGED, 0, 0, 0);
}
void
@@ -469,6 +482,7 @@ on_cursor_follows_playback_activate (GtkMenuItem *menuitem,
gpointer user_data)
{
deadbeef->conf_set_int ("playlist.scroll.cursorfollowplayback", gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (menuitem)));
+ deadbeef->sendmessage (DB_EV_CONFIGCHANGED, 0, 0, 0);
}
GtkWidget*
@@ -515,7 +529,7 @@ on_toggle_eq (GtkMenuItem *menuitem,
deadbeef->conf_set_int ("gtkui.eq.visible", 1);
eq_window_show ();
}
- deadbeef->conf_save ();
+ deadbeef->sendmessage (DB_EV_CONFIGCHANGED, 0, 0, 0);
}
diff --git a/plugins/gtkui/callbacks.h b/plugins/gtkui/callbacks.h
index b38d5f2e..bbd33f0e 100644
--- a/plugins/gtkui/callbacks.h
+++ b/plugins/gtkui/callbacks.h
@@ -1308,3 +1308,11 @@ on_auto_size_columns_toggled (GtkToggleButton *togglebutton,
void
on_searchentry_activate (GtkEntry *entry,
gpointer user_data);
+
+void
+on_stop_after_album_activate (GtkMenuItem *menuitem,
+ gpointer user_data);
+
+void
+on_reset_autostopalbum_toggled (GtkToggleButton *togglebutton,
+ gpointer user_data);
diff --git a/plugins/gtkui/coverart.c b/plugins/gtkui/coverart.c
index ecbb1277..f7d78696 100644
--- a/plugins/gtkui/coverart.c
+++ b/plugins/gtkui/coverart.c
@@ -272,7 +272,7 @@ get_cover_art_callb (const char *fname, const char *artist, const char *album, i
if (width == -1) {
char path[2048];
- coverart_plugin->make_cache_path (path, sizeof (path), album, artist, -1);
+ coverart_plugin->make_cache_path2 (path, sizeof (path), fname, album, artist, -1);
deadbeef->mutex_lock (mutex);
int i_largest = -1;
int size_largest = -1;
diff --git a/plugins/gtkui/ddblistview.c b/plugins/gtkui/ddblistview.c
index 8cff479e..465117ff 100644
--- a/plugins/gtkui/ddblistview.c
+++ b/plugins/gtkui/ddblistview.c
@@ -1795,7 +1795,7 @@ ddb_listview_list_mousemove (DdbListview *ps, GdkEventMotion *ev, int ex, int ey
deadbeef->pl_lock ();
if (ps->dragwait) {
GtkWidget *widget = ps->list;
- if (gtk_drag_check_threshold (widget, ps->lastpos[0], ex, ps->lastpos[1], ey)) {
+ if (gtk_drag_check_threshold (widget, ps->lastpos[0], ps->lastpos[1], ex, ey)) {
ps->dragwait = 0;
ps->drag_source_playlist = deadbeef->plt_get_curr_idx ();
GtkTargetEntry entry = {
diff --git a/plugins/gtkui/ddbseekbar.c b/plugins/gtkui/ddbseekbar.c
index 31740a29..0dbb7594 100644
--- a/plugins/gtkui/ddbseekbar.c
+++ b/plugins/gtkui/ddbseekbar.c
@@ -52,7 +52,6 @@ static gboolean ddb_seekbar_real_button_press_event (GtkWidget* base, GdkEventBu
static gboolean ddb_seekbar_real_button_release_event (GtkWidget* base, GdkEventButton* event);
static gboolean ddb_seekbar_real_motion_notify_event (GtkWidget* base, GdkEventMotion* event);
static gboolean ddb_seekbar_real_configure_event (GtkWidget* base, GdkEventConfigure* event);
-DdbSeekbar* ddb_seekbar_new (void);
DdbSeekbar* ddb_seekbar_construct (GType object_type);
static GObject * ddb_seekbar_constructor (GType type, guint n_construct_properties, GObjectConstructParam * construct_properties);
@@ -158,8 +157,8 @@ DdbSeekbar* ddb_seekbar_construct (GType object_type) {
}
-DdbSeekbar* ddb_seekbar_new (void) {
- return ddb_seekbar_construct (DDB_TYPE_SEEKBAR);
+GtkWidget* ddb_seekbar_new (void) {
+ return GTK_WIDGET (ddb_seekbar_construct (DDB_TYPE_SEEKBAR));
}
@@ -331,7 +330,7 @@ seekbar_draw (GtkWidget *widget, cairo_t *cr) {
cairo_fill (cr);
cairo_reset_clip (cr);
- if ((self->seekbar_moving || self->seekbar_moved > 0.0) && trk) {
+ if (!gtkui_disable_seekbar_overlay && (self->seekbar_moving || self->seekbar_moved > 0.0) && trk) {
float time = 0;
float dur = deadbeef->pl_get_item_duration (trk);
@@ -439,23 +438,65 @@ on_seekbar_button_release_event (GtkWidget *widget,
self->seekbar_moved = 1.0;
DB_playItem_t *trk = deadbeef->streamer_get_playing_track ();
if (trk) {
- GtkAllocation a;
- gtk_widget_get_allocation (widget, &a);
- float time = (event->x - a.x) * deadbeef->pl_get_item_duration (trk) / (a.width);
- if (time < 0) {
- time = 0;
+ if (deadbeef->pl_get_item_duration (trk) >= 0) {
+ GtkAllocation a;
+ gtk_widget_get_allocation (widget, &a);
+ float time = (event->x - a.x) * deadbeef->pl_get_item_duration (trk) / (a.width);
+ if (time < 0) {
+ time = 0;
+ }
+ deadbeef->sendmessage (DB_EV_SEEK, 0, time * 1000, 0);
}
- deadbeef->sendmessage (DB_EV_SEEK, 0, time * 1000, 0);
deadbeef->pl_item_unref (trk);
}
gtk_widget_queue_draw (widget);
return FALSE;
}
-void
-seekbar_redraw (void) {
- GtkWidget *widget = lookup_widget (mainwin, "seekbar");
- gtk_widget_queue_draw (widget);
+static gboolean
+on_evbox_button_press_event (GtkWidget *widget,
+ GdkEventButton *event,
+ gpointer user_data)
+{
+ return gtk_widget_event (GTK_WIDGET (user_data), (GdkEvent *)event);
}
+static gboolean
+on_evbox_button_release_event (GtkWidget *widget,
+ GdkEventButton *event,
+ gpointer user_data)
+{
+ return gtk_widget_event (GTK_WIDGET (user_data), (GdkEvent *)event);
+}
+
+static gboolean
+on_evbox_motion_notify_event (GtkWidget *widget,
+ GdkEventMotion *event,
+ gpointer user_data)
+{
+ return gtk_widget_event (GTK_WIDGET (user_data), (GdkEvent *)event);
+}
+
+static gboolean
+on_evbox_scroll_event (GtkWidget *widget,
+ GdkEvent *event,
+ gpointer user_data) {
+ return gtk_widget_event (GTK_WIDGET (user_data), (GdkEvent *)event);
+}
+
+void
+ddb_seekbar_init_signals (DdbSeekbar *sb, GtkWidget *evbox) {
+ g_signal_connect ((gpointer) evbox, "button_press_event",
+ G_CALLBACK (on_evbox_button_press_event),
+ sb);
+ g_signal_connect ((gpointer) evbox, "button_release_event",
+ G_CALLBACK (on_evbox_button_release_event),
+ sb);
+ g_signal_connect ((gpointer) evbox, "scroll_event",
+ G_CALLBACK (on_evbox_scroll_event),
+ sb);
+ g_signal_connect ((gpointer) evbox, "motion_notify_event",
+ G_CALLBACK (on_evbox_motion_notify_event),
+ sb);
+}
diff --git a/plugins/gtkui/ddbseekbar.h b/plugins/gtkui/ddbseekbar.h
index 7ce90052..b4e470bc 100644
--- a/plugins/gtkui/ddbseekbar.h
+++ b/plugins/gtkui/ddbseekbar.h
@@ -34,10 +34,14 @@ struct _DdbSeekbarClass {
};
-GType ddb_seekbar_get_type (void);
-DdbSeekbar* ddb_seekbar_new (void);
-DdbSeekbar* ddb_seekbar_construct (GType object_type);
+GType
+ddb_seekbar_get_type (void);
+GtkWidget*
+ddb_seekbar_new (void);
+
+void
+ddb_seekbar_init_signals (DdbSeekbar *sb, GtkWidget *evbox);
G_END_DECLS
diff --git a/plugins/gtkui/ddbvolumebar.c b/plugins/gtkui/ddbvolumebar.c
index e56ca03c..dfb3de1f 100644
--- a/plugins/gtkui/ddbvolumebar.c
+++ b/plugins/gtkui/ddbvolumebar.c
@@ -266,17 +266,6 @@ on_volumebar_button_release_event (GtkWidget *widget,
return FALSE;
}
-void
-volumebar_notify_changed (void) {
- GtkWidget *widget = lookup_widget (mainwin, "volumebar");
- gtk_widget_queue_draw (widget);
- char s[100];
- int db = deadbeef->volume_get_db ();
- snprintf (s, sizeof (s), "%s%ddB", db < 0 ? "" : "+", db);
- gtk_widget_set_tooltip_text (widget, s);
- gtk_widget_trigger_tooltip_query (widget);
-}
-
gboolean
on_volumebar_scroll_event (GtkWidget *widget,
GdkEventScroll *event)
@@ -296,7 +285,7 @@ on_volumebar_scroll_event (GtkWidget *widget,
vol = -range;
}
deadbeef->volume_set_db (vol);
- GtkWidget *volumebar = lookup_widget (mainwin, "volumebar");
+ GtkWidget *volumebar = DDB_VOLUMEBAR (widget);
gtk_widget_queue_draw (widget);
char s[100];
int db = deadbeef->volume_get_db ();
@@ -311,3 +300,51 @@ on_volumebar_configure_event (GtkWidget *widget, GdkEventConfigure *event) {
gtkui_init_theme_colors ();
return FALSE;
}
+
+static gboolean
+on_evbox_button_press_event (GtkWidget *widget,
+ GdkEventButton *event,
+ gpointer user_data)
+{
+ return gtk_widget_event (GTK_WIDGET (user_data), (GdkEvent *)event);
+}
+
+static gboolean
+on_evbox_button_release_event (GtkWidget *widget,
+ GdkEventButton *event,
+ gpointer user_data)
+{
+ return gtk_widget_event (GTK_WIDGET (user_data), (GdkEvent *)event);
+}
+
+static gboolean
+on_evbox_motion_notify_event (GtkWidget *widget,
+ GdkEventMotion *event,
+ gpointer user_data)
+{
+ return gtk_widget_event (GTK_WIDGET (user_data), (GdkEvent *)event);
+}
+
+static gboolean
+on_evbox_scroll_event (GtkWidget *widget,
+ GdkEvent *event,
+ gpointer user_data) {
+ return gtk_widget_event (GTK_WIDGET (user_data), (GdkEvent *)event);
+}
+
+void
+ddb_volumebar_init_signals (DdbVolumeBar *vb, GtkWidget *evbox) {
+ g_signal_connect ((gpointer) evbox, "button_press_event",
+ G_CALLBACK (on_evbox_button_press_event),
+ vb);
+ g_signal_connect ((gpointer) evbox, "button_release_event",
+ G_CALLBACK (on_evbox_button_release_event),
+ vb);
+ g_signal_connect ((gpointer) evbox, "scroll_event",
+ G_CALLBACK (on_evbox_scroll_event),
+ vb);
+ g_signal_connect ((gpointer) evbox, "motion_notify_event",
+ G_CALLBACK (on_evbox_motion_notify_event),
+ vb);
+}
+
diff --git a/plugins/gtkui/ddbvolumebar.h b/plugins/gtkui/ddbvolumebar.h
index e8ef0a2d..d560a5cd 100644
--- a/plugins/gtkui/ddbvolumebar.h
+++ b/plugins/gtkui/ddbvolumebar.h
@@ -48,6 +48,9 @@ struct _DdbVolumeBarClass {
GType ddb_volumebar_get_type(void) G_GNUC_CONST;
GtkWidget * ddb_volumebar_new(void);
+void
+ddb_volumebar_init_signals (DdbVolumeBar *vb, GtkWidget *evbox);
+
G_END_DECLS
#endif // __DDBVOLUMEBAR_H
diff --git a/plugins/gtkui/deadbeef.glade b/plugins/gtkui/deadbeef.glade
index 98f85ffc..b75b4589 100644
--- a/plugins/gtkui/deadbeef.glade
+++ b/plugins/gtkui/deadbeef.glade
@@ -582,6 +582,16 @@
</widget>
</child>
+ <child>
+ <widget class="GtkCheckMenuItem" id="stop_after_album">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Stop after current album</property>
+ <property name="use_underline">True</property>
+ <property name="active">False</property>
+ <signal name="activate" handler="on_stop_after_album_activate" last_modification_time="Thu, 01 May 2014 15:14:26 GMT"/>
+ </widget>
+ </child>
+
<child>
<widget class="GtkSeparatorMenuItem" id="separator11">
<property name="visible">True</property>
@@ -724,194 +734,6 @@
</child>
<child>
- <widget class="GtkHBox" id="hbox2">
- <property name="visible">True</property>
- <property name="homogeneous">False</property>
- <property name="spacing">0</property>
-
- <child>
- <widget class="GtkHBox" id="hbox3">
- <property name="visible">True</property>
- <property name="homogeneous">False</property>
- <property name="spacing">0</property>
-
- <child>
- <widget class="GtkButton" id="stopbtn">
- <property name="visible">True</property>
- <property name="relief">GTK_RELIEF_NONE</property>
- <property name="focus_on_click">True</property>
- <signal name="clicked" handler="on_stopbtn_clicked" last_modification_time="Sun, 05 Jul 2009 10:48:41 GMT"/>
-
- <child>
- <widget class="GtkImage" id="image128">
- <property name="visible">True</property>
- <property name="stock">gtk-media-stop</property>
- <property name="icon_size">4</property>
- <property name="xalign">0.5</property>
- <property name="yalign">0.5</property>
- <property name="xpad">0</property>
- <property name="ypad">0</property>
- </widget>
- </child>
- </widget>
- <packing>
- <property name="padding">0</property>
- <property name="expand">False</property>
- <property name="fill">False</property>
- </packing>
- </child>
-
- <child>
- <widget class="GtkButton" id="playbtn">
- <property name="visible">True</property>
- <property name="relief">GTK_RELIEF_NONE</property>
- <property name="focus_on_click">True</property>
- <signal name="clicked" handler="on_playbtn_clicked" last_modification_time="Sun, 05 Jul 2009 10:48:53 GMT"/>
-
- <child>
- <widget class="GtkImage" id="image2">
- <property name="visible">True</property>
- <property name="stock">gtk-media-play</property>
- <property name="icon_size">4</property>
- <property name="xalign">0.5</property>
- <property name="yalign">0.5</property>
- <property name="xpad">0</property>
- <property name="ypad">0</property>
- </widget>
- </child>
- </widget>
- <packing>
- <property name="padding">0</property>
- <property name="expand">False</property>
- <property name="fill">False</property>
- </packing>
- </child>
-
- <child>
- <widget class="GtkButton" id="pausebtn">
- <property name="visible">True</property>
- <property name="relief">GTK_RELIEF_NONE</property>
- <property name="focus_on_click">True</property>
- <signal name="clicked" handler="on_pausebtn_clicked" last_modification_time="Sun, 05 Jul 2009 10:49:01 GMT"/>
-
- <child>
- <widget class="GtkImage" id="image3">
- <property name="visible">True</property>
- <property name="stock">gtk-media-pause</property>
- <property name="icon_size">4</property>
- <property name="xalign">0.5</property>
- <property name="yalign">0.5</property>
- <property name="xpad">0</property>
- <property name="ypad">0</property>
- </widget>
- </child>
- </widget>
- <packing>
- <property name="padding">0</property>
- <property name="expand">False</property>
- <property name="fill">False</property>
- </packing>
- </child>
-
- <child>
- <widget class="GtkButton" id="prevbtn">
- <property name="visible">True</property>
- <property name="relief">GTK_RELIEF_NONE</property>
- <property name="focus_on_click">True</property>
- <signal name="clicked" handler="on_prevbtn_clicked" last_modification_time="Sun, 05 Jul 2009 10:49:08 GMT"/>
-
- <child>
- <widget class="GtkImage" id="image4">
- <property name="visible">True</property>
- <property name="stock">gtk-media-previous</property>
- <property name="icon_size">4</property>
- <property name="xalign">0.5</property>
- <property name="yalign">0.5</property>
- <property name="xpad">0</property>
- <property name="ypad">0</property>
- </widget>
- </child>
- </widget>
- <packing>
- <property name="padding">0</property>
- <property name="expand">False</property>
- <property name="fill">False</property>
- </packing>
- </child>
-
- <child>
- <widget class="GtkButton" id="nextbtn">
- <property name="visible">True</property>
- <property name="relief">GTK_RELIEF_NONE</property>
- <property name="focus_on_click">True</property>
- <signal name="clicked" handler="on_nextbtn_clicked" last_modification_time="Sun, 05 Jul 2009 10:49:12 GMT"/>
-
- <child>
- <widget class="GtkImage" id="image5">
- <property name="visible">True</property>
- <property name="stock">gtk-media-next</property>
- <property name="icon_size">4</property>
- <property name="xalign">0.5</property>
- <property name="yalign">0.5</property>
- <property name="xpad">0</property>
- <property name="ypad">0</property>
- </widget>
- </child>
- </widget>
- <packing>
- <property name="padding">0</property>
- <property name="expand">False</property>
- <property name="fill">False</property>
- </packing>
- </child>
- </widget>
- <packing>
- <property name="padding">0</property>
- <property name="expand">False</property>
- <property name="fill">True</property>
- </packing>
- </child>
-
- <child>
- <widget class="Custom" id="seekbar">
- <property name="width_request">20</property>
- <property name="visible">True</property>
- <property name="creation_function">create_seekbar</property>
- <property name="int1">0</property>
- <property name="int2">0</property>
- <property name="last_modification_time">Fri, 09 Apr 2010 19:51:15 GMT</property>
- </widget>
- <packing>
- <property name="padding">2</property>
- <property name="expand">True</property>
- <property name="fill">True</property>
- </packing>
- </child>
-
- <child>
- <widget class="Custom" id="volumebar">
- <property name="width_request">70</property>
- <property name="visible">True</property>
- <property name="creation_function">create_volumebar_widget</property>
- <property name="int1">0</property>
- <property name="int2">0</property>
- <property name="last_modification_time">Thu, 18 Feb 2010 20:13:13 GMT</property>
- </widget>
- <packing>
- <property name="padding">2</property>
- <property name="expand">False</property>
- <property name="fill">True</property>
- </packing>
- </child>
- </widget>
- <packing>
- <property name="padding">0</property>
- <property name="expand">False</property>
- <property name="fill">False</property>
- </packing>
- </child>
-
- <child>
<widget class="GtkVBox" id="plugins_bottom_vbox">
<property name="visible">True</property>
<property name="homogeneous">False</property>
@@ -3037,6 +2859,26 @@ Album</property>
<property name="fill">False</property>
</packing>
</child>
+
+ <child>
+ <widget class="GtkCheckButton" id="reset_autostopalbum">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes">Auto-reset &quot;Stop after current album&quot;</property>
+ <property name="use_underline">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <property name="active">False</property>
+ <property name="inconsistent">False</property>
+ <property name="draw_indicator">True</property>
+ <signal name="toggled" handler="on_reset_autostopalbum_toggled" last_modification_time="Thu, 01 May 2014 15:30:01 GMT"/>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
</widget>
<packing>
<property name="tab_expand">False</property>
diff --git a/plugins/gtkui/gtkui.c b/plugins/gtkui/gtkui.c
index bb89b17d..5d2dedeb 100644
--- a/plugins/gtkui/gtkui.c
+++ b/plugins/gtkui/gtkui.c
@@ -81,6 +81,8 @@ GtkWidget *theme_button;
static int gtkui_accept_messages = 0;
+static gint refresh_timeout = 0;
+
int fileadded_listener_id;
int fileadd_beginend_listener_id;
// overriden API methods
@@ -99,6 +101,9 @@ int gtkui_groups_pinned;
int gtkui_is_retina = 0;
#endif
+int gtkui_unicode_playstate = 0;
+int gtkui_disable_seekbar_overlay = 0;
+
#define TRAY_ICON "deadbeef_tray_icon"
// that must be called before gtk_init
@@ -111,7 +116,7 @@ gtkpl_init (void) {
gtk_box_pack_start (GTK_BOX (vbox1), theme_treeview, FALSE, FALSE, 0);
gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (theme_treeview), TRUE);
- theme_button = lookup_widget (mainwin, "stopbtn");
+ theme_button = mainwin;//lookup_widget (mainwin, "stopbtn");
}
void
@@ -131,8 +136,6 @@ struct fromto_t {
static gboolean
update_win_title_idle (gpointer data);
-static gboolean
-redraw_seekbar_cb (gpointer nothing);
// update status bar and window title
static int sb_context_id = -1;
@@ -149,7 +152,6 @@ update_songinfo (gpointer ctx) {
}
DB_output_t *output = deadbeef->get_output ();
char sbtext_new[512] = "-";
- float songpos = last_songpos;
float pl_totaltime = deadbeef->pl_get_totaltime ();
int daystotal = (int)pl_totaltime / (3600*24);
@@ -175,7 +177,6 @@ update_songinfo (gpointer ctx) {
if (!output || (output->state () == OUTPUT_STATE_STOPPED || !track || !c)) {
snprintf (sbtext_new, sizeof (sbtext_new), _("Stopped | %d tracks | %s total playtime"), deadbeef->pl_getcount (PL_MAIN), totaltime_str);
- songpos = 0;
}
else {
float playpos = deadbeef->streamer_get_playpos ();
@@ -195,7 +196,6 @@ update_songinfo (gpointer ctx) {
}
int samplerate = c->fmt.samplerate;
int bitspersample = c->fmt.bps;
- songpos = playpos;
// codec_unlock ();
char t[100];
@@ -240,18 +240,6 @@ update_songinfo (gpointer ctx) {
gtk_statusbar_push (sb, sb_context_id, sb_text);
}
- if (mainwin) {
- GtkWidget *widget = lookup_widget (mainwin, "seekbar");
- // translate volume to seekbar pixels
- songpos /= duration;
- GtkAllocation a;
- gtk_widget_get_allocation (widget, &a);
- songpos *= a.width;
- if (fabs (songpos - last_songpos) > 0.01) {
- gtk_widget_queue_draw (widget);
- last_songpos = songpos;
- }
- }
if (track) {
deadbeef->pl_item_unref (track);
}
@@ -289,17 +277,6 @@ on_trayicon_scroll_event (GtkWidget *widget,
vol = deadbeef->volume_get_min_db ();
}
deadbeef->volume_set_db (vol);
- volumebar_redraw ();
-
- //Update volume bar tooltip
- if (mainwin) {
- GtkWidget *volumebar = lookup_widget (mainwin, "volumebar");
- char s[100];
- int db = vol;
- snprintf (s, sizeof (s), "%s%ddB", db < 0 ? "" : "+", db);
- gtk_widget_set_tooltip_text (volumebar, s);
- gtk_widget_trigger_tooltip_query (volumebar);
- }
#if 0
char str[100];
@@ -414,7 +391,6 @@ gtkpl_songchanged_wrapper (DB_playItem_t *from, DB_playItem_t *to) {
deadbeef->pl_item_ref (to);
}
g_idle_add (update_win_title_idle, ft);
- g_idle_add (redraw_seekbar_cb, NULL);
if (searchwin && gtk_widget_get_window (searchwin)) {
int iconified = gdk_window_get_state(gtk_widget_get_window (searchwin)) & GDK_WINDOW_STATE_ICONIFIED;
if (gtk_widget_get_visible (searchwin) && !iconified) {
@@ -508,13 +484,6 @@ gtkui_on_frameupdate (gpointer data) {
}
static gboolean
-gtkui_volumechanged_cb (gpointer ctx) {
- GtkWidget *volumebar = lookup_widget (mainwin, "volumebar");
- gdk_window_invalidate_rect (gtk_widget_get_window (volumebar), NULL, FALSE);
- return FALSE;
-}
-
-static gboolean
gtkui_update_status_icon (gpointer unused) {
int hide_tray_icon = deadbeef->conf_get_int ("gtkui.hide_tray_icon", 0);
if (hide_tray_icon && !trayicon) {
@@ -589,6 +558,19 @@ gtkui_get_curr_playlist_mod (void) {
return res;
}
+void
+gtkui_setup_gui_refresh (void) {
+ int tm = 1000/gtkui_get_gui_refresh_rate ();
+
+ if (refresh_timeout) {
+ g_source_remove (refresh_timeout);
+ refresh_timeout = 0;
+ }
+
+ refresh_timeout = g_timeout_add (tm, gtkui_on_frameupdate, NULL);
+}
+
+
static gboolean
gtkui_on_configchanged (void *data) {
// order and looping
@@ -614,15 +596,28 @@ gtkui_on_configchanged (void *data) {
int stop_after_current = deadbeef->conf_get_int ("playlist.stop_after_current", 0);
gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (lookup_widget (mainwin, "stop_after_current")), stop_after_current ? TRUE : FALSE);
+ // stop after current album
+ int stop_after_album = deadbeef->conf_get_int ("playlist.stop_after_album", 0);
+ gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (lookup_widget (mainwin, "stop_after_album")), stop_after_album ? TRUE : FALSE);
+
// embolden current track
gtkui_embolden_current_track = deadbeef->conf_get_int ("gtkui.embolden_current_track", 0);
// pin groups
gtkui_groups_pinned = deadbeef->conf_get_int ("playlist.pin.groups", 0);
+ // play state images
+ gtkui_unicode_playstate = deadbeef->conf_get_int ("gtkui.unicode_playstate", 0);
+
+ // seekbar overlay
+ gtkui_disable_seekbar_overlay = deadbeef->conf_get_int ("gtkui.disable_seekbar_overlay", 0);
+
// tray icon
gtkui_update_status_icon (NULL);
+ // statusbar refresh
+ gtkui_setup_gui_refresh ();
+
return FALSE;
}
@@ -690,16 +685,6 @@ update_win_title_idle (gpointer data) {
return FALSE;
}
-static gboolean
-redraw_seekbar_cb (gpointer nothing) {
- int iconified = gdk_window_get_state(gtk_widget_get_window(mainwin)) & GDK_WINDOW_STATE_ICONIFIED;
- if (!gtk_widget_get_visible (mainwin) || iconified) {
- return FALSE;
- }
- seekbar_redraw ();
- return FALSE;
-}
-
int
gtkui_add_new_playlist (void) {
int cnt = deadbeef->plt_get_count ();
@@ -732,22 +717,8 @@ gtkui_add_new_playlist (void) {
return -1;
}
-void
-volumebar_redraw (void) {
- GtkWidget *volumebar = lookup_widget (mainwin, "volumebar");
- gdk_window_invalidate_rect (gtk_widget_get_window (volumebar), NULL, FALSE);
-}
-
-//void
-//tabstrip_redraw (void) {
-// GtkWidget *ts = lookup_widget (mainwin, "tabstrip");
-// ddb_tabstrip_refresh (DDB_TABSTRIP (ts));
-//}
-
-static gint refresh_timeout = 0;
-
-void
-gtkui_setup_gui_refresh (void) {
+int
+gtkui_get_gui_refresh_rate () {
int fps = deadbeef->conf_get_int ("gtkui.refresh_rate", 10);
if (fps < 1) {
fps = 1;
@@ -755,15 +726,7 @@ gtkui_setup_gui_refresh (void) {
else if (fps > 30) {
fps = 30;
}
-
- int tm = 1000/fps;
-
- if (refresh_timeout) {
- g_source_remove (refresh_timeout);
- refresh_timeout = 0;
- }
-
- refresh_timeout = g_timeout_add (tm, gtkui_on_frameupdate, NULL);
+ return fps;
}
static void
@@ -834,9 +797,6 @@ gtkui_message (uint32_t id, uintptr_t ctx, uint32_t p1, uint32_t p2) {
case DB_EV_PLAYLISTCHANGED:
g_idle_add (playlistchanged_cb, NULL);
break;
- case DB_EV_VOLUMECHANGED:
- g_idle_add (gtkui_volumechanged_cb, NULL);
- break;
case DB_EV_CONFIGCHANGED:
g_idle_add (gtkui_on_configchanged, NULL);
break;
@@ -856,6 +816,8 @@ gtkui_message (uint32_t id, uintptr_t ctx, uint32_t p1, uint32_t p2) {
return 0;
}
+static const char gtkui_def_layout[] = "vbox expand=\"0 1\" fill=\"1 1\" homogeneous=0 {hbox expand=\"0 1 0\" fill=\"1 1 1\" homogeneous=0 {playtb {} seekbar {} volumebar {} } tabbed_playlist hideheaders=0 {} } ";
+
static void
init_widget_layout (void) {
w_init ();
@@ -864,8 +826,27 @@ init_widget_layout (void) {
gtk_box_pack_start (GTK_BOX(lookup_widget(mainwin, "plugins_bottom_vbox")), rootwidget->widget, TRUE, TRUE, 0);
// load layout
+ // config var name is defined in DDB_GTKUI_CONF_LAYOUT
+ // gtkui.layout: 0.6.0 and 0.6.1
+ // gtkui.layout.major.minor.point: later versions
+
char layout[20000];
- deadbeef->conf_get_str ("gtkui.layout", "tabbed_playlist \"\" { }", layout, sizeof (layout));
+ deadbeef->conf_get_str (DDB_GTKUI_CONF_LAYOUT, "-", layout, sizeof (layout));
+ if (!strcmp (layout, "-")) {
+ // upgrade from 0.6.0 to 0.6.2
+ char layout_060[20000];
+ deadbeef->conf_get_str ("gtkui.layout", "-", layout_060, sizeof (layout_060));
+ if (!strcmp (layout_060, "-")) {
+ // new setup
+ strcpy (layout, gtkui_def_layout);
+ }
+ else {
+ // upgrade with top bar
+ snprintf (layout, sizeof (layout), "vbox expand=\"0 1\" fill=\"1 1\" homogeneous=0 {hbox expand=\"0 1 0\" fill=\"1 1 1\" homogeneous=0 {playtb {} seekbar {} volumebar {} } %s }", layout_060);
+ deadbeef->conf_set_str (DDB_GTKUI_CONF_LAYOUT, layout);
+ deadbeef->conf_save ();
+ }
+ }
ddb_gtkui_widget_t *w = NULL;
w_create_from_string (layout, &w);
@@ -902,7 +883,7 @@ gtkui_connect_cb (void *none) {
DB_plugin_t **plugins = deadbeef->plug_get_list ();
for (int i = 0; plugins[i]; i++) {
DB_plugin_t *p = plugins[i];
- if (p->id && !strcmp (p->id, "artwork")) {
+ if (p->id && !strcmp (p->id, "artwork") && p->version_major == 1 && p->version_minor >= 2) {
trace ("gtkui: found cover-art loader plugin\n");
coverart_plugin = (DB_artwork_plugin_t *)p;
break;
@@ -987,6 +968,10 @@ gtkui_thread (void *ctx) {
w_reg_widget (_("HBox"), 0, w_hbox_create, "hbox", NULL);
w_reg_widget (_("VBox"), 0, w_vbox_create, "vbox", NULL);
w_reg_widget (_("Button"), 0, w_button_create, "button", NULL);
+ w_reg_widget (_("Seekbar"), 0, w_seekbar_create, "seekbar", NULL);
+ w_reg_widget (_("Playback controls"), 0, w_playtb_create, "playtb", NULL);
+ w_reg_widget (_("Volume bar"), 0, w_volumebar_create, "volumebar", NULL);
+ w_reg_widget (_("Chiptune voices"), 0, w_ctvoices_create, "ctvoices", NULL);
mainwin = create_mainwin ();
@@ -1079,8 +1064,6 @@ gtkui_thread (void *ctx) {
init_widget_layout ();
- gtkui_setup_gui_refresh ();
-
char fmt[500];
char str[600];
deadbeef->conf_get_str ("gtkui.titlebar_stopped", "DeaDBeeF-%V", fmt, sizeof (fmt));
@@ -1605,10 +1588,11 @@ ddb_gui_GTK3_load (DB_functions_t *api) {
static const char settings_dlg[] =
"property \"Ask confirmation to delete files from disk\" checkbox gtkui.delete_files_ask 1;\n"
"property \"Status icon volume control sensitivity\" entry gtkui.tray_volume_sensitivity 1;\n"
-// "property \"Show volume in dB (percentage otherwise)\" entry gtkui.show_gain_in_db 1\n"
"property \"Custom status icon\" entry gtkui.custom_tray_icon \"" TRAY_ICON "\" ;\n"
"property \"Run gtk_init with --sync (debug mode)\" checkbox gtkui.sync 0;\n"
"property \"Add separators between plugin context menu items\" checkbox gtkui.action_separators 0;\n"
+ "property \"Use unicode chars instead of images for track state\" checkbox gtkui.unicode_playstate 0;\n"
+ "property \"Disable seekbar overlay text\" checkbox gtkui.disable_seekbar_overlay 0;\n"
;
// define plugin interface
diff --git a/plugins/gtkui/gtkui.h b/plugins/gtkui/gtkui.h
index abd71af7..5ed95c8c 100644
--- a/plugins/gtkui/gtkui.h
+++ b/plugins/gtkui/gtkui.h
@@ -36,6 +36,8 @@ extern GtkWidget *mainwin;
extern GtkWidget *searchwin;
extern int gtkui_embolden_current_track;
extern int gtkui_is_retina;
+extern int gtkui_unicode_playstate;
+extern int gtkui_disable_seekbar_overlay;
struct _GSList;
@@ -94,9 +96,6 @@ int
gtkui_add_new_playlist (void);
void
-seekbar_redraw (void);
-
-void
seekbar_draw (GtkWidget *widget, cairo_t *cr);
gboolean
@@ -112,9 +111,6 @@ on_seekbar_motion_notify_event (GtkWidget *widget,
GdkEventMotion *event);
void
-volumebar_redraw (void);
-
-void
gtkui_set_titlebar (DB_playItem_t *it);
gboolean
@@ -129,9 +125,6 @@ gtkui_set_progress_text_idle (gpointer data);
void
gtkui_playlist_set_curr (int playlist);
-void
-gtkui_setup_gui_refresh ();
-
int
gtkui_get_curr_playlist_mod (void);
@@ -162,4 +155,7 @@ gtkui_quit (void);
void
gtkui_run_preferences_dlg (void);
+int
+gtkui_get_gui_refresh_rate ();
+
#endif
diff --git a/plugins/gtkui/gtkui_api.h b/plugins/gtkui/gtkui_api.h
index c8057339..a3dd95d2 100644
--- a/plugins/gtkui/gtkui_api.h
+++ b/plugins/gtkui/gtkui_api.h
@@ -44,7 +44,10 @@
#endif
#define DDB_GTKUI_API_VERSION_MAJOR 2
-#define DDB_GTKUI_API_VERSION_MINOR 0
+#define DDB_GTKUI_API_VERSION_MINOR 1
+
+// added in API 2.1
+#define DDB_GTKUI_CONF_LAYOUT "gtkui.layout.0.6.2"
// this flag tells that the widget should be added to h/vboxes with expand=FALSE
#define DDB_GTKUI_WIDGET_FLAG_NON_EXPANDABLE 0x00000001
diff --git a/plugins/gtkui/hotkeys.c b/plugins/gtkui/hotkeys.c
index 7111703f..e8bffef9 100644
--- a/plugins/gtkui/hotkeys.c
+++ b/plugins/gtkui/hotkeys.c
@@ -929,6 +929,7 @@ gtkui_set_default_hotkeys (void) {
deadbeef->conf_set_str ("hotkey.key29", "v 0 0 stop");
deadbeef->conf_set_str ("hotkey.key30", "b 0 0 next");
deadbeef->conf_set_str ("hotkey.key31", "n 0 0 playback_random");
+ deadbeef->conf_set_str ("hotkey.key32", "\"Ctrl k\" 0 0 toggle_stop_after_album");
deadbeef->conf_save ();
}
diff --git a/plugins/gtkui/interface.c b/plugins/gtkui/interface.c
index b712cba2..5550996c 100644
--- a/plugins/gtkui/interface.c
+++ b/plugins/gtkui/interface.c
@@ -96,6 +96,7 @@ create_mainwin (void)
GtkWidget *scroll_follows_playback;
GtkWidget *cursor_follows_playback;
GtkWidget *stop_after_current;
+ GtkWidget *stop_after_album;
GtkWidget *separator11;
GtkWidget *jump_to_current_track1;
GtkWidget *Help;
@@ -111,20 +112,6 @@ create_mainwin (void)
GtkWidget *image654;
GtkWidget *translators1;
GtkWidget *image655;
- GtkWidget *hbox2;
- GtkWidget *hbox3;
- GtkWidget *stopbtn;
- GtkWidget *image128;
- GtkWidget *playbtn;
- GtkWidget *image2;
- GtkWidget *pausebtn;
- GtkWidget *image3;
- GtkWidget *prevbtn;
- GtkWidget *image4;
- GtkWidget *nextbtn;
- GtkWidget *image5;
- GtkWidget *seekbar;
- GtkWidget *volumebar;
GtkWidget *plugins_bottom_vbox;
GtkWidget *statusbar;
@@ -400,6 +387,10 @@ create_mainwin (void)
gtk_widget_show (stop_after_current);
gtk_container_add (GTK_CONTAINER (Playback_menu), stop_after_current);
+ stop_after_album = gtk_check_menu_item_new_with_mnemonic (_("Stop after current album"));
+ gtk_widget_show (stop_after_album);
+ gtk_container_add (GTK_CONTAINER (Playback_menu), stop_after_album);
+
separator11 = gtk_separator_menu_item_new ();
gtk_widget_show (separator11);
gtk_container_add (GTK_CONTAINER (Playback_menu), separator11);
@@ -462,78 +453,6 @@ create_mainwin (void)
gtk_widget_show (image655);
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (translators1), image655);
- hbox2 = gtk_hbox_new (FALSE, 0);
- gtk_widget_show (hbox2);
- gtk_box_pack_start (GTK_BOX (vbox1), hbox2, FALSE, FALSE, 0);
-
- hbox3 = gtk_hbox_new (FALSE, 0);
- gtk_widget_show (hbox3);
- gtk_box_pack_start (GTK_BOX (hbox2), hbox3, FALSE, TRUE, 0);
-
- stopbtn = gtk_button_new ();
- gtk_widget_show (stopbtn);
- gtk_box_pack_start (GTK_BOX (hbox3), stopbtn, FALSE, FALSE, 0);
- gtk_widget_set_can_focus(stopbtn, FALSE);
- gtk_button_set_relief (GTK_BUTTON (stopbtn), GTK_RELIEF_NONE);
-
- image128 = gtk_image_new_from_stock ("gtk-media-stop", GTK_ICON_SIZE_BUTTON);
- gtk_widget_show (image128);
- gtk_container_add (GTK_CONTAINER (stopbtn), image128);
-
- playbtn = gtk_button_new ();
- gtk_widget_show (playbtn);
- gtk_box_pack_start (GTK_BOX (hbox3), playbtn, FALSE, FALSE, 0);
- gtk_widget_set_can_focus(playbtn, FALSE);
- gtk_button_set_relief (GTK_BUTTON (playbtn), GTK_RELIEF_NONE);
-
- image2 = gtk_image_new_from_stock ("gtk-media-play", GTK_ICON_SIZE_BUTTON);
- gtk_widget_show (image2);
- gtk_container_add (GTK_CONTAINER (playbtn), image2);
-
- pausebtn = gtk_button_new ();
- gtk_widget_show (pausebtn);
- gtk_box_pack_start (GTK_BOX (hbox3), pausebtn, FALSE, FALSE, 0);
- gtk_widget_set_can_focus(pausebtn, FALSE);
- gtk_button_set_relief (GTK_BUTTON (pausebtn), GTK_RELIEF_NONE);
-
- image3 = gtk_image_new_from_stock ("gtk-media-pause", GTK_ICON_SIZE_BUTTON);
- gtk_widget_show (image3);
- gtk_container_add (GTK_CONTAINER (pausebtn), image3);
-
- prevbtn = gtk_button_new ();
- gtk_widget_show (prevbtn);
- gtk_box_pack_start (GTK_BOX (hbox3), prevbtn, FALSE, FALSE, 0);
- gtk_widget_set_can_focus(prevbtn, FALSE);
- gtk_button_set_relief (GTK_BUTTON (prevbtn), GTK_RELIEF_NONE);
-
- image4 = gtk_image_new_from_stock ("gtk-media-previous", GTK_ICON_SIZE_BUTTON);
- gtk_widget_show (image4);
- gtk_container_add (GTK_CONTAINER (prevbtn), image4);
-
- nextbtn = gtk_button_new ();
- gtk_widget_show (nextbtn);
- gtk_box_pack_start (GTK_BOX (hbox3), nextbtn, FALSE, FALSE, 0);
- gtk_widget_set_can_focus(nextbtn, FALSE);
- gtk_button_set_relief (GTK_BUTTON (nextbtn), GTK_RELIEF_NONE);
-
- image5 = gtk_image_new_from_stock ("gtk-media-next", GTK_ICON_SIZE_BUTTON);
- gtk_widget_show (image5);
- gtk_container_add (GTK_CONTAINER (nextbtn), image5);
-
- seekbar = create_seekbar ("seekbar", "", "", 0, 0);
- gtk_widget_show (seekbar);
- gtk_box_pack_start (GTK_BOX (hbox2), seekbar, TRUE, TRUE, 2);
- gtk_widget_set_size_request (seekbar, 20, -1);
- gtk_widget_set_can_focus(seekbar, FALSE);
- gtk_widget_set_can_default(seekbar, FALSE);
-
- volumebar = create_volumebar_widget ("volumebar", "", "", 0, 0);
- gtk_widget_show (volumebar);
- gtk_box_pack_start (GTK_BOX (hbox2), volumebar, FALSE, TRUE, 2);
- gtk_widget_set_size_request (volumebar, 70, -1);
- gtk_widget_set_can_focus(volumebar, FALSE);
- gtk_widget_set_can_default(volumebar, FALSE);
-
plugins_bottom_vbox = gtk_vbox_new (FALSE, 0);
gtk_widget_show (plugins_bottom_vbox);
gtk_box_pack_start (GTK_BOX (vbox1), plugins_bottom_vbox, TRUE, TRUE, 0);
@@ -677,6 +596,9 @@ create_mainwin (void)
g_signal_connect ((gpointer) stop_after_current, "activate",
G_CALLBACK (on_stop_after_current_activate),
NULL);
+ g_signal_connect ((gpointer) stop_after_album, "activate",
+ G_CALLBACK (on_stop_after_album_activate),
+ NULL);
g_signal_connect ((gpointer) jump_to_current_track1, "activate",
G_CALLBACK (on_jump_to_current_track1_activate),
NULL);
@@ -698,21 +620,6 @@ create_mainwin (void)
g_signal_connect ((gpointer) translators1, "activate",
G_CALLBACK (on_translators1_activate),
NULL);
- g_signal_connect ((gpointer) stopbtn, "clicked",
- G_CALLBACK (on_stopbtn_clicked),
- NULL);
- g_signal_connect ((gpointer) playbtn, "clicked",
- G_CALLBACK (on_playbtn_clicked),
- NULL);
- g_signal_connect ((gpointer) pausebtn, "clicked",
- G_CALLBACK (on_pausebtn_clicked),
- NULL);
- g_signal_connect ((gpointer) prevbtn, "clicked",
- G_CALLBACK (on_prevbtn_clicked),
- NULL);
- g_signal_connect ((gpointer) nextbtn, "clicked",
- G_CALLBACK (on_nextbtn_clicked),
- NULL);
/* Store pointers to all widgets, for use by lookup_widget(). */
GLADE_HOOKUP_OBJECT_NO_REF (mainwin, mainwin, "mainwin");
@@ -780,6 +687,7 @@ create_mainwin (void)
GLADE_HOOKUP_OBJECT (mainwin, scroll_follows_playback, "scroll_follows_playback");
GLADE_HOOKUP_OBJECT (mainwin, cursor_follows_playback, "cursor_follows_playback");
GLADE_HOOKUP_OBJECT (mainwin, stop_after_current, "stop_after_current");
+ GLADE_HOOKUP_OBJECT (mainwin, stop_after_album, "stop_after_album");
GLADE_HOOKUP_OBJECT (mainwin, separator11, "separator11");
GLADE_HOOKUP_OBJECT (mainwin, jump_to_current_track1, "jump_to_current_track1");
GLADE_HOOKUP_OBJECT (mainwin, Help, "Help");
@@ -795,20 +703,6 @@ create_mainwin (void)
GLADE_HOOKUP_OBJECT (mainwin, image654, "image654");
GLADE_HOOKUP_OBJECT (mainwin, translators1, "translators1");
GLADE_HOOKUP_OBJECT (mainwin, image655, "image655");
- GLADE_HOOKUP_OBJECT (mainwin, hbox2, "hbox2");
- GLADE_HOOKUP_OBJECT (mainwin, hbox3, "hbox3");
- GLADE_HOOKUP_OBJECT (mainwin, stopbtn, "stopbtn");
- GLADE_HOOKUP_OBJECT (mainwin, image128, "image128");
- GLADE_HOOKUP_OBJECT (mainwin, playbtn, "playbtn");
- GLADE_HOOKUP_OBJECT (mainwin, image2, "image2");
- GLADE_HOOKUP_OBJECT (mainwin, pausebtn, "pausebtn");
- GLADE_HOOKUP_OBJECT (mainwin, image3, "image3");
- GLADE_HOOKUP_OBJECT (mainwin, prevbtn, "prevbtn");
- GLADE_HOOKUP_OBJECT (mainwin, image4, "image4");
- GLADE_HOOKUP_OBJECT (mainwin, nextbtn, "nextbtn");
- GLADE_HOOKUP_OBJECT (mainwin, image5, "image5");
- GLADE_HOOKUP_OBJECT (mainwin, seekbar, "seekbar");
- GLADE_HOOKUP_OBJECT (mainwin, volumebar, "volumebar");
GLADE_HOOKUP_OBJECT (mainwin, plugins_bottom_vbox, "plugins_bottom_vbox");
GLADE_HOOKUP_OBJECT (mainwin, statusbar, "statusbar");
@@ -1630,6 +1524,7 @@ create_prefwin (void)
GtkWidget *resume_last_session;
GtkWidget *ignore_archives;
GtkWidget *reset_autostop;
+ GtkWidget *reset_autostopalbum;
GtkWidget *label39;
GtkWidget *vbox29;
GtkWidget *hbox80;
@@ -1958,6 +1853,10 @@ create_prefwin (void)
gtk_widget_show (reset_autostop);
gtk_box_pack_start (GTK_BOX (vbox8), reset_autostop, FALSE, FALSE, 0);
+ reset_autostopalbum = gtk_check_button_new_with_mnemonic (_("Auto-reset \"Stop after current album\""));
+ gtk_widget_show (reset_autostopalbum);
+ gtk_box_pack_start (GTK_BOX (vbox8), reset_autostopalbum, FALSE, FALSE, 0);
+
label39 = gtk_label_new (_("Playback"));
gtk_widget_show (label39);
gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), 1), label39);
@@ -2776,6 +2675,9 @@ create_prefwin (void)
g_signal_connect ((gpointer) reset_autostop, "toggled",
G_CALLBACK (on_reset_autostop_toggled),
NULL);
+ g_signal_connect ((gpointer) reset_autostopalbum, "toggled",
+ G_CALLBACK (on_reset_autostopalbum_toggled),
+ NULL);
g_signal_connect ((gpointer) dsp_add, "clicked",
G_CALLBACK (on_dsp_add_clicked),
NULL);
@@ -2987,6 +2889,7 @@ create_prefwin (void)
GLADE_HOOKUP_OBJECT (prefwin, resume_last_session, "resume_last_session");
GLADE_HOOKUP_OBJECT (prefwin, ignore_archives, "ignore_archives");
GLADE_HOOKUP_OBJECT (prefwin, reset_autostop, "reset_autostop");
+ GLADE_HOOKUP_OBJECT (prefwin, reset_autostopalbum, "reset_autostopalbum");
GLADE_HOOKUP_OBJECT (prefwin, label39, "label39");
GLADE_HOOKUP_OBJECT (prefwin, vbox29, "vbox29");
GLADE_HOOKUP_OBJECT (prefwin, hbox80, "hbox80");
diff --git a/plugins/gtkui/mainplaylist.c b/plugins/gtkui/mainplaylist.c
index 926e6cbb..fc781a39 100644
--- a/plugins/gtkui/mainplaylist.c
+++ b/plugins/gtkui/mainplaylist.c
@@ -349,7 +349,7 @@ main_playlist_init (GtkWidget *widget) {
DB_conf_item_t *col = deadbeef->conf_find ("playlist.column.", NULL);
if (!col) {
// create default set of columns
- add_column_helper (listview, _("Playing"), 50, DB_COLUMN_PLAYING, NULL, 0);
+ add_column_helper (listview, "♫", 50, DB_COLUMN_PLAYING, NULL, 0);
add_column_helper (listview, _("Artist / Album"), 150, -1, "%a - %b", 0);
add_column_helper (listview, _("Track No"), 50, -1, "%n", 1);
add_column_helper (listview, _("Title"), 150, -1, "%t", 0);
diff --git a/plugins/gtkui/plcommon.c b/plugins/gtkui/plcommon.c
index 9e3e3cdc..12229d0b 100644
--- a/plugins/gtkui/plcommon.c
+++ b/plugins/gtkui/plcommon.c
@@ -278,7 +278,7 @@ void draw_column_data (DdbListview *listview, cairo_t *cr, DdbListviewIter it, D
}
}
}
- else if (it && it == playing_track && cinf->id == DB_COLUMN_PLAYING) {
+ else if (!gtkui_unicode_playstate && it && it == playing_track && cinf->id == DB_COLUMN_PLAYING) {
int paused = deadbeef->get_output ()->state () == OUTPUT_STATE_PAUSED;
int buffering = !deadbeef->streamer_ok_to_read (-1);
GdkPixbuf *pixbuf;
@@ -296,15 +296,30 @@ void draw_column_data (DdbListview *listview, cairo_t *cr, DdbListviewIter it, D
cairo_fill (cr);
}
else if (it) {
- char text[1024];
- deadbeef->pl_format_title (it, -1, text, sizeof (text), cinf->id, cinf->format);
- char *lb = strchr (text, '\r');
- if (lb) {
- *lb = 0;
+ char text[1024] = "";
+ if (it == playing_track && cinf->id == DB_COLUMN_PLAYING) {
+ int paused = deadbeef->get_output ()->state () == OUTPUT_STATE_PAUSED;
+ int buffering = !deadbeef->streamer_ok_to_read (-1);
+ if (paused) {
+ strcpy (text, "||");
+ }
+ else if (!buffering) {
+ strcpy (text, "â–º");
+ }
+ else {
+ strcpy (text, "⋯⋯⋯");
+ }
}
- lb = strchr (text, '\n');
- if (lb) {
- *lb = 0;
+ else {
+ deadbeef->pl_format_title (it, -1, text, sizeof (text), cinf->id, cinf->format);
+ char *lb = strchr (text, '\r');
+ if (lb) {
+ *lb = 0;
+ }
+ lb = strchr (text, '\n');
+ if (lb) {
+ *lb = 0;
+ }
}
GdkColor *color = NULL;
if (theming) {
@@ -332,7 +347,7 @@ void draw_column_data (DdbListview *listview, cairo_t *cr, DdbListviewIter it, D
draw_init_font_bold (&listview->listctx);
}
if (calign_right) {
- draw_text (&listview->listctx, x+5, y + 3, cwidth-10, 1, text);
+ draw_text (&listview->listctx, x + 5, y + 3, cwidth-10, 1, text);
}
else {
draw_text (&listview->listctx, x + 5, y + 3, cwidth-10, 0, text);
diff --git a/plugins/gtkui/prefwin.c b/plugins/gtkui/prefwin.c
index 6034feef..00b68fbc 100644
--- a/plugins/gtkui/prefwin.c
+++ b/plugins/gtkui/prefwin.c
@@ -215,6 +215,9 @@ gtkui_run_preferences_dlg (void) {
// reset autostop
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (lookup_widget (w, "reset_autostop")), deadbeef->conf_get_int ("playlist.stop_after_current_reset", 0));
+ // reset album autostop
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (lookup_widget (w, "reset_autostopalbum")), deadbeef->conf_get_int ("playlist.stop_after_album_reset", 0));
+
// titlebar text
gtk_entry_set_text (GTK_ENTRY (lookup_widget (w, "titlebar_format_playing")), deadbeef->conf_get_str_fast ("gtkui.titlebar_playing", "%a - %t - DeaDBeeF-%V"));
gtk_entry_set_text (GTK_ENTRY (lookup_widget (w, "titlebar_format_stopped")), deadbeef->conf_get_str_fast ("gtkui.titlebar_stopped", "DeaDBeeF-%V"));
@@ -773,8 +776,6 @@ on_override_bar_colors_toggled (GtkToggleButton *togglebutton,
deadbeef->sendmessage (DB_EV_CONFIGCHANGED, 0, 0, 0);
gtkui_init_theme_colors ();
prefwin_init_theme_colors ();
- seekbar_redraw ();
- volumebar_redraw ();
eq_redraw ();
}
@@ -1052,7 +1053,7 @@ on_gui_fps_value_changed (GtkRange *range,
{
int val = gtk_range_get_value (range);
deadbeef->conf_set_int ("gtkui.refresh_rate", val);
- gtkui_setup_gui_refresh ();
+ deadbeef->sendmessage (DB_EV_CONFIGCHANGED, 0, 0, 0);
}
void
@@ -1070,6 +1071,13 @@ on_reset_autostop_toggled (GtkToggleButton *togglebutton,
deadbeef->conf_set_int ("playlist.stop_after_current_reset", gtk_toggle_button_get_active (togglebutton));
}
+void
+on_reset_autostopalbum_toggled (GtkToggleButton *togglebutton,
+ gpointer user_data)
+{
+ deadbeef->conf_set_int ("playlist.stop_after_album_reset", gtk_toggle_button_get_active (togglebutton));
+}
+
void
diff --git a/plugins/gtkui/trkproperties.c b/plugins/gtkui/trkproperties.c
index 8ab5981f..ffeeaf90 100644
--- a/plugins/gtkui/trkproperties.c
+++ b/plugins/gtkui/trkproperties.c
@@ -243,8 +243,18 @@ on_metadata_edited (GtkCellRendererText *renderer, gchar *path, gchar *new_text,
GtkListStore *store = GTK_LIST_STORE (user_data);
GtkTreePath *treepath = gtk_tree_path_new_from_string (path);
GtkTreeIter iter;
- gtk_tree_model_get_iter (GTK_TREE_MODEL (store), &iter, treepath);
+
+ if (!treepath) {
+ return;
+ }
+
+ gboolean valid = gtk_tree_model_get_iter (GTK_TREE_MODEL (store), &iter, treepath);
gtk_tree_path_free (treepath);
+
+ if (!valid) {
+ return;
+ }
+
GValue value = {0,};
GValue mult = {0,};
gtk_tree_model_get_value (GTK_TREE_MODEL (store), &iter, 1, &value);
@@ -428,7 +438,7 @@ show_track_properties_dlg (int ctx) {
tracks = malloc (sizeof (DB_playItem_t *) * num);
if (!tracks) {
- fprintf (stderr, "gtkui: failed to alloc %d bytes to store selected tracks\n", num * sizeof (void *));
+ fprintf (stderr, "gtkui: failed to alloc %d bytes to store selected tracks\n", (int)(num * sizeof (void *)));
deadbeef->pl_unlock ();
return;
}
diff --git a/plugins/gtkui/widgets.c b/plugins/gtkui/widgets.c
index 70f60fac..2f9ff7af 100644
--- a/plugins/gtkui/widgets.c
+++ b/plugins/gtkui/widgets.c
@@ -37,8 +37,11 @@
#include "namedicons.h"
#include "hotkeys.h" // for building action treeview
#include "../../strdupa.h"
-#include "../../optmath.h"
+#include "../../fastftoi.h"
#include "actions.h"
+#include "ddbseekbar.h"
+#include "ddbvolumebar.h"
+#include "callbacks.h"
//#define trace(...) { fprintf(stderr, __VA_ARGS__); }
#define trace(fmt,...)
@@ -193,6 +196,27 @@ typedef struct {
unsigned use_textcolor : 1;
} w_button_t;
+typedef struct {
+ ddb_gtkui_widget_t base;
+ GtkWidget *seekbar;
+ gint timer;
+ float last_songpos;
+} w_seekbar_t;
+
+typedef struct {
+ ddb_gtkui_widget_t base;
+} w_playtb_t;
+
+typedef struct {
+ ddb_gtkui_widget_t base;
+ GtkWidget *volumebar;
+} w_volumebar_t;
+
+typedef struct {
+ ddb_gtkui_widget_t base;
+ GtkWidget *voices[8];
+} w_ctvoices_t;
+
static int design_mode;
static ddb_gtkui_widget_t *rootwidget;
@@ -455,7 +479,7 @@ void
w_save (void) {
char buf[20000] = "";
save_widget_to_string (buf, sizeof (buf), rootwidget->children);
- deadbeef->conf_set_str ("gtkui.layout", buf);
+ deadbeef->conf_set_str (DDB_GTKUI_CONF_LAYOUT, buf);
deadbeef->conf_save ();
}
@@ -562,12 +586,15 @@ show_widget (GtkWidget *widget, gpointer data) {
gtk_widget_show (widget);
}
+static GtkRequisition prev_req;
+
void
w_menu_deactivate (GtkMenuShell *menushell, gpointer user_data) {
hidden = 0;
ddb_gtkui_widget_t *w = user_data;
if (GTK_IS_CONTAINER (w->widget)) {
gtk_container_foreach (GTK_CONTAINER (w->widget), show_widget, NULL);
+ gtk_widget_set_size_request (w->widget, prev_req.width, prev_req.height);
}
gtk_widget_set_app_paintable (w->widget, FALSE);
gtk_widget_queue_draw (w->widget);
@@ -582,9 +609,12 @@ w_button_press_event (GtkWidget *widget, GdkEventButton *event, gpointer user_da
current_widget = user_data;
widget = current_widget->widget;
hidden = 1;
+
if (GTK_IS_CONTAINER (widget)) {
// hide all children
+ gtk_widget_size_request (widget, &prev_req);
gtk_container_foreach (GTK_CONTAINER (widget), hide_widget, NULL);
+ gtk_widget_set_size_request (widget, prev_req.width, prev_req.height);
}
gtk_widget_set_app_paintable (widget, TRUE);
@@ -857,7 +887,7 @@ w_placeholder_create (void) {
w->base.widget = gtk_event_box_new ();
w->drawarea = gtk_drawing_area_new ();
- gtk_widget_set_size_request (w->drawarea, 20, 20);
+ gtk_widget_set_size_request (w->base.widget, 20, 20);
gtk_widget_show (w->drawarea);
gtk_container_add (GTK_CONTAINER (w->base.widget), w->drawarea);
@@ -1884,11 +1914,11 @@ w_tabbed_playlist_create (void) {
w->tabstrip = DDB_TABSTRIP (tabstrip);
gtk_widget_show (tabstrip);
GtkWidget *list = ddb_listview_new ();
+ gtk_widget_set_size_request (vbox, 100, 100);
w->plt.list = (DdbListview *)list;
gtk_widget_show (list);
gtk_box_pack_start (GTK_BOX (vbox), tabstrip, FALSE, TRUE, 0);
- gtk_widget_set_size_request (tabstrip, -1, 24);
gtk_widget_set_can_focus (tabstrip, FALSE);
gtk_widget_set_can_default (tabstrip, FALSE);
@@ -1896,7 +1926,6 @@ w_tabbed_playlist_create (void) {
main_playlist_init (list);
-// gtk_container_forall (GTK_CONTAINER (w->base.widget), w_override_signals, w);
w_override_signals (w->plt.base.widget, w);
w->plt.base.message = w_tabbed_playlist_message;
@@ -1912,6 +1941,7 @@ w_playlist_create (void) {
w->base.widget = gtk_event_box_new ();
w->list = DDB_LISTVIEW (ddb_listview_new ());
+ gtk_widget_set_size_request (GTK_WIDGET (w->base.widget), 100, 100);
w->base.save = w_playlist_save;
w->base.load = w_playlist_load;
w->base.init = w_playlist_init;
@@ -2920,8 +2950,6 @@ w_hvbox_replace (struct ddb_gtkui_widget_s *container, struct ddb_gtkui_widget_s
return;
}
- w_remove (container, c);
- w_destroy (c);
if (prev) {
prev->next = newchild;
}
@@ -2930,6 +2958,8 @@ w_hvbox_replace (struct ddb_gtkui_widget_s *container, struct ddb_gtkui_widget_s
}
newchild->next = c->next;
newchild->parent = container;
+ w_remove (container, c);
+ w_destroy (c);
gtk_box_pack_start (GTK_BOX (b->box), newchild->widget, TRUE, TRUE, 0);
gtk_widget_show (newchild->widget);
@@ -3445,3 +3475,263 @@ w_button_create (void) {
w_override_signals (w->base.widget, w);
return (ddb_gtkui_widget_t *)w;
}
+
+// seekbar
+static gboolean
+redraw_seekbar_cb (gpointer data) {
+ w_seekbar_t *w = data;
+ int iconified = gdk_window_get_state(gtk_widget_get_window(mainwin)) & GDK_WINDOW_STATE_ICONIFIED;
+ if (!gtk_widget_get_visible (mainwin) || iconified) {
+ return FALSE;
+ }
+ gtk_widget_queue_draw (w->seekbar);
+ return FALSE;
+}
+
+static gboolean
+seekbar_frameupdate (gpointer data) {
+ w_seekbar_t *w = data;
+ DB_output_t *output = deadbeef->get_output ();
+ DB_playItem_t *track = deadbeef->streamer_get_playing_track ();
+ DB_fileinfo_t *c = deadbeef->streamer_get_current_fileinfo (); // FIXME: might crash streamer
+ float songpos = w->last_songpos;
+ float duration = track ? deadbeef->pl_get_item_duration (track) : -1;
+ if (!output || (output->state () == OUTPUT_STATE_STOPPED || !track || !c)) {
+ songpos = 0;
+ }
+ else {
+ songpos = deadbeef->streamer_get_playpos ();
+ }
+ // translate pos to seekbar pixels
+ songpos /= duration;
+ GtkAllocation a;
+ gtk_widget_get_allocation (w->seekbar, &a);
+ songpos *= a.width;
+ if (fabs (songpos - w->last_songpos) > 0.01) {
+ gtk_widget_queue_draw (w->seekbar);
+ w->last_songpos = songpos;
+ }
+ if (track) {
+ deadbeef->pl_item_unref (track);
+ }
+ return TRUE;
+}
+
+static void
+w_seekbar_init (ddb_gtkui_widget_t *base) {
+ w_seekbar_t *w = (w_seekbar_t *)base;
+ if (w->timer) {
+ g_source_remove (w->timer);
+ w->timer = 0;
+ }
+
+ w->timer = g_timeout_add (1000/gtkui_get_gui_refresh_rate (), seekbar_frameupdate, w);
+}
+
+static int
+w_seekbar_message (ddb_gtkui_widget_t *w, uint32_t id, uintptr_t ctx, uint32_t p1, uint32_t p2) {
+ switch (id) {
+ case DB_EV_SONGCHANGED:
+ g_idle_add (redraw_seekbar_cb, w);
+ break;
+ case DB_EV_CONFIGCHANGED:
+ w_seekbar_init (w);
+ break;
+ }
+ return 0;
+}
+
+static void
+w_seekbar_destroy (ddb_gtkui_widget_t *wbase) {
+ w_seekbar_t *w = (w_seekbar_t *)wbase;
+ if (w->timer) {
+ g_source_remove (w->timer);
+ w->timer = 0;
+ }
+}
+
+ddb_gtkui_widget_t *
+w_seekbar_create (void) {
+ w_seekbar_t *w = malloc (sizeof (w_seekbar_t));
+ memset (w, 0, sizeof (w_seekbar_t));
+ w->base.widget = gtk_event_box_new ();
+ w->base.message = w_seekbar_message;
+ w->base.destroy = w_seekbar_destroy;
+ w->base.init = w_seekbar_init;
+ w->seekbar = ddb_seekbar_new ();
+ gtk_widget_set_size_request (w->base.widget, 20, 16);
+ w->last_songpos = -1;
+ ddb_seekbar_init_signals (DDB_SEEKBAR (w->seekbar), w->base.widget);
+ gtk_widget_show (w->seekbar);
+ gtk_container_add (GTK_CONTAINER (w->base.widget), w->seekbar);
+ w_override_signals (w->base.widget, w);
+ return (ddb_gtkui_widget_t*)w;
+}
+
+// play toolbar
+ddb_gtkui_widget_t *
+w_playtb_create (void) {
+ w_playtb_t *w = malloc (sizeof (w_playtb_t));
+ memset (w, 0, sizeof (w_playtb_t));
+ w->base.widget = gtk_hbox_new (FALSE, 0);
+ w->base.flags = DDB_GTKUI_WIDGET_FLAG_NON_EXPANDABLE;
+ gtk_widget_show (w->base.widget);
+
+ GtkWidget *stopbtn;
+ GtkWidget *image128;
+ GtkWidget *playbtn;
+ GtkWidget *image2;
+ GtkWidget *pausebtn;
+ GtkWidget *image3;
+ GtkWidget *prevbtn;
+ GtkWidget *image4;
+ GtkWidget *nextbtn;
+ GtkWidget *image5;
+
+
+ stopbtn = gtk_button_new ();
+ gtk_widget_show (stopbtn);
+ gtk_box_pack_start (GTK_BOX (w->base.widget), stopbtn, FALSE, FALSE, 0);
+ gtk_widget_set_can_focus(stopbtn, FALSE);
+ gtk_button_set_relief (GTK_BUTTON (stopbtn), GTK_RELIEF_NONE);
+
+ image128 = gtk_image_new_from_stock ("gtk-media-stop", GTK_ICON_SIZE_BUTTON);
+ gtk_widget_show (image128);
+ gtk_container_add (GTK_CONTAINER (stopbtn), image128);
+
+ playbtn = gtk_button_new ();
+ gtk_widget_show (playbtn);
+ gtk_box_pack_start (GTK_BOX (w->base.widget), playbtn, FALSE, FALSE, 0);
+ gtk_widget_set_can_focus(playbtn, FALSE);
+ gtk_button_set_relief (GTK_BUTTON (playbtn), GTK_RELIEF_NONE);
+
+ image2 = gtk_image_new_from_stock ("gtk-media-play", GTK_ICON_SIZE_BUTTON);
+ gtk_widget_show (image2);
+ gtk_container_add (GTK_CONTAINER (playbtn), image2);
+
+ pausebtn = gtk_button_new ();
+ gtk_widget_show (pausebtn);
+ gtk_box_pack_start (GTK_BOX (w->base.widget), pausebtn, FALSE, FALSE, 0);
+ gtk_widget_set_can_focus(pausebtn, FALSE);
+ gtk_button_set_relief (GTK_BUTTON (pausebtn), GTK_RELIEF_NONE);
+
+ image3 = gtk_image_new_from_stock ("gtk-media-pause", GTK_ICON_SIZE_BUTTON);
+ gtk_widget_show (image3);
+ gtk_container_add (GTK_CONTAINER (pausebtn), image3);
+
+ prevbtn = gtk_button_new ();
+ gtk_widget_show (prevbtn);
+ gtk_box_pack_start (GTK_BOX (w->base.widget), prevbtn, FALSE, FALSE, 0);
+ gtk_widget_set_can_focus(prevbtn, FALSE);
+ gtk_button_set_relief (GTK_BUTTON (prevbtn), GTK_RELIEF_NONE);
+
+ image4 = gtk_image_new_from_stock ("gtk-media-previous", GTK_ICON_SIZE_BUTTON);
+ gtk_widget_show (image4);
+ gtk_container_add (GTK_CONTAINER (prevbtn), image4);
+
+ nextbtn = gtk_button_new ();
+ gtk_widget_show (nextbtn);
+ gtk_box_pack_start (GTK_BOX (w->base.widget), nextbtn, FALSE, FALSE, 0);
+ gtk_widget_set_can_focus(nextbtn, FALSE);
+ gtk_button_set_relief (GTK_BUTTON (nextbtn), GTK_RELIEF_NONE);
+
+ image5 = gtk_image_new_from_stock ("gtk-media-next", GTK_ICON_SIZE_BUTTON);
+ gtk_widget_show (image5);
+ gtk_container_add (GTK_CONTAINER (nextbtn), image5);
+ w_override_signals (w->base.widget, w);
+
+ g_signal_connect ((gpointer) stopbtn, "clicked",
+ G_CALLBACK (on_stopbtn_clicked),
+ NULL);
+ g_signal_connect ((gpointer) playbtn, "clicked",
+ G_CALLBACK (on_playbtn_clicked),
+ NULL);
+ g_signal_connect ((gpointer) pausebtn, "clicked",
+ G_CALLBACK (on_pausebtn_clicked),
+ NULL);
+ g_signal_connect ((gpointer) prevbtn, "clicked",
+ G_CALLBACK (on_prevbtn_clicked),
+ NULL);
+ g_signal_connect ((gpointer) nextbtn, "clicked",
+ G_CALLBACK (on_nextbtn_clicked),
+ NULL);
+ return (ddb_gtkui_widget_t*)w;
+}
+
+// volumebar
+static gboolean
+redraw_volumebar_cb (gpointer data) {
+ w_volumebar_t *w = data;
+ gtk_widget_queue_draw (w->volumebar);
+ char s[100];
+ int db = deadbeef->volume_get_db ();
+ snprintf (s, sizeof (s), "%s%ddB", db < 0 ? "" : "+", db);
+ gtk_widget_set_tooltip_text (w->volumebar, s);
+ gtk_widget_trigger_tooltip_query (w->volumebar);
+ return FALSE;
+}
+
+static int
+w_volumebar_message (ddb_gtkui_widget_t *w, uint32_t id, uintptr_t ctx, uint32_t p1, uint32_t p2) {
+ switch (id) {
+ case DB_EV_CONFIGCHANGED:
+ case DB_EV_VOLUMECHANGED:
+ g_idle_add (redraw_volumebar_cb, w);
+ break;
+ }
+ return 0;
+}
+
+ddb_gtkui_widget_t *
+w_volumebar_create (void) {
+ w_volumebar_t *w = malloc (sizeof (w_volumebar_t));
+ memset (w, 0, sizeof (w_volumebar_t));
+ w->base.widget = gtk_event_box_new ();
+ w->base.message = w_volumebar_message;
+ w->volumebar = ddb_volumebar_new ();
+ ddb_volumebar_init_signals (DDB_VOLUMEBAR (w->volumebar), w->base.widget);
+ gtk_widget_show (w->volumebar);
+ gtk_widget_set_size_request (w->base.widget, 70, -1);
+ gtk_container_add (GTK_CONTAINER (w->base.widget), w->volumebar);
+ w_override_signals (w->base.widget, w);
+ return (ddb_gtkui_widget_t*)w;
+}
+
+// chiptune voice ctl
+static void
+on_voice_toggled (GtkToggleButton *togglebutton, gpointer user_data) {
+ w_ctvoices_t *w = user_data;
+ int voices = 0;
+ for (int i = 0; i < 8; i++) {
+ int active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w->voices[i]));
+ voices |= active << i;
+ }
+ deadbeef->conf_set_int ("chip.voices", voices);
+ deadbeef->sendmessage (DB_EV_CONFIGCHANGED, 0, 0, 0);
+}
+
+ddb_gtkui_widget_t *
+w_ctvoices_create (void) {
+ w_ctvoices_t *w = malloc (sizeof (w_ctvoices_t));
+ memset (w, 0, sizeof (w_ctvoices_t));
+ w->base.widget = gtk_event_box_new ();
+ GtkWidget *hbox = gtk_hbox_new (FALSE, 0);
+ gtk_widget_show (hbox);
+ gtk_container_add (GTK_CONTAINER (w->base.widget), hbox);
+
+ GtkWidget *label = gtk_label_new_with_mnemonic (_("Voices:"));
+ gtk_widget_show (label);
+ gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
+
+ int voices = deadbeef->conf_get_int ("chip.voices", 0xff);
+ for (int i = 0; i < 8; i++) {
+ w->voices[i] = gtk_check_button_new ();
+ gtk_widget_show (w->voices[i]);
+ gtk_box_pack_start (GTK_BOX (hbox), w->voices[i], FALSE, FALSE, 0);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (w->voices[i]), voices & (1<<i));
+ g_signal_connect ((gpointer) w->voices[i], "toggled", G_CALLBACK (on_voice_toggled), w);
+ }
+
+ w_override_signals (w->base.widget, w);
+ return (ddb_gtkui_widget_t*)w;
+}
diff --git a/plugins/gtkui/widgets.h b/plugins/gtkui/widgets.h
index 964fb665..8521e25d 100644
--- a/plugins/gtkui/widgets.h
+++ b/plugins/gtkui/widgets.h
@@ -122,4 +122,16 @@ w_vbox_create (void);
ddb_gtkui_widget_t *
w_button_create (void);
+ddb_gtkui_widget_t *
+w_seekbar_create (void);
+
+ddb_gtkui_widget_t *
+w_playtb_create (void);
+
+ddb_gtkui_widget_t *
+w_volumebar_create (void);
+
+ddb_gtkui_widget_t *
+w_ctvoices_create (void);
+
#endif
diff --git a/plugins/hotkeys/COPYING b/plugins/hotkeys/COPYING
new file mode 100644
index 00000000..197bfba0
--- /dev/null
+++ b/plugins/hotkeys/COPYING
@@ -0,0 +1,22 @@
+Hotkeys plugin for DeaDBeeF
+
+Copyright (C) 2009-2011 Viktor Semykin <thesame.ml@gmail.com>
+Copyright (C) 2012-2014 Alexey Yakovenko <waker@users.sourceforge.net>
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any damages
+arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source distribution.
diff --git a/plugins/hotkeys/Makefile.am b/plugins/hotkeys/Makefile.am
index 5f5fb965..2fd1ad34 100644
--- a/plugins/hotkeys/Makefile.am
+++ b/plugins/hotkeys/Makefile.am
@@ -7,5 +7,5 @@ hotkeys_la_LDFLAGS = -module -avoid-version
EXTRA_hotkeys_la_SOURCES = keysyms.inc
hotkeys_la_LIBADD = $(LDADD) $(HOTKEYS_LIBS)
-AM_CFLAGS = $(CFLAGS) -std=c99
+AM_CFLAGS = $(CFLAGS) $(HOTKEYS_CFLAGS) -std=c99
endif
diff --git a/plugins/hotkeys/hotkeys.c b/plugins/hotkeys/hotkeys.c
index c8d1fa67..f1deaac8 100644
--- a/plugins/hotkeys/hotkeys.c
+++ b/plugins/hotkeys/hotkeys.c
@@ -3,18 +3,23 @@
Copyright (C) 2009-2011 Viktor Semykin <thesame.ml@gmail.com>
Copyright (C) 2012-2013 Alexey Yakovenko <waker@users.sourceforge.net>
- 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, see <http://www.gnu.org/licenses/>.
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+
+ 3. This notice may not be removed or altered from any source distribution.
*/
#include <stdio.h>
#include <stdlib.h>
@@ -740,6 +745,15 @@ action_toggle_stop_after_current_cb (struct DB_plugin_action_s *action, int ctx)
return 0;
}
+int
+action_toggle_stop_after_album_cb (struct DB_plugin_action_s *action, int ctx) {
+ int var = deadbeef->conf_get_int ("playlist.stop_after_album", 0);
+ var = 1 - var;
+ deadbeef->conf_set_int ("playlist.stop_after_album", var);
+ deadbeef->sendmessage (DB_EV_CONFIGCHANGED, 0, 0, 0);
+ return 0;
+}
+
static DB_plugin_action_t action_reload_metadata = {
.title = "Reload Metadata",
.name = "reload_metadata",
@@ -1053,10 +1067,18 @@ static DB_plugin_action_t action_toggle_stop_after_current = {
.next = &action_volume_down
};
+static DB_plugin_action_t action_toggle_stop_after_album = {
+ .title = "Playback/Toggle Stop After Current Album",
+ .name = "toggle_stop_after_album",
+ .flags = DB_ACTION_COMMON,
+ .callback2 = action_toggle_stop_after_album_cb,
+ .next = &action_toggle_stop_after_current
+};
+
static DB_plugin_action_t *
hotkeys_get_actions (DB_playItem_t *it)
{
- return &action_toggle_stop_after_current;
+ return &action_toggle_stop_after_album;
}
// define plugin interface
diff --git a/plugins/hotkeys/hotkeys.h b/plugins/hotkeys/hotkeys.h
index cfc12108..7c7171f3 100644
--- a/plugins/hotkeys/hotkeys.h
+++ b/plugins/hotkeys/hotkeys.h
@@ -1,21 +1,25 @@
/*
- DeaDBeeF - ultimate music player for GNU/Linux systems with X11
- Copyright (C) 2009-2011 Alexey Yakovenko <waker@users.sourceforge.net>
+ Hotkeys plugin for DeaDBeeF
+ Copyright (C) 2009-2011 Viktor Semykin <thesame.ml@gmail.com>
Copyright (C) 2012-2013 Alexey Yakovenko <waker@users.sourceforge.net>
- 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.
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+
+ 3. This notice may not be removed or altered from any source distribution.
*/
#ifndef __HOTKEYS_H
#define __HOTKEYS_H
diff --git a/plugins/lastfm/lastfm.c b/plugins/lastfm/lastfm.c
index 2750cfb2..a7443e1c 100644
--- a/plugins/lastfm/lastfm.c
+++ b/plugins/lastfm/lastfm.c
@@ -68,6 +68,7 @@ static char lfm_nowplaying[2048]; // packet for nowplaying, or ""
typedef struct {
DB_playItem_t *it;
time_t started_timestamp;
+ float playtime;
} subm_item_t;
static subm_item_t lfm_subm_queue[LFM_SUBMISSION_QUEUE_SIZE];
@@ -278,7 +279,7 @@ auth (void) {
end++;
}
if (end - p > sizeof (lfm_nowplaying_url)-1) {
- trace ("scrobbler nowplaying url is too long:\n", lfm_reply);
+ trace ("scrobbler nowplaying url is too long %d:\n", (int)(end-p));
goto fail;
}
strncpy (lfm_nowplaying_url, p, end-p);
@@ -299,7 +300,7 @@ auth (void) {
end++;
}
if (end - p > sizeof (lfm_submission_url)-1) {
- trace ("scrobbler submission url is too long:\n", lfm_reply);
+ trace ("scrobbler submission url is too long: %d\n", (int)(end-p));
goto fail;
}
strncpy (lfm_submission_url, p, end-p);
@@ -322,7 +323,7 @@ fail:
}
static int
-lfm_fetch_song_info (DB_playItem_t *song, char *a, char *t, char *b, float *l, char *n, char *m) {
+lfm_fetch_song_info (DB_playItem_t *song, float playtime, char *a, char *t, char *b, float *l, char *n, char *m) {
if (deadbeef->conf_get_int ("lastfm.prefer_album_artist", 0)) {
if (!deadbeef->pl_get_meta (song, "band", a, META_FIELD_SIZE)) {
if (!deadbeef->pl_get_meta (song, "album artist", a, META_FIELD_SIZE)) {
@@ -352,10 +353,13 @@ lfm_fetch_song_info (DB_playItem_t *song, char *a, char *t, char *b, float *l, c
*b = 0;
}
*l = deadbeef->pl_get_item_duration (song);
+ if (*l <= 0) {
+ *l = playtime;
+ }
if (!deadbeef->pl_get_meta (song, "track", n, META_FIELD_SIZE)) {
*n = 0;
}
- if (!deadbeef->pl_get_meta (song, "mbid", m, META_FIELD_SIZE)) {
+ if (!deadbeef->pl_get_meta (song, "musicbrainz_trackid", m, META_FIELD_SIZE)) {
*m = 0;
}
return 0;
@@ -433,7 +437,7 @@ lfm_add_keyvalue_uri_encoded (char **out, int *outl, const char *key, const char
// subm is submission idx, or -1 for nowplaying
// returns number of bytes added, or -1
static int
-lfm_format_uri (int subm, DB_playItem_t *song, char *out, int outl, time_t started_timestamp) {
+lfm_format_uri (int subm, DB_playItem_t *song, char *out, int outl, time_t started_timestamp, float playtime) {
if (subm > 50) {
trace ("lastfm: it's only allowed to send up to 50 submissions at once (got idx=%d)\n", subm);
return -1;
@@ -462,7 +466,7 @@ lfm_format_uri (int subm, DB_playItem_t *song, char *out, int outl, time_t start
strcpy (km+1, ka+1);
}
- if (lfm_fetch_song_info (song, a, t, b, &l, n, m) == 0) {
+ if (lfm_fetch_song_info (song, playtime, a, t, b, &l, n, m) == 0) {
// trace ("playtime: %f\nartist: %s\ntitle: %s\nalbum: %s\nduration: %f\ntracknum: %s\n---\n", song->playtime, a, t, b, l, n);
}
else {
@@ -518,7 +522,7 @@ lastfm_songstarted (ddb_event_track_t *ev, uintptr_t data) {
return 0;
}
deadbeef->mutex_lock (lfm_mutex);
- if (lfm_format_uri (-1, ev->track, lfm_nowplaying, sizeof (lfm_nowplaying), ev->started_timestamp) < 0) {
+ if (lfm_format_uri (-1, ev->track, lfm_nowplaying, sizeof (lfm_nowplaying), ev->started_timestamp, 120) < 0) {
lfm_nowplaying[0] = 0;
}
// trace ("%s\n", lfm_nowplaying);
@@ -542,13 +546,14 @@ lastfm_songchanged (ddb_event_trackchange_t *ev, uintptr_t data) {
trace ("lfm songfinished %s\n", deadbeef->pl_find_meta (ev->from, ":URI"));
#if !LFM_IGNORE_RULES
// check submission rules
- // duration must be >= 30 sec
- if (deadbeef->pl_get_item_duration (ev->from) < 30) {
- trace ("track duration is %f seconds. not eligible for submission\n", deadbeef->pl_get_item_duration (ev->from));
+ // duration/playtime must be >= 30 sec
+ float dur = deadbeef->pl_get_item_duration (ev->from);
+ if (dur < 30 && ev->playtime < 30) {
+ trace ("track duration is %f sec, playtime if %f sec. not eligible for submission\n", dur, ev->playtime);
return 0;
}
- // must be played for >=240sec of half the total time
- if (ev->playtime < 240 && ev->playtime < deadbeef->pl_get_item_duration (ev->from)/2) {
+ // must be played for >=240sec or half the total time
+ if (ev->playtime < 240 && ev->playtime < dur/2) {
trace ("track playtime=%f seconds. not eligible for submission\n", ev->playtime);
return 0;
}
@@ -568,6 +573,7 @@ lastfm_songchanged (ddb_event_trackchange_t *ev, uintptr_t data) {
trace ("lfm: song is now in queue for submission\n");
lfm_subm_queue[i].it = ev->from;
lfm_subm_queue[i].started_timestamp = ev->started_timestamp;
+ lfm_subm_queue[i].playtime = ev->playtime;
deadbeef->pl_item_ref (ev->from);
break;
}
@@ -634,7 +640,7 @@ lfm_send_submissions (void) {
deadbeef->mutex_lock (lfm_mutex);
for (i = 0; i < LFM_SUBMISSION_QUEUE_SIZE; i++) {
if (lfm_subm_queue[i].it) {
- res = lfm_format_uri (idx, lfm_subm_queue[i].it, r, len, lfm_subm_queue[i].started_timestamp);
+ res = lfm_format_uri (idx, lfm_subm_queue[i].it, r, len, lfm_subm_queue[i].started_timestamp, lfm_subm_queue[i].playtime);
if (res < 0) {
trace ("lfm: failed to format uri\n");
return;
diff --git a/plugins/mpgmad/Makefile.am b/plugins/mpgmad/Makefile.am
index 814b81e4..a4ae3aca 100644
--- a/plugins/mpgmad/Makefile.am
+++ b/plugins/mpgmad/Makefile.am
@@ -5,5 +5,5 @@ mpgmad_la_SOURCES = mpgmad.c
mpgmad_la_LDFLAGS = -module -avoid-version
mpgmad_la_LIBADD = $(LDADD) $(MAD_LIBS)
-AM_CFLAGS = $(CFLAGS) -std=c99 -fPIC
+AM_CFLAGS = $(CFLAGS) $(MAD_CFLAGS) -std=c99 -fPIC
endif
diff --git a/plugins/mpgmad/mpgmad.c b/plugins/mpgmad/mpgmad.c
index b450ffbc..c5f67ef3 100644
--- a/plugins/mpgmad/mpgmad.c
+++ b/plugins/mpgmad/mpgmad.c
@@ -238,6 +238,8 @@ cmp3_scan_stream (buffer_t *buffer, int sample) {
}
for (;;) {
+ uint32_t hdr;
+ uint8_t sync;
// {{{ parse frame header, sync stream
// mp3 files often have some garbage in the beginning
// try to skip it if this is the case
@@ -254,12 +256,18 @@ cmp3_scan_stream (buffer_t *buffer, int sample) {
break; // eof
}
- uint32_t hdr;
- uint8_t sync = fb[0];
+retry_sync:
+
+ sync = fb[0];
if (sync != 0xff) {
// trace ("[1]frame %d didn't seek to frame end\n", nframe);
lastframe_valid = 0;
- continue; // not an mpeg frame
+ memmove (fb, fb+1, 3);
+ if (deadbeef->fread (fb+3, 1, 1, buffer->file) != 1) {
+ break; // eof
+ }
+ offs++;
+ goto retry_sync; // not an mpeg frame
}
else {
// 2nd sync byte
@@ -267,7 +275,12 @@ cmp3_scan_stream (buffer_t *buffer, int sample) {
if ((sync >> 5) != 7) {
// trace ("[2]frame %d didn't seek to frame end\n", nframe);
lastframe_valid = 0;
- continue;
+ memmove (fb, fb+1, 3);
+ if (deadbeef->fread (fb+3, 1, 1, buffer->file) != 1) {
+ break; // eof
+ }
+ offs++;
+ goto retry_sync; // not an mpeg frame
}
}
// found frame
@@ -839,14 +852,6 @@ cmp3_init (DB_fileinfo_t *_info, DB_playItem_t *it) {
}
else {
deadbeef->fset_track (info->buffer.file, it);
- int64_t len = deadbeef->fgetlength (info->buffer.file);
- if (len > 0) {
- deadbeef->pl_delete_all_meta (it);
- int v2err = deadbeef->junk_id3v2_read (it, info->buffer.file);
- if (v2err != 0) {
- deadbeef->fseek (info->buffer.file, 0, SEEK_SET);
- }
- }
deadbeef->pl_add_meta (it, "title", NULL);
int res = cmp3_scan_stream (&info->buffer, 0);
if (res < 0) {
diff --git a/plugins/pltbrowser/Makefile.am b/plugins/pltbrowser/Makefile.am
index ddd396c3..ffcc610e 100644
--- a/plugins/pltbrowser/Makefile.am
+++ b/plugins/pltbrowser/Makefile.am
@@ -20,7 +20,7 @@ pltbrowser_gtk2_la_LDFLAGS = -module -avoid-version
if STATICLINK
GTK_ROOT=@top_srcdir@/$(LIB)/gtk-2.12.12/usr
-pltbrowser_gtk2_la_LIBADD = $(LDADD) -L$(GTK_ROOT)/lib $(GTK_ROOT)/lib/libgtk-x11-2.0.la $(GTK_ROOT)/lib/libgdk-x11-2.0.la $(GTK_ROOT)/lib/libpangoft2-1.0.la $(GTK_ROOT)/lib/libpangocairo-1.0.la $(GTK_ROOT)/lib/libgdk_pixbuf-2.0.la -lm $(GTK_ROOT)/lib/libcairo.la $(GTK_ROOT)/lib/libpango-1.0.la $(GTK_ROOT)/lib/libgobject-2.0.la $(GTK_ROOT)/lib/libgmodule-2.0.la $(GTK_ROOT)/lib/libgthread-2.0.la -lrt $(GTK_ROOT)/lib/libglib-2.0.la
+pltbrowser_gtk2_la_LIBADD = $(LDADD) -L$(GTK_ROOT)/lib -lgtk-x11-2.0 -lgdk-x11-2.0 -latk-1.0 -lgdk_pixbuf-2.0 -lm -lpangocairo-1.0 -lpango-1.0 -lcairo -lgobject-2.0 -lgmodule-2.0 -ldl -lglib-2.0 -lrt
pltbrowser_gtk2_la_CFLAGS = -std=c99 -I $(GTK_ROOT)/include -I $(GTK_ROOT)/lib/gtk-2.0/include -I $(GTK_ROOT)/include/glib-2.0 -I $(GTK_ROOT)/include/gtk-2.0 -I $(GTK_ROOT)/include/cairo -I $(GTK_ROOT)/lib/glib-2.0/include/ -I $(GTK_ROOT)/include/pango-1.0 -I $(GTK_ROOT)/include/atk-1.0 -DULTRA_COMPATIBLE=1
else
@@ -32,17 +32,8 @@ endif
if HAVE_GTK3
pltbrowser_gtk3_la_SOURCES = pltbrowser.c
pltbrowser_gtk3_la_LDFLAGS = -module -avoid-version
-if STATICLINK
-GTK_ROOT_300=@top_srcdir@/$(LIB)/gtk-3.0.0
-
-pltbrowser_gtk3_la_LIBADD = $(LDADD) -L$(GTK_ROOT_300)/lib -lgtk-3 -lgdk-3 -latk-1.0 -lgio-2.0 -lpangocairo-1.0 -lgdk_pixbuf-2.0 -lcairo-gobject -lpango-1.0 -lcairo -lgobject-2.0 -lglib-2.0 -lfreetype $(SM_LIBADD)
-
-pltbrowser_gtk3_la_CFLAGS = -std=c99 -I$(GTK_ROOT_300)/include/gtk-3.0 -I$(GTK_ROOT_300)/include/pango-1.0 -I$(GTK_ROOT_300)/include/gio-unix-2.0/ -I$(GTK_ROOT_300)/include/atk-1.0 -I$(GTK_ROOT_300)/include/cairo -I$(GTK_ROOT_300)/include/gdk-pixbuf-2.0 -I$(GTK_ROOT_300)/include/freetype2 -I$(GTK_ROOT_300)/include/glib-2.0 -I$(GTK_ROOT_300)/lib/glib-2.0/include $(SM_CFLAGS)
-
-else
pltbrowser_gtk3_la_LIBADD = $(LDADD) $(GTK3_DEPS_LIBS)
pltbrowser_gtk3_la_CFLAGS = -std=c99 $(GTK3_DEPS_CFLAGS)
endif
-endif
endif
diff --git a/plugins/shellexec/shellexec.c b/plugins/shellexec/shellexec.c
index 473fc1a7..3894b6b4 100644
--- a/plugins/shellexec/shellexec.c
+++ b/plugins/shellexec/shellexec.c
@@ -88,6 +88,24 @@ static int shx_exec_track_cmd (Shx_action_t *action, DB_playItem_t *it) {
return -1;
}
strcat (cmd, "&");
+
+ // replace \' with '"'"'
+ size_t l = strlen (cmd);
+ size_t remaining = _POSIX_ARG_MAX - l - 1;
+ for (int i = 0; cmd[i]; i++) {
+ if (cmd[i] == '\\' && cmd[i+1] == '\'' && remaining >= 3) {
+ memmove (&cmd[i+5], &cmd[i+2], l - i + 1 - 2);
+ memcpy (&cmd[i], "'\"'\"'", 5);
+ l += 3;
+ remaining -= 3;
+ i += 5;
+ }
+ else if (remaining < 3) {
+ fprintf (stderr, "shellexec: command is too long.\n");
+ return -1;
+ }
+ }
+
trace ("%s\n", cmd);
res = system (cmd);
return 0;
diff --git a/plugins/shellexecui/Makefile.am b/plugins/shellexecui/Makefile.am
index ee15f428..22d84e57 100644
--- a/plugins/shellexecui/Makefile.am
+++ b/plugins/shellexecui/Makefile.am
@@ -22,7 +22,7 @@ shellexecui_gtk2_la_LDFLAGS = -module -avoid-version
if STATICLINK
GTK_ROOT=@top_srcdir@/$(LIB)/gtk-2.12.12/usr
-shellexecui_gtk2_la_LIBADD = $(LDADD) -L$(GTK_ROOT)/lib $(GTK_ROOT)/lib/libgtk-x11-2.0.la $(GTK_ROOT)/lib/libgdk-x11-2.0.la $(GTK_ROOT)/lib/libpangoft2-1.0.la $(GTK_ROOT)/lib/libpangocairo-1.0.la $(GTK_ROOT)/lib/libgdk_pixbuf-2.0.la -lm $(GTK_ROOT)/lib/libcairo.la $(GTK_ROOT)/lib/libpango-1.0.la $(GTK_ROOT)/lib/libgobject-2.0.la $(GTK_ROOT)/lib/libgmodule-2.0.la $(GTK_ROOT)/lib/libgthread-2.0.la -lrt $(GTK_ROOT)/lib/libglib-2.0.la
+shellexecui_gtk2_la_LIBADD = $(LDADD) -L$(GTK_ROOT)/lib -lgtk-x11-2.0 -lgdk-x11-2.0 -latk-1.0 -lgdk_pixbuf-2.0 -lm -lpangocairo-1.0 -lpango-1.0 -lcairo -lgobject-2.0 -lgmodule-2.0 -ldl -lglib-2.0 -lrt
shellexecui_gtk2_la_CFLAGS = -std=c99 -I $(GTK_ROOT)/include -I $(GTK_ROOT)/lib/gtk-2.0/include -I $(GTK_ROOT)/include/glib-2.0 -I $(GTK_ROOT)/include/gtk-2.0 -I $(GTK_ROOT)/include/cairo -I $(GTK_ROOT)/lib/glib-2.0/include/ -I $(GTK_ROOT)/include/pango-1.0 -I $(GTK_ROOT)/include/atk-1.0 -DULTRA_COMPATIBLE=1
else
@@ -34,18 +34,9 @@ endif
if HAVE_GTK3
shellexecui_gtk3_la_SOURCES = shellexecui.c interface.c support.c callbacks.c interface.h support.h callbacks.h
shellexecui_gtk3_la_LDFLAGS = -module -avoid-version
-if STATICLINK
-GTK_ROOT_300=@top_srcdir@/$(LIB)/gtk-3.0.0
-
-shellexecui_gtk3_la_LIBADD = $(LDADD) -L$(GTK_ROOT_300)/lib -lgtk-3 -lgdk-3 -latk-1.0 -lgio-2.0 -lpangocairo-1.0 -lgdk_pixbuf-2.0 -lcairo-gobject -lpango-1.0 -lcairo -lgobject-2.0 -lglib-2.0 -lfreetype $(SM_LIBADD)
-
-shellexecui_gtk3_la_CFLAGS = -std=c99 -I$(GTK_ROOT_300)/include/gtk-3.0 -I$(GTK_ROOT_300)/include/pango-1.0 -I$(GTK_ROOT_300)/include/gio-unix-2.0/ -I$(GTK_ROOT_300)/include/atk-1.0 -I$(GTK_ROOT_300)/include/cairo -I$(GTK_ROOT_300)/include/gdk-pixbuf-2.0 -I$(GTK_ROOT_300)/include/freetype2 -I$(GTK_ROOT_300)/include/glib-2.0 -I$(GTK_ROOT_300)/lib/glib-2.0/include $(SM_CFLAGS)
-
-else
shellexecui_gtk3_la_LIBADD = $(LDADD) $(GTK3_DEPS_LIBS)
shellexecui_gtk3_la_CFLAGS = -std=c99 $(GTK3_DEPS_CFLAGS)
endif
-endif
endif
diff --git a/plugins/sid/csid.cpp b/plugins/sid/csid.cpp
index 5eb717b6..c4b2744b 100644
--- a/plugins/sid/csid.cpp
+++ b/plugins/sid/csid.cpp
@@ -48,8 +48,6 @@ typedef struct {
float duration; // of the current song
} sid_info_t;
-static uint32_t csid_voicemask;
-
static inline void
le_int16 (int16_t in, unsigned char *out) {
char *pin = (char *)&in;
@@ -78,6 +76,9 @@ static int sldb_loaded;
static sldb_t *sldb;
static int sldb_disable;
+static int chip_voices = 0xff;
+static int chip_voices_changed = 0;
+
static void
sldb_load()
{
@@ -279,6 +280,20 @@ csid_open (uint32_t hints) {
return _info;
}
+static void
+csid_mute_voices (sid_info_t *info, int chip_voices) {
+ int maxsids = info->sidplay->info ().maxsids;
+ for (int k = 0; k < maxsids; k++) {
+ sidemu *emu = info->resid->getsidemu (k);
+ if (emu) {
+ for (int i = 0; i < 3; i++) {
+ bool mute = chip_voices & (1 << i) ? false : true;
+ emu->voice (i, mute ? 0x00 : 0xff, mute);
+ }
+ }
+ }
+}
+
int
csid_init (DB_fileinfo_t *_info, DB_playItem_t *it) {
sid_info_t *info = (sid_info_t *)_info;
@@ -328,16 +343,8 @@ csid_init (DB_fileinfo_t *_info, DB_playItem_t *it) {
_info->fmt.channelmask = _info->fmt.channels == 1 ? DDB_SPEAKER_FRONT_LEFT : (DDB_SPEAKER_FRONT_LEFT | DDB_SPEAKER_FRONT_RIGHT);
_info->readpos = 0;
- int maxsids = info->sidplay->info ().maxsids;
- for (int k = 0; k < maxsids; k++) {
- sidemu *emu = info->resid->getsidemu (k);
- if (emu) {
- for (int i = 0; i < 3; i++) {
- bool mute = csid_voicemask & (1 << i) ? true : false;
- emu->voice (i, mute ? 0x00 : 0xff, mute);
- }
- }
- }
+ chip_voices = deadbeef->conf_get_int ("chip.voices", 0xff);
+ csid_mute_voices (info, chip_voices);
return 0;
}
@@ -359,6 +366,12 @@ csid_read (DB_fileinfo_t *_info, char *bytes, int size) {
return 0;
}
+ if (chip_voices_changed) {
+ chip_voices = deadbeef->conf_get_int ("chip.voices", 0xff);
+ chip_voices_changed = 0;
+ csid_mute_voices (info, chip_voices);
+ }
+
int rd = info->sidplay->play (bytes, size);
int samplesize = (_info->fmt.bps>>3) * _info->fmt.channels;
@@ -549,32 +562,6 @@ csid_insert (ddb_playlist_t *plt, DB_playItem_t *after, const char *fname) {
return after;
}
-#if 0
-int
-csid_numvoices (DB_fileinfo_t *_info) {
- return 3;
-}
-
-void
-csid_mutevoice (DB_fileinfo_t *_info, int voice, int mute) {
- sid_info_t *info = (sid_info_t *)_info;
- csid_voicemask &= ~ (1<<voice);
- csid_voicemask |= ((mute ? 1 : 0) << voice);
- if (info->resid) {
- int maxsids = info->sidplay->info ().maxsids;
- for (int k = 0; k < maxsids; k++) {
- sidemu *emu = info->resid->getsidemu (k);
- if (emu) {
- for (int i = 0; i < 3; i++) {
- bool mute = csid_voicemask & (1 << i) ? true : false;
- emu->voice (i, mute ? 0x00 : 0xff, mute);
- }
- }
- }
- }
-}
-#endif
-
static int
sid_configchanged (void) {
int conf_hvsc_enable = deadbeef->conf_get_int ("hvsc_enable", 0);
@@ -590,6 +577,10 @@ sid_configchanged (void) {
sldb_loaded = 0;
}
+ if (chip_voices != deadbeef->conf_get_int ("chip.voices", 0xff)) {
+ chip_voices_changed = 1;
+ }
+
return 0;
}
diff --git a/plugins/sndfile/Makefile.am b/plugins/sndfile/Makefile.am
index d0116c64..10aca7ef 100644
--- a/plugins/sndfile/Makefile.am
+++ b/plugins/sndfile/Makefile.am
@@ -5,5 +5,5 @@ sndfile_la_SOURCES = sndfile.c
sndfile_la_LDFLAGS = -module -avoid-version
sndfile_la_LIBADD = $(LDADD) $(SNDFILE_LIBS)
-AM_CFLAGS = $(CFLAGS) -std=c99
+AM_CFLAGS = $(CFLAGS) $(WAVPACK_CFLAGS) -std=c99
endif
diff --git a/plugins/vfs_curl/vfs_curl.c b/plugins/vfs_curl/vfs_curl.c
index c3ae2537..a9aaebc2 100644
--- a/plugins/vfs_curl/vfs_curl.c
+++ b/plugins/vfs_curl/vfs_curl.c
@@ -75,6 +75,9 @@ typedef struct {
char http_err[CURL_ERROR_SIZE];
+ float prev_playtime;
+ time_t started_timestamp;
+
// flags (bitfields to save some space)
unsigned seektoend : 1; // indicates that next tell must return length
unsigned gotheader : 1; // tells that all headers (including ICY) were processed (to start reading body)
@@ -205,6 +208,14 @@ http_parse_shoutcast_meta (HTTP_FILE *fp, const char *meta, int size) {
int songstarted = 0;
char *tit = strstr (title, " - ");
deadbeef->pl_lock ();
+ int emulate_trackchange = deadbeef->conf_get_int ("vfs_curl.emulate_trackchange", 0);
+ // create dummy track with previous meta
+ DB_playItem_t *from = NULL;
+ if (emulate_trackchange) {
+ from = deadbeef->pl_item_alloc ();
+ deadbeef->pl_items_copy_junk (fp->track, from, from);
+ }
+
if (tit) {
*tit = 0;
tit += 3;
@@ -224,6 +235,7 @@ http_parse_shoutcast_meta (HTTP_FILE *fp, const char *meta, int size) {
else {
const char *orig_title = deadbeef->pl_find_meta (fp->track, "title");
if (!orig_title || strcasecmp (orig_title, title)) {
+ deadbeef->pl_delete_meta (fp->track, "artist");
vfs_curl_set_meta (fp->track, "title", title);
songstarted = 1;
}
@@ -236,12 +248,34 @@ http_parse_shoutcast_meta (HTTP_FILE *fp, const char *meta, int size) {
}
deadbeef->sendmessage (DB_EV_PLAYLISTCHANGED, 0, 0, 0);
if (songstarted) {
+
+ float playpos = deadbeef->streamer_get_playpos ();
+ if (emulate_trackchange)
+ {
+ ddb_event_trackchange_t *ev = (ddb_event_trackchange_t *)deadbeef->event_alloc (DB_EV_SONGCHANGED);
+
+ ev->from = from;
+ ev->to = fp->track;
+ ev->playtime = playpos - fp->prev_playtime;
+ ev->started_timestamp = fp->started_timestamp;
+ deadbeef->pl_item_ref (ev->from);
+ deadbeef->pl_item_ref (ev->to);
+ deadbeef->event_send ((ddb_event_t *)ev, 0, 0);
+ }
+
ddb_event_track_t *ev = (ddb_event_track_t *)deadbeef->event_alloc (DB_EV_SONGSTARTED);
ev->track = fp->track;
+ fp->started_timestamp = time(NULL);
+ ev->started_timestamp = fp->started_timestamp;
if (ev->track) {
deadbeef->pl_item_ref (ev->track);
}
deadbeef->event_send ((ddb_event_t *)ev, 0, 0);
+ fp->prev_playtime = playpos;
+ }
+ if (from) {
+ deadbeef->pl_item_unref (from);
+ from = NULL;
}
}
return 0;
@@ -1089,7 +1123,10 @@ http_is_streaming (void) {
return 1;
}
-// standard stdio vfs
+static const char settings_dlg[] =
+ "property \"Emulate track change events (for scrobbling)\" checkbox vfs_curl.emulate_trackchange 0;\n"
+;
+
static DB_vfs_t plugin = {
.plugin.api_vmajor = 1,
.plugin.api_vminor = 0,
@@ -1119,6 +1156,7 @@ static DB_vfs_t plugin = {
.plugin.website = "http://deadbeef.sf.net",
.plugin.start = vfs_curl_start,
.plugin.stop = vfs_curl_stop,
+ .plugin.configdialog = settings_dlg,
.open = http_open,
.set_track = http_set_track,
.close = http_close,
diff --git a/plugins/vfs_zip/Makefile.am b/plugins/vfs_zip/Makefile.am
index a2394e11..579baf58 100644
--- a/plugins/vfs_zip/Makefile.am
+++ b/plugins/vfs_zip/Makefile.am
@@ -5,5 +5,5 @@ vfs_zip_la_SOURCES = vfs_zip.c
vfs_zip_la_LDFLAGS = -module -avoid-version
vfs_zip_la_LIBADD = $(LDADD) $(ZLIB_LIBS) $(ZIP_LIBS)
-AM_CFLAGS = $(CFLAGS) -std=c99
+AM_CFLAGS = $(CFLAGS) $(ZLIB_CFLAGS) $(ZIP_CFLAGS) -std=c99
endif
diff --git a/plugins/vfs_zip/vfs_zip.c b/plugins/vfs_zip/vfs_zip.c
index 2f84dc31..087d8366 100644
--- a/plugins/vfs_zip/vfs_zip.c
+++ b/plugins/vfs_zip/vfs_zip.c
@@ -31,6 +31,8 @@
static DB_functions_t *deadbeef;
static DB_vfs_t plugin;
+#define ZIP_BUFFER_SIZE 8192
+
typedef struct {
DB_FILE file;
struct zip* z;
@@ -38,6 +40,10 @@ typedef struct {
int64_t offset;
int index;
int64_t size;
+
+ uint8_t buffer[ZIP_BUFFER_SIZE];
+ int buffer_remaining;
+ int buffer_pos;
} zip_file_t;
static const char *scheme_names[] = { "zip://", NULL };
@@ -99,6 +105,7 @@ vfs_zip_open (const char *fname) {
f->zf = zf;
f->index = st.index;
f->size = st.size;
+ trace ("vfs_zip: end open %s\n", fname);
return (DB_FILE*)f;
}
@@ -118,14 +125,34 @@ vfs_zip_close (DB_FILE *f) {
size_t
vfs_zip_read (void *ptr, size_t size, size_t nmemb, DB_FILE *f) {
zip_file_t *zf = (zip_file_t *)f;
- ssize_t rb = zip_fread (zf->zf, ptr, size * nmemb);
- zf->offset += rb;
- return rb / size;
+// printf ("read: %d\n", size*nmemb);
+
+ int sz = size * nmemb;
+ while (sz) {
+ if (zf->buffer_remaining == 0) {
+ zf->buffer_pos = 0;
+ int rb = zip_fread (zf->zf, zf->buffer, ZIP_BUFFER_SIZE);
+ if (rb <= 0) {
+ break;
+ }
+ zf->buffer_remaining = rb;
+ }
+ int from_buf = min (sz, zf->buffer_remaining);
+ memcpy (ptr, zf->buffer+zf->buffer_pos, from_buf);
+ zf->buffer_remaining -= from_buf;
+ zf->buffer_pos += from_buf;
+ zf->offset += from_buf;
+ sz -= from_buf;
+ ptr += from_buf;
+ }
+
+ return (size * nmemb - sz) / size;
}
int
vfs_zip_seek (DB_FILE *f, int64_t offset, int whence) {
zip_file_t *zf = (zip_file_t *)f;
+// printf ("seek: %lld (%d)\n", offset, whence);
if (whence == SEEK_CUR) {
offset = zf->offset + offset;
@@ -134,6 +161,34 @@ vfs_zip_seek (DB_FILE *f, int64_t offset, int whence) {
offset = zf->size + offset;
}
+ int64_t offs = offset - zf->offset;
+ if ((offs < 0 && -offs <= zf->buffer_pos) || (offs >= 0 && offs < zf->buffer_remaining)) {
+ if (offs != 0) {
+ //printf ("cache success\n");
+
+ //printf ("[before] absoffs: %lld, offs: %lld, rem: %d, pos: %d\n", offset, offs, zf->buffer_remaining, zf->buffer_pos);
+
+ // test cases:
+ // fail: offs = -3, pos = 0, rem = 100
+ // fail: offs = 10, pos = 95, rem = 5
+ // succ: offs = -3, pos = 3, rem = 97 ----> pos = 0, rem=100
+ // succ: offs = 10, pos = 0, rem = 100 ---> pos = 10, rem = 90
+
+ zf->buffer_pos += offs;
+ zf->buffer_remaining -= offs;
+ //printf ("[after] offs: %lld, rem: %d, pos: %d\n", offs, zf->buffer_remaining, zf->buffer_pos);
+ zf->offset = offset;
+ return 0;
+ }
+ else {
+// printf ("cache double success\n");
+ return 0;
+ }
+ }
+// else {
+// printf ("cache miss: abs_offs: %lld, offs: %lld, rem: %d, pos: %d\n", offset, offs, zf->buffer_remaining, zf->buffer_pos);
+// }
+
if (offset < zf->offset) {
// reopen
zip_fclose (zf->zf);
@@ -143,6 +198,8 @@ vfs_zip_seek (DB_FILE *f, int64_t offset, int whence) {
}
zf->offset = 0;
}
+ zf->buffer_pos = 0;
+ zf->buffer_remaining = 0;
char buf[4096];
int64_t n = offset - zf->offset;
while (n > 0) {
@@ -174,6 +231,7 @@ vfs_zip_rewind (DB_FILE *f) {
zf->zf = zip_fopen_index (zf->z, zf->index, 0);
assert (zf->zf); // FIXME: better error handling?
zf->offset = 0;
+ zf->buffer_remaining = 0;
}
int64_t
diff --git a/plugins/vorbis/COPYING b/plugins/vorbis/COPYING
new file mode 100644
index 00000000..f076a6a0
--- /dev/null
+++ b/plugins/vorbis/COPYING
@@ -0,0 +1,55 @@
+OggVorbis plugin for DeaDBeeF
+Copyright (C) 2009-2014 Alexey Yakovenko et al.
+
+vcedit.c - ogg tagging library
+Copyright (C) 2014 Ian Nartowicz <deadbeef@nartowicz.co.uk>
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any damages
+arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source distribution.
+
+
+
+Uses libogg,libvorbis Copyright (c) 2002, Xiph.org Foundation
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+- Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+
+- Neither the name of the DeaDBeeF Player nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/plugins/vorbis/i18n.h b/plugins/vorbis/i18n.h
deleted file mode 100644
index 86248307..00000000
--- a/plugins/vorbis/i18n.h
+++ /dev/null
@@ -1,18 +0,0 @@
-#ifndef VORBIS_TOOLS_I18N_H
-#define VORBIS_TOOLS_I18N_H
-
-#ifdef ENABLE_NLS
-#include <libintl.h>
-#define _(X) gettext(X)
-#else
-#define _(X) (X)
-#define textdomain(X)
-#define bindtextdomain(X, Y)
-#endif
-#ifdef gettext_noop
-#define N_(X) gettext_noop(X)
-#else
-#define N_(X) (X)
-#endif
-
-#endif
diff --git a/plugins/vorbis/vcedit.c b/plugins/vorbis/vcedit.c
index 2300b3da..5709f89c 100644
--- a/plugins/vorbis/vcedit.c
+++ b/plugins/vorbis/vcedit.c
@@ -1,880 +1,285 @@
-/* This program is licensed under the GNU Library General Public License, version 2,
- * a copy of which is included with this program (LICENCE.LGPL).
- *
- * (c) 2000-2001 Michael Smith <msmith@xiph.org>
- *
- *
- * Comment editing backend, suitable for use by nice frontend interfaces.
- *
- * last modified: $Id: vcedit.c 16826 2010-01-27 04:16:24Z xiphmont $
- */
-
-/* Handle muxed streams and the Vorbis renormalization without having
- * to understand remuxing:
- * Linked list of buffers (buffer_chain). Start a link and whenever
- * you encounter an unknown page from the current stream (ie we found
- * its bos in the bos section) push it onto the current buffer. Whenever
- * you encounter the stream being renormalized create a new link in the
- * chain.
- * On writing, write the contents of the first link before every Vorbis
- * page written, and move to the next link. Assuming the Vorbis pages
- * in match vorbis pages out, the order of pages from different logical
- * streams will be unchanged.
- * Special case: header. After writing the vorbis headers, and before
- * starting renormalization, flush accumulated links (takes care of
- * situations where number of secondary vorbis header pages changes due
- * to remuxing. Similarly flush links at the end of renormalization
- * and before the start of the next chain is written.
- *
- */
+/*
+ This file is part of Deadbeef Player source code
+ http://deadbeef.sourceforge.net
+
+ Ogg Vorbis plugin Ogg edit functions
+
+ Copyright (C) 2014 Ian Nartowicz <deadbeef@nartowicz.co.uk>
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
-
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <errno.h>
+#include <limits.h>
+#include <unistd.h>
+#include <stdbool.h>
#include <ogg/ogg.h>
-#include <vorbis/codec.h>
-
+#include <deadbeef.h>
#include "vcedit.h"
-#include "vceditaux.h"
-#include "i18n.h"
-
-#define CHUNKSIZE 4096
-#define BUFFERCHUNK CHUNKSIZE
-
-/* Helper function, shouldn't need to call directly */
-static int page_buffer_push(vcedit_buffer_chain *bufferlink, ogg_page *og) {
- int result=0;
- char *tmp;
- vcedit_page_buffer *buffer;
-
- buffer = &bufferlink->buffer;
- tmp = realloc(buffer->data,
- buffer->data_len + og->header_len + og->body_len);
- if(tmp) {
- buffer->data = tmp;
- memcpy(buffer->data + buffer->data_len, og->header,
- og->header_len);
- buffer->data_len += og->header_len;
- memcpy(buffer->data + buffer->data_len, og->body,
- og->body_len);
- result = 1;
- buffer->data_len += og->body_len;
- } else {
- result = -1;
- }
-
- return result;
-}
-
-/* Write and free the first link using callbacks */
-static int buffer_chain_writelink(vcedit_state *state, void *out) {
- int result = 0;
- vcedit_buffer_chain *tmpchain;
- vcedit_page_buffer *tmpbuffer;
-
- tmpchain = state->sidebuf;
- tmpbuffer = &tmpchain->buffer;
- if(tmpbuffer->data_len)
- {
- if(state->write(tmpbuffer->data,1,tmpbuffer->data_len, out) !=
- (size_t) tmpbuffer->data_len)
- result = -1;
- else
- result = 1;
- }
-
- free(tmpbuffer->data);
- state->sidebuf = tmpchain->next;
- free(tmpchain);
- return result;
-}
-
-
-static int buffer_chain_newlink(vcedit_state *state) {
- int result = 1;
- vcedit_buffer_chain *bufferlink;
-
- if(!state->sidebuf) {
- state->sidebuf = malloc (sizeof *state->sidebuf);
- if(state->sidebuf) {
- bufferlink = state->sidebuf;
- } else {
- result = -1;
- }
- } else {
- bufferlink=state->sidebuf;
- while(bufferlink->next) {
- bufferlink = bufferlink->next;
- }
- bufferlink->next = malloc (sizeof *bufferlink->next);
- if(bufferlink->next) {
- bufferlink = bufferlink->next;
- } else {
- result = -1;
- }
- }
-
- if(result > 0 ) {
- bufferlink->next = 0;
- bufferlink->buffer.data = 0;
- bufferlink->buffer.data_len = 0;
- }
- else
- state->lasterror =
- _("Couldn't get enough memory for input buffering.");
-
- return result;
-}
-
-
-/* Push page onto the end of the buffer chain */
-static int buffer_chain_push(vcedit_state *state, ogg_page *og) {
- /* If there is no sidebuffer yet we need to create one, otherwise
- * traverse to the last buffer and push the new page onto it. */
- int result=1;
- vcedit_buffer_chain *bufferlink;
- if(!state->sidebuf) {
- result = buffer_chain_newlink(state);
- }
-
- if(result > 0) {
- bufferlink = state->sidebuf;
- while(bufferlink->next) {
- bufferlink = bufferlink->next;
- }
- result = page_buffer_push(bufferlink, og);
- }
-
- if(result < 0)
- state->lasterror =
- _("Couldn't get enough memory for input buffering.");
-
- return result;
-}
-
-
-
-static int vcedit_supported_stream(vcedit_state *state, ogg_page *og) {
- ogg_stream_state os;
- vorbis_info vi;
- vorbis_comment vc;
- ogg_packet header;
- int result = 0;
-
- ogg_stream_init(&os, ogg_page_serialno(og));
- vorbis_info_init(&vi);
- vorbis_comment_init(&vc);
-
- if( !ogg_page_bos(og) )
- result = -1;
-
- if(result >= 0 && ogg_stream_pagein(&os, og) < 0)
- {
- state->lasterror =
- _("Error reading first page of Ogg bitstream.");
- result = -1;
- }
-
- if(result >= 0 && ogg_stream_packetout(&os, &header) != 1)
- {
- state->lasterror = _("Error reading initial header packet.");
- result = -1;
- }
-
- if(result >= 0 && vorbis_synthesis_headerin(&vi, &vc, &header) >= 0)
- {
- result = 1;
- } else {
- /* Not vorbis, may eventually become a chain of checks (Speex,
- * Theora), but for the moment return 0, bos scan will push
- * the current page onto the buffer.
- */
- }
-
- ogg_stream_clear(&os);
- vorbis_info_clear(&vi);
- vorbis_comment_clear(&vc);
- return result;
-}
-
-
-static int vcedit_contains_serial (vcedit_state *state, int serialno) {
- int result = 0;
- size_t count;
- for( count=0; count < state->serials.streams_len; count++ ) {
- if ( *(state->serials.streams + count ) == serialno )
- result = 1;
- }
-
- return result;
-}
+#define VORBISNAME "Vorbis"
+#define TAGMAGIC "\3vorbis"
+#define CODEMAGIC "\5vorbis"
-static int vcedit_add_serial (vcedit_state *state, long serial) {
- int result = 0;
- long *tmp;
-
-
- if( vcedit_contains_serial(state, serial) )
- {
- result = 1;
- } else {
- tmp = realloc(state->serials.streams,
- (state->serials.streams_len + 1) * sizeof *tmp);
- if(tmp) {
- state->serials.streams = tmp;
- *(state->serials.streams +
- state->serials.streams_len) = serial;
- state->serials.streams_len += 1;
- result = 1;
- } else {
- state->lasterror =
- _("Couldn't get enough memory to register new stream serial number.");
- result = -1;
- }
- }
- return result;
-}
-
-
-/* For the benefit of the secondary header read only. Quietly creates
- * newlinks and pushes pages onto the buffer in the right way */
-static int vcedit_target_pageout (vcedit_state *state, ogg_page *og) {
- int result = 0;
- int pageout_result;
- pageout_result = ogg_sync_pageout(state->oy, og);
- if(pageout_result > 0)
- {
- if(state->serial == ogg_page_serialno(og))
- result = buffer_chain_newlink(state);
- else
- result = buffer_chain_push(state, og);
- } else if (pageout_result < 0) {
- /* Vorbis comment traditionally ignores the not-synced
- * error from pageout, so give it a different code. */
- result = -2;
- }
- return result;
-}
-
+#define CHUNKSIZE 4096
+#define MAXOGGPAGE 65536
-/* (I'm paranoid about memset(x,0,len) not giving null pointers */
-vcedit_state *vcedit_new_state(void) {
- vcedit_state *state = malloc(sizeof(vcedit_state));
- if(state) {
- memset(state, 0, sizeof(vcedit_state));
- state->sidebuf = 0;
- state->serials.streams = 0;
- state->serials.streams_len = 0;
- }
- return state;
+static const char *ogg_codec(ogg_page *og)
+{
+ typedef struct {
+ const char *magic;
+ const size_t length;
+ const char *codec;
+ } codec_t;
+ const codec_t codecs[] = {
+ {.codec = "Opus", .length = 19, .magic = "OpusHead"},
+ {.codec = "Vorbis", .length = 30, .magic = "\1vorbis"},
+ {.codec = "Flac", .length = 47, .magic = "\177FLAC"},
+ {.codec = "Speex", .length = 80, .magic = "Speex "},
+ {.codec = "Celt", .length = 80, .magic = "CELT"}, // obsolete
+ {.codec = "MIDI", .length = 13, .magic = "OggMIDI\0"},
+ {.codec = "PCM", .length = 28, .magic = "PCM "},
+ {.codec = "Theora", .length = 42, .magic = "\200theora"},
+ {.codec = "Daala", .length = 38, .magic = "\200daala"},
+ {.codec = "Dirac", .length = 5, .magic = "BBCD\0"},
+ {.codec = "Skeleton", .length = 80, .magic = "fishead\0"},
+ {.codec = "Kate", .length = 64, .magic = "\200kate\0\0\0"},
+ {.codec = "CMML", .length = 29, .magic = "CMML\0\0\0\0"},
+ {.codec = "YUV4MPEG", .length = 8, .magic = "YUV4Mpeg"},
+ {.codec = "UVS", .length = 48, .magic = "UVS "},
+ {.codec = "YUV", .length = 32, .magic = "\0YUV"},
+ {.codec = "RGB", .length = 24, .magic = "\0RGB"},
+ {.codec = "JNG", .length = 48, .magic = "\213JNG\r\n\032\n"},
+ {.codec = "MNG", .length = 48, .magic = "\212MNG\r\n\032\n"},
+ {.codec = "PNG", .length = 48, .magic = "\211PNG\r\n\032\n"},
+ {.codec = "Spots", .length = 52, .magic = "SPOTS\0\0\0"},
+ {.codec = NULL}
+ };
+
+ for (const codec_t *match = codecs; match->codec; match++)
+ if ((size_t)og->body_len >= match->length && !memcmp(og->body, match->magic, strlen(match->codec)))
+ return match->codec;
+
+ return "unknown";
}
-char *vcedit_error(vcedit_state *state) {
- return state->lasterror;
+static void _oggpack_chars(oggpack_buffer *opb, const char *s, size_t length)
+{
+ while (length--)
+ oggpack_write(opb, *s++, 8);
}
-vorbis_comment *vcedit_comments(vcedit_state *state) {
- return state->vc;
+static void _oggpack_string(oggpack_buffer *opb, const char *s)
+{
+ oggpack_write(opb, strlen(s), 32);
+ _oggpack_chars(opb, s, strlen(s));
}
-static void vcedit_clear_internals(vcedit_state *state) {
- char *tmp;
- if(state->vc) {
- vorbis_comment_clear(state->vc);
- free(state->vc);
- }
- if(state->os) {
- ogg_stream_clear(state->os);
- free(state->os);
- }
- if(state->oy) {
- ogg_sync_clear(state->oy);
- free(state->oy);
- }
- if(state->serials.streams_len) {
- free(state->serials.streams);
- state->serials.streams_len = 0;
- state->serials.streams = 0;
- }
- while(state->sidebuf) {
- vcedit_buffer_chain *tmpbuffer;
- tmpbuffer = state->sidebuf;
- state->sidebuf = tmpbuffer->next;
- free(tmpbuffer->buffer.data);
- free(tmpbuffer);
- }
- if(state->vendor)
- free(state->vendor);
- if(state->mainbuf)
- free(state->mainbuf);
- if(state->bookbuf)
- free(state->bookbuf);
- if(state->vi) {
- vorbis_info_clear(state->vi);
- free(state->vi);
+static int get_page(DB_FILE *in, ogg_sync_state *oy, ogg_page *og, char **lasterror)
+{
+ uint16_t chunks_left = MAXOGGPAGE / CHUNKSIZE;
+ while (ogg_sync_pageout(oy, og) != 1) {
+ char *buffer = ogg_sync_buffer(oy, CHUNKSIZE);
+ if (!in || !buffer || !chunks_left--) {
+ *lasterror = "can't find Ogg bitstream.";
+ return -1;
+ }
+
+ const size_t bytes = in->vfs->read(buffer, 1, CHUNKSIZE, in);
+ if (!bytes) {
+ *lasterror = "unexpected EOF.";
+ return 0;
+ }
+
+ ogg_sync_wrote(oy, bytes);
}
- tmp = state->lasterror;
- memset(state, 0, sizeof(*state));
- state->lasterror = tmp;
+ return ogg_page_serialno(og);
}
-void vcedit_clear(vcedit_state *state)
+static bool write_page(FILE *out, ogg_page *og)
{
- if(state)
- {
- vcedit_clear_internals(state);
- free(state);
- }
+ return fwrite(og->header, 1, og->header_len, out) != (size_t)og->header_len ||
+ fwrite(og->body, 1, og->body_len, out) != (size_t)og->body_len;
}
-/* Next two functions pulled straight from libvorbis, apart from one change
- * - we don't want to overwrite the vendor string.
- */
-static void _v_writestring(oggpack_buffer *o,char *s, int len)
+static int write_page_and_get_next(DB_FILE *in, FILE *out, ogg_sync_state *oy, ogg_page *og, char **lasterror)
{
- while(len--)
- {
- oggpack_write(o,*s++,8);
- }
-}
+ if (write_page(out, og))
+ return -1;
-static int _commentheader_out(vorbis_comment *vc, char *vendor, ogg_packet *op)
-{
- oggpack_buffer opb;
-
- oggpack_writeinit(&opb);
-
- /* preamble */
- oggpack_write(&opb,0x03,8);
- _v_writestring(&opb,"vorbis", 6);
-
- /* vendor */
- oggpack_write(&opb,strlen(vendor),32);
- _v_writestring(&opb,vendor, strlen(vendor));
-
- /* comments */
- oggpack_write(&opb,vc->comments,32);
- if(vc->comments){
- int i;
- for(i=0;i<vc->comments;i++){
- if(vc->user_comments[i]){
- oggpack_write(&opb,vc->comment_lengths[i],32);
- _v_writestring(&opb,vc->user_comments[i],
- vc->comment_lengths[i]);
- }else{
- oggpack_write(&opb,0,32);
- }
- }
- }
- oggpack_write(&opb,1,1);
-
- op->packet = malloc(oggpack_bytes(&opb));
- memcpy(op->packet, opb.buffer, oggpack_bytes(&opb));
-
- op->bytes=oggpack_bytes(&opb);
- op->b_o_s=0;
- op->e_o_s=0;
- op->granulepos=0;
-
- oggpack_writeclear(&opb);
- return 0;
+ return get_page(in, oy, og, lasterror);
}
-static int _blocksize(vcedit_state *s, ogg_packet *p)
+static bool write_vorbis_tags(FILE *out, const int serial, const char *vendor, const size_t num_tags, char **tags, ogg_packet *codebooks)
{
- int this = vorbis_packet_blocksize(s->vi, p);
- int ret = (this + s->prevW)/4;
-
- if(!s->prevW)
- {
- s->prevW = this;
- return 0;
- }
-
- s->prevW = this;
- return ret;
+ oggpack_buffer opb;
+ oggpack_writeinit(&opb);
+ _oggpack_chars(&opb, TAGMAGIC, strlen(TAGMAGIC));
+ _oggpack_string(&opb, vendor);
+ oggpack_write(&opb, num_tags, 32);
+ for (size_t i = 0; i < num_tags; i++)
+ _oggpack_string(&opb, tags[i]);
+ oggpack_write(&opb, 1, 1);
+ oggpack_writealign(&opb);
+
+
+ ogg_stream_state os;
+ ogg_stream_init(&os, serial);
+ os.b_o_s = 1;
+ os.pageno = 1;
+ ogg_packet op;
+ memset(&op, '\0', sizeof(op));
+ op.packet = oggpack_get_buffer(&opb);
+ op.bytes = oggpack_bytes(&opb);
+ ogg_stream_packetin(&os, &op);
+ oggpack_writeclear(&opb);
+ ogg_stream_packetin(&os, codebooks);
+
+ ogg_page og;
+ while (ogg_stream_flush(&os, &og))
+ if (write_page(out, &og))
+ return true;
+
+ return ogg_stream_check(&os) || ogg_stream_clear(&os);
}
-static int _fetch_next_packet(vcedit_state *s, ogg_packet *p, ogg_page *page)
+static int extract_codebooks(DB_FILE *in, ogg_sync_state *oy, ogg_page *og, int serial, ogg_packet *codebooks, char **lasterror)
{
- int result;
- char *buffer;
- int bytes;
- int serialno;
-
- result = ogg_stream_packetout(s->os, p);
-
- if(result > 0)
- return 1;
- else {
- while(1) {
- if(s->eosin)
- return 0;
-
- while(ogg_sync_pageout(s->oy, page) <= 0)
- {
- buffer = ogg_sync_buffer(s->oy, CHUNKSIZE);
- bytes = s->read(buffer,1, CHUNKSIZE, s->in);
- ogg_sync_wrote(s->oy, bytes);
- if(bytes == 0)
- return 0;
- }
-
- serialno = ogg_page_serialno(page);
- if(ogg_page_serialno(page) != s->serial)
- {
- if(vcedit_contains_serial(s, serialno)) {
- result = buffer_chain_push(s, page);
- if(result < 0)
- return result;
- }
- else
- {
- s->eosin = 1;
- s->extrapage = 1;
- return 0;
- }
- }
- else
- {
- ogg_stream_pagein(s->os, page);
- result = buffer_chain_newlink(s);
- if (result < 0)
- return result;
-
- if(ogg_page_eos(page))
- s->eosin = 1;
- }
- result = ogg_stream_packetout(s->os, p);
- if(result > 0)
- return 1;
- }
- /* Here == trouble */
- return 0;
- }
-}
+ memset(codebooks, '\0', sizeof(codebooks));
+ ogg_stream_state os;
+ if (ogg_stream_init(&os, serial)) {
+ *lasterror = "cannot init Ogg stream.";
+ return -1;
+ }
+ os.pageno = 1;
+ os.b_o_s = 1;
+
+ ogg_packet op;
+ ogg_stream_pagein(&os, og);
+ do {
+ while (ogg_stream_packetpeek(&os, NULL) == 0) {
+ if ((serial = get_page(in, oy, og, lasterror)) <= 0)
+ goto cleanup;
+ fprintf(stderr, "Serial: %d, %ld bytes (%s)\n", serial, og->header_len + og->body_len, og->body);
+ if (ogg_stream_pagein(&os, og)) {
+ *lasterror = "failed to stream page for codebooks packet.";
+ goto cleanup;
+ }
+ }
+ } while (ogg_stream_packetout(&os, &op) != 1 || op.bytes < strlen(CODEMAGIC) || memcmp(op.packet, CODEMAGIC, strlen(CODEMAGIC)));
+
+ if (!(codebooks->packet = malloc(op.bytes))) {
+ *lasterror = "cannot allocate codebooks packet.";
+ goto cleanup;
+ }
+ codebooks->bytes = op.bytes;
+ memcpy(codebooks->packet, op.packet, op.bytes);
-int vcedit_open(vcedit_state *state, FILE *in)
-{
- return vcedit_open_callbacks(state, (void *)in,
- (vcedit_read_func)fread, (vcedit_write_func)fwrite);
+cleanup:
+ ogg_stream_clear(&os);
+
+ return codebooks->packet ? serial : -1;
}
-int vcedit_open_callbacks(vcedit_state *state, void *in,
- vcedit_read_func read_func, vcedit_write_func write_func)
+off_t vcedit_write_metadata(DB_FILE *in, const char *fname, int link, const char *vendor, const int num_tags, char **tags, char **lasterror)
{
-
- char *buffer;
- int bytes,i;
- int chunks = 0;
- int read_bos, test_supported, page_pending;
- int have_vorbis;
- ogg_packet *header;
- ogg_packet header_main;
- ogg_packet header_comments;
- ogg_packet header_codebooks;
- ogg_page og;
-
- state->in = in;
- state->read = read_func;
- state->write = write_func;
-
- state->oy = malloc(sizeof(ogg_sync_state));
- ogg_sync_init(state->oy);
-
- while(1)
- {
- buffer = ogg_sync_buffer(state->oy, CHUNKSIZE);
- bytes = state->read(buffer, 1, CHUNKSIZE, state->in);
-
- ogg_sync_wrote(state->oy, bytes);
-
- if(ogg_sync_pageout(state->oy, &og) == 1)
- break;
-
- if(chunks++ >= 10) /* Bail if we don't find data in the first 40 kB */
- {
- if(bytes<CHUNKSIZE)
- state->lasterror = _("Input truncated or empty.");
- else
- state->lasterror = _("Input is not an Ogg bitstream.");
- goto err;
- }
+ off_t file_size = 0;
+ ogg_page og;
+ ogg_sync_state oy;
+ ogg_sync_init(&oy);
+
+ char outname[PATH_MAX];
+ snprintf(outname, PATH_MAX, "%s.temp", fname);
+ FILE *out = fopen(outname, "w+b");
+ if (!out) {
+ *lasterror = "unable to open temporary file for writing.";
+ goto cleanup;
+ }
+ if (!in) {
+ *lasterror = "file not opened for reading.";
+ goto cleanup;
}
- /* BOS loop, starting with a loaded ogg page. */
- if(buffer_chain_newlink(state) < 0)
- goto err;
-
- for( read_bos = 1, have_vorbis = 0 ; read_bos; )
- {
- test_supported = vcedit_supported_stream(state, &og);
- if(test_supported < 0)
- {
- goto err;
- }
- else if (test_supported == 0 || have_vorbis )
- {
- if(vcedit_add_serial ( state, ogg_page_serialno(&og)) < 0)
- goto err;
- if( buffer_chain_push(state, &og) < 0)
- goto err;
- }
- else if (test_supported > 0)
- {
- if(buffer_chain_newlink(state) < 0)
- goto err;
- state->serial = ogg_page_serialno(&og);
- if(vcedit_add_serial ( state, ogg_page_serialno(&og)) < 0)
- goto err;
-
- state->os = malloc(sizeof(ogg_stream_state));
- ogg_stream_init(state->os, state->serial);
-
- state->vi = malloc(sizeof(vorbis_info));
- vorbis_info_init(state->vi);
-
- state->vc = malloc(sizeof(vorbis_comment));
- vorbis_comment_init(state->vc);
-
- if(ogg_stream_pagein(state->os, &og) < 0)
- {
- state->lasterror =
- _("Error reading first page of Ogg bitstream.");
- goto err;
- }
-
- if(ogg_stream_packetout(state->os, &header_main) != 1)
- {
- state->lasterror =
- _("Error reading initial header packet.");
- goto err;
- }
-
- if(vorbis_synthesis_headerin(state->vi, state->vc,
- &header_main) < 0)
- {
- state->lasterror =
- _("Ogg bitstream does not contain Vorbis data.");
- goto err;
- }
- have_vorbis = 1;
- }
- while(1)
- {
- buffer = ogg_sync_buffer(state->oy, CHUNKSIZE);
- bytes = state->read(buffer, 1, CHUNKSIZE, state->in);
-
- if(bytes == 0)
- {
- state->lasterror =
- _("EOF before recognised stream.");
- goto err;
- }
-
- ogg_sync_wrote(state->oy, bytes);
-
- if(ogg_sync_pageout(state->oy, &og) == 1)
- break;
- }
- if(!ogg_page_bos(&og)) {
- read_bos = 0;
- page_pending = 1;
- }
+ /* Copy through pages until we reach the right info header */
+ int codec_serial = 0;
+ int serial = get_page(in, &oy, &og, lasterror);
+ while (serial > 0 && !codec_serial) {
+ while (serial > 0 && !ogg_page_bos(&og))
+ serial = write_page_and_get_next(in, out, &oy, &og, lasterror);
+
+ while (serial > 0 && ogg_page_bos(&og)) {
+ if (link < 1 && !strcmp(ogg_codec(&og), VORBISNAME)) {
+ codec_serial = serial;
+ }
+ serial = write_page_and_get_next(in, out, &oy, &og, lasterror);
+ }
+ link--;
}
- if(!state->os) {
- state->lasterror = _("Ogg bitstream does not contain a supported data-type.");
- goto err;
- }
-
- state->mainlen = header_main.bytes;
- state->mainbuf = malloc(state->mainlen);
- memcpy(state->mainbuf, header_main.packet, header_main.bytes);
-
- if(ogg_page_serialno(&og) == state->serial)
- {
- if(buffer_chain_newlink(state) < 0)
- goto err;
- }
-
- else
- {
- if(buffer_chain_push(state, &og) < 0)
- goto err;
- page_pending = 0;
- }
-
- i = 0;
- header = &header_comments;
- while(i<2) {
- while(i<2) {
- int result;
- if(!page_pending)
- result = vcedit_target_pageout(state, &og);
- else
- {
- result = 1;
- page_pending = 0;
- }
- if(result == 0 || result == -2) break; /* Too little data so far */
- else if(result == -1) goto err;
- else if(result == 1)
- {
- ogg_stream_pagein(state->os, &og);
- while(i<2)
- {
- result = ogg_stream_packetout(state->os, header);
- if(result == 0) break;
- if(result == -1)
- {
- state->lasterror = _("Corrupt secondary header.");
- goto err;
- }
- vorbis_synthesis_headerin(state->vi, state->vc, header);
- if(i==1)
- {
- state->booklen = header->bytes;
- state->bookbuf = malloc(state->booklen);
- memcpy(state->bookbuf, header->packet,
- header->bytes);
- }
- i++;
- header = &header_codebooks;
- }
- }
- }
-
- buffer = ogg_sync_buffer(state->oy, CHUNKSIZE);
- bytes = state->read(buffer, 1, CHUNKSIZE, state->in);
- if(bytes == 0 && i < 2)
- {
- state->lasterror = _("EOF before end of Vorbis headers.");
- goto err;
- }
- ogg_sync_wrote(state->oy, bytes);
- }
-
- /* Copy the vendor tag */
- state->vendor = malloc(strlen(state->vc->vendor) +1);
- strcpy(state->vendor, state->vc->vendor);
-
- /* Headers are done! */
- return 0;
-
-err:
- vcedit_clear_internals(state);
- return -1;
-}
+ /* Copy additional pages up to our comment header */
+ while (serial > 0 && serial != codec_serial)
+ serial = write_page_and_get_next(in, out, &oy, &og, lasterror);
+ if (serial <= 0)
+ goto cleanup;
+
+ /* Add the codebook packet to our comment header and save it */
+ ogg_packet codebooks;
+ if ((serial = extract_codebooks(in, &oy, &og, codec_serial, &codebooks, lasterror)) <= 0)
+ goto cleanup;
+ const bool write_tags = write_vorbis_tags(out, codec_serial, vendor, num_tags, tags, &codebooks);
+ ogg_packet_clear(&codebooks);
+ if (write_tags) {
+ *lasterror = "internal error writing Vorbis comment header packet.";
+ goto cleanup;
+ }
-int vcedit_write(vcedit_state *state, void *out)
-{
- ogg_stream_state streamout;
- ogg_packet header_main;
- ogg_packet header_comments;
- ogg_packet header_codebooks;
-
- ogg_page ogout, ogin;
- ogg_packet op;
- ogg_int64_t granpos = 0;
- int result;
- char *buffer;
- int bytes;
- int needflush=0, needout=0;
-
- state->eosin = 0;
- state->extrapage = 0;
-
- header_main.bytes = state->mainlen;
- header_main.packet = state->mainbuf;
- header_main.b_o_s = 1;
- header_main.e_o_s = 0;
- header_main.granulepos = 0;
-
- header_codebooks.bytes = state->booklen;
- header_codebooks.packet = state->bookbuf;
- header_codebooks.b_o_s = 0;
- header_codebooks.e_o_s = 0;
- header_codebooks.granulepos = 0;
-
- ogg_stream_init(&streamout, state->serial);
-
- _commentheader_out(state->vc, state->vendor, &header_comments);
-
- ogg_stream_packetin(&streamout, &header_main);
- ogg_stream_packetin(&streamout, &header_comments);
- ogg_stream_packetin(&streamout, &header_codebooks);
-
- while((result = ogg_stream_flush(&streamout, &ogout)))
- {
- if(state->sidebuf && buffer_chain_writelink(state, out) < 0)
- goto cleanup;
- if(state->write(ogout.header,1,ogout.header_len, out) !=
- (size_t) ogout.header_len)
- goto cleanup;
- if(state->write(ogout.body,1,ogout.body_len, out) !=
- (size_t) ogout.body_len)
- goto cleanup;
- }
-
- while(state->sidebuf) {
- if(buffer_chain_writelink(state, out) < 0)
- goto cleanup;
- }
- if(buffer_chain_newlink(state) < 0)
- goto cleanup;
-
- while(_fetch_next_packet(state, &op, &ogin))
- {
- int size;
- size = _blocksize(state, &op);
- granpos += size;
-
- if(needflush)
- {
- if(ogg_stream_flush(&streamout, &ogout))
- {
- if(state->sidebuf &&
- buffer_chain_writelink(state, out) < 0)
- goto cleanup;
- if(state->write(ogout.header,1,ogout.header_len,
- out) != (size_t) ogout.header_len)
- goto cleanup;
- if(state->write(ogout.body,1,ogout.body_len,
- out) != (size_t) ogout.body_len)
- goto cleanup;
- }
- }
- else if(needout)
- {
- if(ogg_stream_pageout(&streamout, &ogout))
- {
- if(state->sidebuf &&
- buffer_chain_writelink(state, out) < 0)
- goto cleanup;
- if(state->write(ogout.header,1,ogout.header_len,
- out) != (size_t) ogout.header_len)
- goto cleanup;
- if(state->write(ogout.body,1,ogout.body_len,
- out) != (size_t) ogout.body_len)
- goto cleanup;
- }
- }
-
- needflush=needout=0;
-
- if(op.granulepos == -1)
- {
- op.granulepos = granpos;
- ogg_stream_packetin(&streamout, &op);
- }
- else /* granulepos is set, validly. Use it, and force a flush to
- account for shortened blocks (vcut) when appropriate */
- {
- if(granpos > op.granulepos)
- {
- granpos = op.granulepos;
- ogg_stream_packetin(&streamout, &op);
- needflush=1;
- }
- else
- {
- ogg_stream_packetin(&streamout, &op);
- needout=1;
- }
- }
- }
-
- streamout.e_o_s = 1;
- while(ogg_stream_flush(&streamout, &ogout))
- {
- if(state->sidebuf && buffer_chain_writelink(state, out) < 0)
- goto cleanup;
- if(state->write(ogout.header,1,ogout.header_len,
- out) != (size_t) ogout.header_len)
- goto cleanup;
- if(state->write(ogout.body,1,ogout.body_len,
- out) != (size_t) ogout.body_len)
- goto cleanup;
- }
-
- if (state->extrapage)
- {
- /* This is the first page of a new chain, get rid of the
- * sidebuffer */
- while(state->sidebuf)
- if(buffer_chain_writelink(state, out) < 0)
- goto cleanup;
- if(state->write(ogin.header,1,ogin.header_len,
- out) != (size_t) ogin.header_len)
- goto cleanup;
- if (state->write(ogin.body,1,ogin.body_len, out) !=
- (size_t) ogin.body_len)
- goto cleanup;
- }
-
- state->eosin=0; /* clear it, because not all paths to here do */
- while(!state->eosin) /* We reached eos, not eof */
- {
- /* We copy the rest of the stream (other logical streams)
- * through, a page at a time. */
- while(1)
- {
- result = ogg_sync_pageout(state->oy, &ogout);
- if(result==0)
- break;
- if(result<0)
- state->lasterror = _("Corrupt or missing data, continuing...");
- else
- {
- /* Don't bother going through the rest, we can just
- * write the page out now */
- if(state->write(ogout.header,1,ogout.header_len,
- out) != (size_t) ogout.header_len) {
- goto cleanup;
- }
- if(state->write(ogout.body,1,ogout.body_len, out) !=
- (size_t) ogout.body_len) {
- goto cleanup;
- }
- }
- }
- buffer = ogg_sync_buffer(state->oy, CHUNKSIZE);
- bytes = state->read(buffer,1, CHUNKSIZE, state->in);
- ogg_sync_wrote(state->oy, bytes);
- if(bytes == 0)
- {
- state->eosin = 1;
- break;
- }
- }
+ /* Blindly copy through the remaining pages */
+ serial = get_page(in, &oy, &og, lasterror);
+ while (serial > 0)
+ serial = write_page_and_get_next(in, out, &oy, &og, lasterror);
+ if (serial < 0)
+ goto cleanup;
+ fseeko(out, 0, SEEK_END);
+ file_size = ftello(out);
cleanup:
- ogg_stream_clear(&streamout);
+ if (in)
+ in->vfs->close(in);
- /* We don't ogg_packet_clear() this, because the memory was allocated in
- _commentheader_out(), so we mirror that here */
- _ogg_free(header_comments.packet);
+ if (out)
+ fclose(out);
- free(state->mainbuf);
- free(state->bookbuf);
- state->mainbuf = state->bookbuf = NULL;
+ ogg_sync_clear(&oy);
- if(!state->eosin)
- {
- state->lasterror =
- _("Error writing stream to output. "
- "Output stream may be corrupted or truncated.");
- return -1;
- }
+ if (file_size <= 0) {
+ unlink(outname);
+ if (!*lasterror)
+ *lasterror = "error writing new file, changes backed out.";
+ return -1;
+ }
- return 0;
+ rename(outname, fname);
+ return file_size;
}
diff --git a/plugins/vorbis/vcedit.h b/plugins/vorbis/vcedit.h
index 173876f3..7eabe877 100644
--- a/plugins/vorbis/vcedit.h
+++ b/plugins/vorbis/vcedit.h
@@ -1,69 +1,35 @@
-/* This program is licensed under the GNU Library General Public License, version 2,
- * a copy of which is included with this program (with filename LICENSE.LGPL).
- *
- * (c) 2000-2001 Michael Smith <msmith@xiph.org>
- *
- * VCEdit header.
- *
- * last modified: $ID:$
- */
+/*
+ This file is part of Deadbeef Player source code
+ http://deadbeef.sourceforge.net
-#ifndef __VCEDIT_H
-#define __VCEDIT_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <stdio.h>
-#include <ogg/ogg.h>
-#include <vorbis/codec.h>
+ Ogg Vorbis plugin Ogg edit functions header
-typedef size_t (*vcedit_read_func)(void *, size_t, size_t, void *);
-typedef size_t (*vcedit_write_func)(const void *, size_t, size_t, void *);
+ Copyright (C) 2014 Ian Nartowicz <deadbeef@nartowicz.co.uk>
-typedef struct {
- long *streams;
- size_t streams_len;
-} vcedit_serial_nos;
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
-typedef struct {
- ogg_sync_state *oy;
- ogg_stream_state *os;
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
- vorbis_comment *vc;
- vorbis_info *vi;
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
- vcedit_read_func read;
- vcedit_write_func write;
+*/
- void *in;
- int serial;
- vcedit_serial_nos serials;
- unsigned char *mainbuf;
- unsigned char *bookbuf;
- int mainlen;
- int booklen;
- char *lasterror;
- char *vendor;
- int prevW;
- int extrapage;
- int eosin;
- struct vcedit_buffer_chain *sidebuf;
-} vcedit_state;
+#ifndef __VCEDIT_H
+#define __VCEDIT_H
-extern vcedit_state * vcedit_new_state(void);
-extern void vcedit_clear(vcedit_state *state);
-extern vorbis_comment * vcedit_comments(vcedit_state *state);
-extern int vcedit_open(vcedit_state *state, FILE *in);
-extern int vcedit_open_callbacks(vcedit_state *state, void *in,
- vcedit_read_func read_func, vcedit_write_func write_func);
-extern int vcedit_write(vcedit_state *state, void *out);
-extern char * vcedit_error(vcedit_state *state);
+#define ALBUM_ART_KEY "METADATA_BLOCK_PICTURE"
+#define ALBUM_ART_META "metadata_block_picture"
-#ifdef __cplusplus
-}
-#endif
+off_t vcedit_write_metadata(DB_FILE *in, const char *fname, int link, const char *vendor, const int num_tags, char **tags, char **lasterror);
#endif /* __VCEDIT_H */
-
diff --git a/plugins/vorbis/vceditaux.h b/plugins/vorbis/vceditaux.h
deleted file mode 100644
index bb40eaeb..00000000
--- a/plugins/vorbis/vceditaux.h
+++ /dev/null
@@ -1,9 +0,0 @@
-typedef struct vcedit_page_buffer {
- char *data;
- size_t data_len;
-} vcedit_page_buffer;
-
-typedef struct vcedit_buffer_chain {
- struct vcedit_buffer_chain *next;
- struct vcedit_page_buffer buffer;
-} vcedit_buffer_chain;
diff --git a/plugins/vorbis/vorbis.c b/plugins/vorbis/vorbis.c
index 5851a95f..1bd4a382 100644
--- a/plugins/vorbis/vorbis.c
+++ b/plugins/vorbis/vorbis.c
@@ -1,20 +1,26 @@
/*
- DeaDBeeF - ultimate music player for GNU/Linux systems with X11
- Copyright (C) 2009-2013 Alexey Yakovenko <waker@users.sourceforge.net>
+ DeaDBeeF -- the music player
+ Copyright (C) 2009-2014 Alexey Yakovenko and other contributors
- 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 software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
- 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.
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+
+ 3. This notice may not be removed or altered from any source distribution.
*/
+
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
@@ -26,6 +32,7 @@
#include <limits.h>
#include <unistd.h>
#include <math.h>
+#include <stdbool.h>
#include "../../deadbeef.h"
#include "vcedit.h"
@@ -35,6 +42,9 @@
//#define trace(...) { fprintf (stderr, __VA_ARGS__); }
#define trace(fmt,...)
+#define RG_REFERENCE_LOUDNESS -1
+#define DELIMITER "\n - \n"
+
static DB_decoder_t plugin;
static DB_functions_t *deadbeef;
@@ -74,6 +84,53 @@ cvorbis_ftell (void *datasource) {
return deadbeef->ftell (datasource);
}
+static const char
+*gain_tag_name(const int tag_enum)
+{
+ switch(tag_enum) {
+ case DDB_REPLAYGAIN_ALBUMGAIN:
+ return "REPLAYGAIN_ALBUM_GAIN";
+ case DDB_REPLAYGAIN_ALBUMPEAK:
+ return "REPLAYGAIN_ALBUM_PEAK";
+ case DDB_REPLAYGAIN_TRACKGAIN:
+ return "REPLAYGAIN_TRACK_GAIN";
+ case DDB_REPLAYGAIN_TRACKPEAK:
+ return "REPLAYGAIN_TRACK_PEAK";
+ case RG_REFERENCE_LOUDNESS:
+ return "REPLAYGAIN_REFERENCE_LOUDNESS";
+ default:
+ return NULL;
+ }
+}
+
+static const char
+*gain_meta_key(const int tag_enum)
+{
+ switch(tag_enum) {
+ case DDB_REPLAYGAIN_ALBUMGAIN:
+ return ":REPLAYGAIN_ALBUMGAIN";
+ case DDB_REPLAYGAIN_ALBUMPEAK:
+ return ":REPLAYGAIN_ALBUMPEAK";
+ case DDB_REPLAYGAIN_TRACKGAIN:
+ return ":REPLAYGAIN_TRACKGAIN";
+ case DDB_REPLAYGAIN_TRACKPEAK:
+ return ":REPLAYGAIN_TRACKPEAK";
+ case RG_REFERENCE_LOUDNESS:
+ return ":REPLAYGAIN_REFERENCE_LOUDNESS";
+ default:
+ return NULL;
+ }
+}
+
+static bool
+is_special_tag(const char *tag) {
+ return !strcasecmp(tag, gain_tag_name(DDB_REPLAYGAIN_ALBUMGAIN)) ||
+ !strcasecmp(tag, gain_tag_name(DDB_REPLAYGAIN_ALBUMPEAK)) ||
+ !strcasecmp(tag, gain_tag_name(DDB_REPLAYGAIN_TRACKGAIN)) ||
+ !strcasecmp(tag, gain_tag_name(DDB_REPLAYGAIN_TRACKPEAK)) ||
+ !strcasecmp(tag, gain_tag_name(RG_REFERENCE_LOUDNESS));
+}
+
static const char *metainfo[] = {
"ARTIST", "artist",
"TITLE", "title",
@@ -142,6 +199,9 @@ update_vorbis_comments (DB_playItem_t *it, vorbis_comment *vc, int refresh_playl
else if (!strncasecmp (s, "replaygain_track_peak=", 22)) {
deadbeef->pl_set_item_replaygain (it, DDB_REPLAYGAIN_TRACKPEAK, atof (s+22));
}
+ else if (!strncasecmp (s, "replaygain_reference_loudness=", 30)) {
+ deadbeef->pl_replace_meta(it, gain_meta_key(RG_REFERENCE_LOUDNESS), s+30);
+ }
else {
const char *p = s;
while (*p && *p != '=') {
@@ -324,7 +384,7 @@ cvorbis_read (DB_fileinfo_t *_info, char *bytes, int size) {
if (!info->info.file->vfs->is_streaming ()) {
if (info->currentsample + size / samplesize > info->endsample) {
size = (info->endsample - info->currentsample + 1) * samplesize;
- trace ("size truncated to %d bytes, cursample=%d, info->endsample=%d, totalsamples=%d\n", size, info->currentsample, info->endsample, ov_pcm_total (&info->vorbis_file, -1));
+ trace ("size truncated to %d bytes, cursample=%d, info->endsample=%d, totalsamples=%lld\n", size, info->currentsample, info->endsample, ov_pcm_total (&info->vorbis_file, -1));
if (size <= 0) {
return 0;
}
@@ -350,7 +410,7 @@ cvorbis_read (DB_fileinfo_t *_info, char *bytes, int size) {
}
// trace ("cvorbis_read %d bytes[2]\n", size);
int initsize = size;
- long ret;
+ int64_t ret;
for (;;)
{
// read ogg
@@ -360,7 +420,7 @@ cvorbis_read (DB_fileinfo_t *_info, char *bytes, int size) {
#endif
if (_info->fmt.channels <= 2 || _info->fmt.channels == 4) {
- ret=ov_read (&info->vorbis_file, bytes, size, endianess, 2, 1, &info->cur_bit_stream);
+ ret = (int64_t)ov_read (&info->vorbis_file, bytes, size, endianess, 2, 1, &info->cur_bit_stream);
}
else {
int16_t temp[size/2];
@@ -368,13 +428,20 @@ cvorbis_read (DB_fileinfo_t *_info, char *bytes, int size) {
if (ret > 0) {
// remap channels to wav format
int idx = _info->fmt.channels - 3;
- static int remap[4][6] = {
+ static int remap[6][8] = {
{0,2,1},
{0,1,2,3}, // should not be used
{0,2,1,3,4},
- {0,2,1,4,5,3}
+ {0,2,1,4,5,3},
+ {0,2,1,4,5,6,3},
+ {0,2,1,6,7,4,5,3}
};
+ if (_info->fmt.channels > 8) {
+ fprintf (stderr, "vorbis plugin doesn't support more than 8 channels\n");
+ return -1;
+ }
+
int i, j;
int16_t *src = temp;
int n = ret / samplesize;
@@ -389,7 +456,7 @@ cvorbis_read (DB_fileinfo_t *_info, char *bytes, int size) {
if (ret <= 0)
{
if (ret < 0) {
- trace ("ov_read returned %d\n", ret);
+ trace ("ov_read returned %lld\n", ret);
switch (ret) {
case OV_HOLE:
trace ("OV_HOLE\n");
@@ -437,11 +504,11 @@ cvorbis_seek_sample (DB_fileinfo_t *_info, int sample) {
trace ("vorbis: file is NULL on seek\n");
return -1;
}
- trace ("vorbis: seek to sample %d\n");
+ trace ("vorbis: seek to sample %d\n", sample);
sample += info->startsample;
int res = ov_pcm_seek (&info->vorbis_file, sample);
if (res != 0 && res != OV_ENOSEEK) {
- trace ("vorbis: error %x seeking to sample %d\n", sample);
+ trace ("vorbis: error %x seeking to sample %d\n", res, sample);
return -1;
}
int tell = ov_pcm_tell (&info->vorbis_file);
@@ -584,7 +651,7 @@ cvorbis_read_metadata (DB_playItem_t *it) {
DB_FILE *fp = NULL;
OggVorbis_File vorbis_file;
vorbis_info *vi = NULL;
-
+
deadbeef->pl_lock ();
fp = deadbeef->fopen (deadbeef->pl_find_meta (it, ":URI"));
deadbeef->pl_unlock ();
@@ -629,153 +696,127 @@ error:
}
-int
-cvorbis_write_metadata (DB_playItem_t *it) {
- vcedit_state *state = NULL;
- vorbis_comment *vc = NULL;
- FILE *fp = NULL;
- FILE *out = NULL;
- int err = -1;
- char outname[PATH_MAX] = "";
- char fname[PATH_MAX];
- deadbeef->pl_get_meta (it, ":URI", fname, sizeof (fname));
-
- struct field {
- struct field *next;
- int size;
- uint8_t data[0];
- };
+static void
+split_tag(vorbis_comment *tags, const char *key, const char *value)
+{
+ if (key && value) {
+ const char *p;
+ while (p = strstr(value, DELIMITER)) {
+ char v[p - value + 1];
+ strncpy(v, value, p-value);
+ v[p-value] = 0;
+ vorbis_comment_add_tag(tags, key, v);
+ value = p + strlen(DELIMITER);
+ }
- struct field *preserved_fields = NULL;
+ vorbis_comment_add_tag(tags, key, value);
+ }
+}
- state = vcedit_new_state ();
- if (!state) {
- trace ("cvorbis_write_metadata: vcedit_new_state failed\n");
- return -1;
+static void
+merge_gain_tag(DB_playItem_t *it, vorbis_comment *vc, vorbis_comment *tags, const int tag_enum, const char *pattern, const int min, const int max)
+{
+ const char *key = gain_tag_name(tag_enum);
+
+ char *end;
+ const char *meta_value = deadbeef->pl_find_meta(it, key);
+ const float value = meta_value ? strtof(meta_value, &end) : 0;
+ if (meta_value && end != meta_value && value > min && value < max) {
+ char tag_value[10];
+ sprintf(tag_value, pattern, value);
+ vorbis_comment_add_tag(tags, key, tag_value);
+ }
+ else {
+ const char *tag_value = vorbis_comment_query(vc, key, 0);
+ if (tag_value)
+ vorbis_comment_add_tag(tags, key, tag_value);
}
- fp = fopen (fname, "rb");
+}
+
+static const char
+*map_tag(const char *key)
+{
+ for (int i = 0; metainfo[i]; i += 2)
+ if (!strcasecmp (metainfo[i+1], key))
+ return metainfo[i];
+ return key;
+}
+
+static vorbis_comment
+*create_tags_list(DB_playItem_t *it, const char *fname, vorbis_comment *tags)
+{
+ DB_FILE *fp = deadbeef->fopen (fname);
if (!fp) {
- trace ("cvorbis_write_metadata: failed to read metadata from %s\n", fname);
- goto error;
+ trace ("vorbis: failed to fopen %s\n", fname);
+ return NULL;
}
- if (vcedit_open (state, fp) != 0) {
- trace ("cvorbis_write_metadata: vcedit_open failed, error: %s\n", vcedit_error (state));
- goto error;
+ ov_callbacks ovcb = {
+ .read_func = cvorbis_fread,
+ .seek_func = cvorbis_fseek,
+ .close_func = cvorbis_fclose,
+ .tell_func = cvorbis_ftell
+ };
+ OggVorbis_File vorbis_file;
+ int err = ov_test_callbacks (fp, &vorbis_file, NULL, 0, ovcb);
+ if (err != 0) {
+ trace ("ov_test_callbacks returned %d\n", err);
+ deadbeef->fclose (fp);
+ return NULL;
}
- vc = vcedit_comments (state);
+ vorbis_comment *vc = ov_comment (&vorbis_file, -1);
if (!vc) {
- trace ("cvorbis_write_metadata: vcedit_comments failed, error: %s\n", vcedit_error (state));
- goto error;
+ trace ("ov_comment failed\n");
+ ov_clear (&vorbis_file);
+ return NULL;
}
-#if 0
- // copy all unknown fields to separate buffer
- for (int i = 0; i < vc->comments; i++) {
- int m;
- for (m = 0; metainfo[m]; m += 2) {
- int l = strlen (metainfo[m]);
- if (vc->comment_lengths[i] > l && !strncasecmp (vc->user_comments[i], metainfo[m], l) && vc->user_comments[i][l] == '=') {
- break;
- }
- }
- if (!metainfo[m]) {
- trace ("preserved field: %s\n", vc->user_comments[i]);
- // unknown field
- struct field *f = malloc (sizeof (struct field) + vc->comment_lengths[i]);
- memset (f, 0, sizeof (struct field));
- memcpy (f->data, vc->user_comments[i], vc->comment_lengths[i]);
- f->size = vc->comment_lengths[i];
- f->next = preserved_fields;
- preserved_fields = f;
- }
+ vorbis_comment_init(tags);
+ if (!(tags->vendor = strdup(vc->vendor))) {
+ ov_clear (&vorbis_file);
+ trace("create_tags_list: cannot allocate tags list\n");
+ return NULL;
}
-#endif
-
- vorbis_comment_clear(vc);
- vorbis_comment_init(vc);
- // add unknown/custom fields
deadbeef->pl_lock ();
- DB_metaInfo_t *m = deadbeef->pl_get_metadata_head (it);
+ merge_gain_tag(it, vc, tags, DDB_REPLAYGAIN_ALBUMGAIN, "%0.2f dB", -100, 100);
+ merge_gain_tag(it, vc, tags, DDB_REPLAYGAIN_ALBUMPEAK, "%0.8f", 0, 2);
+ merge_gain_tag(it, vc, tags, DDB_REPLAYGAIN_TRACKGAIN, "%0.2f dB", -100, 100);
+ merge_gain_tag(it, vc, tags, DDB_REPLAYGAIN_TRACKPEAK, "%0.8f", 0, 2);
+ merge_gain_tag(it, vc, tags, RG_REFERENCE_LOUDNESS, "%0.1f dB", 0, 128);
+ DB_metaInfo_t *m = deadbeef->pl_get_metadata_head(it);
while (m) {
- if (m->key[0] != ':') {
- int i;
- for (i = 0; metainfo[i]; i += 2) {
- if (!strcasecmp (metainfo[i+1], m->key)) {
- break;
- }
- }
- const char *val = m->value;
- if (val && *val) {
- while (val) {
- const char *next = strchr (val, '\n');
- int l;
- if (next) {
- l = next - val;
- next++;
- }
- else {
- l = strlen (val);
- }
- if (l > 0) {
- char s[100+l+1];
- int n = snprintf (s, sizeof (s), "%s=", metainfo[i] ? metainfo[i] : m->key);
- strncpy (s+n, val, l);
- *(s+n+l) = 0;
- vorbis_comment_add (vc, s);
- }
- val = next;
- }
- }
- }
+ if (m->key[0] != ':' && m->key[0] != '!' && !is_special_tag(m->key))
+ split_tag(tags, map_tag(m->key), (char *)m->value);
m = m->next;
}
deadbeef->pl_unlock ();
- // add preserved fields
- for (struct field *f = preserved_fields; f; f = f->next) {
- vorbis_comment_add (vc, f->data);
- }
-
- snprintf (outname, sizeof (outname), "%s.temp.ogg", fname);
+ ov_clear (&vorbis_file);
+ return tags;
+}
- out = fopen (outname, "w+b");
- if (!out) {
- trace ("cvorbis_write_metadata: failed to open %s for writing\n", outname);
- goto error;
- }
+static int
+cvorbis_write_metadata (DB_playItem_t *it) {
+ char fname[PATH_MAX];
+ deadbeef->pl_get_meta (it, ":URI", fname, sizeof (fname));
- if (vcedit_write (state, out) < 0) {
- trace ("cvorbis_write_metadata: failed to write tags to %s, error: %s\n", fname, vcedit_error (state));
- goto error;
- }
+ vorbis_comment tags;
+ if (!create_tags_list(it, fname, &tags))
+ return -1;
- err = 0;
-error:
- if (fp) {
- fclose (fp);
- }
- if (out) {
- fclose (out);
- }
- if (state) {
- vcedit_clear (state);
- }
- while (preserved_fields) {
- struct field *next = preserved_fields->next;
- free (preserved_fields);
- preserved_fields = next;
+ char *vorbis_error = NULL;
+ const off_t file_size = vcedit_write_metadata (deadbeef->fopen(fname), fname, -1, tags.vendor, tags.comments, tags.user_comments, &vorbis_error);
+ vorbis_comment_clear(&tags);
+ if (file_size <= 0) {
+ trace ("cvorbis_write_metadata: failed to write tags to %s, error: %s\n", fname, vorbis_error);
+ return -1;
}
- if (!err) {
- rename (outname, fname);
- }
- else if (out) {
- unlink (outname);
- }
+ deadbeef->pl_set_meta_int(it, ":FILE_SIZE", file_size);
+ return cvorbis_read_metadata(it);
- return err;
+ return 0;
}
@@ -791,22 +832,62 @@ static DB_decoder_t plugin = {
.plugin.id = "stdogg",
.plugin.name = "OggVorbis decoder",
.plugin.descr = "OggVorbis decoder using standard xiph.org libraries",
- .plugin.copyright =
- "Copyright (C) 2009-2013 Alexey Yakovenko <waker@users.sourceforge.net>\n"
- "\n"
- "This program is free software; you can redistribute it and/or\n"
- "modify it under the terms of the GNU General Public License\n"
- "as published by the Free Software Foundation; either version 2\n"
- "of the License, or (at your option) any later version.\n"
- "\n"
- "This program is distributed in the hope that it will be useful,\n"
- "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
- "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
- "GNU General Public License for more details.\n"
- "\n"
- "You should have received a copy of the GNU General Public License\n"
- "along with this program; if not, write to the Free Software\n"
- "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n"
+ .plugin.copyright =
+ "OggVorbis plugin for DeaDBeeF\n"
+ "Copyright (C) 2009-2014 Alexey Yakovenko et al.\n"
+ "\n"
+ "vcedit.c\n"
+ "Ogg Vorbis plugin Ogg edit functions\n"
+ "\n"
+ "Copyright (C) 2014 Ian Nartowicz <deadbeef@nartowicz.co.uk>\n"
+ "This software is provided 'as-is', without any express or implied\n"
+ "warranty. In no event will the authors be held liable for any damages\n"
+ "arising from the use of this software.\n"
+ "\n"
+ "Permission is granted to anyone to use this software for any purpose,\n"
+ "including commercial applications, and to alter it and redistribute it\n"
+ "freely, subject to the following restrictions:\n"
+ "\n"
+ "1. The origin of this software must not be misrepresented; you must not\n"
+ " claim that you wrote the original software. If you use this software\n"
+ " in a product, an acknowledgment in the product documentation would be\n"
+ " appreciated but is not required.\n"
+ "\n"
+ "2. Altered source versions must be plainly marked as such, and must not be\n"
+ " misrepresented as being the original software.\n"
+ "\n"
+ "3. This notice may not be removed or altered from any source distribution.\n"
+ "\n"
+ "\n"
+ "\n"
+ "Uses libogg,libvorbis Copyright (c) 2002, Xiph.org Foundation\n"
+ "\n"
+ "Redistribution and use in source and binary forms, with or without\n"
+ "modification, are permitted provided that the following conditions\n"
+ "are met:\n"
+ "\n"
+ "- Redistributions of source code must retain the above copyright\n"
+ "notice, this list of conditions and the following disclaimer.\n"
+ "\n"
+ "- Redistributions in binary form must reproduce the above copyright\n"
+ "notice, this list of conditions and the following disclaimer in the\n"
+ "documentation and/or other materials provided with the distribution.\n"
+ "\n"
+ "- Neither the name of the DeaDBeeF Player nor the names of its\n"
+ "contributors may be used to endorse or promote products derived from\n"
+ "this software without specific prior written permission.\n"
+ "\n"
+ "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
+ "``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
+ "LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
+ "A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR\n"
+ "CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n"
+ "EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n"
+ "PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n"
+ "PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\n"
+ "LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\n"
+ "NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n"
+ "SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
,
.plugin.website = "http://deadbeef.sf.net",
.plugin.start = vorbis_start,
diff --git a/plugins/wavpack/Makefile.am b/plugins/wavpack/Makefile.am
index 06100ea5..17651ee5 100644
--- a/plugins/wavpack/Makefile.am
+++ b/plugins/wavpack/Makefile.am
@@ -5,5 +5,5 @@ wavpack_la_SOURCES = wavpack.c
wavpack_la_LDFLAGS = -module -avoid-version
wavpack_la_LIBADD = $(LDADD) $(WAVPACK_LIBS)
-AM_CFLAGS = $(CFLAGS) -std=c99
+AM_CFLAGS = $(CFLAGS) $(WAVPACK_CFLAGS) -std=c99
endif
diff --git a/plugins/wma/asfheader.c b/plugins/wma/asfheader.c
index db662103..9e12f12f 100644
--- a/plugins/wma/asfheader.c
+++ b/plugins/wma/asfheader.c
@@ -751,6 +751,9 @@ static int asf_parse_header(DB_FILE *fd, asf_waveformatex_t* wfx, DB_playItem_t
if (type == 0) { // FIXME: custom fields -- after others work
unsigned char *s = id3buf;
asf_utf16LEdecode(fd, length, &id3buf, &id3buf_remaining);
+ if (!strcmp (utf8buf, "MusicBrainz/Track Id")) {
+ strcpy (utf8buf, "musicbrainz_trackid");
+ }
deadbeef->pl_append_meta (it, utf8buf, s);
}
else {