⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vcedit.c

📁 xmms-1.2.10.tar.gz学习使用的就下吧
💻 C
字号:
/* This program is licensed under the GNU Library General Public License, version 2, * a copy of which is included with this program (LICENCE.LGPL). * * (c) 2000-2001 Michael Smith <msmith@labyrinth.net.au> * * * Comment editing backend, suitable for use by nice frontend interfaces. * */#include "config.h"#include <glib.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <ogg/ogg.h>#include <vorbis/codec.h>#include "vcedit.h"#define CHUNKSIZE 4096vcedit_state *vcedit_new_state(void){	vcedit_state *state = g_malloc(sizeof(vcedit_state));	memset(state, 0, sizeof(vcedit_state));	return state;}char *vcedit_error(vcedit_state *state){	return state->lasterror;}vorbis_comment *vcedit_comments(vcedit_state *state){	return state->vc;}static void vcedit_clear_internals(vcedit_state *state){	if(state->vc)	{		vorbis_comment_clear(state->vc);		g_free(state->vc);		state->vc=NULL;	}	if(state->os)	{		ogg_stream_clear(state->os);		g_free(state->os);		state->os=NULL;	}	if(state->oy)	{		ogg_sync_clear(state->oy);		g_free(state->oy);		state->oy=NULL;	}	if(state->vendor)	{		g_free(state->vendor);		state->vendor=NULL;	}}void vcedit_clear(vcedit_state *state){	if(state)	{		vcedit_clear_internals(state);		g_free(state);	}}/* Next two functions pulled straight from libvorbis, apart from one change * - we don't want to overwrite the vendor string. */static void _v_writestring(oggpack_buffer *o,char *s, int len){	while(len--)	{		oggpack_write(o,*s++,8);	}}static int _commentheader_out(vorbis_comment *vc, char *vendor, ogg_packet *op){	oggpack_buffer opb;	oggpack_writeinit(&opb);	/* preamble */  	oggpack_write(&opb,0x03,8);	_v_writestring(&opb,"vorbis", 6);	/* vendor */	oggpack_write(&opb,strlen(vendor),32);	_v_writestring(&opb,vendor, strlen(vendor));	/* comments */	oggpack_write(&opb,vc->comments,32);	if(vc->comments){		int i;		for(i=0;i<vc->comments;i++){			if(vc->user_comments[i]){				oggpack_write(&opb,vc->comment_lengths[i],32);				_v_writestring(&opb,vc->user_comments[i],                         vc->comment_lengths[i]);			}else{				oggpack_write(&opb,0,32);			}		}	}	oggpack_write(&opb,1,1);	op->packet = _ogg_malloc(oggpack_bytes(&opb));	memcpy(op->packet, opb.buffer, oggpack_bytes(&opb));	op->bytes=oggpack_bytes(&opb);	op->b_o_s=0;	op->e_o_s=0;	op->granulepos=0;	return 0;}static int _blocksize(vcedit_state *s, ogg_packet *p){	int this = vorbis_packet_blocksize(&s->vi, p);	int ret = (this + s->prevW)/4;	if(!s->prevW)	{		s->prevW = this;		return 0;	}	s->prevW = this;	return ret;}static int _fetch_next_packet(vcedit_state *s, ogg_packet *p, ogg_page *page){	int result;	char *buffer;	int bytes;	result = ogg_stream_packetout(s->os, p);	if(result > 0)		return 1;	else	{		if(s->eosin)			return 0;		while(ogg_sync_pageout(s->oy, page) <= 0)		{			buffer = ogg_sync_buffer(s->oy, CHUNKSIZE);			bytes = s->read(buffer,1, CHUNKSIZE, s->in);			ogg_sync_wrote(s->oy, bytes);			if(bytes == 0) 				return 0;		}		if(ogg_page_eos(page))			s->eosin = 1;		else if(ogg_page_serialno(page) != s->serial)		{			s->eosin = 1;			s->extrapage = 1;			return 0;		}		ogg_stream_pagein(s->os, page);		return _fetch_next_packet(s, p, page);	}}int vcedit_open(vcedit_state *state, FILE *in){	return vcedit_open_callbacks(state, (void *)in, 			(vcedit_read_func)fread, (vcedit_write_func)fwrite);}int vcedit_open_callbacks(vcedit_state *state, void *in,		vcedit_read_func read_func, vcedit_write_func write_func){	char *buffer;	int bytes,i;	ogg_packet *header;	ogg_packet	header_main;	ogg_packet  header_comments;	ogg_packet	header_codebooks;	ogg_page    og;	state->in = in;	state->read = read_func;	state->write = write_func;	state->oy = g_malloc(sizeof(ogg_sync_state));	ogg_sync_init(state->oy);	buffer = ogg_sync_buffer(state->oy, CHUNKSIZE);	bytes = state->read(buffer, 1, CHUNKSIZE, state->in);	ogg_sync_wrote(state->oy, bytes);	if(ogg_sync_pageout(state->oy, &og) != 1)	{		if(bytes<CHUNKSIZE)			state->lasterror = "Input truncated or empty.";		else			state->lasterror = "Input is not an Ogg bitstream.";		goto err;	}	state->serial = ogg_page_serialno(&og);	state->os = g_malloc(sizeof(ogg_stream_state));	ogg_stream_init(state->os, state->serial);	vorbis_info_init(&state->vi);	state->vc = g_malloc(sizeof(vorbis_comment));	vorbis_comment_init(state->vc);	if(ogg_stream_pagein(state->os, &og) < 0)	{		state->lasterror = "Error reading first page of Ogg bitstream.";		goto err;	}	if(ogg_stream_packetout(state->os, &header_main) != 1)	{		state->lasterror = "Error reading initial header packet.";		goto err;	}	if(vorbis_synthesis_headerin(&state->vi, state->vc, &header_main) < 0)	{		state->lasterror = "Ogg bitstream does not contain vorbis data.";		goto err;	}	state->mainlen = header_main.bytes;	state->mainbuf = g_malloc(state->mainlen);	memcpy(state->mainbuf, header_main.packet, header_main.bytes);	i = 0;	header = &header_comments;	while(i<2) {		while(i<2) {			int result = ogg_sync_pageout(state->oy, &og);			if(result == 0) break; /* Too little data so far */			else if(result == 1)			{				ogg_stream_pagein(state->os, &og);				while(i<2)				{					result = ogg_stream_packetout(state->os, header);					if(result == 0) break;					if(result == -1)					{						state->lasterror = "Corrupt secondary header.";						goto err;					}					vorbis_synthesis_headerin(&state->vi, state->vc, header);					if(i==1)					{						state->booklen = header->bytes;						state->bookbuf = g_malloc(state->booklen);						memcpy(state->bookbuf, header->packet, 								header->bytes);					}					i++;					header = &header_codebooks;				}			}		}		buffer = ogg_sync_buffer(state->oy, CHUNKSIZE);		bytes = state->read(buffer, 1, CHUNKSIZE, state->in);		if(bytes == 0 && i < 2)		{			state->lasterror = "EOF before end of vorbis headers.";			goto err;		}		ogg_sync_wrote(state->oy, bytes);	}	/* Copy the vendor tag */	state->vendor = g_malloc(strlen(state->vc->vendor) +1);	strcpy(state->vendor, state->vc->vendor);	/* Headers are done! */	return 0;err:	vcedit_clear_internals(state);	return -1;}int vcedit_write(vcedit_state *state, void *out){	ogg_stream_state streamout;	ogg_packet header_main;	ogg_packet header_comments;	ogg_packet header_codebooks;	ogg_page ogout, ogin;	ogg_packet op;	ogg_int64_t granpos = 0;	int result;	char *buffer;	int bytes;	int needflush=0, needout=0;	state->eosin = 0;	state->extrapage = 0;	header_main.bytes = state->mainlen;	header_main.packet = state->mainbuf;	header_main.b_o_s = 1;	header_main.e_o_s = 0;	header_main.granulepos = 0;	header_codebooks.bytes = state->booklen;	header_codebooks.packet = state->bookbuf;	header_codebooks.b_o_s = 0;	header_codebooks.e_o_s = 0;	header_codebooks.granulepos = 0;	ogg_stream_init(&streamout, state->serial);	_commentheader_out(state->vc, state->vendor, &header_comments);	ogg_stream_packetin(&streamout, &header_main);	ogg_stream_packetin(&streamout, &header_comments);	ogg_stream_packetin(&streamout, &header_codebooks);	while((result = ogg_stream_flush(&streamout, &ogout)))	{		if(state->write(ogout.header,1,ogout.header_len, out) !=				(size_t) ogout.header_len)			goto cleanup;		if(state->write(ogout.body,1,ogout.body_len, out) != 				(size_t) ogout.body_len)			goto cleanup;	}	while(_fetch_next_packet(state, &op, &ogin))	{		int size;		size = _blocksize(state, &op);		granpos += size;		if(needflush)		{			if(ogg_stream_flush(&streamout, &ogout))			{				if(state->write(ogout.header,1,ogout.header_len, 							out) != (size_t) ogout.header_len)					goto cleanup;				if(state->write(ogout.body,1,ogout.body_len, 							out) != (size_t) ogout.body_len)					goto cleanup;			}		}		else if(needout)		{			if(ogg_stream_pageout(&streamout, &ogout))			{				if(state->write(ogout.header,1,ogout.header_len, 							out) != (size_t) ogout.header_len)					goto cleanup;				if(state->write(ogout.body,1,ogout.body_len, 							out) != (size_t) ogout.body_len)					goto cleanup;			}		}		needflush=needout=0;		if(op.granulepos == -1)		{			op.granulepos = granpos;			ogg_stream_packetin(&streamout, &op);		}		else /* granulepos is set, validly. Use it, and force a flush to 				account for shortened blocks (vcut) when appropriate */ 		{			if(granpos > op.granulepos)			{				granpos = op.granulepos;				ogg_stream_packetin(&streamout, &op);				needflush=1;			}			else 			{				ogg_stream_packetin(&streamout, &op);				needout=1;			}		}			}	streamout.e_o_s = 1;	while(ogg_stream_flush(&streamout, &ogout))	{		if(state->write(ogout.header,1,ogout.header_len, 					out) != (size_t) ogout.header_len)			goto cleanup;		if(state->write(ogout.body,1,ogout.body_len, 					out) != (size_t) ogout.body_len)			goto cleanup;	}	/* FIXME: freeing this here probably leaks memory */	/* Done with this, now */	vorbis_info_clear(&state->vi);	if (state->extrapage)	{		if(state->write(ogin.header,1,ogin.header_len,		                out) != (size_t) ogin.header_len)			goto cleanup;		if (state->write(ogin.body,1,ogin.body_len, out) !=				(size_t) ogin.body_len)			goto cleanup;	}	state->eosin=0; /* clear it, because not all paths to here do */	while(!state->eosin) /* We reached eos, not eof */	{		/* We copy the rest of the stream (other logical streams)		 * through, a page at a time. */		while(1)		{			result = ogg_sync_pageout(state->oy, &ogout);			if(result==0) break;			if(result<0)				state->lasterror = "Corrupt or missing data, continuing...";			else			{				/* Don't bother going through the rest, we can just 				 * write the page out now */				if(state->write(ogout.header,1,ogout.header_len, 						out) != (size_t) ogout.header_len)					goto cleanup;				if(state->write(ogout.body,1,ogout.body_len, out) !=						(size_t) ogout.body_len)					goto cleanup;			}		}		buffer = ogg_sync_buffer(state->oy, CHUNKSIZE);		bytes = state->read(buffer,1, CHUNKSIZE, state->in);		ogg_sync_wrote(state->oy, bytes);		if(bytes == 0) 		{			state->eosin = 1;			break;		}	}							cleanup:	ogg_stream_clear(&streamout);	ogg_packet_clear(&header_comments);	g_free(state->mainbuf);	g_free(state->bookbuf);	vcedit_clear_internals(state);	if(!state->eosin)	{		state->lasterror =  			"Error writing stream to output. "			"Output stream may be corrupted or truncated.";		return -1;	}	return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -