读mp3文件ID3V2信息,文字编码转换…

来源:互联网 发布:java socket通信原理 编辑:程序博客网 时间:2024/06/05 11:51
提取mp3文件ID3V2信息,通过curl命令发送请求,发布微博。ID3V2信息为UTF-16编码,需要在发送curl命令之前先转码成UTF-8

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/mman.h>
#include <fcntl.h>

typedef struct id3_v2_head
{
    charHeader[3];   //必须为"ID3"否则认为标签不存在
    unsignedchar Ver;   //版本号ID3V2.3就记录3
    unsignedcharRevision;   //副版本号此版本记录为0
    unsignedchar Flag;   //存放标志的字节,这个版本只定义了三位,稍后详细解说
    unsignedchar Size[4];   //标签大小,包括标签头的10个字节和所有的标签帧的大小
}id3_v2_head_t;

typedef struct id3_v2_frame
{
    charFrameID[4];  //用四个字符标识一个帧,说明其内容,稍后有常用的标识对照表
    unsignedchar Size[4];  //帧内容的大小,不包括帧头,不得小于1
    unsignedchar Flags[2];  //存放标志,只定义了6位,稍后详细解说
}id3_v2_frame_t;

int get_id3_v2_info(char *string);
int publish_weibo(const char* hdr, const int info_idx[3][2]);
int convert_UTF16toUTF8(const char *input, int *insize, char*output, int *outsize);

int main(int argc,char **argv)
{
    char*filename;
    if(argc!=2){
       return -1;
    }
    filename =argv[1];
   get_id3_v2_info(filename);
    return0;
}

int get_id3_v2_info(char *string)
{
    intinfo_idx[3][2] = {0};
    char*filename=NULL;
    int ret =0;
   id3_v2_head_t * id3_v2_head=NULL;
   id3_v2_frame_t* id3_v2_frame=NULL;
    intfd;
    char *hdr =NULL;
    long intid3_v2_head_length=0;
    long intid3_v2_frame_length=0;
    long inttotal_read=0;
    struct statsb;
    char *info =NULL;
   filename=string;
    fd =open(filename, O_RDONLY);
   if(fd==-1)
    {
       return -1;
    }
   fstat(fd,&sb);
   hdr=(char*)mmap(NULL,sb.st_size,PROT_READ,MAP_PRIVATE,fd,0);
    if(hdr==MAP_FAILED)
    {
       return 0;
       close(fd);
    }
   id3_v2_head=(id3_v2_head_t *)malloc(sizeof(id3_v2_head_t));
   if(id3_v2_head==NULL)
    {
       munmap(hdr,sb.st_size);
       close(fd);
       return -1;
    }
   memcpy(id3_v2_head,hdr,sizeof(id3_v2_head_t));
   if(strncmp(id3_v2_head->Header, "ID3", 3))
    {
       printf("have no id3 v2 info\n");
       munmap(hdr,sb.st_size);
       close(fd);
       return -1;
    }
   printf("have  id3 v2.%d.%dinfo\n",id3_v2_head->Ver,id3_v2_head->Revision);
   id3_v2_head_length =(id3_v2_head->Size[0]&0x7F)*0x200000+(id3_v2_head->Size[1]&0x7F)*0x400+(id3_v2_head->Size[2]&0x7F)*0x80+(id3_v2_head->Size[3]&0x7F);
    printf("headlength:%ld\n",id3_v2_head_length);
    total_read+= sizeof(id3_v2_head_t);
       id3_v2_frame = (id3_v2_frame_t*)malloc(sizeof(id3_v2_frame_t));
       if(id3_v2_frame == NULL) {
           close(fd);
           munmap(hdr,sb.st_size);
           return -1;
       }
   while(total_read < id3_v2_head_length)
    {
       memset(id3_v2_frame, 0, sizeof(id3_v2_frame_t));
       memcpy((char*)id3_v2_frame, hdr+total_read,sizeof(id3_v2_frame_t));
       id3_v2_frame_length =id3_v2_frame->Size[0]*0x100000000+id3_v2_frame->Size[1]*0x10000+id3_v2_frame->Size[2]*0x100+id3_v2_frame->Size[3];
       if(id3_v2_frame_length == 0) {
           printf("id3_v2_frame_length == 0\n");
           break;
       }
       printf("size[0~3] = %d, %d, %d, %d, %d\n",id3_v2_frame->Size[0],id3_v2_frame->Size[1],id3_v2_frame->Size[2],id3_v2_frame->Size[3], id3_v2_frame_length);
       total_read+=sizeof(id3_v2_frame_t);
       info=(char*)malloc(id3_v2_frame_length);
       if(info==NULL) {
           printf("Failed to malloc.\n");
           break;
       }
       memset(info, 0, id3_v2_frame_length);
       memcpy(info, hdr+total_read+1, id3_v2_frame_length-1);
       if (strcmp(id3_v2_frame->FrameID, "TPE1") == 0){
           info_idx[0][0] = total_read+1;
           info_idx[0][1] = id3_v2_frame_length-1;
       } else if (strcmp(id3_v2_frame->FrameID, "TIT2") ==0) {
           info_idx[1][0] = total_read+1;
           info_idx[1][1] = id3_v2_frame_length-1;
       } else if (strcmp(id3_v2_frame->FrameID, "TALB") ==0) {
           info_idx[2][0] = total_read+1;
           info_idx[2][1] = id3_v2_frame_length-1;
       }
       printf("%s:%s\n",id3_v2_frame->FrameID,info);
       total_read += id3_v2_frame_length;
       id3_v2_frame_length=0;
       free(info);
    }
    ret =publish_weibo(hdr, info_idx);
   
   munmap(hdr,sb.st_size);
   close(fd);
   free(id3_v2_frame);
   free(id3_v2_head);
    returnret;
}

int publish_weibo(const char* hdr, const int info_idx[3][2])
{
    #if 1
    // convertUTF16 to UTF8
    int insize =0;
    int outsize= 0;
    // publishweibo
    char *info =NULL;
    int ret =0;
    //constchar* s0 = "curl -k --header "Accept-Charset: utf-8" -Faccess_token=2.00hone4D0ODM9ccc404334c137PJFB -F status="我正在听";
    const char*s0 = "curl -k -F access_token=2.00hone4D0ODM9ccc404334c137PJFB -Fstatus="我正在听 ";
    const char*s2 = "" -F visible!=0 -F pic=@/home/zhangchunyan/tmp/test.jpghttps://upload.api.weibo.com/2/statuses/upload.json";
    int offset =0;
    int length =info_idx[0][1] + info_idx[1][1] + info_idx[2][1];
    if (length== 0) {
       printf("info_idx[0][1] + info_idx[1][1] + info_idx[2][1] ==0\n");
       return -1;
    }
    length +=strlen(s0)+strlen(s2)+128;
   info=(char*)malloc(length);
   if(info==NULL) {
       printf("Failed to malloc.\n");
       return -1;
    }
    memset(info,0, length);
    memcpy(info,s0, strlen(s0));
    offset +=strlen(s0);
    insize =info_idx[0][1];
    outsize =info_idx[0][1]*2;
   printf("outsize=%d\n", outsize);
   convert_UTF16toUTF8(hdr+info_idx[0][0], &insize,info+offset, &outsize);
    printf("1:%soutsize=%d\n", info+offset, outsize);
    //for(int i= 0; i < info_idx[0][1] - outsize+10; i++) {
       //printf("%x ", *(info+offset+i));
       //if (i == 10) printf("\n");
    //}printf("\n");
    offset +=outsize;
    offset +=sprintf(info+offset, "《");
    insize =info_idx[1][1];
    outsize =info_idx[1][1]*2;
   printf("outsize=%d\n", outsize);
   convert_UTF16toUTF8(hdr+info_idx[1][0], &insize,info+offset, &outsize);
    printf("2:%soutsize=%d\n", info+offset, outsize);
    //for(int i= 0; i < info_idx[1][1] - outsize+10; i++) {
       //printf("%x ", *(info+offset+i));
       //if (i == 10) printf("\n");
    //}printf("\n");
    offset +=outsize;
    offset +=sprintf(info+offset, "》(分享自PIA)");
   memcpy(info+offset, s2, strlen(s2));
   printf("3:%s\n", info);
    ret =system(info);
   free(info);
    #endif
    returnret;
}

 
int convert_UTF16toUTF8(const char *input, int *insize, char*output, int *outsize)
{
    char*outstart = output;
    const char*processed = input;
    char* outend= output + *outsize;
    unsignedshort* in = (unsigned short*) input;
    unsignedshort* inend;
    unsigned intc, d, inlen;
    char*tmp;
    intbits;
 
    intisLittleEndian = 1;
 
    if((*insize% 2) == 1) (*insize)--;
    inlen =*insize / 2;
    inend = in +inlen;
    while((in< inend) && (output- outstart + 5 < *outsize))
    {
       if(isLittleEndian)
       {
           c= *in++;
       }
       else
       {
           tmp = (char *) in;
           c = *tmp++;
           c = c | (((unsigned int)*tmp) <<8);
           in++;
       }
       if((c & 0xFC00) == 0xD800)
       {
           if(in >= inend) break;
           if(isLittleEndian) {d = *in++;}
           else
           {
               tmp = (char *) in;
               d = *tmp++;
               d = d | (((unsigned int)*tmp) <<8);
               in++;
           }
           if((d & 0xFC00) == 0xDC00)
           {
               c &= 0x03FF;
               c <<= 10;
               c |= d & 0x03FF;
               c += 0x10000;
           }
           else
           {
               *outsize = output - outstart;
               *insize = processed - input;
               return -1;
           }
       }
 
       if(output >= outend) break;
       if (c < 0x80) {*output++ = c; bits= -6;}
       else if(c < 0x800) {*output++ = ((c>> 6) & 0x1F) | 0xC0;bits= 0;}
       else if(c < 0x10000) {*output++ = ((c>> 12) & 0x0F) |0xE0; bits= 6;}
       else {*output++ = ((c >> 18)& 0x07) | 0xF0; bits= 12;}
 
       for(; bits >= 0; bits-= 6)
       {
           if (output >= outend)
           break;
           *output++ = ((c >> bits)& 0x3F) | 0x80;
       }
       processed = (const char*) in;
    }
 
    *outsize =output - outstart;
    *insize =processed - input;
 
    return0;
}



0 0
原创粉丝点击