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

📄 mp4tags.cpp

📁 完整的RTP RTSP代码库
💻 CPP
字号:
/* mp4tags -- tool to set iTunes-compatible metadata tags *  * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ *  * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. *  * Contributed to MPEG4IP  * by Christopher League <league@contrapunctus.net> */#include "mp4.h"#include "mpeg4ip_getopt.h"/* One-letter options -- if you want to rearrange these, change them   here, immediately below in OPT_STRING, and in the help text. */#define OPT_HELP    'h'#define OPT_VERSION 'v'#define OPT_ALBUM   'A'#define OPT_ARTIST  'a'#define OPT_TEMPO   'b'#define OPT_COMMENT 'c'#define OPT_DISK    'd'#define OPT_DISKS   'D'#define OPT_GENRE   'g'#define OPT_GROUPING 'G'#define OPT_PICTURE 'P'#define OPT_SONG    's'#define OPT_TRACK   't'#define OPT_TRACKS  'T'#define OPT_WRITER  'w'    /* _composer_ */#define OPT_YEAR    'y'#define OPT_REMOVE  'r'#define OPT_ALBUM_ARTIST 'R'#define OPT_STRING  "hvA:a:b:c:d:D:g:G:P:s:t:T:w:y:r:R:"static const char* help_text ="OPTION... FILE...\n""Adds or modifies iTunes-compatible tags on MP4 files.\n""\n""  -h, -help         Display this help text and exit\n""  -v, -version      Display version information and exit\n""  -A, -album    STR  Set the album title\n""  -a, -artist   STR  Set the artist information\n""  -b, -tempo    NUM  Set the tempo (beats per minute)\n""  -c, -comment  STR  Set a general comment\n""  -d, -disk     NUM  Set the disk number\n""  -D, -disks    NUM  Set the number of disks\n""  -g, -genre    STR  Set the genre name\n""  -G, -grouping STR  Set the grouping name\n""  -P, -picture  PTH  Set the picture as a .png\n""  -s, -song     STR  Set the song title\n""  -t, -track    NUM  Set the track number\n""  -T, -tracks   NUM  Set the number of tracks\n""  -w, -writer   STR  Set the composer information\n""  -y, -year     NUM  Set the year\n""  -R, -albumartist STR Set the album artist\n""  -r, -remove   STR  Remove tags by code (e.g. \"-r cs\"\n""                     removes the comment and song tags)\n""\n";int main(int argc, char** argv){  static struct option long_options[] = {    { "help",    0, 0, OPT_HELP    },    { "version", 0, 0, OPT_VERSION },    { "album",   1, 0, OPT_ALBUM   },    { "artist",  1, 0, OPT_ARTIST  },    { "comment", 1, 0, OPT_COMMENT },    { "disk",    1, 0, OPT_DISK    },    { "disks",   1, 0, OPT_DISKS   },    { "genre",   1, 0, OPT_GENRE   },    { "grouping",1, 0, OPT_GROUPING},    { "picture", 1, 0, OPT_PICTURE },    { "song",    1, 0, OPT_SONG    },    { "tempo",   1, 0, OPT_TEMPO   },    { "track",   1, 0, OPT_TRACK   },    { "tracks",  1, 0, OPT_TRACKS  },    { "writer",  1, 0, OPT_WRITER  },    { "year",    1, 0, OPT_YEAR    },    { "remove",  1, 0, OPT_REMOVE  },    { "albumartist", 1, 0, OPT_ALBUM_ARTIST },    { NULL,      0, 0, 0 }  };  /* Sparse arrays of tag data: some space is wasted, but it's more     convenient to say tags[OPT_SONG] than to enumerate all the     metadata types (again) as a struct. */  char *tags[UCHAR_MAX];  int nums[UCHAR_MAX];  memset(tags, 0, sizeof(tags));  memset(nums, 0, sizeof(nums));  /* Any modifications requested? */  int mods = 0;  /* Option-processing loop. */  int c = getopt_long_only(argc, argv, OPT_STRING, long_options, NULL);  while (c != -1) {    int r = 2;    switch(c) {      /* getopt() returns '?' if there was an error.  It already         printed the error message, so just return. */    case '?':      return 1;      /* Help and version requests handled here. */    case OPT_HELP:      fprintf(stderr, "usage %s %s", argv[0], help_text);      return 0;    case OPT_VERSION:      fprintf(stderr, "%s - %s version %s\n", argv[0], MPEG4IP_PACKAGE, 	      MPEG4IP_VERSION);      return 0;      /* Numeric arguments: convert them using sscanf(). */    case OPT_DISK: case OPT_DISKS:    case OPT_TRACK: case OPT_TRACKS:    case OPT_TEMPO:      r = sscanf(optarg, "%d", &nums[c]);      if (r < 1) {        fprintf(stderr, "%s: option requires numeric argument -- %c\n",                argv[0], c);        return 2;      }      /* Break not, lest ye be broken.  :) */      /* All arguments: all valid options end up here, and we just         stuff the string pointer into the tags[] array. */    default:      tags[c] = optarg;      mods++;    } /* end switch */        c = getopt_long_only(argc, argv, OPT_STRING, long_options, NULL);  } /* end while */  /* Check that we have at least one non-option argument */  if ((argc - optind) < 1) {    fprintf(stderr,             "%s: You must specify at least one MP4 file.\n",             argv[0]);    fprintf(stderr, "usage %s %s", argv[0], help_text);    return 3;  }  /* Check that we have at least one requested modification.  Probably     it's useful instead to print the metadata if no modifications are     requested? */  if (!mods) {    fprintf(stderr,             "%s: You must specify at least one tag modification.\n",             argv[0]);    fprintf(stderr, "usage %s %s", argv[0], help_text);    return 4;  }  /* Loop through the non-option arguments, and modify the tags as     requested. */   while (optind < argc) {    char *mp4 = argv[optind++];    MP4FileHandle h = MP4Modify(mp4);    if (h == MP4_INVALID_FILE_HANDLE) {      fprintf(stderr, "Could not open '%s'... aborting\n", mp4);      return 5;    }    /* Remove any tags */    if( tags[OPT_REMOVE] ) {      for(const char *p = tags[OPT_REMOVE]; *p; p++ ) {        switch(*p) {        case OPT_ALBUM:   MP4DeleteMetadataAlbum(h); break;        case OPT_ARTIST:  MP4DeleteMetadataArtist(h); break;        case OPT_COMMENT: MP4DeleteMetadataComment(h); break;        case OPT_DISK:    MP4DeleteMetadataDisk(h); break;        case OPT_DISKS:   MP4DeleteMetadataDisk(h); break;        case OPT_GENRE:   MP4DeleteMetadataGenre(h); break;        case OPT_GROUPING:MP4DeleteMetadataGrouping(h); break;        case OPT_SONG:    MP4DeleteMetadataName(h); break;        case OPT_WRITER:  MP4DeleteMetadataWriter(h); break;        case OPT_YEAR:    MP4DeleteMetadataYear(h); break;        case OPT_TEMPO:   MP4DeleteMetadataTempo(h); break;        case OPT_TRACK:   MP4DeleteMetadataTrack(h); break;        case OPT_TRACKS:  MP4DeleteMetadataTrack(h); break;	case OPT_PICTURE: MP4DeleteMetadataCoverArt(h); break;	case OPT_ALBUM_ARTIST: MP4DeleteMetadataAlbumArtist(h); break ;        }      }    }    /* Track/disk numbers need to be set all at once, but we'd like to       allow users to just specify -T 12 to indicate that all existing       track numbers are out of 12.  This means we need to look up the       current info if it is not being set. */    uint16_t n0, m0, n1, m1;    if (tags[OPT_TRACK] || tags[OPT_TRACKS]) {      n0 = m0 = 0;      MP4GetMetadataTrack(h, &n0, &m0);      n1 = tags[OPT_TRACK]? nums[OPT_TRACK] : n0;      m1 = tags[OPT_TRACKS]? nums[OPT_TRACKS] : m0;      MP4SetMetadataTrack(h, n1, m1);    }    if (tags[OPT_DISK] || tags[OPT_DISKS]) {      n0 = m0 = 0;      MP4GetMetadataDisk(h, &n0, &m0);      n1 = tags[OPT_DISK]? nums[OPT_DISK] : n0;      m1 = tags[OPT_DISKS]? nums[OPT_DISKS] : m0;      MP4SetMetadataDisk(h, n1, m1);    }        /* Set the other relevant attributes */    for (int i = 0;  i < UCHAR_MAX;  i++) {      if (tags[i]) {        switch(i) {        case OPT_ALBUM:   MP4SetMetadataAlbum(h, tags[i]); break;        case OPT_ARTIST:  MP4SetMetadataArtist(h, tags[i]); break;        case OPT_COMMENT: MP4SetMetadataComment(h, tags[i]); break;        case OPT_GENRE:   MP4SetMetadataGenre(h, tags[i]); break;        case OPT_GROUPING:MP4SetMetadataGrouping(h, tags[i]); break;        case OPT_SONG:    MP4SetMetadataName(h, tags[i]); break;        case OPT_WRITER:  MP4SetMetadataWriter(h, tags[i]); break;        case OPT_YEAR:    MP4SetMetadataYear(h, tags[i]); break;        case OPT_TEMPO:   MP4SetMetadataTempo(h, nums[i]); break;	case OPT_ALBUM_ARTIST: MP4SetMetadataAlbumArtist(h, tags[i]); break;	case OPT_PICTURE: {	  FILE *artFile = fopen(tags[i], FOPEN_READ_BINARY);	  if (artFile != NULL) {	    uint64_t artSize;	    fseek(artFile, 0, SEEK_END);	    artSize = ftell(artFile);	    uint8_t *art;	    art = (uint8_t *)malloc(artSize);	    fseek(artFile, 0, SEEK_SET);	    clearerr(artFile);	    if (fread(art, artSize, 1, artFile) == 1) {	      MP4SetMetadataCoverArt(h, art, artSize);	    }	    free(art);	    fclose(artFile);	  } else {	    fprintf(stderr, "Art file %s not found\n", tags[i]);	  }	}        }      }    }    MP4Close(h);  } /* end while optind < argc */  return 0;}

⌨️ 快捷键说明

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