Example #1
0
static int mad_stream_info(input_object *obj, stream_info *info)
{
	struct mad_local_data *data;	
	unsigned len;
	char metadata[256];
	char *s, *p;

	if (!obj || !info)
		return 0;

	data = (struct mad_local_data *)obj->local_data;

	if (data) {
		if (!data->parse_id3) {
			sprintf(data->sinfo.title, "%s", data->filename);
		} else if (!data->parsed_id3) {
			if (reader_seekable(data->mad_fd)) {
				parse_id3 (data->path, &data->sinfo);
				if ((len = strlen(data->sinfo.title))) {
					s = data->sinfo.title + (len - 1);
					while (s != data->sinfo.title && *s == ' ')
						*(s--) = '\0';
				}
				if ((len = strlen(data->sinfo.artist))) {
					s = data->sinfo.artist + (len - 1);
					while (s != data->sinfo.artist && *s == ' ')
						*(s--) = '\0';
				}
			}
			strncpy (data->sinfo.path, data->path, sizeof(data->sinfo.path));
			data->parsed_id3 = 1;
		}
		memset(metadata, 0, sizeof(metadata));
		if ((len = reader_metadata(data->mad_fd, sizeof(metadata), metadata))) {
			//alsaplayer_error("Metadata: %s", metadata);
			if ((s = strstr(metadata, "StreamTitle='"))) {
				s += 13;
				if ((p = strstr(s, "'"))) {
					*p = '\0';
					snprintf(data->sinfo.title, 128, "%s", s);
				} else {
					alsaplayer_error("Malformed metadata: \"%s\"", metadata);
				}
			}
		}	
		/* Restore permanently filled info */
		memcpy (info, &data->sinfo, sizeof (data->sinfo));

		/* Compose path, stream_type and status fields */
		sprintf(info->stream_type, "MP3 %dKHz %s %-3ldkbit",
				data->frame.header.samplerate / 1000,
				obj->nr_channels == 2 ? "stereo" : "mono",
				data->frame.header.bitrate / 1000);

		if (data->seeking)
			sprintf(info->status, "Seeking...");
	}				
	return 1;
}
Example #2
0
static int mad_open(input_object *obj, const char *path)
{
	struct mad_local_data *data;
	char *p;
	int mode;

	if (!obj)
		return 0;

	obj->local_data = malloc(sizeof(struct mad_local_data));
	if (!obj->local_data) {
		puts("failed to allocate local data");
		return 0;
	}
	data = (struct mad_local_data *)obj->local_data;
	memset(data, 0, sizeof(struct mad_local_data));

	if ((data->mad_fd = reader_open(path, &reader_status, obj)) == NULL) {
		fprintf(stderr, "mad_open(obj, %s) failed\n", path);
		free(obj->local_data);
		obj->local_data = NULL;
		return 0;
	}
	obj->flags = 0;

	if (strncasecmp(path, "http://", 7) == 0) {
		obj->flags |= P_STREAMBASED;
		strcpy(data->sinfo.status, "Prebuffering");
	} else {
		obj->flags |= P_FILEBASED;
	}
	if (!reader_seekable(data->mad_fd)) {
		data->seekable = 0;
	} else {
		obj->flags |= P_SEEK;
		obj->flags |= P_PERFECTSEEK;
		data->seekable = 1;
	}
	obj->flags |= P_REENTRANT;

	mad_init_decoder(data);
	memset(&data->xing, 0, sizeof(struct xing));
	xing_init (&data->xing);
	data->mad_init = 1;
	fill_buffer(data, -1);
	//alsaplayer_error("initial bytes_avail = %d", data->bytes_avail);
	if (obj->flags & P_PERFECTSEEK) {
		data->offset = find_initial_frame(data->mad_map, 
				data->bytes_avail < STREAM_BUFFER_SIZE ? data->bytes_avail :
				STREAM_BUFFER_SIZE);
	} else {
		data->offset = 0;
	}	
	data->highest_frame = 0;
	if (data->offset < 0) {
		//fprintf(stderr, "mad_open() couldn't find valid MPEG header\n");
		data->offset = 0;
	}
	//alsaplayer_error("data->offset = %d", data->offset);
	if (data->offset > data->bytes_avail) {
		data->seekable = 1;
		//alsaplayer_error("Need to refill buffer (data->offset = %d)", data->offset);
		fill_buffer(data, 0);
		mad_stream_buffer(&data->stream, data->mad_map, data->bytes_avail);
	} else {
		mad_stream_buffer(&data->stream, data->mad_map + data->offset,
				data->bytes_avail - data->offset);
		data->bytes_avail -= data->offset;
	}	
first_frame:

	if ((mad_header_decode(&data->frame.header, &data->stream) == -1)) {
		switch (data->stream.error) {
			case MAD_ERROR_BUFLEN:
				return 0;
			case MAD_ERROR_LOSTSYNC:
			case MAD_ERROR_BADEMPHASIS:
			case MAD_ERROR_BADBITRATE:
			case MAD_ERROR_BADLAYER:	
			case MAD_ERROR_BADSAMPLERATE:	
				//alsaplayer_error("Error %x (frame %d)", data->stream.error, data->current_frame);
				data->bytes_avail-=(data->stream.next_frame - data->stream.this_frame);
				goto first_frame;
				break;
			case MAD_ERROR_BADBITALLOC:
				return 0;
			case MAD_ERROR_BADCRC:
				alsaplayer_error("MAD_ERROR_BADCRC: %s", error_str(data->stream.error, data->str));
			case MAD_ERROR_BADBIGVALUES:
			case MAD_ERROR_BADDATAPTR:
				break;
			default:
				alsaplayer_error("ERROR: %s", error_str(data->stream.error, data->str));
				alsaplayer_error("No valid frame found at start (pos: %d, error: 0x%x --> %x %x %x %x) (%s)", data->offset, data->stream.error, 
						data->stream.this_frame[0],
						data->stream.this_frame[1],
						data->stream.this_frame[2],
						data->stream.this_frame[3],path);
				return 0;
		}
	}

	mad_frame_decode(&data->frame, &data->stream);
	/*	
		alsaplayer_error("xing parsing...%x %x %x %x (%x %d)", 
		data->stream.this_frame[0], data->stream.this_frame[1],
		data->stream.this_frame[2], data->stream.this_frame[3],
		data->stream.anc_ptr, data->stream.anc_bitlen);
		*/		
	if (xing_parse(&data->xing, data->stream.anc_ptr, data->stream.anc_bitlen) == 0) {
		// We use the xing data later on
	}

	mode = (data->frame.header.mode == MAD_MODE_SINGLE_CHANNEL) ?
		1 : 2;
	data->samplerate = data->frame.header.samplerate;
	data->bitrate	= data->frame.header.bitrate;
	mad_synth_frame (&data->synth, &data->frame);
	{
		struct mad_pcm *pcm = &data->synth.pcm;			

		obj->nr_channels = pcm->channels;
		//alsaplayer_error("nr_channels = %d", obj->nr_channels);
	}
	//alsaplayer_error("Initial: %d, %d, %d", data->samplerate, data->bitrate, obj->nr_channels);
	/* Calculate some values */
	data->bytes_avail = data->stream.bufend - data->stream.next_frame;
	{
		int64_t time;
		int64_t samples;
		int64_t frames;

		long oldpos = reader_tell(data->mad_fd);
		reader_seek(data->mad_fd, 0, SEEK_END);

		data->filesize = reader_tell(data->mad_fd);
		data->filesize -= data->offset;

		reader_seek(data->mad_fd, oldpos, SEEK_SET);
		if (data->bitrate)
			time = (data->filesize * 8) / (data->bitrate);
		else
			time = 0;

		samples = 32 * MAD_NSBSAMPLES(&data->frame.header);

		obj->frame_size = (int) samples << 2; /* Assume 16-bit stereo */
		frames = data->samplerate * (time+1) / samples;
		if (data->xing.flags & XING_FRAMES) {
			obj->nr_frames = data->xing.frames;
		} else {	
			obj->nr_frames = (int) frames;
		}	
		obj->nr_tracks = 1;
	}
	/* Determine if nr_frames makes sense */
	if (!(obj->flags & P_SEEK) && (obj->flags & P_STREAMBASED)) {
		obj->nr_frames = -1;
	}	

	/* Allocate frame index */
	if (!data->seekable  || obj->nr_frames > 1000000 ||
			(data->frames = (ssize_t *)malloc((obj->nr_frames + FRAME_RESERVE) * sizeof(ssize_t))) == NULL) {
		data->seekable = 0; // Given really
	}	else {
		data->seekable = 1;
		data->frames[0] = 0;
	}	
	data->mad_init = 1;

	p = strrchr(path, '/');
	if (p) {
		strcpy(data->filename, ++p);
	} else {
		strcpy(data->filename, path);
	}
	strcpy(data->path, path);

	data->parse_id3 = prefs_get_bool(ap_prefs, "mad", "parse_id3", 1);

	return 1;
}
Example #3
0
static int
flac_open (input_object * obj, const char * name)
{
    if (!obj)
	return 0;
    if (!name)
	return 0;

    reader_type * rdr = reader_open (name, NULL, NULL);
    if (!rdr)
    {
	alsaplayer_error ("flac_open: reader_open failed");
	return 0;
    }

    obj->flags = 0;
    Flac::FlacStream * f = 0;
    try
    {
	if (Flac::FlacStream::isFlacStream (name))
	{
	    if (reader_seekable (rdr))
	    {
		f = new Flac::FlacSeekableStream (name, rdr);
		obj->flags |= P_SEEK | P_PERFECTSEEK;
	    }
	    else
		f = new Flac::FlacStream (name, rdr);
	}
#ifdef HAVE_LIBOGGFLC
	else
	{
	    f = new Flac::OggFlacStream (name, rdr);
	}
#endif
    }
    catch (...)
    {
	alsaplayer_error ("flac_open: unable to allocate memory for plugin.");
	delete f;
	reader_close (rdr);
	return 0;
    }

    if (f && f->open ())
    {
	obj->block_size  = f->engine ()->apBlockSize ();

	// attach a song info tag

	if (Flac::FlacTag::hasTag (f->name ()))
	{
	    Flac::FlacTag * t = Flac::FlacTag::newTag (f->name ());
	    f->setTag (t);
	}

	if (strncasecmp (name, "http://", 7) == 0)
	    obj->flags |= P_STREAMBASED;
	else
	    obj->flags |= P_FILEBASED;
	obj->nr_channels  = f->engine ()->apChannels ();
	obj->flags       |= P_REENTRANT;
	obj->nr_blocks    = f->engine ()->apBlocks ();
	obj->nr_tracks    = 1;
	obj->ready        = 1;
	obj->local_data   = (void *) f;
	return 1;
    }
    else
    {
	alsaplayer_error ("flac_open: unable to open flac stream or "
			  "unsupported flac stream (%s)", name);
	delete f;
	obj->block_size  = 0;
	obj->nr_channels = 0;
	obj->flags       = 0;
	obj->nr_blocks   = 0;
	obj->nr_tracks   = 0;
	obj->ready       = 0;
	obj->local_data  = 0;
	return 0;
    }
}