Beispiel #1
0
static int
opusdec_read_metadata (DB_playItem_t *it) {
    int res = -1;

    DB_FILE *fp = NULL;
    OggOpusFile *opusfile = NULL;
    const OpusHead *head = NULL;

    deadbeef->pl_lock ();
    const char *uri = strdupa (deadbeef->pl_find_meta (it, ":URI"));
    deadbeef->pl_unlock ();
    fp = deadbeef->fopen (uri);
    if (!fp) {
        goto error;
    }
    if (fp->vfs->is_streaming ()) {
        goto error;
    }

    opusfile = opus_file_open (fp);
    if (!opusfile) {
        goto error;
    }

    int tracknum = deadbeef->pl_find_meta_int (it, ":TRACKNUM", -1);
    head = op_head (opusfile, tracknum);
    if (!head) {
        goto error;
    }

    if (update_vorbis_comments (it, opusfile, tracknum)) {
        goto error;
    }

    res = 0;
error:
    if (opusfile) {
        op_free (opusfile);
    }
    if (fp) {
        deadbeef->fclose (fp);
    }
    return res;
}
Beispiel #2
0
static bool
new_streaming_link(opusdec_info_t *info, const int new_link)
{
    if (!info->info.file->vfs->is_streaming () || new_link < 0) {
        return false;
    }

    update_vorbis_comments(info->it, info->opusfile, new_link);
    send_event(info->it, DB_EV_SONGSTARTED);
    send_event(info->it, DB_EV_TRACKINFOCHANGED);
    deadbeef->sendmessage(DB_EV_PLAYLISTCHANGED, 0, DDB_PLAYLIST_CHANGE_CONTENT, 0);
    info->cur_bit_stream = new_link;

    const OpusHead *head = op_head (info->opusfile, new_link);
    if (head && info->info.fmt.channels != head->channel_count) {
        info->info.fmt.channels = head->channel_count;
        deadbeef->pl_set_meta_int (info->it, ":CHANNELS", head->channel_count);
        return true;
    }

    return false;
}
Beispiel #3
0
// refresh_playlist == 1 means "send playlistchanged event if metadata had been changed"
// refresh_playlist == 2 means "don't change memory, just check for changes"
static int
update_vorbis_comments (DB_playItem_t *it, vorbis_comment *vc, int refresh_playlist) {
    if (refresh_playlist == 1) {
        if (!update_vorbis_comments (it, vc, 2)) {
            return 0;
        }
    }

    if (vc) {
        if (refresh_playlist != 2) {
            deadbeef->pl_delete_all_meta (it);
        }
        for (int i = 0; i < vc->comments; i++) {
            char *s = vc->user_comments[i];
            int m;
            for (m = 0; metainfo[m]; m += 2) {
                int l = strlen (metainfo[m]);
                if (vc->comment_lengths[i] > l && !strncasecmp (metainfo[m], s, l) && s[l] == '=') {
                    if (refresh_playlist == 2) {
                        deadbeef->pl_lock ();
                        const char *val = deadbeef->pl_find_meta (it, metainfo[m+1]);
                        if (!val || strcmp (val, s+l+1)) {
                            deadbeef->pl_unlock ();
                            return 1;
                        }
                        deadbeef->pl_unlock ();
                    }
                    else {
                        deadbeef->pl_append_meta (it, metainfo[m+1], s + l + 1);
                        break;
                    }
                }
            }
            if (!metainfo[m] && refresh_playlist != 2) {
                if (!strncasecmp (s, "cuesheet=", 9)) {
                    deadbeef->pl_add_meta (it, "cuesheet", s + 9);
                }
                else if (!strncasecmp (s, "replaygain_album_gain=", 22)) {
                    deadbeef->pl_set_item_replaygain (it, DDB_REPLAYGAIN_ALBUMGAIN, atof (s+22));
                }
                else if (!strncasecmp (s, "replaygain_album_peak=", 22)) {
                    deadbeef->pl_set_item_replaygain (it, DDB_REPLAYGAIN_ALBUMPEAK, atof (s+22));
                }
                else if (!strncasecmp (s, "replaygain_track_gain=", 22)) {
                    deadbeef->pl_set_item_replaygain (it, DDB_REPLAYGAIN_TRACKGAIN, atof (s+22));
                }
                else if (!strncasecmp (s, "replaygain_track_peak=", 22)) {
                    deadbeef->pl_set_item_replaygain (it, DDB_REPLAYGAIN_TRACKPEAK, atof (s+22));
                }
                else {
                    const char *p = s;
                    while (*p && *p != '=') {
                        p++;
                    }
                    if (*p == '=') {
                        char key[p-s+1];
                        memcpy (key, s, p-s);
                        key[p-s] = 0;
                        deadbeef->pl_add_meta (it, key, p+1);
                    }
                }
            }
        }
    }
    if (refresh_playlist == 2) {
        return 0;
    }
    deadbeef->pl_add_meta (it, "title", NULL);
    uint32_t f = deadbeef->pl_get_item_flags (it);
    f &= ~DDB_TAG_MASK;
    f |= DDB_TAG_VORBISCOMMENTS;
    deadbeef->pl_set_item_flags (it, f);
    ddb_playlist_t *plt = deadbeef->plt_get_curr ();
    if (plt) {
        deadbeef->plt_modified (plt);
        deadbeef->plt_unref (plt);
    }

    if (refresh_playlist) {
        deadbeef->sendmessage (DB_EV_PLAYLISTCHANGED, 0, 0, 0);
    }
    return 0;
}
Beispiel #4
0
static DB_playItem_t *
opusdec_insert (ddb_playlist_t *plt, DB_playItem_t *after, const char *fname) {
    DB_FILE *fp = deadbeef->fopen (fname);
    if (!fp) {
        return NULL;
    }
    int64_t fsize = deadbeef->fgetlength (fp);
    if (fp->vfs->is_streaming ()) {
        DB_playItem_t *it = deadbeef->pl_item_alloc_init (fname, plugin.plugin.id);
        deadbeef->plt_set_item_duration (plt, it, -1);
        deadbeef->pl_add_meta (it, "title", NULL);
        after = deadbeef->plt_insert_item (plt, after, it);
        deadbeef->pl_item_unref (it);
        deadbeef->fclose (fp);
        return after;
    }

    OggOpusFile *opusfile = opus_file_open (fp);
    if (!opusfile) {
        deadbeef->fclose (fp);
        return NULL;
    }

    long nstreams = op_link_count (opusfile);
    int64_t currentsample = 0;
    for (int stream = 0; stream < nstreams; stream++) {
        const OpusHead *head = op_head (opusfile, stream);
        if (!head) {
            continue;
        }
        int64_t totalsamples = op_pcm_total (opusfile, stream);
        const float duration = totalsamples / 48000.f;

        DB_playItem_t *it = deadbeef->pl_item_alloc_init (fname, plugin.plugin.id);
        deadbeef->pl_set_meta_int (it, ":TRACKNUM", stream);
        deadbeef->plt_set_item_duration (plt, it, duration);
        if (nstreams > 1) {
            deadbeef->pl_item_set_startsample (it, currentsample);
            deadbeef->pl_item_set_endsample (it, currentsample + totalsamples - 1);
            deadbeef->pl_set_item_flags (it, DDB_IS_SUBTRACK);
        }

        if (update_vorbis_comments (it, opusfile, stream))
            continue;
        int samplerate = 48000;

        int64_t startsample = deadbeef->pl_item_get_startsample (it);
        int64_t endsample = deadbeef->pl_item_get_endsample (it);

        const off_t start_offset = sample_offset(opusfile, startsample-1);
        const off_t end_offset = sample_offset(opusfile, endsample);
        char *filetype = NULL;
        const off_t stream_size = oggedit_opus_stream_info(deadbeef->fopen(fname), start_offset, end_offset, &filetype);
        if (filetype) {
            deadbeef->pl_replace_meta(it, ":FILETYPE", filetype);
            free(filetype);
        }
        if (stream_size > 0) {
            set_meta_ll(it, ":OPUS_STREAM_SIZE", stream_size);
            deadbeef->pl_set_meta_int(it, ":BITRATE", 8.f * samplerate * stream_size / totalsamples / 1000);
        }
        set_meta_ll (it, ":FILE_SIZE", fsize);
        deadbeef->pl_set_meta_int (it, ":CHANNELS", head->channel_count);
        deadbeef->pl_set_meta_int (it, ":SAMPLERATE", samplerate);

        if (nstreams == 1) {
            DB_playItem_t *cue = deadbeef->plt_process_cue (plt, after, it,  totalsamples, samplerate);
            if (cue) {
                deadbeef->pl_item_unref (it);
                op_free(opusfile);
                deadbeef->fclose (fp);
                return cue;
            }
        }
        else {
            currentsample += totalsamples;
        }

        after = deadbeef->plt_insert_item (plt, after, it);
        deadbeef->pl_item_unref (it);
    }
    op_free(opusfile);
    deadbeef->fclose (fp);
    return after;
}
Beispiel #5
0
static int
opusdec_init (DB_fileinfo_t *_info, DB_playItem_t *it) {
    opusdec_info_t *info = (opusdec_info_t *)_info;

    if (!info->info.file) {
        deadbeef->pl_lock ();
	const char *uri = strdupa (deadbeef->pl_find_meta (it, ":URI"));
        deadbeef->pl_unlock ();
        DB_FILE *fp = deadbeef->fopen (uri);

        if (!fp) {
            return -1;
        }
        info->info.file = fp;
        info->it = it;
        deadbeef->pl_item_ref (it);
    }

    info->opusfile = opus_file_open (info->info.file);
    if (!info->opusfile) {
        return -1;
    }

    const OpusHead *head = op_head (info->opusfile, 0);

    if (head->channel_count > 8) {
        trace ("opus: the track has %d channels, but 8 is max supported.\n");
        return -1;
    }

    // take this parameters from your input file
    // we set constants for clarity sake
    _info->fmt.bps = 32;
    _info->fmt.is_float = 1;
    _info->fmt.channels = head->channel_count;
    _info->fmt.samplerate  = 48000;
    if (head->mapping_family == 1) {
        info->channelmap = oggedit_vorbis_channel_map (head->channel_count);
    }

    for (int i = 0; i < (_info->fmt.channels&0x1f); i++) {
        _info->fmt.channelmask |= 1 << i;
    }
    _info->readpos = 0;
    _info->plugin = &plugin;

    // set all gain adjustment to 0, because deadbeef is performing that.
    op_set_gain_offset (info->opusfile, OP_ABSOLUTE_GAIN, 0);

    if (info->info.file->vfs->is_streaming ()) {
        deadbeef->pl_item_set_startsample (it, 0);
        if (deadbeef->pl_get_item_duration (it) < 0) {
            deadbeef->pl_item_set_endsample (it, -1);
        }
        else {
            deadbeef->pl_item_set_endsample (it, op_pcm_total (info->opusfile, -1) - 1);
        }

        if (update_vorbis_comments (it, info->opusfile, -1))
            return -1;

        deadbeef->pl_set_meta_int(it, ":TRACKNUM", 0);
    }
    else {
        opusdec_seek_sample (_info, 0);
    }

    deadbeef->pl_replace_meta (it, "!FILETYPE", "Ogg Opus");
    deadbeef->pl_set_meta_int (it, ":CHANNELS", head->channel_count);

    info->cur_bit_stream = -1;

    return 0;
}