This script, inspired by @Steve link, allows us to edit the metadata of a single Mp3 file at a time, although, through the navigation buttons, we can reach other files and edit them as well.
Important: When modifying a file, before moving to another, we must save the changes.
To install it, just download it:
Mp3 Tag File.js.txt (18.8 KB)
And copy it to:
"/dopusdata\Script AddIns"
Once installed, we only have to create a button with the Mp3TagFile
command.
The musical genres present in the "Genre" drop-down list are those of Opus, located in /dopusdata\ConfigFiles\musicgenres.xml
However, this list can be edited to individual taste, adding or eliminating genres. To do this, just go to Preferences > Toolbars > Scripts
and click on the Scripts Management
link, or directly access this window through a button with the command Prefs PAGE=scripts
. Once in this window, just locate the script (Mp3 Tag File) and click on the gear shaped icon.
Before finishing, I want to once again express my eternal gratitude to @errante, @lxp, @WKen and @bytespiller, four giants of programming, for all the help provided, without whom the creation of this script would not have been possible!!!
// Mp3 Tag File
// (c) 2024 DASOTA
// Script para Directory Opus.
function OnInit(initData) {
initData.name = 'Mp3 Tag File';
initData.version = '1.0';
initData.copyright = '(c) 2024 DASOTA';
initData.desc = 'Mp3 Tag File';
initData.default_enable = true;
initData.min_version = '13.0';
initData.config_desc = DOpus.Create.Map();
initData.config_desc('genre') = 'Add/remove music genres';
var gen_perso = DOpus.Create.Vector();
gen_perso.push_back('A Cappella');
gen_perso.push_back('Abstract');
gen_perso.push_back('Acid');
gen_perso.push_back('Acoustic');
gen_perso.push_back('Alternative');
gen_perso.push_back('Ambient');
gen_perso.push_back('Anime');
gen_perso.push_back('Ballad');
gen_perso.push_back('Baroque');
gen_perso.push_back('Blues');
gen_perso.push_back('Breakbeat');
gen_perso.push_back('Cabaret');
gen_perso.push_back('Chorus');
gen_perso.push_back('Christian');
gen_perso.push_back('Classical');
gen_perso.push_back('Comedy');
gen_perso.push_back('Country');
gen_perso.push_back('Cult');
gen_perso.push_back('Dance');
gen_perso.push_back('Disco');
gen_perso.push_back('Dream');
gen_perso.push_back('Electro');
gen_perso.push_back('Electronic');
gen_perso.push_back('Folklore');
gen_perso.push_back('Freestyle');
gen_perso.push_back('Funk');
gen_perso.push_back('Fusion');
gen_perso.push_back('Game');
gen_perso.push_back('Gospel');
gen_perso.push_back('Gothic');
gen_perso.push_back('Grunge');
gen_perso.push_back('Hard Rock');
gen_perso.push_back('Hardcore');
gen_perso.push_back('Heavy Metal');
gen_perso.push_back('Hip-Hop');
gen_perso.push_back('House');
gen_perso.push_back('Humour');
gen_perso.push_back('Industrial');
gen_perso.push_back('Industro-Goth');
gen_perso.push_back('Instrumental');
gen_perso.push_back('Jazz');
gen_perso.push_back('Latin');
gen_perso.push_back('Meditative');
gen_perso.push_back('Merengue');
gen_perso.push_back('Metal');
gen_perso.push_back('Musical');
gen_perso.push_back('Noise');
gen_perso.push_back('Oldies');
gen_perso.push_back('Opera');
gen_perso.push_back('Other');
gen_perso.push_back('Podcast');
gen_perso.push_back('Pop');
gen_perso.push_back('Pranks');
gen_perso.push_back('Primus');
gen_perso.push_back('Punk');
gen_perso.push_back('Rap');
gen_perso.push_back('Reggae');
gen_perso.push_back('Retro');
gen_perso.push_back('Rock');
gen_perso.push_back('Rock & Roll');
gen_perso.push_back('Salsa');
gen_perso.push_back('Samba');
gen_perso.push_back('Sonata');
gen_perso.push_back('Soul');
gen_perso.push_back('Space');
gen_perso.push_back('Tango');
gen_perso.push_back('Techno');
gen_perso.push_back('Trailer');
gen_perso.push_back('Tribal');
gen_perso.push_back('Vocal');
initData.config['genre'] = gen_perso;
}
function OnAddCommands(addCmdData) {
var cmd = addCmdData.AddCommand();
cmd.name = 'Mp3TagFile';
cmd.method = 'OnMp3TagFile';
cmd.desc = '';
cmd.label = 'Mp3 Tag File';
cmd.template = 'Mp3TagFile';
cmd.hide = false;
cmd.icon = 'script';
}
function OnMp3TagFile(scriptCmdData) {
var dlg = scriptCmdData.func.Dlg();
dlg.title = 'Mp3 Tag File - Directory Opus';
dlg.template = 'Mp3TagFile';
dlg.detach = true;
dlg.Create();
var tab = scriptCmdData.func.sourcetab;
if (!tab || tab.selected_files.count == 0) {
DOpus.Output('There are no valid files to continue');
return;
}
var item;
var genres = Script.config['genre'];
var org_cover_usuario, cover_interna;
function loadMP3Data(audio_item) {
if (!audio_item || audio_item.ext != '.mp3' || audio_item.metadata != 'audio') {
DOpus.Output('An mp3 file is required to continue');
return false;
}
try {
DOpus.Output('Reading ' + audio_item);
dlg.Control('archivo').value = audio_item.name_stem;
dlg.Control('titulo').value = audio_item.metadata.audio.mp3title;
dlg.Control('artista').value = audio_item.metadata.audio.mp3artist;
dlg.Control('album').value = audio_item.metadata.audio.mp3album;
dlg.Control('anio').value = audio_item.metadata.audio.mp3year;
dlg.Control('pista').value = audio_item.metadata.audio.mp3track;
dlg.Control('comentario').value = audio_item.metadata.audio.mp3comment;
dlg.Control('artista_album').value = audio_item.metadata.audio.mp3albumartist;
dlg.Control('compositor').value = audio_item.metadata.audio.composers;
dlg.Control('derechos').value = audio_item.metadata.audio.copyright;
dlg.Control('numero_disco').value = audio_item.metadata.audio.mp3disc;
cover_interna = '';
if (audio_item.metadata.audio.coverart > 0) {
var reso;
for (var i = 0; i < audio_item.metadata.audio.coverart.count; i++) {
reso = audio_item.metadata.audio.coverart(i);
if (reso + '' == 'front') {
cover_interna = reso + '';
break;
}
}
if (cover_interna) {
var tmpFile = DOpus.FSUtil().GetTempFile();
tmpFile.Write(reso.data);
tmpFile.Close();
org_cover_usuario = tmpFile.path + '';
dlg.Control('caratula').label = Script.LoadImage(tmpFile);
dlg.Control('resolucion').label = reso.width + ' x ' + reso.height + ' x ' + reso.depth + ' (' + reso.size.fmt + ')';
} else DOpus.Output('No front cover found');
}
if (!cover_interna) {
cover_interna = 'front';
org_cover_usuario = '';
dlg.Control('caratula').label = '';
dlg.Control('resolucion').label = '';
}
genres.unique();
dlg.Control('genero').redraw = false;
dlg.Control('genero').RemoveItem(-1);
for (var i = 0; i < genres.length; i++)
dlg.Control('genero').AddItem(genres(i));
dlg.Control('genero').InsertItemAt(0, audio_item.metadata.audio.mp3genre);
dlg.Control('genero').redraw = true;
dlg.Control('genero').value = 0;
item = audio_item;
return true;
} catch (err) {
DOpus.Output('Error reading the file ' + audio_item + ':' + err);
return false;
}
}
first_item = item + '';
dlg.Control('caratula').bg = '#FFFFFF';
dlg.Control('resolucion').fg = '#000000';
dlg.Control('resolucion').bg = '#FFFFFF';
dlg.Control('btn_guardar').enabled = dlg.Control('btn_eliminar_todo').enabled = dlg.Control('btn_anadir_caratula').enabled = dlg.Control('btn_eliminar_caratula').enabled = loadMP3Data(tab.selected_files(0));
var cmd = scriptCmdData.func.command;
cmd.ClearFiles();
var new_coverart_usuario;
var cover_usuario = org_cover_usuario;
dlg.WatchTab(tab, 'add,delete');
var item_count = tab.stats.items;
dlg.Show();
var count;
while (true) {
msg = dlg.GetMsg();
if (!msg.result) break;
if (msg.event == 'tab') {
DOpus.Output('value:' + msg.value + '; data:' + msg.data);
switch (msg.value) {
case 'close':
dlg.Control('btn_anterior').enabled = false;
dlg.Control('btn_siguiente').enabled = false;
break;
case 'filechange':
if (msg.data & 1) {
DOpus.Output('A file was added');
item_count++;
}
if (msg.data & 2) {
DOpus.Output('A file was deleted');
item_count--;
}
break;
}
} else if (msg.event == 'click') {
switch (msg.control) {
case 'btn_anterior':
case 'btn_siguiente':
count = 0;
do {
if (cmd.RunCommand('Select ' + (msg.control == 'btn_anterior' ? 'PREV' : 'NEXT'))) {
DOpus.Delay(10);
item = tab.GetFocusItem();
} else break;
count++;
} while (count <= item_count && (item == null || item.ext != '.mp3' || item + '' == first_item));
dlg.Control('btn_guardar').enabled = dlg.Control('btn_eliminar_todo').enabled = dlg.Control('btn_anadir_caratula').enabled = dlg.Control('btn_eliminar_caratula').enabled = loadMP3Data(item);
break;
case 'btn_anadir_caratula':
new_coverart_usuario = dlg.Open('Covert');
try {
if (new_coverart_usuario.result && new_coverart_usuario.metadata == 'image') {
dlg.Control('caratula').label = Script.LoadImage(new_coverart_usuario);
dlg.Control('resolucion').label = new_coverart_usuario.metadata.image.picwidth + ' x ' + new_coverart_usuario.metadata.image.picheight + ' x ' + new_coverart_usuario.metadata.image.picdepth + ' (' + new_coverart_usuario.size.fmt + ')';
cover_usuario = new_coverart_usuario + '';
}
} catch (err) {
DOpus.Output('Error reading the new covert : ' + err);
}
break;
case 'btn_eliminar_caratula':
dlg.Control('caratula').label = '';
dlg.Control('resolucion').label = '';
cover_usuario = '';
break;
case 'btn_eliminar_todo':
dlg.Control('titulo').value = '';
dlg.Control('artista').value = '';
dlg.Control('album').value = '';
dlg.Control('anio').value = '';
dlg.Control('pista').value = '';
dlg.Control('genero').label = '';
dlg.Control('comentario').value = '';
dlg.Control('artista_album').value = '';
dlg.Control('compositor').value = '';
dlg.Control('derechos').value = '';
dlg.Control('numero_disco').value = '';
dlg.Control('caratula').label = '';
dlg.Control('resolucion').label = '';
cover_usuario = '';
break;
case "btn_desde_archivo":
var name = dlg.Control("archivo").value;
var pista_name = name.replace(/(^[0-9]*)(.*)/, "$1");
var match = name.match(/(^[0-9\.\s]*)(.*)(\s-\s)(.*)/);
if (match) {
var title_name = name.replace(/(^[0-9\.\s]*)(.*)(\s-\s)(.*)/, "$2");
var artist_name = name.replace(/(^[0-9\.\s]*)(.*)(\s-\s)(.*)/, "$4");
} else {
var title_name = name.replace(/(^[0-9\.\s]*)(.*)/, "$2");
var artist_name = "";
}
var carpeta_superior = item.path.filepart;
dlg.Control("pista").value = pista_name;
dlg.Control("titulo").value = title_name;
dlg.Control("artista").value = artist_name;
dlg.Control("album").value = carpeta_superior;
break;
case "btn_ayuda":
var dlg2 = DOpus.Dlg;
dlg2.window = dlg;
dlg2.title = "Help";
dlg2.icon = "info";
dlg2.message = "This option allows you to set the values of the track, title, artist and album fields from the file name.\n\nEXAMPLE\n\nFavorite ballads (folder)\n 01. Words - Bee Gees.mp3\n \nRESULT \n\nTrack: 01\nTitle: Words\nArtist: Bee Gees\nAlbum: Favorite Ballads\n\nNote: This option will work even if the file name does not exactly match with the format ##. Title - Artist, applying only information that matches.";
dlg2.buttons = "OK";
dlg2.Show();
break;
case 'btn_guardar':
cmd.RunCommand('SetAttr' + ' FILE="' + item + '" META "title:' + dlg.Control("titulo").value + '"');
cmd.RunCommand('SetAttr' + ' FILE="' + item + '" META "artist:' + dlg.Control("artista").value + '"');
cmd.RunCommand('SetAttr' + ' FILE="' + item + '" META "album:' + dlg.Control("album").value + '"');
cmd.RunCommand('SetAttr' + ' FILE="' + item + '" META "year:' + dlg.Control("anio").value + '"');
cmd.RunCommand('SetAttr' + ' FILE="' + item + '" META "track:' + dlg.Control("pista").value + '"');
cmd.RunCommand('SetAttr' + ' FILE="' + item + '" META "genre:' + dlg.Control("genero").value.name + '"');
cmd.RunCommand('SetAttr' + ' FILE="' + item + '" META "comment:' + dlg.Control("comentario").value + '"');
cmd.RunCommand('SetAttr' + ' FILE="' + item + '" META "albumartist:' + dlg.Control("artista_album").value + '"');
cmd.RunCommand('SetAttr' + ' FILE="' + item + '" META "composers:' + dlg.Control("compositor").value + '"');
cmd.RunCommand('SetAttr' + ' FILE="' + item + '" META "copyright:' + dlg.Control("derechos").value + '"');
cmd.RunCommand('SetAttr' + ' FILE="' + item + '" META "discnumber:' + dlg.Control("numero_disco").value + '"');
if (org_cover_usuario != cover_usuario)
cmd.RunCommand('SetAttr FILE="' + item + '" META' + ' "coverart:' + (cover_usuario ? (cover_interna + ':' + cover_usuario) : ('-' + cover_interna)) + '"');
break;
case 'btn_cancelar':
dlg.EndDlg(0);
break;
}
}
}
DOpus.Output('FINNISH!');
}
==SCRIPT RESOURCES
<resources>
<resource name="Mp3TagFile" type="dialog">
<dialog fontsize="9" height="193" lang="esm" title="Mp3TagFile" width="332">
<control halign="left" height="8" name="archivo_t" title="File:" type="static" valign="top" width="48" x="8" y="8" />
<control halign="left" height="12" name="archivo" readonly="yes" type="edit" width="148" x="58" y="6" />
<control halign="left" height="8" name="titulo_t" title="Title:" type="static" valign="top" width="48" x="8" y="23" />
<control halign="left" height="12" name="titulo" type="edit" width="148" x="58" y="21" />
<control halign="left" height="8" name="artista_t" title="Artist:" type="static" valign="top" width="48" x="8" y="38" />
<control halign="left" height="12" name="artista" type="edit" width="148" x="58" y="36" />
<control halign="left" height="8" name="album_t" title="Album:" type="static" valign="top" width="48" x="8" y="53" />
<control halign="left" height="12" name="album" type="edit" width="148" x="58" y="51" />
<control halign="left" height="8" name="anio_t" title="Year:" type="static" valign="top" width="48" x="8" y="68" />
<control halign="left" height="12" name="anio" number="yes" type="edit" updown="yes" val_min="1" width="50" x="58" y="66" />
<control halign="left" height="8" name="pista_t" title="Track:" type="static" valign="top" width="18" x="136" y="68" />
<control halign="left" height="12" name="pista" number="yes" type="edit" updown="yes" val_min="1" width="30" x="157" y="66" />
<control halign="left" height="8" name="genero_t" title="Genre:" type="static" valign="top" width="48" x="8" y="84" />
<control edit="yes" height="40" name="genero" sort="yes" type="combo" width="148" x="58" y="82" />
<control halign="left" height="8" name="comentario_t" title="Comment:" type="static" valign="top" width="48" x="8" y="99" />
<control halign="left" height="12" name="comentario" type="edit" width="148" x="58" y="97" />
<control halign="left" height="8" name="artista_album_t" title="Album artist:" type="static" valign="top" width="48" x="9" y="113" />
<control halign="left" height="12" name="artista_album" type="edit" width="148" x="59" y="112" />
<control halign="left" height="8" name="compositor_t" title="Composers:" type="static" valign="top" width="48" x="8" y="129" />
<control halign="left" height="12" name="compositor" type="edit" width="148" x="58" y="127" />
<control halign="left" height="8" name="derechos_t" title="Copyright:" type="static" valign="top" width="48" x="8" y="144" />
<control halign="left" height="12" name="derechos" type="edit" updown="yes" val_min="1" width="148" x="58" y="142" />
<control halign="left" height="8" name="numero_disco_t" title="Disc number:" type="static" valign="top" width="48" x="8" y="159" />
<control halign="left" height="12" name="numero_disco" type="edit" updown="yes" val_min="1" width="148" x="58" y="157" />
<control height="14" name="btn_desde_archivo" title="Track, title, artist and album from file" type="button" width="132" x="57" y="174" />
<control height="14" name="btn_ayuda" title="?" type="button" width="14" x="192" y="174" />
<control height="12" name="btn_anterior" title="<" type="button" width="30" x="236" y="6" />
<control height="12" name="btn_siguiente" title=">" type="button" width="30" x="273" y="6" />
<control height="122" name="caratula_t" title="Cover" type="group" width="113" x="212" y="21" />
<control halign="center" height="8" name="resolucion" type="static" valign="top" width="100" x="218" y="112" />
<control halign="center" height="86" image="yes" name="caratula" type="static" valign="center" width="100" x="218" y="32" />
<control height="14" name="btn_anadir_caratula" title="Add..." type="button" width="41" x="225" y="124" />
<control height="14" name="btn_eliminar_caratula" title="Delete" type="button" width="41" x="271" y="124" />
<control height="14" name="btn_eliminar_todo" title="Delete all" type="button" width="51" x="242" y="147" />
<control default="yes" height="14" name="btn_guardar" title="Save" type="button" width="45" x="220" y="171" />
<control height="14" name="btn_cancelar" title="Exit" type="button" width="45" x="271" y="171" />
</dialog>
</resource>
</resources>