Initial commit of mpg123-1.29.3
This commit is contained in:
62
doc/examples/Makefile
Normal file
62
doc/examples/Makefile
Normal file
@@ -0,0 +1,62 @@
|
||||
targets = \
|
||||
feedseek \
|
||||
mpg123_to_out123 \
|
||||
mpg123_to_wav_replaced_io \
|
||||
scan \
|
||||
id3dump \
|
||||
mpglib \
|
||||
dump_seekindex \
|
||||
extract_frames
|
||||
|
||||
all: $(targets)
|
||||
|
||||
# On largefile-aware systems you might want to use these instead:
|
||||
#MPG123_CFLAGS := $(shell pkg-config --cflags libmpg123_64)
|
||||
#MPG123_LDFLAGS := $(shell pkg-config --libs libmpg123_64)
|
||||
# This works on sane setups where off_t is off_t, and just that.
|
||||
ifeq ($(MPG123_PREFIX),)
|
||||
MPG123_CFLAGS := $(shell pkg-config --cflags libmpg123)
|
||||
MPG123_LDFLAGS := $(shell pkg-config --libs libmpg123)
|
||||
OUT123_CFLAGS := $(shell pkg-config --cflags libout123)
|
||||
OUT123_LDFLAGS := $(shell pkg-config --libs libout123)
|
||||
else # Yeah, that's with GNU/Linux in mind, at least GNU ld ...
|
||||
MPG123_CFLAGS := -I$(MPG123_PREFIX)/include
|
||||
MPG123_LDFLAGS := -L$(MPG123_PREFIX)/lib -Wl,-rpath $(MPG123_PREFIX)/lib -lmpg123
|
||||
OUT123_CFLAGS := -I$(MPG123_PREFIX)/include
|
||||
OUT123_LDFLAGS := -L$(MPG123_PREFIX)/lib -Wl,-rpath $(MPG123_PREFIX)/lib -lout123
|
||||
endif
|
||||
|
||||
# Define to any C99 compiler.
|
||||
CC = cc -std=c99
|
||||
CFLAGS = -O
|
||||
|
||||
# Oder of libs not that important here...
|
||||
compile = $(CC) $(CPPFLAGS) $(CFLAGS) $(MPG123_CFLAGS)
|
||||
linkflags = $(MPG123_LDFLAGS) $(LDFLAGS)
|
||||
|
||||
mpg123_to_out123: mpg123_to_out123.c
|
||||
$(compile) -o $@ $< $(OUT123_CFLAGS) $(OUT123_LDFLAGS) $(linkflags)
|
||||
|
||||
mpg123_to_wav_replaced_io: mpg123_to_wav_replaced_io.c
|
||||
$(compile) -o $@ $< $(OUT123_CFLAGS) $(OUT123_LDFLAGS) $(linkflags)
|
||||
|
||||
feedseek: feedseek.c
|
||||
$(compile) -o feedseek feedseek.c $(OUT123_CFLAGS) $(OUT123_LDFLAGS) $(linkflags)
|
||||
|
||||
scan: scan.c
|
||||
$(compile) -o scan scan.c $(linkflags)
|
||||
|
||||
id3dump:id3dump.c
|
||||
$(compile) -o id3dump id3dump.c $(linkflags)
|
||||
|
||||
dump_seekindex: dump_seekindex.c
|
||||
$(compile) -o dump_seekindex dump_seekindex.c $(linkflags)
|
||||
|
||||
mpglib: mpglib.c
|
||||
$(compile) -o mpglib mpglib.c $(linkflags)
|
||||
|
||||
extract_frames: extract_frames.c
|
||||
$(compile) -o $@ $< $(linkflags)
|
||||
|
||||
clean:
|
||||
rm -vf $(targets)
|
||||
44
doc/examples/dump_seekindex.c
Normal file
44
doc/examples/dump_seekindex.c
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
dump_seekindex: Scan a mpeg file and dump its seek index.
|
||||
|
||||
This is example code only sensible to be considered in the public domain.
|
||||
Initially written by Patrick Dehne.
|
||||
*/
|
||||
|
||||
#include <mpg123.h>
|
||||
#include <stdio.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
mpg123_handle *m;
|
||||
off_t* offsets;
|
||||
off_t step;
|
||||
size_t fill, i;
|
||||
|
||||
if(argc != 2)
|
||||
{
|
||||
fprintf(stderr, "\nI will dump the frame index of an MPEG audio file.\n");
|
||||
fprintf(stderr, "\nUsage: %s <mpeg audio file>\n\n", argv[0]);
|
||||
return -1;
|
||||
}
|
||||
#if MPG123_API_VERSION < 46
|
||||
// Newer versions of the library don't need that anymore, but it is safe
|
||||
// to have the no-op call present for compatibility with old versions.
|
||||
mpg123_init();
|
||||
#endif
|
||||
m = mpg123_new(NULL, NULL);
|
||||
mpg123_param(m, MPG123_RESYNC_LIMIT, -1, 0);
|
||||
mpg123_param(m, MPG123_INDEX_SIZE, -1, 0);
|
||||
mpg123_open(m, argv[1]);
|
||||
mpg123_scan(m);
|
||||
|
||||
mpg123_index(m, &offsets, &step, &fill);
|
||||
for(i=0; i<fill;i++) {
|
||||
printf("Frame number %"PRIiMAX": file offset %"PRIiMAX"\n", (intmax_t)(i * step), (intmax_t)offsets[i]);
|
||||
}
|
||||
|
||||
mpg123_close(m);
|
||||
mpg123_delete(m);
|
||||
return 0;
|
||||
}
|
||||
97
doc/examples/extract_frames.c
Normal file
97
doc/examples/extract_frames.c
Normal file
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
extract_frams: utlize the framebyframe API and mpg123_framedata to extract the MPEG frames out of a stream (strip off anything else).
|
||||
|
||||
This is example code only sensible to be considered in the public domain.
|
||||
Initially written by Thomas Orgis.
|
||||
*/
|
||||
|
||||
#include <mpg123.h>
|
||||
|
||||
/* unistd.h is not available under MSVC,
|
||||
io.h defines the read and write functions */
|
||||
#ifndef _MSC_VER
|
||||
#include <unistd.h>
|
||||
#else
|
||||
#include <io.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/** The actual work on the existing handle. */
|
||||
int do_work(mpg123_handle *m);
|
||||
|
||||
/** The main program. */
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int ret = 0;
|
||||
mpg123_handle *m;
|
||||
|
||||
#if MPG123_API_VERSION < 46
|
||||
// Newer versions of the library don't need that anymore, but it is safe
|
||||
// to have the no-op call present for compatibility with old versions.
|
||||
mpg123_init();
|
||||
#endif
|
||||
m = mpg123_new(NULL, &ret);
|
||||
|
||||
if(m == NULL)
|
||||
{
|
||||
fprintf(stderr, "Cannot create handle: %s", mpg123_plain_strerror(ret));
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "I'll take your dirty MPEG audio from standard input and will write the extracted pure MPEG data to standard output.\n");
|
||||
if(argc > 1 && strcmp(argv[1], "--noinfo") == 0)
|
||||
{
|
||||
fprintf(stderr, "Enabling parsing/consuming of the Info frame so that it will not appear in output.\n");
|
||||
ret = mpg123_param(m, MPG123_REMOVE_FLAGS, MPG123_IGNORE_INFOFRAME, 0.);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "If you'd have given --noinfo as argument, I would omit a LAME/Xing info frame.\n");
|
||||
ret = mpg123_param(m, MPG123_ADD_FLAGS, MPG123_IGNORE_INFOFRAME, 0.);
|
||||
}
|
||||
if(ret == 0) ret = do_work(m);
|
||||
|
||||
if(ret != 0) fprintf(stderr, "Some error occured: %s\n", mpg123_strerror(m));
|
||||
|
||||
|
||||
mpg123_delete(m); /* Closes, too. */
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int do_work(mpg123_handle *m)
|
||||
{
|
||||
int ret;
|
||||
size_t count = 0;
|
||||
ret = mpg123_open_fd(m, STDIN_FILENO);
|
||||
if(ret != MPG123_OK) return ret;
|
||||
|
||||
while( (ret = mpg123_framebyframe_next(m)) == MPG123_OK || ret == MPG123_NEW_FORMAT )
|
||||
{
|
||||
unsigned long header;
|
||||
unsigned char *bodydata;
|
||||
size_t bodybytes;
|
||||
if(mpg123_framedata(m, &header, &bodydata, &bodybytes) == MPG123_OK)
|
||||
{
|
||||
/* Need to extract the 4 header bytes from the native storage in the correct order. */
|
||||
unsigned char hbuf[4];
|
||||
int i;
|
||||
for(i=0; i<4; ++i) hbuf[i] = (unsigned char) ((header >> ((3-i)*8)) & 0xff);
|
||||
|
||||
/* Now write out both header and data, fire and forget. */
|
||||
write(STDOUT_FILENO, hbuf, 4);
|
||||
write(STDOUT_FILENO, bodydata, bodybytes);
|
||||
fprintf(stderr, "%zu: header 0x%08lx, %zu body bytes\n", ++count, header, bodybytes);
|
||||
}
|
||||
}
|
||||
|
||||
if(ret != MPG123_DONE)
|
||||
fprintf(stderr, "Some error occured (non-fatal?): %s\n", mpg123_strerror(m));
|
||||
|
||||
fprintf(stderr, "Done with %zu MPEG frames.\n", count);
|
||||
|
||||
return 0;
|
||||
}
|
||||
164
doc/examples/feedseek.c
Normal file
164
doc/examples/feedseek.c
Normal file
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
feedseek: test program for libmpg123, showing how to use fuzzy seeking in feeder mode
|
||||
|
||||
This is example code only sensible to be considered in the public domain.
|
||||
|
||||
It takes MPEG data from standard input and feeds that to libmpg123, combined
|
||||
with a fuzzy seek. Libmpg123 could access stdin in other ways directly, but
|
||||
usage of the feeder API is the point here.
|
||||
*/
|
||||
|
||||
#define _POSIX_C_SOURCE 200112L /**< POSIX standard for ftello. */
|
||||
#include <mpg123.h>
|
||||
#include <out123.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define INBUFF 16384 * 2 * 2 /**< input buffer size */
|
||||
|
||||
/** Error handling helper, end program if condition is not met.
|
||||
* Yes, a goto for error handling. Controlled cleanup in a final section instead
|
||||
* of just jumping out of the program.
|
||||
*/
|
||||
#define CHECK(cond, ...) if(!(cond)){ fprintf(stderr, __VA_ARGS__); goto bad_end; }
|
||||
|
||||
/** The whole operation. */
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
unsigned char buf[INBUFF];
|
||||
mpg123_handle *m = NULL;
|
||||
out123_handle *o = NULL;
|
||||
const char *driver = NULL;
|
||||
char *device = NULL;
|
||||
int ret = 0;
|
||||
off_t inoffset;
|
||||
off_t cur_inoffset;
|
||||
off_t seek_point = 0;
|
||||
off_t seek_target;
|
||||
|
||||
// 0. Argument parsing.
|
||||
|
||||
if(argc < 2)
|
||||
{
|
||||
fprintf(stderr, "Usage:\n\n %s <offset> [outfile] < <MPEG input data>\n", argv[0]);
|
||||
fprintf( stderr, "\n"
|
||||
"This will decode standard input to the default audio device or the\n"
|
||||
"given output file as decoded WAV after seeking to the given PCM sample\n"
|
||||
"offset to demonstrate fuzzy seeking\n" );
|
||||
return 1;
|
||||
}
|
||||
|
||||
seek_point = atol(argv[1]);
|
||||
CHECK(seek_point >= 0, "No negative offset, please.\n")
|
||||
|
||||
if(argc >= 3)
|
||||
{
|
||||
driver = "wav";
|
||||
device = argv[2];
|
||||
}
|
||||
|
||||
// 1. Initialize libmpg123 and libout123 handles.
|
||||
|
||||
#if MPG123_API_VERSION < 46
|
||||
// Newer versions of the library don't need that anymore, but it is safe
|
||||
// to have the no-op call present for compatibility with old versions.
|
||||
mpg123_init();
|
||||
#endif
|
||||
|
||||
m = mpg123_new(NULL, &ret);
|
||||
CHECK(m != NULL, "Unable to create mpg123 handle: %s\n", mpg123_plain_strerror(ret))
|
||||
|
||||
o = out123_new();
|
||||
CHECK(o != NULL, "Unable to create out123 handle.\n")
|
||||
|
||||
ret = out123_open(o, driver, device);
|
||||
CHECK(ret == OUT123_OK, "Failed to open output device: %s\n", out123_strerror(o))
|
||||
|
||||
mpg123_param(m, MPG123_VERBOSE, 2, 0);
|
||||
|
||||
mpg123_param(m, MPG123_FLAGS, MPG123_FUZZY | MPG123_SEEKBUFFER | MPG123_GAPLESS, 0);
|
||||
CHECK(ret == MPG123_OK, "Unable to set library options: %s\n", mpg123_plain_strerror(ret))
|
||||
|
||||
// 2. Open the feeder, feed data until libmpg123 can tell us where to go in the input
|
||||
// for the desired output offset.
|
||||
|
||||
ret = mpg123_open_feed(m);
|
||||
CHECK(ret == MPG123_OK, "Unable open feed: %s\n", mpg123_plain_strerror(ret))
|
||||
|
||||
fprintf(stderr, "\nDetermining input offset for seek ...\n");
|
||||
/* That condition is tricky... parentheses are crucial... */
|
||||
while( (seek_target = mpg123_feedseek(m, seek_point, SEEK_SET, &inoffset))
|
||||
== MPG123_NEED_MORE )
|
||||
{
|
||||
fprintf(stderr, " *** need more data before deciding on fuzzy input offset ***\n");
|
||||
size_t len = fread(buf, 1, INBUFF, stdin);
|
||||
if(len < 0 || (len == 0 && (feof(stdin) || ferror(stdin))))
|
||||
break;
|
||||
ret = mpg123_feed(m, buf, len);
|
||||
CHECK(ret == MPG123_OK, "Error feeding the decoder: %s", mpg123_strerror(m))
|
||||
}
|
||||
CHECK(ret == MPG123_OK, "Feedseek failed: %s\n", mpg123_strerror(m))
|
||||
fprintf( stderr, "Fuzzy seek to %lld, actually to %lld.\n"
|
||||
, (long long)seek_point, (long long)seek_target );
|
||||
CHECK(inoffset >=0 , "Bogus input offset: %lld\n", (long long)inoffset)
|
||||
|
||||
// 3. Go to the indicated input offset.
|
||||
|
||||
fprintf(stderr, "\nSeeking to input offset ...\n");
|
||||
// In a normal file, we would call fseek() here, for stdin, we just consume data.
|
||||
while( (cur_inoffset=ftello(stdin)) < inoffset && !ferror(stdin) )
|
||||
{
|
||||
CHECK(cur_inoffset >= 0, "Cannot tell input position.\n")
|
||||
off_t block = inoffset - cur_inoffset;
|
||||
if(block > INBUFF)
|
||||
block = INBUFF;
|
||||
if(fread(buf, 1, block, stdin) == 0 && feof(stdin))
|
||||
break;
|
||||
}
|
||||
CHECK( ftello(stdin) == inoffset, "Input seeking failed: %lld != %lld\n"
|
||||
, (long long)ftello(stdin), (long long)inoffset )
|
||||
|
||||
// 4. Feed the decoder from that point on and get the decoded audio.
|
||||
|
||||
fprintf(stderr, "\nStarting decode...\n");
|
||||
while(1)
|
||||
{
|
||||
size_t len = fread(buf, sizeof(unsigned char), INBUFF, stdin);
|
||||
if(len <= 0)
|
||||
break;
|
||||
ret = mpg123_feed(m, buf, len);
|
||||
|
||||
while(ret != MPG123_ERR && ret != MPG123_NEED_MORE)
|
||||
{
|
||||
off_t num;
|
||||
unsigned char *audio;
|
||||
size_t bytes;
|
||||
ret = mpg123_decode_frame(m, &num, &audio, &bytes);
|
||||
if(ret == MPG123_NEW_FORMAT)
|
||||
{
|
||||
long rate;
|
||||
int channels, enc;
|
||||
mpg123_getformat(m, &rate, &channels, &enc);
|
||||
fprintf(stderr
|
||||
, "New format: %li Hz, %i channels, encoding value %i\n"
|
||||
, rate, channels, enc );
|
||||
ret = out123_start(o, rate, channels, enc);
|
||||
CHECK(ret == OUT123_OK, "Cannot (re)start audio output with given format.\n")
|
||||
}
|
||||
CHECK(out123_play(o, audio, bytes) == bytes, "Output error: %s", out123_strerror(o))
|
||||
}
|
||||
|
||||
CHECK(ret != MPG123_ERR, "Error: %s", mpg123_strerror(m))
|
||||
}
|
||||
|
||||
fprintf(stderr, "Finished\n");
|
||||
|
||||
good_end: // Everything went fine: go directly to the cleanup section.
|
||||
goto end;
|
||||
bad_end: // Some unspecified error, set error state and clean up.
|
||||
ret = -1;
|
||||
end: // Clean up and return.
|
||||
out123_del(o);
|
||||
mpg123_delete(m);
|
||||
return ret ? EXIT_FAILURE : EXIT_SUCCESS;
|
||||
}
|
||||
181
doc/examples/id3dump.c
Normal file
181
doc/examples/id3dump.c
Normal file
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
id3dump: Print ID3 tags of files, scanned using libmpg123.
|
||||
|
||||
This is example code only sensible to be considered in the public domain.
|
||||
Initially written by Thomas Orgis.
|
||||
*/
|
||||
|
||||
#include "mpg123.h"
|
||||
#include <string.h>
|
||||
#include "stdio.h"
|
||||
#include "sys/types.h"
|
||||
|
||||
/** Helper for v1 printing, get these strings their zero byte. */
|
||||
void safe_print(char* name, char *data, size_t size)
|
||||
{
|
||||
char safe[31];
|
||||
if(size>30) return;
|
||||
|
||||
memcpy(safe, data, size);
|
||||
safe[size] = 0;
|
||||
printf("%s: %s\n", name, safe);
|
||||
}
|
||||
|
||||
/** Print out ID3v1 info. */
|
||||
void print_v1(mpg123_id3v1 *v1)
|
||||
{
|
||||
safe_print("Title", v1->title, sizeof(v1->title));
|
||||
safe_print("Artist", v1->artist, sizeof(v1->artist));
|
||||
safe_print("Album", v1->album, sizeof(v1->album));
|
||||
safe_print("Year", v1->year, sizeof(v1->year));
|
||||
safe_print("Comment", v1->comment, sizeof(v1->comment));
|
||||
printf("Genre: %i", v1->genre);
|
||||
}
|
||||
|
||||
/** Split up a number of lines separated by \\n, \\r, both or just zero byte
|
||||
and print out each line with specified prefix. */
|
||||
void print_lines(const char* prefix, mpg123_string *inlines)
|
||||
{
|
||||
size_t i;
|
||||
int hadcr = 0, hadlf = 0;
|
||||
char *lines = NULL;
|
||||
char *line = NULL;
|
||||
size_t len = 0;
|
||||
|
||||
if(inlines != NULL && inlines->fill)
|
||||
{
|
||||
lines = inlines->p;
|
||||
len = inlines->fill;
|
||||
}
|
||||
else return;
|
||||
|
||||
line = lines;
|
||||
for(i=0; i<len; ++i)
|
||||
{
|
||||
if(lines[i] == '\n' || lines[i] == '\r' || lines[i] == 0)
|
||||
{
|
||||
char save = lines[i]; /* saving, changing, restoring a byte in the data */
|
||||
if(save == '\n') ++hadlf;
|
||||
if(save == '\r') ++hadcr;
|
||||
if((hadcr || hadlf) && hadlf % 2 == 0 && hadcr % 2 == 0) line = "";
|
||||
|
||||
if(line)
|
||||
{
|
||||
lines[i] = 0;
|
||||
printf("%s%s\n", prefix, line);
|
||||
line = NULL;
|
||||
lines[i] = save;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hadlf = hadcr = 0;
|
||||
if(line == NULL) line = lines+i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Print out the named ID3v2 fields. */
|
||||
void print_v2(mpg123_id3v2 *v2)
|
||||
{
|
||||
print_lines("Title: ", v2->title);
|
||||
print_lines("Artist: ", v2->artist);
|
||||
print_lines("Album: ", v2->album);
|
||||
print_lines("Year: ", v2->year);
|
||||
print_lines("Comment: ", v2->comment);
|
||||
print_lines("Genre: ", v2->genre);
|
||||
}
|
||||
|
||||
/** Print out all stored ID3v2 fields with their 4-character IDs. */
|
||||
void print_raw_v2(mpg123_id3v2 *v2)
|
||||
{
|
||||
size_t i;
|
||||
for(i=0; i<v2->texts; ++i)
|
||||
{
|
||||
char id[5];
|
||||
char lang[4];
|
||||
memcpy(id, v2->text[i].id, 4);
|
||||
id[4] = 0;
|
||||
memcpy(lang, v2->text[i].lang, 3);
|
||||
lang[3] = 0;
|
||||
if(v2->text[i].description.fill)
|
||||
printf("%s language(%s) description(%s)\n", id, lang, v2->text[i].description.p);
|
||||
else printf("%s language(%s)\n", id, lang);
|
||||
|
||||
print_lines(" ", &v2->text[i].text);
|
||||
}
|
||||
for(i=0; i<v2->extras; ++i)
|
||||
{
|
||||
char id[5];
|
||||
memcpy(id, v2->extra[i].id, 4);
|
||||
id[4] = 0;
|
||||
printf( "%s description(%s)\n",
|
||||
id,
|
||||
v2->extra[i].description.fill ? v2->extra[i].description.p : "" );
|
||||
print_lines(" ", &v2->extra[i].text);
|
||||
}
|
||||
for(i=0; i<v2->comments; ++i)
|
||||
{
|
||||
char id[5];
|
||||
char lang[4];
|
||||
memcpy(id, v2->comment_list[i].id, 4);
|
||||
id[4] = 0;
|
||||
memcpy(lang, v2->comment_list[i].lang, 3);
|
||||
lang[3] = 0;
|
||||
printf( "%s description(%s) language(%s): \n",
|
||||
id,
|
||||
v2->comment_list[i].description.fill ? v2->comment_list[i].description.p : "",
|
||||
lang );
|
||||
print_lines(" ", &v2->comment_list[i].text);
|
||||
}
|
||||
}
|
||||
|
||||
/** The whole operation. */
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
mpg123_handle* m;
|
||||
if(argc < 2)
|
||||
{
|
||||
fprintf(stderr, "\nI will print some ID3 tag fields of MPEG audio files.\n");
|
||||
fprintf(stderr, "\nUsage: %s <mpeg audio file list>\n\n", argv[0]);
|
||||
return -1;
|
||||
}
|
||||
#if MPG123_API_VERSION < 46
|
||||
// Newer versions of the library don't need that anymore, but it is safe
|
||||
// to have the no-op call present for compatibility with old versions.
|
||||
mpg123_init();
|
||||
#endif
|
||||
m = mpg123_new(NULL, NULL);
|
||||
|
||||
for(i=1; i < argc; ++i)
|
||||
{
|
||||
mpg123_id3v1 *v1;
|
||||
mpg123_id3v2 *v2;
|
||||
int meta;
|
||||
if(mpg123_open(m, argv[i]) != MPG123_OK)
|
||||
{
|
||||
fprintf(stderr, "Cannot open %s: %s\n", argv[i], mpg123_strerror(m));
|
||||
continue;
|
||||
}
|
||||
mpg123_scan(m);
|
||||
meta = mpg123_meta_check(m);
|
||||
if(meta & MPG123_ID3 && mpg123_id3(m, &v1, &v2) == MPG123_OK)
|
||||
{
|
||||
printf("Tag data on %s:\n", argv[i]);
|
||||
printf("\n==== ID3v1 ====\n");
|
||||
if(v1 != NULL) print_v1(v1);
|
||||
|
||||
printf("\n==== ID3v2 ====\n");
|
||||
if(v2 != NULL) print_v2(v2);
|
||||
|
||||
printf("\n==== ID3v2 Raw frames ====\n");
|
||||
if(v2 != NULL) print_raw_v2(v2);
|
||||
}
|
||||
else printf("Nothing found for %s.\n", argv[i]);
|
||||
|
||||
mpg123_close(m);
|
||||
}
|
||||
mpg123_delete(m);
|
||||
return 0;
|
||||
}
|
||||
169
doc/examples/mpg123_to_out123.c
Normal file
169
doc/examples/mpg123_to_out123.c
Normal file
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
mpg123_to_wav.c
|
||||
|
||||
This is example code only sensible to be considered in the public domain.
|
||||
Initially written by Nicholas Humfrey.
|
||||
|
||||
The most complicated part is about the choices to make about output format,
|
||||
and prepare for the unlikely case a bastard mp3 might file change it.
|
||||
*/
|
||||
|
||||
#include <out123.h>
|
||||
#include <mpg123.h>
|
||||
#include <stdio.h>
|
||||
#include <strings.h>
|
||||
|
||||
/** Print usage info. */
|
||||
void usage(const char *cmd)
|
||||
{
|
||||
printf("Usage: %s <input> [<driver> [<output> [encoding [buffersize]]]]\n"
|
||||
, cmd);
|
||||
printf( "\nPlay MPEG audio from intput file to output file/device using\n"
|
||||
"specified out123 driver, sample encoding and buffer size optional.\n\n" );
|
||||
exit(99);
|
||||
}
|
||||
|
||||
/** Free handles. */
|
||||
void cleanup(mpg123_handle *mh, out123_handle *ao)
|
||||
{
|
||||
out123_del(ao);
|
||||
/* It's really to late for error checks here;-) */
|
||||
mpg123_close(mh);
|
||||
mpg123_delete(mh);
|
||||
}
|
||||
|
||||
/** The whole operation. */
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
mpg123_handle *mh = NULL;
|
||||
out123_handle *ao = NULL;
|
||||
char *infile = NULL;
|
||||
char *driver = NULL;
|
||||
char *outfile = NULL;
|
||||
unsigned char* buffer = NULL;
|
||||
const char *encname;
|
||||
size_t buffer_size = 0;
|
||||
size_t done = 0;
|
||||
int channels = 0;
|
||||
int encoding = 0;
|
||||
int framesize = 1;
|
||||
long rate = 0;
|
||||
int err = MPG123_OK;
|
||||
off_t samples = 0;
|
||||
|
||||
if(argc<2)
|
||||
usage(argv[0]);
|
||||
|
||||
infile = argv[1];
|
||||
if(argc >= 3)
|
||||
driver = argv[2];
|
||||
if(argc >= 4)
|
||||
outfile = argv[3];
|
||||
printf("Input file: %s\n", infile);
|
||||
printf("Output driver: %s\n", driver ? driver : "<nil> (default)");
|
||||
printf("Output file: %s\n", outfile ? outfile : "<nil> (default)");
|
||||
|
||||
#if MPG123_API_VERSION < 46
|
||||
// Newer versions of the library don't need that anymore, but it is safe
|
||||
// to have the no-op call present for compatibility with old versions.
|
||||
err = mpg123_init();
|
||||
#endif
|
||||
if(err != MPG123_OK || (mh = mpg123_new(NULL, &err)) == NULL)
|
||||
{
|
||||
fprintf(stderr, "Basic setup goes wrong: %s", mpg123_plain_strerror(err));
|
||||
cleanup(mh, ao);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ao = out123_new();
|
||||
if(!ao)
|
||||
{
|
||||
fprintf(stderr, "Cannot create output handle.\n");
|
||||
cleanup(mh, ao);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(argc >= 5)
|
||||
{ /* Make mpg123 support the desired encoding only for all rates. */
|
||||
const long *rates;
|
||||
size_t rate_count;
|
||||
size_t i;
|
||||
int enc;
|
||||
/* If that is zero, you'll get the error soon enough from mpg123. */
|
||||
enc = out123_enc_byname(argv[4]);
|
||||
mpg123_format_none(mh);
|
||||
mpg123_rates(&rates, &rate_count);
|
||||
for(i=0; i<rate_count; ++i)
|
||||
mpg123_format(mh, rates[i], MPG123_MONO|MPG123_STEREO, enc);
|
||||
}
|
||||
|
||||
/* Let mpg123 work with the file, that excludes MPG123_NEED_MORE messages. */
|
||||
if( mpg123_open(mh, infile) != MPG123_OK
|
||||
/* Peek into track and get first output format. */
|
||||
|| mpg123_getformat(mh, &rate, &channels, &encoding) != MPG123_OK )
|
||||
{
|
||||
fprintf( stderr, "Trouble with mpg123: %s\n", mpg123_strerror(mh) );
|
||||
cleanup(mh, ao);
|
||||
return -1;
|
||||
}
|
||||
if(out123_open(ao, driver, outfile) != OUT123_OK)
|
||||
{
|
||||
fprintf(stderr, "Trouble with out123: %s\n", out123_strerror(ao));
|
||||
cleanup(mh, ao);
|
||||
return -1;
|
||||
}
|
||||
/* It makes no sense for that to give an error now. */
|
||||
out123_driver_info(ao, &driver, &outfile);
|
||||
printf("Effective output driver: %s\n", driver ? driver : "<nil> (default)");
|
||||
printf("Effective output file: %s\n", outfile ? outfile : "<nil> (default)");
|
||||
|
||||
/* Ensure that this output format will not change
|
||||
(it might, when we allow it). */
|
||||
mpg123_format_none(mh);
|
||||
mpg123_format(mh, rate, channels, encoding);
|
||||
|
||||
encname = out123_enc_name(encoding);
|
||||
printf( "Playing with %i channels and %li Hz, encoding %s.\n"
|
||||
, channels, rate, encname ? encname : "???" );
|
||||
if( out123_start(ao, rate, channels, encoding)
|
||||
|| out123_getformat(ao, NULL, NULL, NULL, &framesize) )
|
||||
{
|
||||
fprintf(stderr, "Cannot start output / get framesize: %s\n"
|
||||
, out123_strerror(ao));
|
||||
cleanup(mh, ao);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Buffer could be almost any size here, mpg123_outblock() is just some
|
||||
recommendation. The size should be a multiple of the PCM frame size. */
|
||||
buffer_size = argc >= 6 ? atol(argv[5]) : mpg123_outblock(mh);
|
||||
buffer = malloc( buffer_size );
|
||||
|
||||
do
|
||||
{
|
||||
size_t played;
|
||||
err = mpg123_read( mh, buffer, buffer_size, &done );
|
||||
played = out123_play(ao, buffer, done);
|
||||
if(played != done)
|
||||
{
|
||||
fprintf(stderr
|
||||
, "Warning: written less than gotten from libmpg123: %li != %li\n"
|
||||
, (long)played, (long)done);
|
||||
}
|
||||
samples += played/framesize;
|
||||
/* We are not in feeder mode, so MPG123_OK, MPG123_ERR and
|
||||
MPG123_NEW_FORMAT are the only possibilities.
|
||||
We do not handle a new format, MPG123_DONE is the end... so
|
||||
abort on anything not MPG123_OK. */
|
||||
} while (done && err==MPG123_OK);
|
||||
|
||||
free(buffer);
|
||||
|
||||
if(err != MPG123_DONE)
|
||||
fprintf( stderr, "Warning: Decoding ended prematurely because: %s\n",
|
||||
err == MPG123_ERR ? mpg123_strerror(mh) : mpg123_plain_strerror(err) );
|
||||
|
||||
printf("%li samples written.\n", (long)samples);
|
||||
cleanup(mh, ao);
|
||||
return 0;
|
||||
}
|
||||
97
doc/examples/mpglib.c
Normal file
97
doc/examples/mpglib.c
Normal file
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
mpglib: test program for libmpg123, in the style of the legacy mpglib test program
|
||||
|
||||
This is example code only sensible to be considered in the public domain.
|
||||
Initially written by Thomas Orgis.
|
||||
*/
|
||||
|
||||
#include <mpg123.h>
|
||||
|
||||
/* unistd.h is not available under MSVC,
|
||||
io.h defines the read and write functions */
|
||||
#ifndef _MSC_VER
|
||||
#include <unistd.h>
|
||||
#else
|
||||
#include <io.h>
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#define INBUFF 16384 /**< input buffer size */
|
||||
#define OUTBUFF 32768 /**< output buffer size */
|
||||
|
||||
/** The whole operation. */
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
size_t size;
|
||||
unsigned char buf[INBUFF]; /* input buffer */
|
||||
unsigned char out[OUTBUFF]; /* output buffer */
|
||||
ssize_t len;
|
||||
int ret;
|
||||
size_t in = 0, outc = 0;
|
||||
mpg123_handle *m;
|
||||
|
||||
#ifdef _WIN32
|
||||
_setmode(_fileno(stdin),_O_BINARY);
|
||||
_setmode(_fileno(stdout),_O_BINARY);
|
||||
#endif
|
||||
|
||||
#if MPG123_API_VERSION < 46
|
||||
// Newer versions of the library don't need that anymore, but it is safe
|
||||
// to have the no-op call present for compatibility with old versions.
|
||||
mpg123_init();
|
||||
#endif
|
||||
m = mpg123_new(argc > 1 ? argv[1] : NULL, &ret);
|
||||
if(m == NULL)
|
||||
{
|
||||
fprintf(stderr,"Unable to create mpg123 handle: %s\n", mpg123_plain_strerror(ret));
|
||||
return -1;
|
||||
}
|
||||
mpg123_param(m, MPG123_VERBOSE, 2, 0); /* Brabble a bit about the parsing/decoding. */
|
||||
|
||||
/* Now mpg123 is being prepared for feeding. The main loop will read chunks from stdin and feed them to mpg123;
|
||||
then take decoded data as available to write to stdout. */
|
||||
mpg123_open_feed(m);
|
||||
if(m == NULL) return -1;
|
||||
|
||||
fprintf(stderr, "Feed me some MPEG audio to stdin, I will decode to stdout.\n");
|
||||
while(1) /* Read and write until everything is through. */
|
||||
{
|
||||
len = read(0,buf,INBUFF);
|
||||
if(len <= 0)
|
||||
{
|
||||
fprintf(stderr, "input data end\n");
|
||||
break;
|
||||
}
|
||||
in += len;
|
||||
/* Feed input chunk and get first chunk of decoded audio. */
|
||||
ret = mpg123_decode(m,buf,len,out,OUTBUFF,&size);
|
||||
if(ret == MPG123_NEW_FORMAT)
|
||||
{
|
||||
long rate;
|
||||
int channels, enc;
|
||||
mpg123_getformat(m, &rate, &channels, &enc);
|
||||
fprintf(stderr, "New format: %li Hz, %i channels, encoding value %i\n", rate, channels, enc);
|
||||
}
|
||||
if(write(1,out,size) != size)
|
||||
fprintf(stderr, "Output truncated.\n");
|
||||
outc += size;
|
||||
while(ret != MPG123_ERR && ret != MPG123_NEED_MORE)
|
||||
{ /* Get all decoded audio that is available now before feeding more input. */
|
||||
ret = mpg123_decode(m,NULL,0,out,OUTBUFF,&size);
|
||||
if(write(1,out,size) != size)
|
||||
fprintf(stderr, "Output truncated.\n");
|
||||
outc += size;
|
||||
}
|
||||
if(ret == MPG123_ERR){ fprintf(stderr, "some error: %s", mpg123_strerror(m)); break; }
|
||||
}
|
||||
fprintf(stderr, "%lu bytes in, %lu bytes out\n", (unsigned long)in, (unsigned long)outc);
|
||||
|
||||
/* Done decoding, now just clean up and leave. */
|
||||
mpg123_delete(m);
|
||||
return 0;
|
||||
}
|
||||
48
doc/examples/scan.c
Normal file
48
doc/examples/scan.c
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
scan: Estimate length (sample count) of a mpeg file and compare to length from exact scan.
|
||||
|
||||
This is example code only sensible to be considered in the public domain.
|
||||
Initially written by Thomas Orgis
|
||||
*/
|
||||
|
||||
/* Note the lack of error checking here.
|
||||
While it would be nicer to inform the user about troubles, libmpg123 is designed _not_ to bite you on operations with invalid handles , etc.
|
||||
You just jet invalid results on invalid operations... */
|
||||
|
||||
#include <mpg123.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/** The whole operation. */
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
mpg123_handle *m;
|
||||
int i;
|
||||
if(argc < 2)
|
||||
{
|
||||
fprintf(stderr, "\nI will give you the estimated and exact sample lengths of MPEG audio files.\n");
|
||||
fprintf(stderr, "\nUsage: %s <mpeg audio file list>\n\n", argv[0]);
|
||||
return -1;
|
||||
}
|
||||
#if MPG123_API_VERSION < 46
|
||||
mpg123_init();
|
||||
#endif
|
||||
m = mpg123_new(NULL, NULL);
|
||||
mpg123_param(m, MPG123_RESYNC_LIMIT, -1, 0); /* New in library version 0.0.1 . */
|
||||
for(i = 1; i < argc; ++i)
|
||||
{
|
||||
off_t a, b;
|
||||
|
||||
mpg123_open(m, argv[i]);
|
||||
|
||||
a = mpg123_length(m);
|
||||
mpg123_scan(m);
|
||||
b = mpg123_length(m);
|
||||
|
||||
mpg123_close(m);
|
||||
|
||||
printf("File %i: estimated %li vs. scanned %li\n", i, (long)a, (long)b);
|
||||
}
|
||||
|
||||
mpg123_delete(m);
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user