Comment créer des playlists musicales sous Linux

J’ai récemment écrit un programme C sous Linux pour créer une petite sélection aléatoire de fichiers MP3 à partir de ma vaste bibliothèque MP3. Le programme parcourt un répertoire contenant ma bibliothèque MP3, puis crée un répertoire avec une sélection aléatoire et plus petite de chansons. Je copie ensuite les fichiers MP3 sur mon smartphone pour les écouter en déplacement.
La Suède est un pays peu peuplé avec de nombreuses zones rurales où vous n’avez pas une couverture complète de téléphonie mobile. C’est l’une des raisons d’avoir des fichiers MP3 sur un smartphone. Une autre raison est que je n’ai pas toujours l’argent pour un service de streaming, donc j’aime avoir mes propres copies des chansons que j’apprécie.
Vous pouvez télécharger mon application à partir de son Référentiel Git. Je l’ai écrit spécifiquement pour Linux en partie parce qu’il est facile de trouver des routines d’E/S de fichiers bien testées sous Linux. Il y a de nombreuses années, j’ai essayé d’écrire le même programme sur Windows en utilisant des bibliothèques C propriétaires, et je suis resté bloqué en essayant de faire fonctionner le routage de copie de fichiers. Linux donne à l’utilisateur un accès facile et direct au système de fichiers.
Dans l’esprit de l’open source, il n’a pas fallu beaucoup de recherches avant que je trouve le code d’E/S de fichier pour Linux pour m’inspirer. J’ai aussi trouvé du code pour allouer de la mémoire qui m’a inspiré. J’ai écrit le code pour la génération de nombres aléatoires.
Le programme fonctionne comme décrit ici :
- Il demande le répertoire source et destination.
- Il demande le nombre de fichiers dans le répertoire des fichiers MP3.
- Il recherche le pourcentage (de 1,0 à 88,0 %) de votre collection que vous souhaitez copier. Vous pouvez également entrer un nombre comme 12,5 %, si vous avez une collection de 1000 fichiers et souhaitez copier 125 fichiers de votre collection plutôt que 120 fichiers. J’ai mis le plafond à 88% car copier plus de 88% de votre bibliothèque générerait principalement une collection similaire à votre collection de base. Bien sûr, le code est open source, vous pouvez donc le modifier librement à votre guise.
- Il alloue de la mémoire à l’aide de pointeurs et de malloc. De la mémoire est nécessaire pour plusieurs actions, notamment la liste des chaînes représentant les fichiers de votre collection musicale. Il existe également une liste pour contenir les numéros générés au hasard.
- Il génère une liste de nombres aléatoires dans la plage de tous les fichiers (par exemple, 1 à 1000, si la collection contient 1000 fichiers).
- Il copie les fichiers.
Certaines de ces parties sont plus simples que d’autres, mais le code ne fait qu’environ 100 lignes :
#include <dirent.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h> /* include necessary header files */
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#define BUF_SIZE 4096 /* use buffer of 4096 bytes */
#define OUTPUT_MODE 0700 /*protect output file */
#define MAX_STR_LEN 256
int main(void) {
DIR *d;
struct dirent *dir;
char strTemp[256], srcFile[256],
dstFile[256], srcDir[256], dstDir[256];
char **ptrFileLst;
char buffer[BUF_SIZE];
int nrOfStrs=-1, srcFileDesc,
dstFileDesc, readByteCount,
writeByteCount, numFiles;
int indPtrFileAcc, q;
float nrFilesCopy;
//vars for generatingRandNumList
int i, k, curRanNum, curLstInd,
numFound, numsToGen, largNumRange;
int *numLst;
float procFilesCopy;
printf("Enter name of source Directory\n");
scanf("%s", srcDir);
printf("Enter name of destionation Directory\n");
scanf("%s", dstDir);
printf("How many files does the directory with mp3 files contain?\n");
scanf("%d", &numFiles);
printf("What percent of the files do you wish to make a random selection of\n");
printf("enter a number between 1 and 88\n");
scanf("%f", &procFilesCopy);
//allocate memory for filesList, list of random numbers
ptrFileLst= (char**) malloc(numFiles * sizeof(char*));
for (i=0; i<numFiles; i++)
ptrFileLst[i] = (char*)malloc(MAX_STR_LEN * sizeof(char));
largNumRange=numFiles;
nrFilesCopy=(procFilesCopy/100)*numFiles;
numsToGen=(int)((procFilesCopy/100)*numFiles);
printf("nrFilesCopy=%f", nrFilesCopy);
printf("NumsToGen=%d", numsToGen);
numLst = malloc(numsToGen * sizeof(int));
srand(time(0));
numLst[0]=rand()%largNumRange+1;
numFound=0;
do { curRanNum=(int)rand()%largNumRange+1;
if(numLst[0]==curRanNum) {
numFound=1; }
} while(numFound==1);
numLst[1]=curRanNum;
getchar();
curLstInd=1;
i=0;
while(1){
do{
numFound=0;
curRanNum=(int)rand()%largNumRange+1;
for(int k=0; k<=curLstInd; k++){
if(numLst[k]==curRanNum)
numFound=1;
}
} while(numFound==1);
numLst[curLstInd+1]=curRanNum;
curLstInd++;
i++;
// numsToGen=Total numbers to generate minus two
// already generated by the code above this loop
if(i==(numsToGen-2))
break;
}
d = opendir(srcDir);
if(d){
while ( (dir = readdir(d)) != NULL ){
strcpy(strTemp, dir->d_name);
if(strTemp[0]!='.'){
nrOfStrs++;
strcpy(ptrFileLst[nrOfStrs], strTemp);
} }
closedir(d); }
for(q=0; q<=curLstInd; q++){
indPtrFileAcc=numLst[q];
strcpy(srcFile,srcDir);
strcat(srcFile, "https://opensource.com/");
strcat(srcFile,ptrFileLst[indPtrFileAcc]);
strcpy(dstFile,dstDir);
strcat(dstFile, "https://opensource.com/");
strcat(dstFile,ptrFileLst[indPtrFileAcc]);
srcFileDesc = open(srcFile, O_RDONLY);
dstFileDesc = creat(dstFile, OUTPUT_MODE);
while(1){
readByteCount = read(srcFileDesc, buffer, BUF_SIZE);
if(readByteCount<=0)
break;
writeByteCount = write(dstFileDesc, buffer, readByteCount);
if(writeByteCount<=0)
exit(4); }
//close the files
close(srcFileDesc);
close(dstFileDesc); } }
Ce code est peut-être le plus complexe :
while(1){
readByteCount = read(srcFileDesc, buffer, BUF_SIZE);
if(readByteCount<=0)
break;
writeByteCount = write(dstFileDesc, buffer, readByteCount);
if(writeByteCount<=0)
exit(4); }
Cela lit un certain nombre d’octets (readByteCount) à partir d’un fichier spécifié dans le tampon de caractères. Le premier paramètre de la fonction est le nom du fichier (srcFileDesc). Le deuxième paramètre est un pointeur sur le tampon de caractères, déclaré précédemment dans le programme. Le dernier paramètre de la fonction est la taille du tampon.
Le programme renvoie le nombre d’octets lus (dans ce cas, 4 octets). La première if
La clause sort de la boucle si un nombre inférieur ou égal à 0 est renvoyé.
Si le nombre d’octets lus est 0, alors toute l’écriture est effectuée et la boucle s’interrompt pour écrire le fichier suivant. Si le nombre d’octets lus est inférieur à 0, une erreur s’est produite et le programme se termine.
Lorsque les 4 octets sont lus, il y écrira. La fonction d’écriture prend trois arguments. Le premier est le fichier dans lequel écrire, le second est le tampon de caractères et le troisième est le nombre d’octets à écrire (4 octets) . La fonction renvoie le nombre d’octets écrits.
Si 0 octets sont écrits, alors une erreur d’écriture s’est produite, donc le deuxième if
clause quitte le programme.
La while
loop lit et copie le fichier, 4 octets à la fois, jusqu’à ce que le fichier soit copié. Lorsque la copie est terminée, vous pouvez copier le répertoire des fichiers mp3 générés aléatoirement sur votre smartphone.
Les routines de copie et d’écriture sont assez efficaces car elles utilisent des appels de système de fichiers sous Linux.
Améliorer le code
Ce programme est simple et pourrait être amélioré en termes d’interface utilisateur et de flexibilité. Vous pouvez implémenter une fonction qui calcule le nombre de fichiers dans le répertoire source afin que vous n’ayez pas à le saisir manuellement, par exemple. Vous pouvez ajouter des options pour transmettre le pourcentage et le chemin de manière non interactive. Mais le code fait ce dont j’ai besoin, et c’est une démonstration de la simple efficacité du langage de programmation C.