Ejemplo n.º 1
0
int main(int argc, char * argv[]) {
    /* parse arguments */
    char *exe = argv[0];
    char *filename;
    struct GrooveFile *file;
    int i;
    char *arg;
    char *key;
    char *value;
    struct GrooveTag *tag;

    if (argc < 2)
        return usage(exe);

    printf("Using libgroove v%s\n", groove_version());

    filename = argv[1];
    groove_init();
    atexit(groove_finish);
    groove_set_logging(GROOVE_LOG_INFO);
    file = groove_file_open(filename);
    if (!file) {
        fprintf(stderr, "error opening file\n");
        return 1;
    }

    for (i = 2; i < argc; i += 1) {
        arg = argv[i];
        if (strcmp("--update", arg) == 0) {
            if (i + 2 >= argc) {
                groove_file_close(file);
                fprintf(stderr, "--update requires 2 arguments");
                return usage(exe);
            }
            key = argv[++i];
            value = argv[++i];
            groove_file_metadata_set(file, key, value, 0);
        } else if (strcmp("--delete", arg) == 0) {
            if (i + 1 >= argc) {
                groove_file_close(file);
                fprintf(stderr, "--delete requires 1 argument");
                return usage(exe);
            }
            key = argv[++i];
            groove_file_metadata_set(file, key, NULL, 0);
        } else {
            groove_file_close(file);
            return usage(exe);
        }
    }
    tag = NULL;
    printf("duration=%f\n", groove_file_duration(file));
    while ((tag = groove_file_metadata_get(file, "", tag, 0)))
        printf("%s=%s\n", groove_tag_key(tag), groove_tag_value(tag));
    if (file->dirty && groove_file_save(file) < 0)
        fprintf(stderr, "error saving file\n");
    groove_file_close(file);
    return 0;
}
Ejemplo n.º 2
0
int groove_file_open(struct GrooveFile *file,
        const char *filename, const char *filename_hint)
{
    struct GrooveFilePrivate *f = (struct GrooveFilePrivate *) file;

    f->stdfile = fopen(filename, "rb");
    if (!f->stdfile) {
        int err = errno;
        assert(err != EINVAL);
        groove_file_close(file);
        if (err == ENOMEM) {
            return GrooveErrorNoMem;
        } else if (err == ENOENT) {
            return GrooveErrorFileNotFound;
        } else if (err == EPERM) {
            return GrooveErrorPermissions;
        } else {
            return GrooveErrorFileSystem;
        }
    }

    f->prealloc_custom_io.userdata = f;
    f->prealloc_custom_io.read_packet = file_read_packet;
    f->prealloc_custom_io.write_packet = file_write_packet;
    f->prealloc_custom_io.seek = file_seek;

    return groove_file_open_custom(file, &f->prealloc_custom_io, filename_hint);
}
Ejemplo n.º 3
0
void groove_file_destroy(struct GrooveFile *file) {
    struct GrooveFilePrivate *f = (struct GrooveFilePrivate *)file;

    if (!file)
        return;

    groove_file_close(file);

    deallocate(f);
}
Ejemplo n.º 4
0
int main(int argc, char * argv[]) {
    // parse arguments
    const char *exe = argv[0];
    if (argc < 2) return usage(exe);

    groove_init();
    atexit(groove_finish);
    groove_set_logging(GROOVE_LOG_INFO);
    struct GroovePlaylist *playlist = groove_playlist_create();

    if (!playlist) {
        fprintf(stderr, "Error creating playlist.\n");
        return 1;
    }

    struct GroovePlayer *player = groove_player_create();

    for (int i = 1; i < argc; i += 1) {
        char *arg = argv[i];
        if (arg[0] == '-' && arg[1] == '-') {
            arg += 2;
            if (strcmp(arg, "dummy") == 0) {
                player->device_index = GROOVE_PLAYER_DUMMY_DEVICE;
            } else if (i + 1 >= argc) {
                return usage(exe);
            } else if (strcmp(arg, "volume") == 0) {
                double volume = atof(argv[++i]);
                groove_playlist_set_gain(playlist, volume);
            } else {
                return usage(exe);
            }
        } else {
            struct GrooveFile * file = groove_file_open(arg);
            if (!file) {
                fprintf(stderr, "Not queuing %s\n", arg);
                continue;
            }
            groove_playlist_insert(playlist, file, 1.0, 1.0, NULL);
        }
    }
    groove_player_attach(player, playlist);

    union GroovePlayerEvent event;
    struct GroovePlaylistItem *item;
    while (groove_player_event_get(player, &event, 1) >= 0) {
        switch (event.type) {
        case GROOVE_EVENT_BUFFERUNDERRUN:
            fprintf(stderr, "buffer underrun\n");
            break;
        case GROOVE_EVENT_NOWPLAYING:
            groove_player_position(player, &item, NULL);
            if (!item) {
                printf("done\n");
                item = playlist->head;
                while (item) {
                    struct GrooveFile *file = item->file;
                    struct GroovePlaylistItem *next = item->next;
                    groove_playlist_remove(playlist, item);
                    groove_file_close(file);
                    item = next;
                }
                groove_player_detach(player);
                groove_player_destroy(player);
                groove_playlist_destroy(playlist);
                return 0;
            }
            struct GrooveTag *artist_tag = groove_file_metadata_get(item->file, "artist", NULL, 0);
            struct GrooveTag *title_tag = groove_file_metadata_get(item->file, "title", NULL, 0);
            if (artist_tag && title_tag) {
                printf("Now playing: %s - %s\n", groove_tag_value(artist_tag),
                        groove_tag_value(title_tag));
            } else {
                printf("Now playing: %s\n", item->file->filename);
            }
            break;
        }
    }
    return 1;
}
Ejemplo n.º 5
0
int groove_file_open_custom(struct GrooveFile *file, struct GrooveCustomIo *custom_io,
        const char *filename_hint)
{
    struct GrooveFilePrivate *f = (struct GrooveFilePrivate *) file;

    f->custom_io = custom_io;

    if (pthread_mutex_init(&f->seek_mutex, NULL)) {
        groove_file_close(file);
        return GrooveErrorSystemResources;
    }

    f->ic = avformat_alloc_context();
    if (!f->ic) {
        groove_file_close(file);
        return GrooveErrorNoMem;
    }
    file->filename = f->ic->filename;
    f->ic->interrupt_callback.callback = decode_interrupt_cb;
    f->ic->interrupt_callback.opaque = f;

    const int buffer_size = 8 * 1024;
    f->avio_buf = allocate_nonzero<unsigned char>(buffer_size);
    if (!f->avio_buf) {
        groove_file_close(file);
        return GrooveErrorNoMem;
    }

    f->avio = avio_alloc_context(f->avio_buf, buffer_size, 0, f,
            avio_read_packet, avio_write_packet, avio_seek);
    if (!f->avio) {
        groove_file_close(file);
        return GrooveErrorNoMem;
    }
    f->avio->seekable = AVIO_SEEKABLE_NORMAL;
    f->avio->direct = AVIO_FLAG_DIRECT;

    f->ic->pb = f->avio;
    int err = avformat_open_input(&f->ic, filename_hint, NULL, NULL);
    if (err < 0) {
        assert(err != AVERROR(EINVAL));
        groove_file_close(file);
        if (err == AVERROR(ENOMEM)) {
            return GrooveErrorNoMem;
        } else if (err == AVERROR(ENOENT)) {
            return GrooveErrorFileNotFound;
        } else if (err == AVERROR(EPERM)) {
            return GrooveErrorPermissions;
        } else {
            return GrooveErrorUnknownFormat;
        }
    }

    err = avformat_find_stream_info(f->ic, NULL);
    if (err < 0) {
        groove_file_close(file);
        return GrooveErrorStreamNotFound;
    }

    // set all streams to discard. in a few lines here we will find the audio
    // stream and cancel discarding it
    if (f->ic->nb_streams > INT_MAX) {
        groove_file_close(file);
        return GrooveErrorTooManyStreams;
    }
    int stream_count = (int)f->ic->nb_streams;

    for (int i = 0; i < stream_count; i++)
        f->ic->streams[i]->discard = AVDISCARD_ALL;

    f->audio_stream_index = av_find_best_stream(f->ic, AVMEDIA_TYPE_AUDIO, -1, -1, &f->decoder, 0);

    if (f->audio_stream_index < 0) {
        groove_file_close(file);
        return GrooveErrorStreamNotFound;
    }

    if (!f->decoder) {
        groove_file_close(file);
        return GrooveErrorDecoderNotFound;
    }

    f->audio_st = f->ic->streams[f->audio_stream_index];
    f->audio_st->discard = AVDISCARD_DEFAULT;

    AVCodecContext *avctx = f->audio_st->codec;

    if (avcodec_open2(avctx, f->decoder, NULL) < 0) {
        groove_file_close(file);
        return GrooveErrorDecoding;
    }

    if (!avctx->channel_layout)
        avctx->channel_layout = av_get_default_channel_layout(avctx->channels);
    if (!avctx->channel_layout) {
        groove_file_close(file);
        return GrooveErrorInvalidChannelLayout;
    }

    // copy the audio stream metadata to the context metadata
    av_dict_copy(&f->ic->metadata, f->audio_st->metadata, 0);

    return 0;
}