|
- /*
- * Copyright (C) 2019 Anthony Chomienne, anthony@mob-dev.fr
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 3
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <getopt.h>
- #include <string.h>
- #include <sys/types.h>
- #include <sys/wait.h>
- #include <sys/stat.h>
- #include <fcntl.h>
-
-
- #define PROG_NAME "Split Audio File"
- #define VERSION "0.1"
-
- struct internal_data {
- char* input_file;
- char* output_dir;
- char* split_file_info;
- };
-
- struct track_info {
- int num;
- char* title;
- char* start;
- char* end;
- };
-
- struct album_info {
- int info_number;
- char* group;
- char* album;
- char* year;
- char* genre;
- int track_number;
- struct track_info* tracks;
- };
-
- char* prog_name;
-
- void help()
- {
- fprintf(stderr, "---------------- "PROG_NAME" --------------------------------\n");
- fprintf(stderr, "Usage: %s [options]\n" \
- " Available options:\n" \
- " \t -i | --input-file : Input File to split\n" \
- " \t -o | --output-dir : Output Directory for split files\n" \
- " \t -s | --split-file-info : Split File information\n" \
- " \t -h | --help : Print this help\n" \
- " \t -v | --version : Print programm version\n" \
- " All other arguments are data for the command, handled depending on the command.\n", prog_name);
- fprintf(stderr, "-----------------------------------------------------------------------\n");
- }
-
- void extract_trackinfo(FILE* split_file_info, struct track_info* info, int track_number)
- {
- int eof = 0;
- int parsed_tracks = 0;
- while(!eof && parsed_tracks < track_number)
- {
- char* line = NULL;
- size_t default_size = 0;
- int final_size = getline(&line,&default_size,split_file_info);
- if(final_size == -1) {
- eof = 1;
- continue;
- }
- char* split = strtok(line,";");
- size_t success = sscanf(split,"%d",&info[parsed_tracks].num);
- if(!success) {
- fprintf(stderr,"File Malformed: Track Number Error");
- }
- split = strtok(NULL,";");
- info[parsed_tracks].title = strdup(split);
- split = strtok(NULL,";");
- info[parsed_tracks].start = strdup(split);
- split = strtok(NULL,";");
- info[parsed_tracks].end = strdup(split);
- parsed_tracks++;
- free(line);
- }
- }
-
- void extract_albuminfo(struct internal_data* glob, struct album_info* info)
- {
- FILE* split_file = fopen(glob->split_file_info,"r");
- if(split_file == NULL)
- {
- fprintf(stderr,"%s doesn't exist\n", glob->split_file_info);
- exit(-1);
- }
-
- int found_tracks = 0;
-
- while(!found_tracks)
- {
- char* line = NULL;
- size_t default_size = 0;
- getline(&line,&default_size,split_file);
-
- char* category = strtok(line,";");
- if(strcmp(category,"group") == 0)
- {
- category = strtok(NULL,";");
- info->group = strdup(category);
- info->info_number++;
- }
- else if(strcmp(category,"album") == 0)
- {
- category = strtok(NULL,";");
- info->album = strdup(category);
- info->info_number++;
- }
- else if(strcmp(category,"year") == 0)
- {
- category = strtok(NULL,";");
- info->year = strdup(category);
- info->info_number++;
- }
- else if(strcmp(category,"genre") == 0)
- {
- category = strtok(NULL,";");
- info->genre = strdup(category);
- info->info_number++;
- }
- else if(strcmp(category,"tracks") == 0)
- {
- category = strtok(NULL,";");
- size_t success = sscanf(category,"%d",&info->track_number);
- if(!success)
- {
- fprintf(stderr,"File Malformed: Number of Tracks Error\n");
- exit(-1);
- }
- found_tracks = 1;
- info->info_number+=4*info->track_number;
-
- }
- free(line);
- }
- info->tracks = malloc(info->track_number * sizeof(struct track_info));
- extract_trackinfo(split_file,info->tracks, info->track_number);
-
- fclose(split_file);
- }
-
- void build_args(char* input_file, char* output_dir, struct album_info* info,int track_id, char*** args)
- {
- *args = malloc((15+2*info->info_number+1)*sizeof(char*));
- (*args)[0]="ffmpeg";
- (*args)[1]="-i";
- (*args)[2]=input_file;
- (*args)[3]="-acodec";
- (*args)[4]="copy";
- int optionnal = 5;
- if(info->group != NULL)
- {
- (*args)[optionnal++]="-metadata";
- (*args)[optionnal] = malloc(strlen("artist=")+strlen(info->group)+1);
- sprintf((*args)[optionnal++],"artist=%s",info->group);
- }
- if(info->album != NULL)
- {
- (*args)[optionnal++]="-metadata";
- (*args)[optionnal] = malloc(strlen("album=")+strlen(info->album)+1);
- sprintf((*args)[optionnal++],"album=%s",info->album);
- }
- if(info->genre != NULL)
- {
- (*args)[optionnal++]="-metadata";
- (*args)[optionnal] = malloc(strlen("genre=")+strlen(info->genre)+1);
- sprintf((*args)[optionnal++],"genre=%s",info->genre);
- }
- if(info->year != NULL)
- {
- (*args)[optionnal++]="-metadata";
- (*args)[optionnal] = malloc(strlen("date=")+strlen(info->year)+1);
- sprintf((*args)[optionnal++],"date=%s",info->year);
- }
-
- (*args)[optionnal++]="-metadata";
- (*args)[optionnal] = malloc(strlen("title=")+strlen(info->tracks[track_id].title)+1);
- sprintf((*args)[optionnal++],"title=%s",info->tracks[track_id].title);
-
- (*args)[optionnal++]="-metadata";
- (*args)[optionnal] = malloc(strlen("tracknumber=")+2+1);
- sprintf((*args)[optionnal++],"tracknumber=%02d",info->tracks[track_id].num);
- (*args)[optionnal++]="-ss";
- (*args)[optionnal] = malloc(8+1);
- sprintf((*args)[optionnal++],"00:%s",info->tracks[track_id].start);
- (*args)[optionnal++]="-to";
- (*args)[optionnal] = malloc(8+1);
- sprintf((*args)[optionnal++],"00:%s",info->tracks[track_id].end);
-
- (*args)[optionnal] = malloc(strlen(output_dir)+1+2+3+strlen(info->tracks[track_id].title)+4+1);
- sprintf((*args)[optionnal++],"%s/%02d - %s.ogg",output_dir,info->tracks[track_id].num,info->tracks[track_id].title);
- (*args)[optionnal]=NULL;
- printf("%d\n",optionnal);
- }
-
- void split_into_files(struct internal_data* data, struct album_info* info)
- {
- for(int i=0; i < info->track_number; i++)
- {
- if(fork() == 0)
- {
- char** args = NULL;
- build_args(data->input_file, data->output_dir, info, i, &args);
- execvp("ffmpeg",args);
- fprintf(stderr,"Error starting ffmpeg\n");
- exit(-1);
- }
- wait(NULL);
- }
- }
-
- void cleanup(struct album_info* info)
- {
- free(info->year);
- free(info->group);
- free(info->album);
- free(info->genre);
- for(int i=0; i < info->track_number; i++)
- {
- free(info->tracks[i].title);
- free(info->tracks[i].start);
- free(info->tracks[i].end);
- }
- free(info->tracks);
- }
-
- int main(int argc, char* argv[])
- {
-
- prog_name = argv[0];
-
- struct internal_data glob;
- memset(&glob,0,sizeof(struct internal_data));
- while(1)
- {
- int option_index = 0;
- int c = 0;
-
- struct option long_options[] = {
- {"input-file", required_argument, 0, 'i'},
- {"output-dir", required_argument, 0, 'o'},
- {"split-file-info", required_argument, 0, 's'},
- {"help", no_argument, 0, 'h'},
- {"version", no_argument, 0, 'v'},
- {0, 0, 0, 0}
- };
-
- c = getopt_long(argc, argv, "i:o:s:hv", long_options, &option_index);
-
- /* no more options to parse */
- if (c == -1) break;
- switch (c)
- {
- /* i Input Audio File */
- case 'i':
- glob.input_file = optarg;
- break;
-
- /* o, Output Directory*/
- case 'o':
- glob.output_dir = optarg;
- break;
-
- /* s, Split Information File */
- case 's':
- glob.split_file_info = optarg;
- break;
-
- /* v, version */
- case 'v':
- printf("%s Version %s\n", PROG_NAME, VERSION);
- return 0;
- break;
-
- /* h, help */
- case 'h':
- default:
- help();
- return 0;
- }
- }
-
-
- if(glob.input_file == NULL || glob.output_dir == NULL || glob.split_file_info == NULL)
- {
- fprintf(stderr,"Error, need input file, output directory and split file informations\n");
- help(argv[0]);
- }
-
- struct album_info album_info;
- memset(&album_info,0,sizeof(struct album_info));
-
- extract_albuminfo(&glob,&album_info);
- split_into_files(&glob,&album_info);
- cleanup(&album_info);
-
- return 0;
- }
|