Init
This commit is contained in:
commit
138ffbbba3
|
@ -0,0 +1,29 @@
|
||||||
|
================================================================================
|
||||||
|
SONGATTR
|
||||||
|
================================================================================
|
||||||
|
songattr.sh uses FFMPEG to fill the Audio:* & Media:* attributes for audio
|
||||||
|
files. It will populate Audio:Artist, Audio:Album, Audio:Track, Media:Title,
|
||||||
|
and Media:Year, as possible. Additionally, if lyrics are embedded in the file,
|
||||||
|
it will set the non-standard Audio:Lyrics attribute.
|
||||||
|
|
||||||
|
In addition, it can set the Album:Artist and Media:Year attributes for the
|
||||||
|
parent directory (assumed to be the Album folder), using a custom audio/x-album
|
||||||
|
filetype. You can add the Album type to your system by building and running
|
||||||
|
album_attr/ once.
|
||||||
|
|
||||||
|
========================================
|
||||||
|
USAGE
|
||||||
|
========================================
|
||||||
|
usage: songattr [-ha] file
|
||||||
|
-h print more detailed help info
|
||||||
|
-a treat the parent directory as an Album file
|
||||||
|
|
||||||
|
Since songattr can only take one file at a time, you'll probably end up using
|
||||||
|
it like this:
|
||||||
|
$ for file in ./*.mp3; do songattr "$file"; done
|
||||||
|
|
||||||
|
========================================
|
||||||
|
BORING STUFF
|
||||||
|
========================================
|
||||||
|
MIT License
|
||||||
|
Jaidyn Ann, jadedctrl@teknik.io
|
|
@ -0,0 +1,131 @@
|
||||||
|
## Haiku Generic Makefile v2.6 ##
|
||||||
|
|
||||||
|
## Fill in this file to specify the project being created, and the referenced
|
||||||
|
## Makefile-Engine will do all of the hard work for you. This handles any
|
||||||
|
## architecture of Haiku.
|
||||||
|
##
|
||||||
|
## For more information, see:
|
||||||
|
## file:///system/develop/documentation/makefile-engine.html
|
||||||
|
|
||||||
|
# The name of the binary.
|
||||||
|
NAME = album_attr
|
||||||
|
|
||||||
|
# The type of binary, must be one of:
|
||||||
|
# APP: Application
|
||||||
|
# SHARED: Shared library or add-on
|
||||||
|
# STATIC: Static library archive
|
||||||
|
# DRIVER: Kernel driver
|
||||||
|
TYPE = APP
|
||||||
|
|
||||||
|
# If you plan to use localization, specify the application's MIME signature.
|
||||||
|
APP_MIME_SIG =
|
||||||
|
|
||||||
|
# The following lines tell Pe and Eddie where the SRCS, RDEFS, and RSRCS are
|
||||||
|
# so that Pe and Eddie can fill them in for you.
|
||||||
|
#%{
|
||||||
|
# @src->@
|
||||||
|
|
||||||
|
# Specify the source files to use. Full paths or paths relative to the
|
||||||
|
# Makefile can be included. All files, regardless of directory, will have
|
||||||
|
# their object files created in the common object directory. Note that this
|
||||||
|
# means this Makefile will not work correctly if two source files with the
|
||||||
|
# same name (source.c or source.cpp) are included from different directories.
|
||||||
|
# Also note that spaces in folder names do not work well with this Makefile.
|
||||||
|
SRCS = main.cpp
|
||||||
|
|
||||||
|
# Specify the resource definition files to use. Full or relative paths can be
|
||||||
|
# used.
|
||||||
|
RDEFS =
|
||||||
|
|
||||||
|
# Specify the resource files to use. Full or relative paths can be used.
|
||||||
|
# Both RDEFS and RSRCS can be utilized in the same Makefile.
|
||||||
|
RSRCS =
|
||||||
|
|
||||||
|
# End Pe/Eddie support.
|
||||||
|
# @<-src@
|
||||||
|
#%}
|
||||||
|
|
||||||
|
# Specify libraries to link against.
|
||||||
|
# There are two acceptable forms of library specifications:
|
||||||
|
# - if your library follows the naming pattern of libXXX.so or libXXX.a,
|
||||||
|
# you can simply specify XXX for the library. (e.g. the entry for
|
||||||
|
# "libtracker.so" would be "tracker")
|
||||||
|
#
|
||||||
|
# - for GCC-independent linking of standard C++ libraries, you can use
|
||||||
|
# $(STDCPPLIBS) instead of the raw "stdc++[.r4] [supc++]" library names.
|
||||||
|
#
|
||||||
|
# - if your library does not follow the standard library naming scheme,
|
||||||
|
# you need to specify the path to the library and it's name.
|
||||||
|
# (e.g. for mylib.a, specify "mylib.a" or "path/mylib.a")
|
||||||
|
LIBS = be $(STDCPPLIBS)
|
||||||
|
|
||||||
|
# Specify additional paths to directories following the standard libXXX.so
|
||||||
|
# or libXXX.a naming scheme. You can specify full paths or paths relative
|
||||||
|
# to the Makefile. The paths included are not parsed recursively, so
|
||||||
|
# include all of the paths where libraries must be found. Directories where
|
||||||
|
# source files were specified are automatically included.
|
||||||
|
LIBPATHS =
|
||||||
|
|
||||||
|
# Additional paths to look for system headers. These use the form
|
||||||
|
# "#include <header>". Directories that contain the files in SRCS are
|
||||||
|
# NOT auto-included here.
|
||||||
|
SYSTEM_INCLUDE_PATHS =
|
||||||
|
|
||||||
|
# Additional paths paths to look for local headers. These use the form
|
||||||
|
# #include "header". Directories that contain the files in SRCS are
|
||||||
|
# automatically included.
|
||||||
|
LOCAL_INCLUDE_PATHS =
|
||||||
|
|
||||||
|
# Specify the level of optimization that you want. Specify either NONE (O0),
|
||||||
|
# SOME (O1), FULL (O3), or leave blank (for the default optimization level).
|
||||||
|
OPTIMIZE :=
|
||||||
|
|
||||||
|
# Specify the codes for languages you are going to support in this
|
||||||
|
# application. The default "en" one must be provided too. "make catkeys"
|
||||||
|
# will recreate only the "locales/en.catkeys" file. Use it as a template
|
||||||
|
# for creating catkeys for other languages. All localization files must be
|
||||||
|
# placed in the "locales" subdirectory.
|
||||||
|
LOCALES =
|
||||||
|
|
||||||
|
# Specify all the preprocessor symbols to be defined. The symbols will not
|
||||||
|
# have their values set automatically; you must supply the value (if any) to
|
||||||
|
# use. For example, setting DEFINES to "DEBUG=1" will cause the compiler
|
||||||
|
# option "-DDEBUG=1" to be used. Setting DEFINES to "DEBUG" would pass
|
||||||
|
# "-DDEBUG" on the compiler's command line.
|
||||||
|
DEFINES =
|
||||||
|
|
||||||
|
# Specify the warning level. Either NONE (suppress all warnings),
|
||||||
|
# ALL (enable all warnings), or leave blank (enable default warnings).
|
||||||
|
WARNINGS =
|
||||||
|
|
||||||
|
# With image symbols, stack crawls in the debugger are meaningful.
|
||||||
|
# If set to "TRUE", symbols will be created.
|
||||||
|
SYMBOLS :=
|
||||||
|
|
||||||
|
# Includes debug information, which allows the binary to be debugged easily.
|
||||||
|
# If set to "TRUE", debug info will be created.
|
||||||
|
DEBUGGER :=
|
||||||
|
|
||||||
|
# Specify any additional compiler flags to be used.
|
||||||
|
COMPILER_FLAGS =
|
||||||
|
|
||||||
|
# Specify any additional linker flags to be used.
|
||||||
|
LINKER_FLAGS =
|
||||||
|
|
||||||
|
# Specify the version of this binary. Example:
|
||||||
|
# -app 3 4 0 d 0 -short 340 -long "340 "`echo -n -e '\302\251'`"1999 GNU GPL"
|
||||||
|
# This may also be specified in a resource.
|
||||||
|
APP_VERSION :=
|
||||||
|
|
||||||
|
# (Only used when "TYPE" is "DRIVER"). Specify the desired driver install
|
||||||
|
# location in the /dev hierarchy. Example:
|
||||||
|
# DRIVER_PATH = video/usb
|
||||||
|
# will instruct the "driverinstall" rule to place a symlink to your driver's
|
||||||
|
# binary in ~/add-ons/kernel/drivers/dev/video/usb, so that your driver will
|
||||||
|
# appear at /dev/video/usb when loaded. The default is "misc".
|
||||||
|
DRIVER_PATH =
|
||||||
|
|
||||||
|
## Include the Makefile-Engine
|
||||||
|
DEVEL_DIRECTORY := \
|
||||||
|
$(shell findpaths -r "makefile_engine" B_FIND_PATH_DEVELOP_DIRECTORY)
|
||||||
|
include $(DEVEL_DIRECTORY)/etc/makefile-engine
|
|
@ -0,0 +1,41 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <InterfaceDefs.h>
|
||||||
|
#include <Message.h>
|
||||||
|
#include <MimeType.h>
|
||||||
|
|
||||||
|
// add the given attribute to a BMessage for use as attr info
|
||||||
|
// borrowed from mailserver, thanks!
|
||||||
|
static void addAttribute
|
||||||
|
( BMessage& msg, const char* name, const char* publicName, int32 type, int32 width )
|
||||||
|
{
|
||||||
|
msg.AddString( "attr:name", name );
|
||||||
|
msg.AddString( "attr:public_name", publicName );
|
||||||
|
msg.AddInt32( "attr:type", type );
|
||||||
|
msg.AddInt32( "attr:width", width );
|
||||||
|
msg.AddInt32( "attr:alignment", B_ALIGN_LEFT );
|
||||||
|
msg.AddBool( "attr:extra", false );
|
||||||
|
msg.AddBool( "attr:viewable", true );
|
||||||
|
msg.AddBool( "attr:editable", true );
|
||||||
|
}
|
||||||
|
|
||||||
|
// install the x-album filetype for folders containing music
|
||||||
|
int main ( int argc, char** argv )
|
||||||
|
{
|
||||||
|
BMessage info;
|
||||||
|
BMimeType mime( "audio/x-album" );
|
||||||
|
if ( mime.IsInstalled() ) return 2;
|
||||||
|
|
||||||
|
std::cout << "DAD";
|
||||||
|
mime.GetAttrInfo( &info );
|
||||||
|
|
||||||
|
mime.SetShortDescription( "Album" );
|
||||||
|
mime.SetLongDescription( "Generic audio container" );
|
||||||
|
|
||||||
|
addAttribute( info, "Audio:Artist", "", B_STRING_TYPE, 200 );
|
||||||
|
addAttribute( info, "Album:Title", "", B_STRING_TYPE, 200 );
|
||||||
|
addAttribute( info, "Media:Year", "Year", B_INT32_TYPE, 200 );
|
||||||
|
|
||||||
|
mime.SetAttrInfo( &info );
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,171 @@
|
||||||
|
#!/bin/sh
|
||||||
|
# --------------------------------------
|
||||||
|
# name: music2attr
|
||||||
|
# main: jadedctrl<@teknik.io>
|
||||||
|
# lisc: MIT
|
||||||
|
# date: 2020-11
|
||||||
|
# --------------------------------------
|
||||||
|
|
||||||
|
# ======================================
|
||||||
|
# FFMPEG PARSING
|
||||||
|
# ======================================
|
||||||
|
# prints metadata output from FFMPEG of the given file
|
||||||
|
function song_metadata {
|
||||||
|
local file="$1"
|
||||||
|
|
||||||
|
ffmpeg -i "$file" 2>&1 \
|
||||||
|
| sed '1,/Metadata/d' \
|
||||||
|
| head -n -1 \
|
||||||
|
| sed 's% : %:%'
|
||||||
|
}
|
||||||
|
|
||||||
|
# get value of song's metadata key, from it's `song_metadata` output
|
||||||
|
function get_value {
|
||||||
|
local trait="$1"
|
||||||
|
|
||||||
|
sed -n "/^ *${trait}.*:/I,\$p" \
|
||||||
|
| sed "s/$trait//i" \
|
||||||
|
| print_until_nonempty
|
||||||
|
}
|
||||||
|
|
||||||
|
# ======================================
|
||||||
|
# ATTRIBUTES
|
||||||
|
# ======================================
|
||||||
|
|
||||||
|
|
||||||
|
# set a song's metadata attribute, if file contains it
|
||||||
|
# pipe in output from `song_metadata`
|
||||||
|
function set_attr {
|
||||||
|
local file="$1"
|
||||||
|
local key="$2"
|
||||||
|
local attr="$3"
|
||||||
|
local type="$4"
|
||||||
|
|
||||||
|
local value="$(get_value "$key")"
|
||||||
|
|
||||||
|
if test "$type" = "time"; then set_time_attr "$file" "$attr" "$value"; return; fi
|
||||||
|
if echo "$type"|grep -q "^int";then set_int_attr "$file" "$attr" "$value" "$type";return;fi
|
||||||
|
|
||||||
|
if test -n "$value"; then
|
||||||
|
addattr -t "$type" "$attr" "$value" "$file"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# we have some special sanitization to do for time attributes (helper of 'set_attr')
|
||||||
|
function set_time_attr {
|
||||||
|
local file="$1"; local attr="$2"; local value="$3"
|
||||||
|
|
||||||
|
if test 5 -eq "$(echo "$value" | wc -c)"; then
|
||||||
|
value="${value}-01-01"
|
||||||
|
fi
|
||||||
|
if test -n "$value"; then
|
||||||
|
addattr -t "time" "$attr" "$value" "$file"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# we have some special sanitization to do for ints, too (helper of 'set_attr')
|
||||||
|
function set_int_attr {
|
||||||
|
local file="$1"; local attr="$2"; local value="$3"; local type="$4"
|
||||||
|
|
||||||
|
value="$(echo "$value" | sed 's%[A-z/, -].*%%')"
|
||||||
|
if test -n "$value"; then
|
||||||
|
addattr -t "$type" "$attr" "$value" "$file"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# set a file's entire all song-related attributes
|
||||||
|
function set_song_attrs {
|
||||||
|
local file="$1"
|
||||||
|
meta="$(song_metadata "$file")"
|
||||||
|
|
||||||
|
echo "$meta" | set_title_attr "$file" "Media:title"
|
||||||
|
echo "$meta" | set_year_attr "$file" "Media:Year"
|
||||||
|
echo "$meta" | set_lyrics_attr "$file" "Audio:Lyrics"
|
||||||
|
echo "$meta" | set_artist_attr "$file" "Audio:Artist"
|
||||||
|
echo "$meta" | set_album_attr "$file" "Audio:Album"
|
||||||
|
echo "$meta" | set_track_attr "$file" "Audio:Track"
|
||||||
|
}
|
||||||
|
|
||||||
|
# set all of an album's necessary attributes
|
||||||
|
function set_album_attrs {
|
||||||
|
song="$1"
|
||||||
|
album="$(dirname "$song")"
|
||||||
|
meta="$(song_metadata "$song")"
|
||||||
|
|
||||||
|
addattr -t mime "BEOS:TYPE" "audio/x-album" "$album"
|
||||||
|
echo "$meta" | set_artist_attr "$album" "Album:Artist"
|
||||||
|
echo "$meta" | set_year_attr "$album" "Media:Year"
|
||||||
|
}
|
||||||
|
|
||||||
|
function set_title_attr { set_attr "$1" "TITLE" "$2" "string"; }
|
||||||
|
function set_year_attr { set_attr "$1" "DATE" "$2" "int32"; }
|
||||||
|
function set_lyrics_attr { set_attr "$1" "LYRICS" "$2" "string"; }
|
||||||
|
function set_artist_attr { set_attr "$1" "ARTIST" "$2" "string"; }
|
||||||
|
function set_album_attr { set_attr "$1" "ALBUM" "$2" "string"; }
|
||||||
|
function set_track_attr { set_attr "$1" "TRACK" "$2" "int32"; }
|
||||||
|
|
||||||
|
# ======================================
|
||||||
|
# UTIL
|
||||||
|
# ======================================
|
||||||
|
# selects all fields except the first, until a a line's first field is non-empty
|
||||||
|
# delimiter used is a colon.
|
||||||
|
function print_until_nonempty {
|
||||||
|
awk -F ':' \
|
||||||
|
'{ lines[NR] = $0 }
|
||||||
|
END { i = 1
|
||||||
|
split( lines[i], L )
|
||||||
|
while ( i <= NR && match( L[1], /^( )+$/ ) ) {
|
||||||
|
for ( j = 2; j <= length(L); j = j + 1 ) {
|
||||||
|
if ( j > 2 )
|
||||||
|
printf ":"
|
||||||
|
printf L[j]
|
||||||
|
}
|
||||||
|
printf "\n"
|
||||||
|
i = i + 1
|
||||||
|
split( lines[i], L )
|
||||||
|
}
|
||||||
|
}'
|
||||||
|
}
|
||||||
|
|
||||||
|
# ======================================
|
||||||
|
# INVOCATION
|
||||||
|
# ======================================
|
||||||
|
function help {
|
||||||
|
echo "usage: $(basename $0) [-hi] [-A|a] file"
|
||||||
|
echo
|
||||||
|
echo \
|
||||||
|
"Use a song file's metadata to populate related attributes. The attributes set
|
||||||
|
are 'Media:Title', 'Audio:Artist', 'Audio:Album', 'Audio:Track', and 'Media:year'.
|
||||||
|
|
||||||
|
In addition, the parent directory is assumed to be the 'album' folder, its
|
||||||
|
type is set to 'audio/x-album', and has its attributes populated with relevant
|
||||||
|
metadata. The attributes set to 'album' folders are 'Album:Artist' and
|
||||||
|
'Media:Year', based on the song files' metadata.
|
||||||
|
|
||||||
|
$(basename $0) requires 'ffmpeg' to be installed.
|
||||||
|
|
||||||
|
-a don't edit the parent directory's attributes
|
||||||
|
-A only edit the parent directory's attributes
|
||||||
|
-h prints this message."
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
ALBUM=1
|
||||||
|
SONG=1
|
||||||
|
|
||||||
|
while getopts ":haAi" arg; do
|
||||||
|
case $arg in
|
||||||
|
a) ALBUM=0;;
|
||||||
|
A) ALBUM=1; SONG=0;;
|
||||||
|
|
||||||
|
h) help;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
shift $(($OPTIND - 1))
|
||||||
|
|
||||||
|
if test -z "$@"; then help; fi
|
||||||
|
if test ! -e /bin/ffmpeg; then help; fi
|
||||||
|
|
||||||
|
if test "$SONG" -eq 1; then set_song_attrs "$@"; fi
|
||||||
|
if test "$ALBUM" -eq 1; then set_album_attrs "$@"; fi
|
Ŝarĝante…
Reference in New Issue