aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.am4
-rw-r--r--configure.ac3
-rw-r--r--doc/idest.texi413
-rw-r--r--examples/Makefile.am21
-rw-r--r--examples/list1.scm15
-rw-r--r--examples/list2.scm28
-rw-r--r--examples/shortlist.scm19
-rw-r--r--examples/title.scm29
-rw-r--r--src/getopt.m42
-rw-r--r--src/guile.c6
-rw-r--r--src/main.c26
11 files changed, 466 insertions, 100 deletions
diff --git a/Makefile.am b/Makefile.am
index 7ef641d..3b985e8 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -15,11 +15,11 @@
# along with Idest. If not, see <http://www.gnu.org/licenses/>.
ACLOCAL_AMFLAGS = -I gint -I m4
-SUBDIRS=gnu libid3tag gint src doc
+SUBDIRS=gnu libid3tag gint src doc examples
.PHONY: ChangeLog
ChangeLog:
- if test -d .git; then \
+ $(AM_V_GEN)if test -d .git; then \
$(top_srcdir)/build-aux/gitlog-to-changelog | \
sed '/<unknown>$$/d' | fmt -s > ChangeLog; \
echo " " >> ChangeLog; \
diff --git a/configure.ac b/configure.ac
index 957a66d..0802239 100644
--- a/configure.ac
+++ b/configure.ac
@@ -66,5 +66,6 @@ AC_CONFIG_FILES([Makefile
gnu/Makefile
gint/Makefile
src/Makefile
- doc/Makefile])
+ doc/Makefile
+ examples/Makefile])
AC_OUTPUT
diff --git a/doc/idest.texi b/doc/idest.texi
index ff1632a..6529644 100644
--- a/doc/idest.texi
+++ b/doc/idest.texi
@@ -189,7 +189,7 @@ corresponding to the ID3v1 fields, are:
Viewing existing tags is simple. Just give @command{idest} a list
of files to extract information from, with no additional options:
-@smallexample
+@example
$ idest file.mp3
title: Diamonds & Rust
album: Diamonds & Rust
@@ -198,7 +198,7 @@ comment:
artist: Joan Baez
year: 1975
genre: Folk
-@end smallexample
+@end example
@cindex query mode
@xopindex{query, introduced}
@@ -208,25 +208,37 @@ display only a subset of them, use the @option{--query} option
(or @option{-q}, for short). It takes a comma-separated list of the
frame names to query. For example:
-@smallexample
+@example
$ idest --query=artist,title,year file.mp3
artist: Joan Baez
title: Diamonds & Rust
year: 1975
-@end smallexample
+@end example
If the long option form is used, as in the example above, then the
frame list must be separated from it by an equal sign, with no
surrounding white space. If the short option form is used, the list
must follow the option letter, with no white space in between, e.g.:
-@smallexample
+@example
$ idest -qartist,title,year file.mp3
-@end smallexample
+@end example
The frame list may contain either field names (@pxref{ID3v1}) or
the corresponding standard frame names (@pxref{ID3v2}).
+@anchor{describe}
+@xopindex{describe, introduced}
+To describe frames in a verbose manner, use the @option{--describe}
+(@option{-D}) option''
+
+@example
+$ idest --describe -qartist,title,year file.mp3
+Lead performer(s)/soloist(s): Joan Baez
+Title/songname/content description: Diamonds & Rust
+Recording time: 1975
+@end example
+
@xopindex{latin1, introduced}
@cindex UTF-8
@cindex ISO-8859-1
@@ -234,7 +246,7 @@ All textual fields are displayed in their original encoding. For ID3
version 2 it is usually UTF-8. The @option{--latin1} option may be
used to display them in ISO-8859-1, e.g.:
-@smallexample
+@example
$ idest --latin1 track06.mp3
title: D@'ona'm sa m@`a
album: Torna aviat
@@ -243,23 +255,25 @@ comment:
artist: Llu@'is Llach
year: 1991
genre:
-@end smallexample
+@end example
Of course, @option{--latin1} and @option{--query} can be used
together:
-@smallexample
+@example
$ idest --latin1 --query=title,artist,album track06.mp3
title: D@'ona'm sa m@`a
artist: Llu@'is Llach
album: Torna aviat
-@end smallexample
+@end example
Future versions of @command{idest} will provide more sophisticated
recoding facilities.
@anchor{comment frames}
@cindex comment frames, in query mode
+@cindex content descriptor, in comment frames
+@cindex language, in comment frames
If several frames match a queried frame name, @command{idest}
concatenates their values and displays them on a single line. Comment
frames are treated specially. Each comment frame has a @dfn{language
@@ -267,11 +281,57 @@ field}, which holds a three-letter code of the language the comment is
written in, and a @dfn{content descriptor} field, which is supposed to
help discern multiple comment entries. In the concatenated string,
each frame value is prefixed by the corresponding content
-descriptor enclosed in square brackets.
+descriptor enclosed in square brackets. For example:
+
+@example
+$ idest track01.mp3
+title: Cor i arbre
+album: Fronteres
+track: 1
+comment: [Bit_Rate]: 320 [Sample_Rate]: 44100
+artist: Josep Tero
+year: 2009
+genre:
+@end example
@anchor{all-frames query}
+@anchor{fully qualified comment}
@xopindex{all, introduced}
-FIXME
+@cindex comment, fully qualified form
+There is a special option which instructs @command{idest} to output
+all frames: the @option{--all} (@option{-a}) option. When it is used,
+comment headers are output in @dfn{fully qualified} form, i.e.:
+
+@example
+comment:@var{lang}:@var{descr}
+@end example
+
+@noindent
+where @var{lang} is the three-letter language code and @var{descr} is
+the content descriptor. For example:
+
+@example
+$ idest --all track01.mp3
+title: Cor i arbre
+album: Fronteres
+track: 1
+comment:eng:Bit_Rate: 320
+comment:eng:Sample_Rate: 44100
+TENC: Myencoder 1.0
+artist: Josep Tero
+year: 2009
+genre:
+@end example
+
+You can also use fully qualified comment form in frame lists given
+with the @option{--query} option, e.g.:
+
+@example
+$ idest --all title,track,comment::Sample_Rate track01.mp3
+title: Cor i arbre
+track: 1
+comment: [Sample_Rate]: track01.mp3
+@end example
@node Modify
@chapter Modifying Existing Tags
@@ -280,25 +340,41 @@ FIXME
To modify a particular field or frame, use the @option{--set} (@option{-s})
option. For example:
-@smallexample
+@example
$ idest --set artist='Jacques Brel' track01.mp3
-@end smallexample
+@end example
Several @option{--set} options may be used together to set several
fields at once:
-@smallexample
+@example
$ idest --set artist='Jacques Brel' \
--set title='Ne me quitte pas' track01.mp3
-@end smallexample
+@end example
+
+When setting comment frames, you can use fully qualified form
+(@pxref{fully qualified comment}), e.g.:
+
+@example
+$ idest --set comment:eng:My_comment='Noise reduction on' track01.mp3
+@end example
+
+If a comment with this content descriptor exists, its content will be
+replaced with the new one. If not, a new comment frame will be
+created.
+
+If comment is given without a particular content descriptor, all
+existing comments will be removed and a new comment frame will be
+added. Its content descriptor field will be empty and its
+language field will be set to @samp{XXX}.
@xopindex{latin1, using with --set}
Textual fields will be saved in the UTF-8 encoding. To store them
in ISO-8859-1, use the @option{--latin1} option:
-@smallexample
+@example
$ idest --latin1 --set artist='Llu@'is Llach' *.mp3
-@end smallexample
+@end example
@node Delete
@chapter Deleting Tags
@@ -308,9 +384,9 @@ $ idest --latin1 --set artist='Llu@'is Llach' *.mp3
to remove ID3 tags from the file (or files). If no argument is
specified, all tags are deleted:
-@smallexample
+@example
$ idest --delete *.mp3
-@end smallexample
+@end example
After this operation, all ID3 data are irrevocably lost, so use it
with caution.
@@ -319,9 +395,17 @@ with caution.
@option{--delete} (similarly to @option{--query}). For example, to
delete only comment and genre tags:
-@smallexample
+@example
$ idest --delete=comment,genre *.mp3
-@end smallexample
+@end example
+
+Specifying @samp{comment} (a non-qualified form) results in removing
+all comment frames. To remove a particular one, use its qualified
+form:
+
+@example
+$ idest --delete=comment::Bit_Rate track01.mp3
+@end example
@node ID Versioning
@chapter Storing Tags in Different ID3 Versions
@@ -339,16 +423,16 @@ ID3 major version number and converts the existing tags to the given
format. If there is no existing data, the new tags will be created in
this format. Thus, for example:
-@smallexample
+@example
$ idest --convert=1 *.mp3
-@end smallexample
+@end example
@noindent
changes the ID3 format in all @samp{*.mp3} files to version 1. The command:
-@smallexample
+@example
$ idest --convert=1 --set artist='Jacques Brel' *.mp3
-@end smallexample
+@end example
@noindent
sets the @samp{artist} field on each file. Those files that already
@@ -360,9 +444,9 @@ have it created in version 1 format.
addition of ID3 tags in version 1 format. For example, if the
file @file{track01.mp3} contains ID3v2 header, then this command:
-@smallexample
+@example
$ idest -V1 --set artist='Jacques Brel' track01.mp3
-@end smallexample
+@end example
@noindent
changes the @samp{artist} field and duplicates the ID3 data ID3v1
@@ -412,44 +496,106 @@ description of Guile and its features, see
@ref{Top,,Overview,guile,The Guile Reference Manual}.
The scripting mode is enabled when the option
-@option{--script} (@option{-S}) is given in the command line. The
-argument to this option specifies the name of the script file:
+@option{--script} (@option{-S}) is given in the command line. This
+option stops further option processing, so any other @command{idest}
+command line options must be given before it. The argument
+to this option specifies the name of the script file:
-@smallexample
+@example
$ idest --script list.scm *.mp3
-@end smallexample
+@end example
- As a result of this invocation, the script is read and evaluated, and
-its @dfn{main function} is applied to each input file in turn. The
-main function must be declared as:
+ When this option is given, the following operations are performed:
+
+@enumerate 1
+@item
+@findex .idest.scm
+@findex idest.scm
+@cindex Guile startup files
+The program looks for files @file{.idest.scm}, @file{$HOME/.idest.scm}
+and @file{$GUILE_SITE/idest/idest.scm} in that order. Here,
+@samp{$HOME} stands for the user home directory and @samp{$GUILE_SITE}
+stands for the Guile site-wide directory. If any of these files is
+found, it is loaded as a Scheme source code and further search is
+discontinued. This allows you to configure Guile settings on
+per-directory, per-user and site-wide basis.
+
+@item
+@cindex load path, Guile
+@anchor{load-path}
+Unless the supplied script name contains directory separators
+(@samp{/}), it is searched in the Guile's @code{%load-path}.
+The default load path is formed as follows:
+@samp{.:$GUILE_SITE/idest:$GUILE_SITE:@var{load-path}}, where
+@samp{$GUILE_SITE} is as described above and @var{load-path} is
+the default value of @code{%load-path}.
+
+@item
+The script is read and evaluated.
+
+The script can access command line arguments via the usual
+@code{command-line} function (@pxref{Runtime
+Environment,,command-line,guile,The Guile Reference Manual}). It
+can also modify the argument list (e.g. by removing its command
+line options). Any changes it does to the argument list become
+visible to @command{idest}. The only requirement is that the modified
+argument list must contain only input file names.
+
+@item
+The script's @dfn{main function} is applied to each
+input file in turn.
+@end enumerate
-@defun main file frames
+The main function must be declared as:
+
+@defun idest-main file frames
@end defun
It takes two arguments. The @var{file} argument supplies the name of
the file being processed. The @var{frames} argument is a list of ID3
frames read from that file. Each element of @var{frames} is a pair,
-consisting of the frame name and its value.
+with the frame name in its @code{car} and an association list of
+@dfn{frame properties} in its @code{cdr}.
-If the function does not modify frames, it should return @code{#f}.
-If it does modify them, it should return a list of modified frames, in
-the same format as the @var{frames} argument. To delete all existing
-frames, the function should return @code{()} (empty list).
+The properties are identified by property names, which are Scheme
+symbols. The following property names are defined:
-In order to inform @command{idest} about the main function and its
-capabilities, the script must set the following built in variables:
+@table @asis
+@item text
+Value of this frame, as a string.
-@defvar idest-main
-This variable keeps the main function.
-@end defvar
+@item descr
+Frame description. It is a string, verbosely describing the frame.
+For example, the description of @samp{TRCK} frames is @samp{Track
+number/position in set}.
+
+These are the same descriptions that are output with the
+@option{--describe} option (@pxref{describe}).
+
+@item lang
+A three-letter code of the language in which the text is written.
+This property is present only in comment fields.
+
+@item condesc
+Content descriptor. This property is present only in comment fields.
+@end table
+
+The mode in which input files are open is controlled by the
+@code{idest-readonly} variable:
@defvar idest-readonly
This is a boolean variable that indicates whether @code{idest-main}
can modify tag frames. If its value is @code{#t}, the function return
-value will be ignored, and input files will be opened in read-only mode.
+value will be ignored, and input files will be opened in read-only
+mode. This is the default.
@end defvar
-The two following sections illustrate the concept of the script files.
+If @code{idest-readonly} is @samp{#f} the @code{idest-main} function
+should return the new list of frames. If it returns an empty list,
+all existing frames will be deleted. If the function chooses not
+to modify any frames, it must return @code{#f}.
+
+The two following sections show how to write script files.
@menu
* list.scm:: Using Scripts to List ID3 Frames
@@ -458,51 +604,148 @@ The two following sections illustrate the concept of the script files.
@node list.scm
@section Using Scripts to List ID3 Frames
-@cindex list.scm
This section illustrates how to use the scripting facility for
-listing the contents of ID3 tags. We will create a Scheme script
-which, for each input file, will print its name, followed by the
-title, artist name and year, as shown in this sample output:
+listing the contents of ID3 tags.
+
+ The simplest way to list all frames using a Guile script is:
+
+@lisp
+;; list1.scm -- lists all frames.
+(define (idest-main name tags)
+ (display name)
+ (newline)
+ (for-each
+ (lambda (tag)
+ (display tag)
+ (newline))
+ tags))
+@end lisp
+
+Here is a sample output:
+
+@example
+$ idest --script list1.scm track01.scm
+track01.mp3
+(TIT2 (descr . Title/songname/content description) (text . Cor i arbre))
+(TRCK (descr . Track number/position in set) (text . 1))
+(COMM (descr . Comments) (condesc . Bit_Rate) (lang . eng) (text . 320))
+(TENC (descr . Encoded by) (text . Myencoder 1.0))
+(COMM (descr . Comments) (condesc . Sample_Rate) (lang . eng) (text . 44100))
+@end example
+
+As mentioned above, a script can access the command-line arguments.
+To illustrate this, let's modify the @file{list1.scm} to display only
+a subset of frames, given as a comma-separated list in the first
+argument. To do so, we will need a list of requested frames:
+
+@lisp
+(define frame-list '())
+@end lisp
+
+The main function consults this list to see whether to display a
+frame:
+
+@lisp
+(define (idest-main name tags)
+ (display name)
+ (newline)
+ (for-each
+ (lambda (tag)
+ (if (member (car tag) frame-list)
+ (begin
+ (display tag)
+ (newline))))
+ tags))
+@end lisp
+
+Finally, the following code initializes @code{frame-list} from the
+first argument and removes that argument from the list seen by
+@command{idest}. Note that the 0th argument is the name of the
+script itself, and it should not be modified.
+
+@lisp
+(let ((cmd (command-line)))
+ (cond
+ ((< (length cmd) 3)
+ (error "usage: list2.scm FRAME-LIST FILE...")
+ (exit 1))
+ (else
+ (set! frame-list (string-split (list-ref cmd 1) #\,))
+ (set-program-arguments (cons (car cmd) (list-tail cmd 2))))))
+@end lisp
+
+The full script text is then:
+
+@lisp
+;; list2.scm -- lists only requested frames.
+(define frame-list '())
+
+(define (idest-main name tags)
+ (display name)
+ (newline)
+ (for-each
+ (lambda (tag)
+ (if (member (car tag) frame-list)
+ (begin
+ (display tag)
+ (newline))))
+ tags))
+
+(let ((cmd (command-line)))
+ (cond
+ ((< (length cmd) 3)
+ (error "usage: list2.scm FRAME-LIST FILE...")
+ (exit 1))
+ (else
+ (set! frame-list (string-split (list-ref cmd 1) #\,))
+ (set-program-arguments (cons (car cmd) (list-tail cmd 2))))))
+@end lisp
-@smallexample
-$ idest -S list.scm *.mp3
+Sample usage:
+
+@example
+$ idest --script list2.scm TIT2,TENC track01.scm
+(TIT2 (descr . Title/songname/content description) (text . Cor i arbre))
+(TENC (descr . Encoded by) (text . Myencoder 1.0))
+@end example
+
+ A more elaborate example will print, for each input file, its name,
+followed by the title, artist name and year, as shown in this sample output:
+
+@example
+$ idest -S shortlist.scm *.mp3
dnr.mp3: Diamonds & Rust by Joan Baez, 1975
ams.mp3: Amsterdam, by Jacques Brel, 1968
-@dots{}
-@end smallexample
+@end example
-To implement this, we would need a function that returns the value of
+ To implement this, we would need a function that returns the value of
a given frame from the frame list. Remember, that the latter is a
list of pairs, so the task is achieved easily by using the
@code{assoc-ref} function:
-@smalllisp
+@lisp
(define (get-frame code frames)
(or (assoc-ref
(or (assoc-ref frames code) '())
'text)
"unknown"))
-@end smalllisp
+@end lisp
+
+The inner @code{assoc-ref} selects a requested frame. An
+empty list is returned if such a frame is not found. The outer
+@code{assoc-ref} selects the @samp{text} property.
Now, we define the main function:
-@smalllisp
-(define (lister name frames)
+@lisp
+(define (idest-main name frames)
(format #t "~A: ~A by ~A, ~A~%"
name
(get-frame "TIT2" frames) ; Title
(get-frame "TPE1" frames) ; Artist
(get-frame "TDRC" frames))) ; Year
-@end smalllisp
-
-Finally, we notify @command{idest} about the main function it should
-use, and inform it that the function does not modify the tags:
-
-@smalllisp
-(set! idest-main lister)
-(set! idest-readonly #t)
-@end smalllisp
+@end lisp
@node title.scm
@section Using Scripts to Modify ID3 Frames
@@ -519,11 +762,13 @@ created using the following algorithm:
Here is the implementation:
-@smalllisp
+@lisp
+;; title.scm - set title (TIT2) frame based on the file name.
+
(use-modules (ice-9 regex)
(srfi srfi-13))
-(define (modname file frames)
+(define (idest-main file frames)
(cond
((string-match "(.*)\\.mp3" file) =>
(lambda (match)
@@ -541,14 +786,13 @@ created using the following algorithm:
(else
#f)))
-(set! idest-main modname)
(set! idest-readonly #f)
-@end smalllisp
+@end lisp
An example of using this script on all files in the current directory:
@example
-$ idest --script settitle.scm *.mp3
+$ idest --script title.scm *.mp3
@end example
@node Backups
@@ -580,9 +824,9 @@ applied again, until a unique name is found.
For example, first call to:
-@smallexample
+@example
$ idest --backup=simple track01.mp3
-@end smallexample
+@end example
@noindent
will create backup copy in file @file{track01.mp~}. Second invocation
@@ -602,9 +846,9 @@ Always make numbered backups. The backup file name is created by
appending a unique numeric suffix to the original file name. For
example, when using:
-@smallexample
+@example
$ idest --backup=t track01.mp3
-@end smallexample
+@end example
@noindent
the first backup will be called @file{track01.mp3.~0~}, the second one
@@ -622,9 +866,9 @@ of the others.
modified to a separate directory. It can be requested with the
@option{backup-directory} option, e.g.:
-@smallexample
+@example
$ idest --backup-directory=/var/backups track01.mp3
-@end smallexample
+@end example
If the backup directory already contains a copy of the file, the new
backup name will be chosen using the method set with the
@@ -640,7 +884,7 @@ brackets.
@table @option
@item -a
@itemx --all
-Query all frames.
+Query all frames. @xref{all-frames query}.
@item --backup[=@var{control}]
backup before modifying, choose version @var{control}. @xref{Backups}.
@@ -660,6 +904,11 @@ Delete ID3 tags. The @var{flist} is a comma-separated list of the
names of frames to delete. If @var{flist} is not given, all frames
are deleted. @xref{Delete}.
+@item -D
+@itemx --describe
+Print verbose frame descriptions instead of short names.
+@xref{describe}.
+
@item -f
@itemx --function=@var{name}
Guile function to call. @xref{Scripting}.
diff --git a/examples/Makefile.am b/examples/Makefile.am
new file mode 100644
index 0000000..28327bc
--- /dev/null
+++ b/examples/Makefile.am
@@ -0,0 +1,21 @@
+# This file is part of Idest
+# Copyright (C) 2009-2011 Sergey Poznyakoff
+#
+# Idest 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, or (at your option)
+# any later version.
+#
+# Idest 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 Idest. If not, see <http://www.gnu.org/licenses/>.
+
+EXTRA_DIST = \
+ list1.scm\
+ list2.scm\
+ shortlist.scm\
+ title.scm \ No newline at end of file
diff --git a/examples/list1.scm b/examples/list1.scm
new file mode 100644
index 0000000..943b240
--- /dev/null
+++ b/examples/list1.scm
@@ -0,0 +1,15 @@
+;; list1.scm -- lists all frames.
+;; Copyright (C) 2011 Sergey Poznyakoff
+;; License GPLv3+: GNU GPL version 3 or later
+;; <http://gnu.org/licenses/gpl.html>
+;; This is free software: you are free to change and redistribute it.
+;; There is NO WARRANTY, to the extent permitted by law.
+
+(define (idest-main name tags)
+ (display name)
+ (newline)
+ (for-each
+ (lambda (tag)
+ (display tag)
+ (newline))
+ tags))
diff --git a/examples/list2.scm b/examples/list2.scm
new file mode 100644
index 0000000..6f58e81
--- /dev/null
+++ b/examples/list2.scm
@@ -0,0 +1,28 @@
+;; list2.scm -- lists only requested frames.
+;; Copyright (C) 2011 Sergey Poznyakoff
+;; License GPLv3+: GNU GPL version 3 or later
+;; <http://gnu.org/licenses/gpl.html>
+;; This is free software: you are free to change and redistribute it.
+;; There is NO WARRANTY, to the extent permitted by law.
+
+(define frame-list '())
+
+(define (idest-main name tags)
+ (display name)
+ (newline)
+ (for-each
+ (lambda (tag)
+ (if (member (car tag) frame-list)
+ (begin
+ (display tag)
+ (newline))))
+ tags))
+
+(let ((cmd (command-line)))
+ (cond
+ ((< (length cmd) 3)
+ (error "usage: list2.scm FRAME-LIST FILE...")
+ (exit 1))
+ (else
+ (set! frame-list (string-split (list-ref cmd 1) #\,))
+ (set-program-arguments (cons (car cmd) (list-tail cmd 2))))))
diff --git a/examples/shortlist.scm b/examples/shortlist.scm
new file mode 100644
index 0000000..635ab69
--- /dev/null
+++ b/examples/shortlist.scm
@@ -0,0 +1,19 @@
+;; shortlist.scm - List file name, artist and year, on a single line.
+;; Copyright (C) 2011 Sergey Poznyakoff
+;; License GPLv3+: GNU GPL version 3 or later
+;; <http://gnu.org/licenses/gpl.html>
+;; This is free software: you are free to change and redistribute it.
+;; There is NO WARRANTY, to the extent permitted by law.
+
+(define (get-frame code frames)
+ (or (assoc-ref
+ (or (assoc-ref frames code) '())
+ 'text)
+ "unknown"))
+
+(define (idest-main name frames)
+ (format #t "~A: ~A by ~A, ~A~%"
+ name
+ (get-frame "TIT2" frames) ; Title
+ (get-frame "TPE1" frames) ; Artist
+ (get-frame "TDRC" frames))) ; Year
diff --git a/examples/title.scm b/examples/title.scm
new file mode 100644
index 0000000..e541b66
--- /dev/null
+++ b/examples/title.scm
@@ -0,0 +1,29 @@
+;; title.scm - set title (TIT2) frame based on the file name.
+;; Copyright (C) 2011 Sergey Poznyakoff
+;; License GPLv3+: GNU GPL version 3 or later
+;; <http://gnu.org/licenses/gpl.html>
+;; This is free software: you are free to change and redistribute it.
+;; There is NO WARRANTY, to the extent permitted by law.
+
+(use-modules (ice-9 regex)
+ (srfi srfi-13))
+
+(define (idest-main file frames)
+ (cond
+ ((string-match "(.*)\\.mp3" file) =>
+ (lambda (match)
+ (cons
+ (cons "TIT2"
+ (string-map
+ (lambda (c)
+ (if (char=? c #\_) #\space c))
+ (match:substring match 1)))
+ ;;
+ (filter
+ (lambda (elt)
+ (not (string=? (car elt) "TIT2")))
+ frames))))
+ (else
+ #f)))
+
+(set! idest-readonly #f)
diff --git a/src/getopt.m4 b/src/getopt.m4
index 295c7e8..c6f0ae2 100644
--- a/src/getopt.m4
+++ b/src/getopt.m4
@@ -457,7 +457,7 @@ const char version_etc_copyright[] =
/* Do *not* mark this string for translation. %s is a copyright
symbol suitable for this locale, and %d is the copyright
year. */
- "Copyright %s 2005, 2006, 2007, 2008 Sergey Poznyakoff";
+ "Copyright %s 2005-2011 Sergey Poznyakoff";
void
print_version_only(const char *program_version, FILE *stream)
diff --git a/src/guile.c b/src/guile.c
index d370108..ab73850 100644
--- a/src/guile.c
+++ b/src/guile.c
@@ -30,7 +30,7 @@ char *guile_function;
char **guile_argv;
SCM_GLOBAL_VARIABLE_INIT (sym_idest_main, "idest-main", SCM_EOL);
-SCM_GLOBAL_VARIABLE_INIT(sym_idest_readonly, "idest-readonly", SCM_BOOL_F);
+SCM_GLOBAL_VARIABLE_INIT(sym_idest_readonly, "idest-readonly", SCM_BOOL_T);
SCM_GLOBAL_SYMBOL(idest_text, "text");
SCM_GLOBAL_SYMBOL(idest_lang, "lang");
@@ -164,7 +164,9 @@ field_to_scm(union id3_field *field, int genre)
id3_ucs4_t const *ucs4;
char *str;
SCM ret = SCM_EOL;
-
+
+ if (!field)
+ return ret;
switch (id3_field_type(field)) {
case ID3_FIELD_TYPE_TEXTENCODING:
case ID3_FIELD_TYPE_INT8:
diff --git a/src/main.c b/src/main.c
index b57d251..8d286ee 100644
--- a/src/main.c
+++ b/src/main.c
@@ -258,19 +258,21 @@ ed_list_add_item(struct id3_frame *frame, gl_list_t list)
(itm = (struct ed_item *) gl_list_node_value(ed_list,
node)) &&
ed_item_matches_frame(itm, frame)) {
+
+ struct ed_item dummy;
+ memset(&dummy, 0, sizeof(dummy));
+ ed_item_set_comment_fields(&dummy, frame);
+ if (dummy.condesc) {
+ char *str =
+ xmalloc(strlen(dummy.condesc)
+ + 5);
+ sprintf(str, "[%s]:", dummy.condesc);
+ gl_list_add_first(list, str);
+ free(dummy.condesc);
+ free(dummy.lang);
+ }
+
if (itm->v.vlist) {
- struct ed_item dummy;
- memset(&dummy, 0, sizeof(dummy));
- ed_item_set_comment_fields(&dummy, frame);
- if (dummy.condesc) {
- char *str =
- xmalloc(strlen(dummy.condesc)
- + 5);
- sprintf(str, "[%s]:", dummy.condesc);
- gl_list_add_last(itm->v.vlist, str);
- free(dummy.condesc);
- free(dummy.lang);
- }
concat_string_list(itm->v.vlist, list);
gl_list_free(list);
} else

Return to:

Send suggestions and report system problems to the System administrator.