summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--main.c34
-rw-r--r--plugins/artwork/albumartorg.c13
-rw-r--r--plugins/artwork/artwork.c4
-rw-r--r--plugins/artwork/lastfm.c13
-rw-r--r--plugins/gtkui/coverart.c15
-rw-r--r--plugins/gtkui/ddblistview.c10
-rw-r--r--plugins/gtkui/ddbtabstrip.c4
-rw-r--r--plugins/vfs_curl/vfs_curl.c38
-rw-r--r--plugins/vorbis/vorbis.c96
9 files changed, 163 insertions, 64 deletions
diff --git a/main.c b/main.c
index 2887fc8a..0cae38ba 100644
--- a/main.c
+++ b/main.c
@@ -38,6 +38,7 @@
#include <sys/fcntl.h>
#include <sys/errno.h>
#include <signal.h>
+#include <execinfo.h>
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
@@ -428,9 +429,40 @@ sigterm_handler (int sig) {
exit (0);
}
+void
+sigsegv_handler (int sig) {
+ fprintf (stderr, "Segmentation Fault\n");
+ int j, nptrs;
+#define SIZE 100
+ void *buffer[100];
+ char **strings;
+
+ nptrs = backtrace(buffer, SIZE);
+ printf("backtrace() returned %d addresses\n", nptrs);
+
+ /* The call
+ * backtrace_symbols_fd(buffer,
+ * nptrs,
+ * STDOUT_FILENO)
+ would produce similar output to the following: */
+
+ strings = backtrace_symbols(buffer, nptrs);
+ if (strings == NULL) {
+ perror("backtrace_symbols");
+ exit(EXIT_FAILURE);
+ }
+
+ for (j = 0; j < nptrs; j++)
+ printf("%s\n", strings[j]);
+
+ free(strings);
+ exit (0);
+}
+
int
main (int argc, char *argv[]) {
- setlocale (LC_ALL, "");
+ signal (SIGSEGV, sigsegv_handler);
+ setlocale (LC_ALL, "");
setlocale (LC_NUMERIC, "C");
#ifdef ENABLE_NLS
// fprintf (stderr, "enabling gettext support: package=" PACKAGE ", dir=" LOCALEDIR "...\n");
diff --git a/plugins/artwork/albumartorg.c b/plugins/artwork/albumartorg.c
index 18b494a4..d438cf9c 100644
--- a/plugins/artwork/albumartorg.c
+++ b/plugins/artwork/albumartorg.c
@@ -74,9 +74,11 @@ fetch_from_albumart_org (const char *artist, const char *album, const char *dest
}
current_file = fp;
- FILE *out = fopen (dest, "w+b");
+ char temp[PATH_MAX];
+ snprintf (temp, sizeof (temp), "%s.part", dest);
+ FILE *out = fopen (temp, "w+b");
if (!out) {
- trace ("fetch_from_albumart_org: failed to open %s for writing\n", dest);
+ trace ("fetch_from_albumart_org: failed to open %s for writing\n", temp);
current_file = NULL;
deadbeef->fclose (fp);
return -1;
@@ -98,9 +100,16 @@ fetch_from_albumart_org (const char *artist, const char *album, const char *dest
deadbeef->fclose (fp);
if (error) {
+ unlink (temp);
+ return -1;
+ }
+
+ if (rename (temp, dest) != 0) {
+ unlink (temp);
unlink (dest);
return -1;
}
+
return 0;
}
diff --git a/plugins/artwork/artwork.c b/plugins/artwork/artwork.c
index ef2d0e00..4af9658b 100644
--- a/plugins/artwork/artwork.c
+++ b/plugins/artwork/artwork.c
@@ -435,7 +435,7 @@ fetcher_thread (void *none)
char*
get_album_art (const char *fname, const char *artist, const char *album, artwork_callback callback, void *user_data)
{
-// trace ("get_album_art: %s (%s - %s)\n", fname, artist, album);
+ trace ("get_album_art: %s (%s - %s)\n", fname, artist, album);
char path [1024];
if (!album) {
@@ -470,7 +470,7 @@ get_album_art (const char *fname, const char *artist, const char *album, artwork
}
}
-// trace ("found %s in cache\n", path);
+ trace ("found %s in cache\n", path);
return strdup (path);
}
diff --git a/plugins/artwork/lastfm.c b/plugins/artwork/lastfm.c
index 2aed6d7c..bf76ccca 100644
--- a/plugins/artwork/lastfm.c
+++ b/plugins/artwork/lastfm.c
@@ -64,9 +64,11 @@ fetch_from_lastfm (const char *artist, const char *album, const char *dest)
}
current_file = fp;
- FILE *out = fopen (dest, "w+b");
+ char temp[PATH_MAX];
+ snprintf (temp, sizeof (temp), "%s.part", dest);
+ FILE *out = fopen (temp, "w+b");
if (!out) {
- trace ("fetch_from_lastfm: failed to open %s for writing\n", dest);
+ trace ("fetch_from_lastfm: failed to open %s for writing\n", temp);
deadbeef->fclose (fp);
current_file = NULL;
return -1;
@@ -88,8 +90,15 @@ fetch_from_lastfm (const char *artist, const char *album, const char *dest)
deadbeef->fclose (fp);
if (error) {
+ unlink (temp);
+ return -1;
+ }
+
+ if (rename (temp, dest) != 0) {
+ unlink (temp);
unlink (dest);
return -1;
}
+
return 0;
}
diff --git a/plugins/gtkui/coverart.c b/plugins/gtkui/coverart.c
index af6ed4d3..778d83f1 100644
--- a/plugins/gtkui/coverart.c
+++ b/plugins/gtkui/coverart.c
@@ -140,17 +140,18 @@ loading_thread (void *none) {
usleep (500000);
continue;
}
- trace ("loading image %s\n", queue->fname);
- GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file (queue->fname, NULL);
+// GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file (queue->fname, NULL);
+ GError *error;
+ GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file_at_scale (queue->fname, queue->width, queue->width, TRUE, &error);
if (!pixbuf) {
- trace ("GDK failed to load pixbuf from file %s\n", queue->fname);
pixbuf = gdk_pixbuf_new_from_file (DEFAULT_COVER_PATH, NULL);
}
if (!pixbuf) {
// make default empty image
pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, 2, 2);
}
+#if 0
else {
int w, h;
w = gdk_pixbuf_get_width (pixbuf);
@@ -179,6 +180,7 @@ loading_thread (void *none) {
pixbuf = scaled;
}
}
+#endif
if (cache_min != -1) {
deadbeef->mutex_lock (mutex);
cache[cache_min].pixbuf = pixbuf;
@@ -217,9 +219,10 @@ get_pixbuf (const char *fname, int width) {
if (cache[i].pixbuf) {
if (!strcmp (fname, cache[i].fname) && cache[i].width == width) {
gettimeofday (&cache[i].tm, NULL);
- g_object_ref (cache[i].pixbuf);
+ GdkPixbuf *pb = cache[i].pixbuf;
+ g_object_ref (pb);
deadbeef->mutex_unlock (mutex);
- return cache[i].pixbuf;
+ return pb;
}
}
}
@@ -242,7 +245,7 @@ get_cover_art (const char *fname, const char *artist, const char *album, int wid
return NULL;
}
char *image_fname = coverart_plugin->get_album_art (fname, artist, album, cover_avail_callback, (void *)(intptr_t)width);
- if (fname) {
+ if (image_fname) {
GdkPixbuf *pb = get_pixbuf (image_fname, width);
free (image_fname);
return pb;
diff --git a/plugins/gtkui/ddblistview.c b/plugins/gtkui/ddblistview.c
index c9f4c6da..3ddd3568 100644
--- a/plugins/gtkui/ddblistview.c
+++ b/plugins/gtkui/ddblistview.c
@@ -28,7 +28,6 @@
#include <stdlib.h>
#include <time.h>
#include <string.h>
-#include <assert.h>
#include <unistd.h>
#include <ctype.h>
#include <assert.h>
@@ -37,6 +36,8 @@
#include "drawing.h"
#include "gtkui.h"
+#pragma GCC optimize("O0")
+
#define min(x,y) ((x)<(y)?(x):(y))
#define max(x,y) ((x)>(y)?(x):(y))
@@ -707,6 +708,7 @@ ddb_listview_list_expose_event (GtkWidget *widget,
void
ddb_listview_list_expose (DdbListview *listview, int x, int y, int w, int h) {
+// printf ("listview height: %d\n", listview->list->allocation.height);
GtkWidget *widget = listview->list;
if (widget->window && listview->backbuf) {
draw_drawable (widget->window, widget->style->black_gc, listview->backbuf, x, y, x, y, w, h);
@@ -974,6 +976,12 @@ ddb_listview_list_drag_leave (GtkWidget *widget,
// debug function for gdk_draw_drawable
static inline void
draw_drawable (GdkDrawable *window, GdkGC *gc, GdkDrawable *drawable, int x1, int y1, int x2, int y2, int w, int h) {
+ gint width1, height1;
+ gint width2, height2;
+ gdk_drawable_get_size (window, &width1, &height1);
+ gdk_drawable_get_size (drawable, &width2, &height2);
+// assert (y1 >= 0 && y1 + h < height2);
+// assert (y2 >= 0 && y2 + h < height1);
// printf ("dd: %p %p %p %d %d %d %d %d %d\n", window, gc, drawable, x1, y1, x2, y2, w, h);
gdk_draw_drawable (window, gc, drawable, x1, y1, x2, y2, w, h);
}
diff --git a/plugins/gtkui/ddbtabstrip.c b/plugins/gtkui/ddbtabstrip.c
index 6f01499b..82b11003 100644
--- a/plugins/gtkui/ddbtabstrip.c
+++ b/plugins/gtkui/ddbtabstrip.c
@@ -461,7 +461,7 @@ tabstrip_render (DdbTabStrip *ts) {
}
if (need_draw_moving) {
x = -ts->hscrollpos + tabs_left_margin;
- for (idx = 0; idx < 10; idx++) {
+ for (idx = 0; idx < cnt; idx++) {
w = widths[idx];
if (idx == ts->dragging) {
#if 0
@@ -475,7 +475,7 @@ tabstrip_render (DdbTabStrip *ts) {
break;
}
if (w > 0) {
-// gtk_paint_box (widget->style, backbuf, GTK_STATE_SELECTED, GTK_SHADOW_OUT, NULL, widget, "button", x, 0, w, h);
+ //gtk_paint_box (widget->style, backbuf, GTK_STATE_SELECTED, GTK_SHADOW_OUT, NULL, widget, "button", x, 0, w, h);
ddb_tabstrip_draw_tab (widget, backbuf, 1, x, y, w, h);
char tab_title[100];
plt_get_title_wrapper (idx, tab_title, sizeof (tab_title));
diff --git a/plugins/vfs_curl/vfs_curl.c b/plugins/vfs_curl/vfs_curl.c
index 22b00216..eb64b17d 100644
--- a/plugins/vfs_curl/vfs_curl.c
+++ b/plugins/vfs_curl/vfs_curl.c
@@ -25,8 +25,10 @@
#include <time.h>
#include "../../deadbeef.h"
-//#define trace(...) { fprintf(stderr, __VA_ARGS__); }
-#define trace(fmt,...)
+#pragma GCC optimize("O0")
+
+#define trace(...) { fprintf(stderr, __VA_ARGS__); }
+//#define trace(fmt,...)
#define min(x,y) ((x)<(y)?(x):(y))
#define max(x,y) ((x)>(y)?(x):(y))
@@ -40,12 +42,13 @@ static DB_functions_t *deadbeef;
#define TIMEOUT 10 // in seconds
-#define STATUS_INITIAL 0
-//#define STATUS_STARTING 1
-#define STATUS_READING 2
-#define STATUS_FINISHED 3
-#define STATUS_ABORTED 4
-#define STATUS_SEEK 5
+enum {
+ STATUS_INITIAL = 0,
+ STATUS_READING = 1,
+ STATUS_FINISHED = 2,
+ STATUS_ABORTED = 3,
+ STATUS_SEEK = 4,
+};
typedef struct {
DB_vfs_t *vfs;
@@ -495,7 +498,7 @@ http_thread_func (void *ctx) {
curl_easy_setopt (curl, CURLOPT_MAXREDIRS, 10);
headers = curl_slist_append (headers, "Icy-Metadata:1");
curl_easy_setopt (curl, CURLOPT_HTTPHEADER, headers);
- if (fp->pos > 0) {
+ if (fp->pos > 0 && fp->length >= 0) {
curl_easy_setopt (curl, CURLOPT_RESUME_FROM, fp->pos);
}
if (deadbeef->conf_get_int ("network.proxy", 0)) {
@@ -551,6 +554,23 @@ http_thread_func (void *ctx) {
trace ("curl error:\n%s\n", http_err);
}
deadbeef->mutex_lock (fp->mutex);
+ if (status == 0 && fp->length < 0 && fp->status != STATUS_ABORTED && fp->status != STATUS_SEEK) {
+ trace ("vfs_curl: restarting stream\n");
+ fp->status = STATUS_INITIAL;
+ fp->skipbytes = 0;
+ if (fp->content_type) {
+ free (fp->content_type);
+ fp->content_type = NULL;
+ }
+ fp->seektoend = 0;
+ fp->gotheader = 0;
+ fp->icyheader = 0;
+ fp->gotsomeheader = 0;
+ fp->wait_meta = 0;
+ fp->icy_metaint = 0;
+ deadbeef->mutex_unlock (fp->mutex);
+ continue;
+ }
if (fp->status != STATUS_SEEK) {
deadbeef->mutex_unlock (fp->mutex);
break;
diff --git a/plugins/vorbis/vorbis.c b/plugins/vorbis/vorbis.c
index 6704f8fe..a7b95b29 100644
--- a/plugins/vorbis/vorbis.c
+++ b/plugins/vorbis/vorbis.c
@@ -144,7 +144,7 @@ cvorbis_init (DB_fileinfo_t *_info, DB_playItem_t *it) {
ogg_info_t *info = (ogg_info_t *)_info;
info->info.file = NULL;
info->vi = NULL;
- info->cur_bit_stream = -1;
+ info->cur_bit_stream = it->tracknum;
info->ptrack = it;
deadbeef->pl_item_ref (it);
@@ -187,7 +187,7 @@ cvorbis_init (DB_fileinfo_t *_info, DB_playItem_t *it) {
}
// deadbeef->pl_set_item_duration (it, ov_time_total (&vorbis_file, -1));
}
- info->vi = ov_info (&info->vorbis_file, -1);
+ info->vi = ov_info (&info->vorbis_file, info->cur_bit_stream);
if (!info->vi) { // not a vorbis stream
trace ("not a vorbis stream\n");
return -1;
@@ -385,46 +385,64 @@ cvorbis_insert (DB_playItem_t *after, const char *fname) {
trace ("ov_open_callbacks returned %d\n", err);
return NULL;
}
- vi = ov_info (&vorbis_file, -1);
- if (!vi) { // not a vorbis stream
- trace ("vorbis: failed to ov_open %s\n", fname);
- return NULL;
- }
- float duration = ov_time_total (&vorbis_file, -1);
- int totalsamples = ov_pcm_total (&vorbis_file, -1);
- DB_playItem_t *it = deadbeef->pl_item_alloc ();
- it->decoder_id = deadbeef->plug_get_decoder_id (plugin.plugin.id);
- it->fname = strdup (fname);
- it->filetype = "OggVorbis";
- deadbeef->pl_set_item_duration (it, duration);
+ long nstreams = ov_streams (&vorbis_file);
+ int currentsample = 0;
+ for (int stream = 0; stream < nstreams; stream++) {
+ vi = ov_info (&vorbis_file, stream);
+ if (!vi) { // not a vorbis stream
+ trace ("vorbis: ov_info failed for file %s stream %d\n", fname, stream);
+ continue;
+ }
+ float duration = ov_time_total (&vorbis_file, stream);
+ int totalsamples = ov_pcm_total (&vorbis_file, stream);
- // metainfo
- vorbis_comment *vc = ov_comment (&vorbis_file, -1);
- update_vorbis_comments (it, vc);
- int samplerate = vi->rate;
- ov_clear (&vorbis_file);
+ DB_playItem_t *it = deadbeef->pl_item_alloc ();
+ it->decoder_id = deadbeef->plug_get_decoder_id (plugin.plugin.id);
+ it->fname = strdup (fname);
+ it->filetype = "OggVorbis";
+ it->tracknum = stream;
+ deadbeef->pl_set_item_duration (it, duration);
+ if (nstreams > 0) {
+ it->startsample = currentsample;
+ it->endsample = currentsample + totalsamples;
+ deadbeef->pl_set_item_flags (it, DDB_IS_SUBTRACK);
+ }
- DB_playItem_t *cue = deadbeef->pl_insert_cue (after, it, totalsamples, samplerate);
- if (cue) {
- deadbeef->pl_item_unref (it);
- deadbeef->pl_item_unref (cue);
- return cue;
- }
-
- // embedded cue
- const char *cuesheet = deadbeef->pl_find_meta (it, "cuesheet");
- if (cuesheet) {
- cue = deadbeef->pl_insert_cue_from_buffer (after, it, cuesheet, strlen (cuesheet), totalsamples, samplerate);
- if (cue) {
- deadbeef->pl_item_unref (it);
- deadbeef->pl_item_unref (cue);
- return cue;
+ // metainfo
+ vorbis_comment *vc = ov_comment (&vorbis_file, stream);
+ update_vorbis_comments (it, vc);
+ int samplerate = vi->rate;
+
+ if (nstreams == 1) {
+ DB_playItem_t *cue = deadbeef->pl_insert_cue (after, it, totalsamples, samplerate);
+ if (cue) {
+ deadbeef->pl_item_unref (it);
+ deadbeef->pl_item_unref (cue);
+ ov_clear (&vorbis_file);
+ return cue;
+ }
+
+ // embedded cue
+ const char *cuesheet = deadbeef->pl_find_meta (it, "cuesheet");
+ if (cuesheet) {
+ cue = deadbeef->pl_insert_cue_from_buffer (after, it, cuesheet, strlen (cuesheet), totalsamples, samplerate);
+ if (cue) {
+ deadbeef->pl_item_unref (it);
+ deadbeef->pl_item_unref (cue);
+ ov_clear (&vorbis_file);
+ return cue;
+ }
+ }
+ }
+ else {
+ currentsample += totalsamples;
}
- }
- after = deadbeef->pl_insert_item (after, it);
- deadbeef->pl_item_unref (it);
+ after = deadbeef->pl_insert_item (after, it);
+ deadbeef->pl_item_unref (it);
+ }
+ ov_clear (&vorbis_file);
return after;
}
@@ -464,14 +482,14 @@ cvorbis_read_metadata (DB_playItem_t *it) {
trace ("cvorbis_read_metadata: ov_open_callbacks returned %d\n", res);
goto error;
}
- vi = ov_info (&vorbis_file, -1);
+ vi = ov_info (&vorbis_file, it->tracknum);
if (!vi) { // not a vorbis stream
trace ("cvorbis_read_metadata: failed to ov_open %s\n", it->fname);
goto error;
}
// metainfo
- vorbis_comment *vc = ov_comment (&vorbis_file, -1);
+ vorbis_comment *vc = ov_comment (&vorbis_file, it->tracknum);
if (vc) {
update_vorbis_comments (it, vc);
}