Major refactoring.
The only visible change is a better tolerance with options (-ld6 is
accepted for -l -d 6).
Use DESTDIR and prefix with their usual meaning.
Change destdir default from /usr/local to /usr.
Drop trailing whitespaces.
Encode in UTF-8.
Drop obsolete TODO list.
Update VCS URL.
Handle 'q' key without a separate task.
Rewrite call of C functions.
Manpage: sort options, update options, improve formatting.
Nicolas Boulenguez
4 years ago
5 | 5 | BUILDER_OPTIONS := |
6 | 6 | |
7 | 7 | # Inherit ADAFLAGS, LDFLAGS if set in the environment. |
8 | ADAFLAGS ?= -g -O2 -gnatf -gnatwa -gnaty -gnatwe | |
8 | ADAFLAGS ?= -g -O2 -gnatf -gnatwa -gnaty | |
9 | 9 | LDFLAGS ?= |
10 | 10 | |
11 | 11 | GZIP_FLAGS := --best --name |
12 | 12 | STRIP_OPTION := |
13 | 13 | MSGFMT_FLAGS := |
14 | 14 | |
15 | DESTDIR := / | |
16 | PREFIX := usr/local | |
17 | INSTALL_BIN := $(DESTDIR)/$(PREFIX)/bin | |
18 | INSTALL_DOC := $(DESTDIR)/$(PREFIX)/share/doc/$(MAIN) | |
15 | DESTDIR ?= | |
16 | prefix ?= /usr | |
17 | INSTALL_BIN := $(DESTDIR)$(prefix)/bin | |
18 | INSTALL_DOC := $(DESTDIR)$(prefix)/share/doc/$(MAIN) | |
19 | 19 | INSTALL_ETC := $(DESTDIR)/etc |
20 | INSTALL_EXAMPLES := $(DESTDIR)/$(PREFIX)/share/doc/$(MAIN)/examples | |
21 | INSTALL_LOCALE := $(DESTDIR)/$(PREFIX)/share/locale | |
22 | INSTALL_MAN := $(DESTDIR)/$(PREFIX)/share/man | |
20 | INSTALL_EXAMPLES := $(DESTDIR)$(prefix)/share/doc/$(MAIN)/examples | |
21 | INSTALL_LOCALE := $(DESTDIR)$(prefix)/share/locale | |
22 | INSTALL_MAN := $(DESTDIR)$(prefix)/share/man | |
23 | 23 | |
24 | 24 | |
25 | 25 | # Default target. |
0 | This is music123 version 16.3 (new versioning policy to include minor | |
1 | changes and bug fixes) | |
0 | This is music123 version 16.4. | |
2 | 1 | |
3 | 2 | music123's goal in life is simple. With just mpg123 or ogg123, there |
4 | 3 | was no way to randomly play a mixed batch of ogg's and mp3's. If |
27 | 26 | sound system, check the programs that music123 calls. In specific, |
28 | 27 | both ogg123 and mpg321 use libao, so they can be set to use arts |
29 | 28 | by setting "default_driver=arts" in /etc/libao.conf or ~/.libao, |
30 | or by changing | |
29 | or by changing | |
31 | 30 | tool ogg123 ogg,Ogg,OGG "" |
32 | 31 | to |
33 | 32 | tool ogg123 ogg,Ogg,OGG "-d arts" |
34 | 33 | in /etc/music123. (I generally recommend the first approach.) aplay, |
35 | 34 | which plays wave files, is a Linux-only program; I, unfortunately, |
36 | don't know a more general replacement. | |
35 | don't know a more general replacement. | |
37 | 36 | |
38 | 37 | The half-second pause between songs is deliberate, so music123 can |
39 | 38 | be killed by Control-C. Note that it can be removed with the -D |
43 | 42 | I can add it into the master file (probably commented out). Note |
44 | 43 | that it expects the exact same case for the extension as listed in |
45 | 44 | that file. |
46 | ||
47 | -- | |
45 | ||
46 | -- | |
48 | 47 | David Starner - dvdeug@debian.org |
49 | 48 | Last change on December 16, 2756 AUC (2003 AD). |
50 | 49 | -- |
0 | * TRANSLATION | |
1 | - -i message to translate | |
2 | - -L message to translate | |
3 | - remove english test from music123.pl.1 |
0 | 0 | Changes to the source of this package are stored in a version control |
1 | 1 | system, publicly available at |
2 | http://www.ada-france.org:8081/branch/changes/org.music123 | |
2 | ttps://salsa.debian.org/debian/music123 |
0 | with Ada.Text_IO; | |
1 | ||
2 | package body Commands is | |
3 | ||
4 | ------------------ | |
5 | -- Handler_Task -- | |
6 | ------------------ | |
7 | ||
8 | task body Handler_Task is | |
9 | Available : Boolean; | |
10 | C : Character; | |
11 | begin | |
12 | select | |
13 | accept Start; | |
14 | or | |
15 | terminate; | |
16 | end select; | |
17 | loop | |
18 | Ada.Text_IO.Get_Immediate (C, Available); | |
19 | if Available then | |
20 | case C is | |
21 | when 'q' | 'Q' => | |
22 | Repository.Quit; | |
23 | select | |
24 | accept Stop; | |
25 | exit; | |
26 | or | |
27 | terminate; | |
28 | end select; | |
29 | when others => | |
30 | null; | |
31 | end case; | |
32 | end if; | |
33 | select | |
34 | accept Stop; | |
35 | exit; | |
36 | or | |
37 | delay 0.5; | |
38 | end select; | |
39 | end loop; | |
40 | end Handler_Task; | |
41 | ||
42 | protected body Repository is | |
43 | ||
44 | procedure Quit is | |
45 | begin | |
46 | Quit_Pressed := True; | |
47 | Ada.Text_IO.New_Line; | |
48 | Ada.Text_IO.Put_Line ("music213 will end at the end of this song"); | |
49 | end Quit; | |
50 | ||
51 | function Have_To_Quit return Boolean is | |
52 | begin | |
53 | return Quit_Pressed; | |
54 | end Have_To_Quit; | |
55 | ||
56 | end Repository; | |
57 | ||
58 | end Commands; |
0 | package Commands is | |
1 | ||
2 | task type Handler_Task is | |
3 | entry Start; | |
4 | entry Stop; | |
5 | end Handler_Task; | |
6 | ||
7 | protected Repository is | |
8 | procedure Quit; | |
9 | function Have_To_Quit return Boolean; | |
10 | private | |
11 | Quit_Pressed : Boolean := False; | |
12 | end Repository; | |
13 | ||
14 | end Commands; |
0 | ----------------------------------------------------------------------- | |
1 | -- GtkAda - Ada95 binding for the Gimp Toolkit -- | |
2 | -- -- | |
3 | -- Copyright (C) 2000 -- | |
4 | -- Emmanuel Briot, Joel Brobecker and Arnaud Charlet -- | |
5 | -- -- | |
6 | -- This library is free software; you can redistribute it and/or -- | |
7 | -- modify it under the terms of the GNU General Public -- | |
8 | -- License as published by the Free Software Foundation; either -- | |
9 | -- version 2 of the License, or (at your option) any later version. -- | |
10 | -- -- | |
11 | -- This library is distributed in the hope that it will be useful, -- | |
12 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- | |
13 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -- | |
14 | -- General Public License for more details. -- | |
15 | -- -- | |
16 | -- You should have received a copy of the GNU General Public -- | |
17 | -- License along with this library; if not, write to the -- | |
18 | -- Free Software Foundation, Inc., 59 Temple Place - Suite 330, -- | |
19 | -- Boston, MA 02111-1307, USA. -- | |
20 | -- -- | |
21 | -- As a special exception, if other files instantiate generics from -- | |
22 | -- this unit, or you link this unit with other files to produce an -- | |
23 | -- executable, this unit does not by itself cause the resulting -- | |
24 | -- executable to be covered by the GNU General Public License. This -- | |
25 | -- exception does not however invalidate any other reasons why the -- | |
26 | -- executable file might be covered by the GNU Public License. -- | |
27 | ----------------------------------------------------------------------- | |
28 | ||
29 | with Interfaces.C.Strings; | |
30 | ||
31 | package body Intl is | |
32 | ||
33 | use Interfaces.C; | |
34 | use Interfaces.C.Strings; | |
35 | ||
36 | ------------- | |
37 | -- Gettext -- | |
38 | ------------- | |
39 | ||
40 | function Gettext (Msg : String) return String is | |
41 | function Internal (msgid : in char_array) | |
42 | return chars_ptr; | |
43 | pragma Import (C, Internal, "gettext"); | |
44 | R : constant chars_ptr := Internal (To_C (Msg)); | |
45 | begin | |
46 | if R = Null_Ptr then | |
47 | raise Locale_Error; | |
48 | end if; | |
49 | return Value (R); | |
50 | end Gettext; | |
51 | ||
52 | -------------- | |
53 | -- Dgettext -- | |
54 | -------------- | |
55 | ||
56 | function Dgettext (Domain : String; Msg : String) return String is | |
57 | function Internal (domainname : in char_array; | |
58 | msgid : in char_array) | |
59 | return chars_ptr; | |
60 | pragma Import (C, Internal, "dgettext"); | |
61 | R : constant chars_ptr := Internal (To_C (Domain), To_C (Msg)); | |
62 | begin | |
63 | if R = Null_Ptr then | |
64 | raise Locale_Error; | |
65 | end if; | |
66 | return Value (R); | |
67 | end Dgettext; | |
68 | ||
69 | --------------- | |
70 | -- Dcgettext -- | |
71 | --------------- | |
72 | ||
73 | function Dcgettext | |
74 | (Domain : String; Msg : String; Category : Integer) return String | |
75 | is | |
76 | function Internal (domainname : in char_array; | |
77 | msgid : in char_array; | |
78 | category : in int) | |
79 | return chars_ptr; | |
80 | pragma Import (C, Internal, "dcgettext"); | |
81 | R : constant chars_ptr := Internal (To_C (Domain), To_C (Msg), | |
82 | int (Category)); | |
83 | begin | |
84 | if R = Null_Ptr then | |
85 | raise Locale_Error; | |
86 | end if; | |
87 | return Value (R); | |
88 | end Dcgettext; | |
89 | ||
90 | ------------------------- | |
91 | -- Default_Text_Domain -- | |
92 | ------------------------- | |
93 | ||
94 | function Default_Text_Domain return String is | |
95 | function Internal (domainname : in chars_ptr) | |
96 | return chars_ptr; | |
97 | pragma Import (C, Internal, "textdomain"); | |
98 | R : constant chars_ptr := Internal (Null_Ptr); | |
99 | begin | |
100 | if R = Null_Ptr then | |
101 | raise Locale_Error; | |
102 | end if; | |
103 | return Value (R); | |
104 | end Default_Text_Domain; | |
105 | ||
106 | ----------------- | |
107 | -- Text_Domain -- | |
108 | ----------------- | |
109 | ||
110 | procedure Text_Domain (Domain : String := "") is | |
111 | function Internal (domainname : in char_array) | |
112 | return chars_ptr; | |
113 | pragma Import (C, Internal, "textdomain"); | |
114 | begin | |
115 | if Internal (To_C (Domain)) = Null_Ptr then | |
116 | raise Locale_Error; | |
117 | end if; | |
118 | end Text_Domain; | |
119 | ||
120 | ---------------------- | |
121 | -- Bind_Text_Domain -- | |
122 | ---------------------- | |
123 | ||
124 | procedure Bind_Text_Domain (Domain : String; Dirname : String) is | |
125 | function Internal (domainname : in char_array; | |
126 | dirname : in char_array) | |
127 | return chars_ptr; | |
128 | pragma Import (C, Internal, "bindtextdomain"); | |
129 | begin | |
130 | if Internal (To_C (Domain), To_C (Dirname)) = Null_Ptr then | |
131 | raise Locale_Error; | |
132 | end if; | |
133 | end Bind_Text_Domain; | |
134 | ||
135 | procedure Set_Locale is | |
136 | function Internal (category : in int; | |
137 | locale : in char_array) | |
138 | return chars_ptr; | |
139 | pragma Import (C, Internal, "setlocale"); | |
140 | LC_ALL : constant := 6; | |
141 | begin | |
142 | if Internal (LC_ALL, To_C ("")) = Null_Ptr then | |
143 | raise Locale_Error; | |
144 | end if; | |
145 | end Set_Locale; | |
146 | ||
147 | end Intl; |
0 | ----------------------------------------------------------------------- | |
1 | -- GtkAda - Ada95 binding for the Gimp Toolkit -- | |
2 | -- -- | |
3 | -- Copyright (C) 2000 -- | |
4 | -- Emmanuel Briot, Joel Brobecker and Arnaud Charlet -- | |
5 | -- -- | |
6 | -- This library is free software; you can redistribute it and/or -- | |
7 | -- modify it under the terms of the GNU General Public -- | |
8 | -- License as published by the Free Software Foundation; either -- | |
9 | -- version 2 of the License, or (at your option) any later version. -- | |
10 | -- -- | |
11 | -- This library is distributed in the hope that it will be useful, -- | |
12 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- | |
13 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -- | |
14 | -- General Public License for more details. -- | |
15 | -- -- | |
16 | -- You should have received a copy of the GNU General Public -- | |
17 | -- License along with this library; if not, write to the -- | |
18 | -- Free Software Foundation, Inc., 59 Temple Place - Suite 330, -- | |
19 | -- Boston, MA 02111-1307, USA. -- | |
20 | -- -- | |
21 | -- As a special exception, if other files instantiate generics from -- | |
22 | -- this unit, or you link this unit with other files to produce an -- | |
23 | -- executable, this unit does not by itself cause the resulting -- | |
24 | -- executable to be covered by the GNU General Public License. This -- | |
25 | -- exception does not however invalidate any other reasons why the -- | |
26 | -- executable file might be covered by the GNU Public License. -- | |
27 | ----------------------------------------------------------------------- | |
28 | ||
29 | -- <description> | |
30 | -- | |
31 | -- This package provides support for string internationalization using the | |
32 | -- libintl library. | |
33 | -- | |
34 | -- To change the current locale setting, use on the environment variables | |
35 | -- "LANG" or "LC_MESSAGES". For example, to switch to the french locale using | |
36 | -- bash: | |
37 | -- | |
38 | -- $ export LANG=fr | |
39 | -- | |
40 | -- Depending on the specific implementation of gettext, the following | |
41 | -- environment variables may be set to change the default settings of locale | |
42 | -- parameters: | |
43 | -- | |
44 | -- - LANG Specifies locale name. | |
45 | -- | |
46 | -- - LC_MESSAGES | |
47 | -- Specifies messaging locale, and if present overrides | |
48 | -- LANG for messages. | |
49 | -- | |
50 | -- - TEXTDOMAIN | |
51 | -- Specifies the text domain name, which is identical to | |
52 | -- the message object filename without .mo suffix. | |
53 | -- | |
54 | -- - TEXTDOMAINDIR | |
55 | -- Specifies the pathname to the message database, and if | |
56 | -- present replaces the default (e.g /usr/lib/locale on Solaris, | |
57 | -- /usr/share/locale on Linux). | |
58 | -- | |
59 | -- See the gettext documentation of your specific OS for more details. | |
60 | -- | |
61 | -- The recommended way to use the gettext capability in your application is | |
62 | -- to use Dgettext with your own domain, and define the following shortcut: | |
63 | -- | |
64 | -- function "-" (Msg : String) return String; | |
65 | -- -- Convenient shortcut to the Gettext function. | |
66 | -- | |
67 | -- function "-" (Msg : String) return String is | |
68 | -- begin | |
69 | -- return Dgettext ("my_domain", Msg); | |
70 | -- end "-"; | |
71 | -- | |
72 | -- Do not forget to call Bind_Text_Domain ("my_domain", "my locale prefix") | |
73 | -- at the beginning of your program. For example, if the prefix of your | |
74 | -- application is /usr, the standard location of the locale would | |
75 | -- be /usr/share/locale, e.g: | |
76 | -- Bind_Text_Domain ("GtkAda", "/usr/share/locale"); | |
77 | -- | |
78 | -- Under this locale directory, the functions provided by this package | |
79 | -- will look for the directory $LANG/LC_MESSAGES, | |
80 | -- /usr/share/locale/fr/LC_MESSAGES in our example; and in this directory, | |
81 | -- the file <domain>.mo will be used, e.g | |
82 | -- /usr/share/locale/fr/LC_MESSAGES/GtkAda.mo | |
83 | -- | |
84 | -- The .mo files can be generated using the GNU tool msgfmt that takes a | |
85 | -- text file containing for each string the original and the translation. | |
86 | -- See msgfmt documentation for more details. | |
87 | -- Here is a sample translation file that can be used as an input for msgfmt: | |
88 | -- | |
89 | -- # gtkada-fr.po | |
90 | -- msgid "Help" | |
91 | -- msgstr "Aide" | |
92 | -- | |
93 | -- msgid "Yes" | |
94 | -- msgstr "Oui" | |
95 | -- | |
96 | -- $ msgfmt gtkada-fr.po -o gtkada-fr.gmo | |
97 | -- $ cp gtkada-fr.gmo /usr/share/locale/fr/LC_MESSAGES/GtkAda.mo | |
98 | -- | |
99 | -- Then, to enable the string translation in your application, use the "-" | |
100 | -- function defined above, e.g: | |
101 | -- | |
102 | -- Gtk_New (Label, -"Help"); | |
103 | -- Gtk_New (Label, -("Help ?") & ASCII.LF & -("Yes")); | |
104 | -- | |
105 | -- </description> | |
106 | ||
107 | -- Rather than mess around with depending on gtkada, and hoping I'd | |
108 | -- never get in a situtation where I had to link in gtkada and gtk | |
109 | -- and xlibs, I just copied the code here. | |
110 | ||
111 | package Intl is | |
112 | pragma Preelaborate; | |
113 | ||
114 | function Gettext (Msg : String) return String; | |
115 | -- Look up Msg in the current default message catalog. | |
116 | -- Use the current locale as specified by LC_MESSAGES. If not found, return | |
117 | -- Msg itself (the default text). | |
118 | ||
119 | function Dgettext (Domain : String; Msg : String) return String; | |
120 | -- Look up Msg in the Domain message catalog for the current locale. | |
121 | ||
122 | function Dcgettext | |
123 | (Domain : String; Msg : String; Category : Integer) return String; | |
124 | -- Look up Msg in the Domain message catalog for the Category locale. | |
125 | ||
126 | function Default_Text_Domain return String; | |
127 | -- Return the current default message catalog. | |
128 | ||
129 | procedure Text_Domain (Domain : String := ""); | |
130 | -- Set the current default message catalog to Domain. | |
131 | -- If Domain is "", reset to the default of "messages". | |
132 | ||
133 | procedure Bind_Text_Domain (Domain : String; Dirname : String); | |
134 | -- Specify that the Domain message catalog will be found in Dirname. | |
135 | -- This overrides the default system locale data base. | |
136 | ||
137 | procedure Set_Locale; | |
138 | ||
139 | Locale_Error : exception; | |
140 | ||
141 | end Intl; |
0 | 0 | Copyright: Copyright (C) 2001-2009 David Starner <dvdeug@debian.org> |
1 | 1 | Copyright (C) 2009-2015 Xavier Grave <xavier.grave@csnsm.in2p3.fr> |
2 | Copyright (C) 2014-2015 Nicolas Boulenguez <nicolas.boulenguez@free.fr> | |
2 | Copyright (C) 2014-2020 Nicolas Boulenguez <nicolas@debian.org> | |
3 | 3 | License: Expat |
4 | 4 | Permission is hereby granted, free of charge, to any person obtaining a |
5 | 5 | copy of this software and associated documentation files (the "Software"), |
18 | 18 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
19 | 19 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
20 | 20 | DEALINGS IN THE SOFTWARE. |
21 | ||
22 | Files: intl.adb intl.ads | |
23 | Copyright: Copyright (C) 2000 Emmanuel Briot, Joel Brobecker and Arnaud Charlet | |
24 | Copyright (C) 2015 Nicolas Boulenguez <nicolas.boulenguez@free.fr> | |
25 | License: GPL-2 with GNAT exception | |
26 | intl.adb and intl.ads are from libgtkada. They are licensed under the | |
27 | GPL-2, see /usr/share/common-licenses/GPL-2, with the following | |
28 | exception. | |
29 | . | |
30 | As a special exception, if other files instantiate generics from | |
31 | this unit, or you link this unit with other files to produce an | |
32 | executable, this unit does not by itself cause the resulting | |
33 | executable to be covered by the GNU General Public License. This | |
34 | exception does not however invalidate any other reasons why the | |
35 | executable file might be covered by the GNU General Public License. |
4 | 4 | |
5 | 5 | .SH SYNOPSIS |
6 | 6 | .B music123 |
7 | [ | |
8 | .B \-hqrvz | |
9 | ] | |
10 | .I file | |
11 | .B ... | |
7 | .RB [ \-DhiLlqrvZz ] | |
8 | [\fB\-d \fIARG\fR] | |
9 | [\fB\-@ \fIARG\fR] | |
10 | .RB [ -- ] | |
11 | \fIfiles\fR ... | |
12 | 12 | |
13 | 13 | .SH DESCRIPTION |
14 | 14 | .B music123 |
18 | 18 | in /etc/music123rc or ~/.music123rc. |
19 | 19 | |
20 | 20 | .SH OPTIONS |
21 | .IP \-D | |
22 | Equivalent to \fB\-d0\fR. | |
23 | .\" | |
24 | May make music123 harder to kill. | |
25 | .IP \-d | |
26 | Customize the time music123 delays between songs. | |
27 | .\" | |
28 | \fB\-d\fR takes one argument, expressed in seconds, which may have a | |
29 | fractional part. | |
21 | 30 | .IP \-h |
22 | Show command help and exit; | |
31 | Show command help and exit immediately. | |
32 | .IP \-i | |
33 | Ignore case of file path extensions. | |
34 | .\" | |
35 | For example, \fI.ogg\fR and \fI.OGG\fR are considered equivalent. | |
36 | .IP \-l | |
37 | Loop at the end of the playlist. | |
38 | .IP \-L | |
39 | List files and exit immediately. | |
23 | 40 | .IP \-q |
24 | Quiet mode. No messages are displayed. | |
41 | Quiet mode. | |
42 | .\" | |
43 | No messages are displayed. | |
25 | 44 | .IP \-r |
26 | 45 | Recurse into directories, instead of ignoring them. |
46 | .IP \-T | |
47 | Redirect standard input, allowing \fIq\fR or \fIQ\fR keys to stop | |
48 | after current file. | |
49 | .\" | |
50 | The player will not see its standard output anymore. | |
27 | 51 | .IP \-v |
28 | Display version information and exit. | |
52 | Display version information and exit immediately. | |
29 | 53 | .IP \-z |
30 | Play files in random order. | |
54 | Randomize the song list once before starting to play. | |
55 | .\" | |
56 | music123 will shuffle the list once and for all, then play the songs | |
57 | without repetition (and repeat the selected order over and over with | |
58 | \-l). | |
31 | 59 | .IP \-Z |
32 | Play the files randomly and endlessly. | |
33 | .IP \-l | |
34 | Loop. \-z \-l differs from \-Z in that \-z \-l will randomize, play | |
35 | through the song list (without repetition) in random order once, | |
36 | and repeat the songs in that order over and over; \-Z will randomly | |
37 | play the songs, without any order, and will possibly play a song | |
38 | right after itself. | |
39 | .IP \-i | |
40 | Ignore extension case. | |
41 | .IP \-L | |
42 | List files and exit. | |
43 | .IP \-T | |
44 | Start a task that handle commands, only one command supported : quit, | |
45 | using q or Q will quit the application at the end of the current song. | |
46 | .IP \-D | |
47 | Set music123 not to delay between songs. (May make music123 harder to | |
48 | kill). | |
49 | .IP \-d | |
50 | Customize the time music123 delays between songs. \-d takes one argument, | |
51 | expressed in seconds, which may have a fractional part. | |
60 | Pick up a song after the other randomly and endlessly, possibly | |
61 | playing a given song twice in a row, or never playing a given song. | |
62 | .\" | |
63 | This disables \fI\-l\fR and \fI-z\fR options. | |
52 | 64 | .IP \-@ |
53 | Play the files listed in the mandatory argument of \-@. Other files can be | |
54 | added on the command line, and this option can be given several times. | |
65 | Play the files listed in the mandatory argument of \-@. | |
66 | .\" | |
67 | Other files can be added on the command line, and this option can be | |
68 | given several times. | |
69 | .\" | |
55 | 70 | Note that music123 doesn't yet play URLs. |
56 | 71 | .IP \-\- |
57 | 72 | End option list. |
73 | .\" | |
74 | Following arguments are interpreted as file names, even if they start | |
75 | with a dash. | |
58 | 76 | |
59 | 77 | .SH EXAMPLES |
60 | 78 | |
66 | 84 | |
67 | 85 | Play a couple of directories and other songs at random: |
68 | 86 | .RS |
69 | .B music123 \-z \-r Rock/ test1.ogg Pop/ test4.wav | |
87 | .B music123 \-rz Rock/ test1.ogg Pop/ test4.wav | |
88 | .RE | |
89 | .PP | |
90 | ||
91 | Play a playlist then a strange file name with a delay between the songs: | |
92 | .RS | |
93 | .B music123 \-d 6.0 \-@playlist \-\− \-strange.ogg | |
70 | 94 | .RE |
71 | 95 | .PP |
72 | 96 | |
89 | 113 | .TP |
90 | 114 | Authors: |
91 | 115 | .br |
92 | David Starner <dvdeug@debian.org> | |
116 | David Starner <dvdeug@debian.org>, | |
117 | Xavier Grave <xavier.grave@csnsm.in2p3.fr>, | |
118 | Nicolas Boulenguez <nicolas@debian.org> | |
93 | 119 | .br |
0 | -- music123 by David Starner <dvdeug@debian.org> | |
1 | ||
2 | with Ada.Command_Line; use Ada.Command_Line; | |
0 | -- music123 by | |
1 | -- David Starner <dvdeug@debian.org> | |
2 | -- Xavier Grave <xavier.grave@csnsm.in2p3.fr> | |
3 | -- Nicolas Boulenguez <nicolas@debian.org> | |
4 | ||
5 | with Ada.Characters.Latin_1; | |
6 | with Ada.Command_Line; | |
7 | with Ada.Containers.Indefinite_Hashed_Maps; | |
8 | with Ada.Containers.Indefinite_Vectors; | |
9 | with Ada.Directories; | |
10 | use all type Ada.Directories.Directory_Entry_Type; | |
11 | use all type Ada.Directories.File_Kind; | |
12 | use all type Ada.Directories.Search_Type; | |
13 | with Ada.Environment_Variables; | |
14 | with Ada.Numerics.Float_Random; | |
15 | use all type Ada.Numerics.Float_Random.Generator; | |
16 | with Ada.Strings.Fixed; | |
17 | with Ada.Strings.Hash; | |
18 | with Ada.Strings.Maps; | |
19 | use all type Ada.Strings.Maps.Character_Set; | |
20 | with Ada.Strings.Maps.Constants; use Ada.Strings.Maps.Constants; | |
21 | with Ada.Strings.Unbounded; | |
22 | use all type Ada.Strings.Unbounded.Unbounded_String; | |
3 | 23 | with Ada.Text_IO; |
4 | ||
5 | with Support_Routines; use Support_Routines; | |
6 | with Intl; | |
7 | with Commands; | |
24 | with Interfaces.C.Strings; | |
8 | 25 | |
9 | 26 | procedure Music123 is |
10 | Seeing_Minus_Options : Boolean := True; | |
11 | Arg_Num : Positive; | |
12 | Option_Task : Boolean := False; | |
13 | Option_Quiet : Boolean := False; | |
14 | Option_Recurse : Boolean := False; | |
15 | Option_Random : Boolean := False; | |
16 | Option_Loop : Boolean := False; | |
17 | Option_Eternal_Random : Boolean := False; | |
18 | Option_Ignore_Extension_Case : Boolean := False; | |
19 | Option_List_Files_Only : Boolean := False; | |
20 | Delay_Length : Duration := 0.5; | |
21 | File_List : UString_List.Vector; | |
22 | Program_List : Tool_List.Vector; | |
23 | Command_Task : Commands.Handler_Task; | |
24 | ||
27 | ||
28 | Version_Number : constant String := "16.5"; | |
29 | System_Configuration : constant String := "/etc/music123rc"; | |
30 | User_Configuration : constant String := ".music123rc"; | |
31 | -- User_Configuration is relative to the HOME directory. | |
32 | ||
33 | ---------------------------------------------------------------------- | |
34 | -- Interface with C. | |
35 | ||
36 | C_Error : exception; | |
37 | -- Used to report errors at the C level. | |
38 | ||
39 | LC_ALL : constant := 6; | |
40 | -- Quite arbitrary, but has been working for years, and gcc is not | |
41 | -- able to generate such values yet. | |
42 | ||
43 | -- From locale.h: | |
44 | procedure Setlocale (Category : Interfaces.C.int; | |
45 | Locale : String); | |
46 | ||
47 | -- From libintl.h: | |
48 | procedure Textdomain (Domainname : String); | |
49 | procedure Bindtextdomain (Domainname : String; | |
50 | Dirname : String); | |
51 | function "+" (Msgid : String) return String; -- gettext | |
52 | ||
53 | -- From stdlib.h: | |
54 | procedure System (Command : String); | |
55 | ||
56 | ---------------------------------------------------------------------- | |
57 | -- Error reporting | |
58 | ||
59 | Error : exception; -- Report and set exit status. | |
60 | procedure Warn (Message : String); -- Report but continue. | |
61 | ||
62 | ---------------------------------------------------------------------- | |
63 | -- Random numbers | |
64 | ||
65 | Generator : Ada.Numerics.Float_Random.Generator; | |
66 | ||
67 | function Random (Maximum : Positive) return Positive | |
68 | with Post => Random'Result in 1 .. Maximum; | |
69 | ||
70 | ---------------------------------------------------------------------- | |
71 | -- Types | |
72 | ||
73 | type An_Option_List is record | |
74 | Catch_Q_In_Stdin : Boolean := False; | |
75 | Delay_Length : Duration := 0.5; | |
76 | Eternal_Random : Boolean := False; | |
77 | Ignore_Extension_Case : Boolean := False; | |
78 | List_Files_Only : Boolean := False; | |
79 | Quiet : Boolean := False; | |
80 | Random : Boolean := False; | |
81 | Recurse : Boolean := False; | |
82 | Repeat : Boolean := False; | |
83 | end record; | |
84 | ||
85 | package Tool_Maps is new Ada.Containers.Indefinite_Hashed_Maps | |
86 | (Key_Type => String, | |
87 | Element_Type => String, | |
88 | Hash => Ada.Strings.Hash, | |
89 | Equivalent_Keys => "="); | |
90 | -- For each known extension, store to the first matching tool in | |
91 | -- the configuration file. The element contains the name of the | |
92 | -- program followed by the options. | |
93 | ||
94 | package String_Vectors is new Ada.Containers.Indefinite_Vectors | |
95 | (Index_Type => Positive, | |
96 | Element_Type => String); | |
97 | package String_Sorting is new String_Vectors.Generic_Sorting ("<"); | |
98 | ||
99 | procedure Parse_Command_Line (Paths : in out String_Vectors.Vector; | |
100 | Options : in out An_Option_List; | |
101 | Done : out Boolean); | |
102 | ||
103 | -- The options are transmitted so that the extensions are | |
104 | -- translated to lower case if necessary. | |
105 | procedure Parse_Configuration (Tools : in out Tool_Maps.Map; | |
106 | Options : An_Option_List); | |
107 | ||
108 | -- Ignore directories (unless Options.Recurse), special files, or | |
109 | -- files without matching command in Tools. | |
110 | -- For selected paths, construct a shell script playing the song | |
111 | -- and append it to Commands. | |
112 | -- If Options.List_Files_Only, then Commands are not modified but | |
113 | -- selected paths are printed instead. | |
114 | procedure Add_Command (Commands : in out String_Vectors.Vector; | |
115 | Path : String; | |
116 | Tools : Tool_Maps.Map; | |
117 | Options : An_Option_List); | |
118 | ||
119 | procedure Randomize (Commands : in out String_Vectors.Vector); | |
120 | ||
121 | procedure Play_Songs (Commands : String_Vectors.Vector; | |
122 | Options : An_Option_List); | |
123 | ||
124 | ---------------------------------------------------------------------- | |
125 | -- Implementations | |
126 | ||
127 | function "+" (Msgid : String) return String is | |
128 | use Interfaces.C, Interfaces.C.Strings; | |
129 | function F (A1 : char_array := To_C (Msgid)) return chars_ptr | |
130 | with Import, Convention => C, External_Name => "gettext"; | |
131 | Ret : constant chars_ptr := F; | |
132 | begin | |
133 | if Ret = Null_Ptr then | |
134 | raise C_Error with "gettext failed"; | |
135 | end if; | |
136 | return Value (Ret); | |
137 | end "+"; | |
138 | ||
139 | procedure Bindtextdomain (Domainname : String; | |
140 | Dirname : String) is | |
141 | use Interfaces.C, Interfaces.C.Strings; | |
142 | function F (A1 : char_array := To_C (Domainname); | |
143 | A2 : char_array := To_C (Dirname)) return chars_ptr | |
144 | with Import, Convention => C, External_Name => "bindtextdomain"; | |
145 | begin | |
146 | if F = Null_Ptr then | |
147 | raise C_Error with "bindtextdomain failed"; | |
148 | end if; | |
149 | end Bindtextdomain; | |
150 | ||
151 | procedure Add_Command (Commands : in out String_Vectors.Vector; | |
152 | Path : String; | |
153 | Tools : Tool_Maps.Map; | |
154 | Options : An_Option_List) is | |
155 | ||
156 | procedure Process_Directory; | |
157 | procedure Process_Ordinary_File; | |
158 | ||
159 | procedure Process_Directory is | |
160 | Search : Ada.Directories.Search_Type; | |
161 | Directory_Entry : Ada.Directories.Directory_Entry_Type; | |
162 | More_Paths : String_Vectors.Vector; | |
163 | begin | |
164 | begin | |
165 | Start_Search (Search, Directory => Path, Pattern => ""); | |
166 | exception | |
167 | when Ada.Directories.Name_Error => | |
168 | Warn (+"Empty directory: " & Path); | |
169 | return; | |
170 | when Ada.Directories.Use_Error => | |
171 | Warn (+"Not allowed to enter directory: " & Path); | |
172 | return; | |
173 | end; | |
174 | while More_Entries (Search) loop | |
175 | Get_Next_Entry (Search, Directory_Entry); | |
176 | -- Ignore . .. and more generally hidden files. | |
177 | declare | |
178 | S : constant String := Simple_Name (Directory_Entry); | |
179 | begin | |
180 | if S /= "" and then S (S'First) /= '.' then | |
181 | More_Paths.Append (Full_Name (Directory_Entry)); | |
182 | end if; | |
183 | end; | |
184 | end loop; | |
185 | -- Make the order independant from the underlying file system. | |
186 | String_Sorting.Sort (String_Vectors.Vector (More_Paths)); | |
187 | for New_Path of More_Paths loop | |
188 | Add_Command (Commands, New_Path, Tools, Options); | |
189 | end loop; | |
190 | end Process_Directory; | |
191 | ||
192 | procedure Process_Ordinary_File is | |
193 | Ext : constant String := Ada.Directories.Extension (Path); | |
194 | Key : constant String | |
195 | := (if Options.Ignore_Extension_Case | |
196 | then Ada.Strings.Fixed.Translate (Ext, Lower_Case_Map) | |
197 | else Ext); | |
198 | Position : constant Tool_Maps.Cursor := Tools.Find (Key); | |
199 | Buffer : Ada.Strings.Unbounded.Unbounded_String; | |
200 | begin | |
201 | if not Tool_Maps.Has_Element (Position) then | |
202 | Warn (+"Unknown extension: " & Path); | |
203 | elsif Options.List_Files_Only then | |
204 | Ada.Text_IO.Put_Line (Path); | |
205 | else | |
206 | Set_Unbounded_String (Buffer, Tools (Position)); | |
207 | Append (Buffer, " '"); | |
208 | for Char of Path loop | |
209 | if Char = ''' then | |
210 | Append (Buffer, "'\''"); | |
211 | else | |
212 | Append (Buffer, Char); | |
213 | end if; | |
214 | end loop; | |
215 | Append (Buffer, '''); | |
216 | if Options.Quiet then | |
217 | Append (Buffer, " > /dev/null"); | |
218 | end if; | |
219 | if Options.Catch_Q_In_Stdin then | |
220 | Append (Buffer, " < /dev/null"); | |
221 | end if; | |
222 | Commands.Append (To_String (Buffer)); | |
223 | end if; | |
224 | end Process_Ordinary_File; | |
225 | ||
226 | begin | |
227 | if Ada.Directories.Exists (Path) then | |
228 | case Kind (Path) is | |
229 | when Special_File => | |
230 | Warn (+"Not an ordinary file: " & Path); | |
231 | when Directory => | |
232 | if Options.Recurse then | |
233 | Process_Directory; | |
234 | else | |
235 | Warn (+"Directory: " & Path); | |
236 | end if; | |
237 | when Ordinary_File => | |
238 | Process_Ordinary_File; | |
239 | end case; | |
240 | else | |
241 | Warn (+"No such file: " & Path); | |
242 | end if; | |
243 | end Add_Command; | |
244 | ||
245 | procedure Parse_Command_Line (Paths : in out String_Vectors.Vector; | |
246 | Options : in out An_Option_List; | |
247 | Done : out Boolean) is | |
248 | ||
249 | procedure Display_Help; | |
250 | procedure Display_Version; | |
251 | procedure Read_Playlist (Path : String); | |
252 | procedure Read_Playlist_Line (Line : String); | |
253 | procedure Set_Delay (Value : String); | |
254 | ||
255 | procedure Display_Help is | |
256 | use Ada.Text_IO; | |
257 | begin | |
258 | Put_Line | |
259 | (+"Usage: music123 [-DhiLlqrvZz] [-d ARG] [-@ ARG] [--] files ..."); | |
260 | Put_Line (+"-z Shuffle list before playing"); | |
261 | Put_Line (+"-l Loop when reaching end of playlist"); | |
262 | Put_Line (+"-Z Play randomly. Never stop"); | |
263 | New_Line; | |
264 | Put_Line (+"-r Recurse over directories"); | |
265 | Put_Line (+"-@ ARG Add lines of ARG to files"); | |
266 | Put_Line (+"-- Following arguments are files, not options"); | |
267 | Put_Line (+"-i Ignore case of file extensions (.OGG = .ogg)"); | |
268 | Put_Line (+"-L List files and exit. No music"); | |
269 | New_Line; | |
270 | Put_Line (+"-q Run quietly"); | |
271 | Put_Line (+"-d ARG Delay ARG seconds between songs (default: 0.5)"); | |
272 | Put_Line (+"-D Shortcut for -d 0"); | |
273 | Put_Line (+"-T Catch q key to quit after current song"); | |
274 | New_Line; | |
275 | Put_Line (+"-v Print version information"); | |
276 | Put_Line (+"-h Print this help"); | |
277 | New_Line; | |
278 | Put_Line (+"See the manpage for more options."); | |
279 | end Display_Help; | |
280 | ||
281 | procedure Display_Version is | |
282 | -- Translate the format, then replace the major version. | |
283 | Format : constant String := +"music123 version %d by David Starner"; | |
284 | I : constant Positive := Ada.Strings.Fixed.Index (Format, "%d"); | |
285 | begin | |
286 | Ada.Text_IO.Put_Line | |
287 | (Ada.Strings.Fixed.Replace_Slice (Source => Format, | |
288 | Low => I, | |
289 | High => I + 1, | |
290 | By => Version_Number)); | |
291 | end Display_Version; | |
292 | ||
293 | procedure Read_Playlist (Path : String) is | |
294 | use Ada.Text_IO; | |
295 | Playlist : Ada.Text_IO.File_Type; | |
296 | begin | |
297 | begin | |
298 | Open (Playlist, In_File, Path); | |
299 | exception | |
300 | when others => | |
301 | raise Error with +"Playlist file not found."; | |
302 | end; | |
303 | while not End_Of_File (Playlist) loop | |
304 | Read_Playlist_Line (Get_Line (Playlist)); | |
305 | end loop; | |
306 | Close (Playlist); | |
307 | exception | |
308 | when others => | |
309 | if Is_Open (Playlist) then | |
310 | Close (Playlist); | |
311 | end if; | |
312 | raise Error with +"unable to parse playlist: " & Path; | |
313 | end Read_Playlist; | |
314 | ||
315 | procedure Read_Playlist_Line (Line : String) is | |
316 | Path : constant String | |
317 | := Ada.Strings.Fixed.Trim (Line, Ada.Strings.Both); | |
318 | begin | |
319 | if Path /= "" and then Path (Path'First) /= '#' then | |
320 | Paths.Append (Path); | |
321 | end if; | |
322 | end Read_Playlist_Line; | |
323 | ||
324 | procedure Set_Delay (Value : String) is | |
325 | begin | |
326 | Options.Delay_Length := Duration'Value (Value); | |
327 | exception | |
328 | when Constraint_Error => | |
329 | raise Error with +"Bad argument for -d."; | |
330 | end Set_Delay; | |
331 | ||
332 | use Ada.Command_Line; | |
333 | Arg_Num : Positive := 1; | |
334 | Ignore_Options : Boolean := False; | |
335 | begin | |
336 | while Arg_Num <= Argument_Count loop | |
337 | declare | |
338 | Arg : String renames Argument (Arg_Num); | |
339 | -- The reference manual guarantees that Arg'First = 1. | |
340 | begin | |
341 | if Ignore_Options or else Arg'Last < 2 or else Arg (1) /= '-' then | |
342 | Paths.Append (Arg); | |
343 | else | |
344 | Letters : for I in 2 .. Arg'Last loop | |
345 | case Arg (I) is | |
346 | when '-' => | |
347 | if Arg'Last /= 2 then | |
348 | raise Error with +"Unknown option: -"; | |
349 | end if; | |
350 | Ignore_Options := True; | |
351 | when '@' => | |
352 | if I < Arg'Last then | |
353 | Read_Playlist (Arg (I + 1 .. Arg'Last)); | |
354 | exit Letters; | |
355 | elsif Arg_Num < Argument_Count then | |
356 | Arg_Num := Arg_Num + 1; | |
357 | Read_Playlist (Argument (Arg_Num)); | |
358 | else | |
359 | raise Error with +"Missing argument for: -" & "@"; | |
360 | end if; | |
361 | when 'D' => | |
362 | Options.Delay_Length := 0.0; | |
363 | when 'd' => | |
364 | if I < Arg'Last then | |
365 | Set_Delay (Arg (I + 1 .. Arg'Last)); | |
366 | exit Letters; | |
367 | elsif Arg_Num < Argument_Count then | |
368 | Arg_Num := Arg_Num + 1; | |
369 | Set_Delay (Argument (Arg_Num)); | |
370 | else | |
371 | raise Error with +"Missing argument for -" & "d"; | |
372 | end if; | |
373 | when 'h' => | |
374 | Display_Version; | |
375 | Display_Help; | |
376 | Done := True; | |
377 | return; | |
378 | when 'i' => | |
379 | Options.Ignore_Extension_Case := True; | |
380 | when 'L' => | |
381 | Options.List_Files_Only := True; | |
382 | when 'l' => | |
383 | Options.Repeat := True; | |
384 | when 'q' => | |
385 | Options.Quiet := True; | |
386 | when 'r' => | |
387 | Options.Recurse := True; | |
388 | when 'T' => | |
389 | Options.Catch_Q_In_Stdin := True; | |
390 | when 'v' => | |
391 | Display_Version; | |
392 | Done := True; | |
393 | return; | |
394 | when 'Z' => | |
395 | Options.Eternal_Random := True; | |
396 | when 'z' => | |
397 | Options.Random := True; | |
398 | when others => | |
399 | raise Error with +"Unknown option: " & Arg (I); | |
400 | end case; | |
401 | end loop Letters; | |
402 | end if; | |
403 | end; | |
404 | Arg_Num := Arg_Num + 1; | |
405 | end loop; | |
406 | Done := False; | |
407 | end Parse_Command_Line; | |
408 | ||
409 | procedure Parse_Configuration (Tools : in out Tool_Maps.Map; | |
410 | Options : An_Option_List) is | |
411 | ||
412 | procedure Parse_File (Path : String); | |
413 | procedure Parse_Line (Line : String); | |
414 | ||
415 | procedure Parse_File (Path : String) is | |
416 | use Ada.Text_IO; | |
417 | File : File_Type; | |
418 | begin | |
419 | Open (File, In_File, Path); | |
420 | while not End_Of_File (File) loop | |
421 | Parse_Line (Get_Line (File)); | |
422 | end loop; | |
423 | Close (File); | |
424 | exception | |
425 | when others => | |
426 | if Is_Open (File) then | |
427 | Close (File); | |
428 | end if; | |
429 | Warn (+"error in configuration file: " & Path); | |
430 | raise; | |
431 | end Parse_File; | |
432 | ||
433 | procedure Parse_Line (Line : String) is | |
434 | HT : Character renames Ada.Characters.Latin_1.HT; | |
435 | Outside : Ada.Strings.Membership renames Ada.Strings.Outside; | |
436 | Whitespace : constant Ada.Strings.Maps.Character_Set | |
437 | := To_Set (Sequence => (' ', HT)); | |
438 | T_F, T_L, P_F, P_L, E_F, E_L, O_F, O_L : Integer; | |
439 | use Ada.Strings.Fixed; | |
440 | begin | |
441 | Find_Token (Line, Whitespace, Outside, T_F, T_L); | |
442 | if T_L = 0 -- Line only contains blanks. | |
443 | or else Line (T_F) = '#' -- Comment. | |
444 | then | |
445 | return; | |
446 | elsif Line (T_F .. T_L) /= "tool" -- Unexpected keyword. | |
447 | or else T_L = Line'Last -- Only "tool" | |
448 | then | |
449 | Warn (+"suspicious configuration line: " & Line); | |
450 | return; | |
451 | end if; | |
452 | ||
453 | Find_Token (Line, Whitespace, T_L + 1, Outside, P_F, P_L); | |
454 | if P_L = 0 or else P_L = Line'Last then | |
455 | Warn (+"suspicious configuration line::" & Line); | |
456 | return; | |
457 | end if; | |
458 | ||
459 | Find_Token (Line, Whitespace, P_L + 1, Outside, E_F, E_L); | |
460 | if E_L = 0 or else E_L = Line'Last then | |
461 | Warn (+"suspicious configuration line::" & Line); | |
462 | return; | |
463 | end if; | |
464 | ||
465 | O_F := Index (Line, Whitespace, E_L + 1, Outside); | |
466 | if O_F = 0 or else O_F = Line'Last or else Line (O_F) /= '"' then | |
467 | Warn (+"suspicious configuration line::" & Line); | |
468 | return; | |
469 | end if; | |
470 | ||
471 | O_L := Index (Line, """", O_F + 1); | |
472 | if O_L = 0 | |
473 | or else (for some I in O_L + 1 .. Line'Last => | |
474 | not Is_In (Line (I), Whitespace)) | |
475 | then | |
476 | Warn (+"suspicious configuration line::" & Line); | |
477 | return; | |
478 | end if; | |
479 | ||
480 | -- Now, split the extension list. | |
481 | declare | |
482 | Tool : constant String | |
483 | := Line (P_F .. P_L) & ' ' & Line (O_F + 1 .. O_L - 1); | |
484 | Position : Tool_Maps.Cursor; | |
485 | Inserted : Boolean; | |
486 | First : Positive := E_F; | |
487 | Last : Natural; | |
488 | begin | |
489 | loop | |
490 | if E_L < First or else Line (First) = ',' then | |
491 | Warn (+"suspicious configuration line::" & Line); | |
492 | return; | |
493 | end if; | |
494 | Last := First; | |
495 | while Last < E_L and then Line (Last + 1) /= ',' loop | |
496 | Last := Last + 1; | |
497 | end loop; | |
498 | Tools.Insert | |
499 | (Key => (if Options.Ignore_Extension_Case | |
500 | then Translate (Line (First .. Last), | |
501 | Lower_Case_Map) | |
502 | else (Line (First .. Last))), | |
503 | New_Item => Tool, | |
504 | Position => Position, | |
505 | Inserted => Inserted); | |
506 | if not Inserted then | |
507 | Warn (+"multiple tools given for extension: " | |
508 | & Line (First .. Last)); | |
509 | end if; | |
510 | exit when Last = E_L; | |
511 | First := Last + 2; | |
512 | end loop; | |
513 | end; | |
514 | end Parse_Line; | |
515 | ||
516 | begin | |
517 | if Ada.Environment_Variables.Exists ("HOME") then | |
518 | declare | |
519 | Home : constant String := Ada.Environment_Variables.Value ("HOME"); | |
520 | Path : constant String | |
521 | := Ada.Directories.Compose (Home, User_Configuration); | |
522 | begin | |
523 | if Ada.Directories.Exists (Path) then | |
524 | Parse_File (Path); | |
525 | return; | |
526 | end if; | |
527 | end; | |
528 | else | |
529 | Warn (+"variable HOME not found in the environment"); | |
530 | end if; | |
531 | ||
532 | if Ada.Directories.Exists (System_Configuration) then | |
533 | Parse_File (System_Configuration); | |
534 | return; | |
535 | end if; | |
536 | ||
537 | raise Error with +"No configuration file found: " & User_Configuration | |
538 | & ", " & System_Configuration; | |
539 | end Parse_Configuration; | |
540 | ||
541 | procedure Play_Songs (Commands : String_Vectors.Vector; | |
542 | Options : An_Option_List) is | |
543 | I : Positive := (if Options.Eternal_Random | |
544 | then Random (Commands.Last_Index) else 1); | |
545 | Available : Boolean; | |
546 | Key : Character; | |
547 | begin | |
548 | Songs : loop | |
549 | ||
550 | if not Options.Quiet then | |
551 | Ada.Text_IO.New_Line; | |
552 | Ada.Text_IO.Put_Line (+"music123 is running: " & Commands (I)); | |
553 | Ada.Text_IO.Put_Line (+"Control-c : quit immediately"); | |
554 | if Options.Catch_Q_In_Stdin then | |
555 | Ada.Text_IO.Put_Line (+"q : quit after this song"); | |
556 | end if; | |
557 | Ada.Text_IO.New_Line; | |
558 | end if; | |
559 | ||
560 | System (Commands (I)); | |
561 | ||
562 | if Options.Catch_Q_In_Stdin then | |
563 | loop | |
564 | Ada.Text_IO.Get_Immediate (Key, Available); | |
565 | exit when not Available; | |
566 | exit Songs when Key in 'q' | 'Q'; | |
567 | end loop; | |
568 | end if; | |
569 | ||
570 | if Options.Eternal_Random then | |
571 | I := Random (Commands.Last_Index); | |
572 | elsif I = Commands.Last_Index then | |
573 | exit Songs when not Options.Repeat; | |
574 | I := 1; | |
575 | else | |
576 | I := I + 1; | |
577 | end if; | |
578 | ||
579 | -- Only delay if there is a next song. | |
580 | delay Options.Delay_Length; | |
581 | ||
582 | end loop Songs; | |
583 | end Play_Songs; | |
584 | ||
585 | function Random (Maximum : Positive) return Positive is | |
586 | -- From ARM A.5.2.51. | |
587 | (Integer (Float (Maximum) * Random (Generator)) mod Maximum + 1); | |
588 | ||
589 | procedure Randomize (Commands : in out String_Vectors.Vector) is | |
590 | begin | |
591 | -- From Knuth, TAOCP vol. 2, edition 3, page 146, 3.4.2, algorithm P | |
592 | for J in reverse 2 .. Commands.Last_Index loop | |
593 | Commands.Swap (J, Random (J - 1)); | |
594 | end loop; | |
595 | end Randomize; | |
596 | ||
597 | procedure Setlocale (Category : Interfaces.C.int; | |
598 | Locale : String) is | |
599 | use Interfaces.C, Interfaces.C.Strings; | |
600 | function F (A1 : int := Category; | |
601 | A2 : char_array := To_C (Locale)) return chars_ptr | |
602 | with Import, Convention => C, External_Name => "setlocale"; | |
603 | begin | |
604 | if F = Null_Ptr then | |
605 | raise C_Error with "setlocale failed"; | |
606 | end if; | |
607 | end Setlocale; | |
608 | ||
609 | procedure System (Command : String) is | |
610 | use Interfaces.C; | |
611 | function F (A1 : char_array := To_C (Command)) return int | |
612 | with Import, Convention => C, External_Name => "system"; | |
613 | begin | |
614 | if F /= 0 then | |
615 | raise C_Error with "subprocess failed: " & Command; | |
616 | end if; | |
617 | end System; | |
618 | ||
619 | procedure Textdomain (Domainname : String) is | |
620 | use Interfaces.C, Interfaces.C.Strings; | |
621 | function F (A1 : char_array := To_C (Domainname)) return chars_ptr | |
622 | with Import, Convention => C, External_Name => "textdomain"; | |
623 | begin | |
624 | if F = Null_Ptr then | |
625 | raise C_Error with "textdomain failed"; | |
626 | end if; | |
627 | end Textdomain; | |
628 | ||
629 | procedure Warn (Message : String) is | |
630 | begin | |
631 | Ada.Text_IO.Put_Line (Ada.Text_IO.Standard_Error, Message); | |
632 | end Warn; | |
633 | ||
634 | ---------------------------------------------------------------------- | |
635 | ||
636 | Paths : String_Vectors.Vector; | |
637 | Options : An_Option_List; | |
638 | Done : Boolean; | |
639 | Tools : Tool_Maps.Map; | |
640 | Commands : String_Vectors.Vector; | |
25 | 641 | begin |
26 | Intl.Set_Locale; | |
27 | Intl.Text_Domain ("music123"); | |
28 | Intl.Bind_Text_Domain ("music123", "/usr/share/locale"); | |
29 | ||
30 | -- Import conffile first | |
31 | Import_Conffile (Program_List); | |
32 | ||
33 | -- Read command-line arguments | |
34 | if Argument_Count = 0 then | |
35 | Error (N ("No arguments found.")); | |
36 | raise Noted_Error; | |
37 | end if; | |
38 | ||
39 | Arg_Num := 1; | |
40 | while Arg_Num <= Argument_Count loop | |
41 | if Seeing_Minus_Options | |
42 | and then Argument (Arg_Num)'Length = 2 | |
43 | and then Argument (Arg_Num) (1) = '-' | |
44 | then | |
45 | case Argument (Arg_Num) (2) is | |
46 | when 'h' => | |
47 | Error (""); | |
48 | Set_Exit_Status (Success); | |
49 | return; | |
50 | when 'q' => Option_Quiet := True; | |
51 | when 'z' => Option_Random := True; | |
52 | when 'Z' => Option_Eternal_Random := True; | |
53 | when 'l' => Option_Loop := True; | |
54 | when 'r' => Option_Recurse := True; | |
55 | when 'i' => Option_Ignore_Extension_Case := True; | |
56 | when 'v' => | |
57 | Ada.Text_IO.Put_Line (Version); | |
58 | Set_Exit_Status (Success); | |
59 | return; | |
60 | when 'D' => | |
61 | Delay_Length := 0.0; | |
62 | when 'd' => | |
63 | if Arg_Num >= Argument_Count then | |
64 | Error (N ("Missing argument for -d.")); | |
65 | raise Noted_Error; | |
66 | end if; | |
67 | Arg_Num := Arg_Num + 1; | |
68 | begin | |
69 | Delay_Length := Duration'Value (Argument (Arg_Num)); | |
70 | exception | |
71 | when Constraint_Error => | |
72 | Error (N ("Bad argument for -d.")); | |
73 | raise Noted_Error; | |
74 | end; | |
75 | when 'L' => Option_List_Files_Only := True; | |
76 | when 'T' => Option_Task := True; | |
77 | when '-' => Seeing_Minus_Options := False; | |
78 | when '@' => | |
79 | if Arg_Num >= Argument_Count then | |
80 | Error (N ("Missing argument for -@.")); | |
81 | raise Noted_Error; | |
82 | end if; | |
83 | Arg_Num := Arg_Num + 1; | |
84 | Read_Playlist (Argument (Arg_Num), File_List); | |
85 | when others => | |
86 | Error (N ("Unknown argument found.")); | |
87 | raise Noted_Error; | |
88 | end case; | |
89 | elsif Check_Filename (Argument (Arg_Num), | |
90 | Program_List, | |
91 | Option_Ignore_Extension_Case) | |
92 | then | |
93 | File_List.Append (Argument (Arg_Num)); | |
94 | else | |
95 | Ada.Text_IO.Put_Line ("Ignoring file """ & Argument (Arg_Num) & """"); | |
96 | end if; | |
97 | Arg_Num := Arg_Num + 1; | |
98 | end loop; | |
99 | ||
100 | Expand_And_Check_Filenames (File_List, | |
101 | Option_Recurse, | |
102 | Program_List, | |
103 | Option_Ignore_Extension_Case); | |
104 | ||
105 | if Option_List_Files_Only then | |
106 | Display_Songs (File_List); | |
107 | Set_Exit_Status (Success); | |
642 | Setlocale (LC_ALL, ""); | |
643 | Textdomain ("music123"); | |
644 | Bindtextdomain ("music123", "/usr/share/locale"); | |
645 | ||
646 | Reset (Generator); | |
647 | ||
648 | Parse_Command_Line (Paths, Options, Done); | |
649 | if Done then | |
108 | 650 | return; |
109 | 651 | end if; |
110 | 652 | |
111 | if Option_Task then | |
112 | Command_Task.Start; | |
653 | Parse_Configuration (Tools, Options); | |
654 | ||
655 | for Path of Paths loop | |
656 | Add_Command (Commands, Path, Tools, Options); | |
657 | end loop; | |
658 | if Options.List_Files_Only then | |
659 | return; | |
660 | elsif Commands.Is_Empty then | |
661 | raise Error with +"No valid filenames found."; | |
113 | 662 | end if; |
114 | 663 | |
115 | Play_Songs | |
116 | (File_List, | |
117 | Program_List, | |
118 | Delay_Length => Delay_Length, | |
119 | Option_Quiet => Option_Quiet, | |
120 | Option_Loop => Option_Loop, | |
121 | Option_Random => Option_Random, | |
122 | Option_Eternal_Random => Option_Eternal_Random, | |
123 | Option_Ignore_Extension_Case => Option_Ignore_Extension_Case); | |
124 | ||
125 | if Option_Task then | |
126 | Command_Task.Stop; | |
664 | if Options.Random then | |
665 | Randomize (Commands); | |
127 | 666 | end if; |
128 | 667 | |
129 | Set_Exit_Status (Success); | |
130 | exception | |
131 | when Noted_Error => | |
132 | Set_Exit_Status (Failure); | |
668 | Play_Songs (Commands, Options); | |
133 | 669 | end Music123; |
0 | .TH music123 1 "25 lipiec 2002" | |
1 | ||
2 | .SH NAZWA | |
3 | music123 \- odtwarza ró¿ne pliki d¼wiêkowe (w tym MP3, Ogg i Wav). | |
4 | ||
5 | .SH SK£ADNIA | |
6 | .B music123 | |
7 | [ | |
8 | .B \-hqrvz | |
9 | ] | |
10 | .I plik | |
11 | .B ... | |
12 | ||
13 | .SH OPIS | |
14 | .B music123 | |
15 | jest pow³ok± wokó³ ró¿nych programów s³u¿±cych do odtwarzania plików | |
16 | muzycznych. Mo¿e zag³êbiaæ siê w strukturê katalogów przy pomocy \-r | |
17 | oraz losowo odtwarzaæ utwory przy pomozy \-z. U¿ywane programy i opcje | |
18 | im przekazywane s± zawarte w plikach /etc/music123rc lub ~/.music123rc. | |
19 | ||
20 | .SH OPCJE | |
21 | .IP \-h | |
22 | Poka¿ pomoc do polecenia i zakoñcz dzia³anie. | |
23 | .IP \-q | |
24 | Tryb cichy. ¯adne komunikaty nie s± wy¶wietlane. | |
25 | .IP \-r | |
26 | Rekurencyjnie zag³êbiaj siê w katalogi, zamiast je ignorowaæ. | |
27 | .IP \-v | |
28 | Poka¿ informacjê o wersji programu i zakoñcz dzia³anie. | |
29 | .IP \-z | |
30 | Odtwarzaj pliki w losowej kolejno¶ci. | |
31 | .IP \-Z | |
32 | Odtwarzaj pliki w losowej kolejno¶ci i bez koñca. | |
33 | .IP \-l | |
34 | Pêtla. \-z \-l ró¿ni siê od \-Z tym, ¿e \-z \-l najpierw wylosuje | |
35 | kolejno¶æ, a nastêpnie bêdzie odtwarza³ pliki w tej¿e kolejno¶ci | |
36 | raz po raz; \-Z za¶ odtwarza piosenki w losowej kolejno¶ci | |
37 | pozbawionej jakiegokolwiek porz±dku, w zwiazku z czym istnieje | |
38 | mo¿liwo¶æ odtworzenia tego samego pliku dwa (lub wiêcej) razy | |
39 | pod rz±d. | |
40 | .IP \-i | |
41 | Ignore extension case. | |
42 | .IP \-L | |
43 | List files and exit. | |
44 | .IP \-T | |
45 | Start a task that handle commands, only one command supported : quit, | |
46 | using q or Q will quit the application at the end of the current song. | |
47 | .IP \-D | |
48 | Nie rób przerw miêdzy piosenkami (mo¿e uczyniæ music123 trudniejszym | |
49 | do zabicia) | |
50 | .IP \-d | |
51 | Ustawia d³ugo¶æ przerw miêdzy piosenkami. \-d przyjmuje jeden argument, | |
52 | wyra¿ony w sekundach. Czas mo¿e zawieraæ czê¶æ u³amkow±. | |
53 | .IP \-@ | |
54 | Odtwarzaj pliki wymienione w obowi±zkowym argumencie do \-@. Inne pliki mog± | |
55 | byæ dodane z linii poleceñ. Ta opcja mo¿e byæ podana kilkakrotnie. Zauwa¿, | |
56 | ¿e music123 jeszcze nie odtwarza URLi. | |
57 | .IP \-\- | |
58 | Koniec listy opcji. | |
59 | ||
60 | .SH PRZYK£ADY | |
61 | ||
62 | Odtwórz trzy piosenki: | |
63 | .RS | |
64 | .B music123 test1.ogg test2.mp3 test3.wav | |
65 | .RE | |
66 | .PP | |
67 | ||
68 | Odtwórz losowo parê katalogów i piosenek: | |
69 | .RS | |
70 | .B music123 \-z \-r Rock/ test1.ogg Pop/ test4.wav | |
71 | .RE | |
72 | .PP | |
73 | ||
74 | .SH PLIKI | |
75 | ||
76 | .TP | |
77 | /etc/music123rc | |
78 | Opisuje których programów | |
79 | .B music123 | |
80 | ma u¿yæ, jakie typy plików obs³uguje | |
81 | i jakie opcje przekazuje tym¿e programom. | |
82 | ||
83 | .TP | |
84 | ~/.music123rc | |
85 | Indywidualne ustawienia danego u¿ytkownika. | |
86 | .PP | |
87 | ||
88 | .SH AUTORZY | |
89 | ||
90 | .TP | |
91 | Autorzy: | |
92 | .br | |
93 | David Starner <dvdeug@debian.org> | |
94 | .br | |
95 | ||
96 | .SH T£UMACZENIE | |
97 | ||
98 | .TP | |
99 | T³umacze: | |
100 | .br | |
101 | Grzegorz Ku¶nierz <konik@v\-lo.krakow.pl> | |
102 | .br | |
0 | .TH music123 1 "25 lipiec 2002" | |
1 | ||
2 | .SH NAZWA | |
3 | music123 \- odtwarza ró¿ne pliki d¼wiêkowe (w tym MP3, Ogg i Wav). | |
4 | ||
5 | .SH SK£ADNIA | |
6 | .B music123 | |
7 | ||
8 | .SH OPIS | |
9 | .B music123 | |
10 | jest pow³ok± wokó³ ró¿nych programów s³u¿±cych do odtwarzania plików | |
11 | muzycznych. Mo¿e zag³êbiaæ siê w strukturê katalogów przy pomocy \-r | |
12 | oraz losowo odtwarzaæ utwory przy pomozy \-z. U¿ywane programy i opcje | |
13 | im przekazywane s± zawarte w plikach /etc/music123rc lub ~/.music123rc. | |
14 | ||
15 | .SH OPCJE | |
16 | .IP \-D | |
17 | Nie rób przerw miêdzy piosenkami (mo¿e uczyniæ music123 trudniejszym | |
18 | do zabicia) | |
19 | .IP \-d | |
20 | Ustawia d³ugo¶æ przerw miêdzy piosenkami. \-d przyjmuje jeden argument, | |
21 | wyra¿ony w sekundach. Czas mo¿e zawieraæ czê¶æ u³amkow±. | |
22 | .IP \-i | |
23 | Ignore extension case. | |
24 | .IP \-h | |
25 | Poka¿ pomoc do polecenia i zakoñcz dzia³anie. | |
26 | .IP \-l | |
27 | Pêtla. \-z \-l ró¿ni siê od \-Z tym, ¿e \-z \-l najpierw wylosuje | |
28 | kolejno¶æ, a nastêpnie bêdzie odtwarza³ pliki w tej¿e kolejno¶ci | |
29 | raz po raz; \-Z za¶ odtwarza piosenki w losowej kolejno¶ci | |
30 | pozbawionej jakiegokolwiek porz±dku, w zwiazku z czym istnieje | |
31 | mo¿liwo¶æ odtworzenia tego samego pliku dwa (lub wiêcej) razy | |
32 | pod rz±d. | |
33 | .IP \-L | |
34 | List files and exit. | |
35 | .IP \-q | |
36 | Tryb cichy. ¯adne komunikaty nie s± wy¶wietlane. | |
37 | .IP \-r | |
38 | Rekurencyjnie zag³êbiaj siê w katalogi, zamiast je ignorowaæ. | |
39 | .IP \-T | |
40 | Redirect standard input, allowing \fIq\fR or \fIQ\fR keys to stop | |
41 | after current file. | |
42 | The player will not see its standard output anymore. | |
43 | .IP \-v | |
44 | Poka¿ informacjê o wersji programu i zakoñcz dzia³anie. | |
45 | .IP \-z | |
46 | Odtwarzaj pliki w losowej kolejno¶ci. | |
47 | .IP \-Z | |
48 | Odtwarzaj pliki w losowej kolejno¶ci i bez koñca. | |
49 | .IP \-\- | |
50 | Koniec listy opcji. | |
51 | .IP \-@ | |
52 | Odtwarzaj pliki wymienione w obowi±zkowym argumencie do \-@. Inne pliki mog± | |
53 | byæ dodane z linii poleceñ. Ta opcja mo¿e byæ podana kilkakrotnie. Zauwa¿, | |
54 | ¿e music123 jeszcze nie odtwarza URLi. | |
55 | ||
56 | .SH PRZYK£ADY | |
57 | ||
58 | Odtwórz trzy piosenki: | |
59 | .RS | |
60 | .B music123 test1.ogg test2.mp3 test3.wav | |
61 | .RE | |
62 | .PP | |
63 | ||
64 | Odtwórz losowo parê katalogów i piosenek: | |
65 | .RS | |
66 | .B music123 \-z \-r Rock/ test1.ogg Pop/ test4.wav | |
67 | .RE | |
68 | .PP | |
69 | ||
70 | .SH PLIKI | |
71 | ||
72 | .TP | |
73 | /etc/music123rc | |
74 | Opisuje których programów | |
75 | .B music123 | |
76 | ma u¿yæ, jakie typy plików obs³uguje | |
77 | i jakie opcje przekazuje tym¿e programom. | |
78 | ||
79 | .TP | |
80 | ~/.music123rc | |
81 | Indywidualne ustawienia danego u¿ytkownika. | |
82 | .PP | |
83 | ||
84 | .SH AUTORZY | |
85 | ||
86 | .TP | |
87 | Autorzy: | |
88 | .br | |
89 | David Starner <dvdeug@debian.org> | |
90 | .br | |
91 | ||
92 | .SH T£UMACZENIE | |
93 | ||
94 | .TP | |
95 | T³umacze: | |
96 | .br | |
97 | Grzegorz Ku¶nierz <konik@v\-lo.krakow.pl> | |
98 | .br |
23 | 23 | # music123.adb |
24 | 24 | # changed by dvdeug |
25 | 25 | msgid "Bad argument for -d." |
26 | msgstr "Falsches Argument für -d." | |
26 | msgstr "Falsches Argument für -d." | |
27 | 27 | |
28 | 28 | # music123.adb |
29 | 29 | # changed by dvdeug |
30 | 30 | msgid "Missing argument for -d." |
31 | msgstr "Fehlendes Argument für -d." | |
31 | msgstr "Fehlendes Argument für -d." | |
32 | 32 | |
33 | 33 | # music123.adb |
34 | 34 | msgid "Missing argument for -@." |
35 | msgstr "Fehlendes Argument für -@." | |
35 | msgstr "Fehlendes Argument für -@." | |
36 | 36 | |
37 | 37 | # music123.adb |
38 | 38 | msgid "Unknown argument found." |
39 | 39 | msgstr "Unbekanntes Argument gefunden" |
40 | 40 | |
41 | # support_routines.adb | |
41 | # music123.adb | |
42 | 42 | msgid "music123: " |
43 | 43 | msgstr "music123: " |
44 | 44 | |
45 | # support_routines.adb | |
45 | # music123.adb | |
46 | 46 | msgid "usage: music123 [-hqrvz] files ..." |
47 | 47 | msgstr "usage: music123 [-hqrvz] files ..." |
48 | 48 | |
49 | # support_routines.adb | |
49 | # music123.adb | |
50 | 50 | msgid "-h This help" |
51 | 51 | msgstr "-h Diese Hilfe" |
52 | 52 | |
53 | # support_routines.adb | |
53 | # music123.adb | |
54 | 54 | msgid "-q Run quiet" |
55 | 55 | msgstr "-q Programmablauf ohne Ausgabe" |
56 | 56 | |
57 | # support_routines.adb | |
57 | # music123.adb | |
58 | 58 | msgid "-r Recurse over directories" |
59 | 59 | msgstr "-r rekursiv durch die Verzeichnisse" |
60 | 60 | |
61 | # support_routines.adb | |
61 | # music123.adb | |
62 | 62 | msgid "-v Print the version and exit" |
63 | 63 | msgstr "-v gibt die Version aus" |
64 | 64 | |
65 | # support_routines.adb | |
65 | # music123.adb | |
66 | 66 | msgid "-z Randomize the filelist" |
67 | 67 | msgstr "-z mischt die Dateiliste" |
68 | 68 | |
69 | # support_routines.adb | |
69 | # music123.adb | |
70 | 70 | msgid "See the manpage for more options." |
71 | msgstr "Für weitere Optionen siehe Man-Page" | |
71 | msgstr "Für weitere Optionen siehe Man-Page" | |
72 | 72 | |
73 | # support_routines.adb | |
73 | # music123.adb | |
74 | 74 | msgid "Neither /etc/music123rc or ~/.music123rc found. Exiting." |
75 | 75 | msgstr "Weder /etc/music123rc noch ~/.music123rc wurden gefunden. Abbruch" |
76 | 76 | |
77 | # support_routines.adb | |
77 | # music123.adb | |
78 | 78 | msgid "The config file (~/.music123rc or /etc/music123rc) is corrupt." |
79 | msgstr "Die Konfigdatei (~/.music123rc oder /etc/music123rc) sind beschädigt" | |
79 | msgstr "Die Konfigdatei (~/.music123rc oder /etc/music123rc) sind beschädigt" | |
80 | 80 | |
81 | # support_routines.adb | |
81 | # music123.adb | |
82 | 82 | msgid "No valid filenames found." |
83 | msgstr "Kein gültiger Dateiname gefunden" | |
83 | msgstr "Kein gültiger Dateiname gefunden" | |
84 | 84 | |
85 | # support_routines.adb | |
85 | # music123.adb | |
86 | 86 | msgid "Playlist file not found." |
87 | 87 | msgstr "Playlist Datei nicht gefunden" |
0 | # Mesaøoj por music123 de David Starner. | |
0 | # Mesaĝoj por music123 de David Starner. | |
1 | 1 | # Edmund GRIMLEY EVANS <edmundo@rano.org>, 2001. |
2 | 2 | # |
3 | 3 | msgid "" |
37 | 37 | msgid "Unknown argument found." |
38 | 38 | msgstr "Nekonata argumento." |
39 | 39 | |
40 | # support_routines.adb | |
40 | # music123.adb | |
41 | 41 | msgid "music123: " |
42 | 42 | msgstr "music123: " |
43 | 43 | |
44 | # support_routines.adb | |
44 | # music123.adb | |
45 | 45 | msgid "usage: music123 [-hqrvz] files ..." |
46 | 46 | msgstr "uzado: music123 [-hqrvz] dosieroj ..." |
47 | 47 | |
48 | # support_routines.adb | |
48 | # music123.adb | |
49 | 49 | msgid "-h This help" |
50 | msgstr "-h Æi tiu helpo" | |
50 | msgstr "-h Ĉi tiu helpo" | |
51 | 51 | |
52 | # support_routines.adb | |
52 | # music123.adb | |
53 | 53 | msgid "-q Run quiet" |
54 | 54 | msgstr "-q Ruli silente" |
55 | 55 | |
56 | # support_routines.adb | |
56 | # music123.adb | |
57 | 57 | msgid "-r Recurse over directories" |
58 | 58 | msgstr "-r Trakti dosierujojn rekurse" |
59 | 59 | |
60 | # support_routines.adb | |
60 | # music123.adb | |
61 | 61 | msgid "-v Print the version and exit" |
62 | 62 | msgstr "-v Montri la version kaj eliri" |
63 | 63 | |
64 | # support_routines.adb | |
64 | # music123.adb | |
65 | 65 | msgid "-z Randomize the filelist" |
66 | 66 | msgstr "-z Hazarde reordigi la dosierliston" |
67 | 67 | |
68 | # support_routines.adb | |
68 | # music123.adb | |
69 | 69 | msgid "See the manpage for more options." |
70 | msgstr "Vidu la manpaøon por pli da opcioj." | |
70 | msgstr "Vidu la manpaĝon por pli da opcioj." | |
71 | 71 | |
72 | # support_routines.adb | |
72 | # music123.adb | |
73 | 73 | msgid "Neither /etc/music123rc or ~/.music123rc found. Exiting." |
74 | 74 | msgstr "Nek /etc/music123rc nek ~/.music123rc estas trovita. Eliras." |
75 | 75 | |
76 | # support_routines.adb | |
76 | # music123.adb | |
77 | 77 | msgid "The config file (~/.music123rc or /etc/music123rc) is corrupt." |
78 | msgstr "La agordodosiero (~/.music123rc aý /etc/music123rc) estas fuþita." | |
78 | msgstr "La agordodosiero (~/.music123rc aŭ /etc/music123rc) estas fuŝita." | |
79 | 79 | |
80 | # support_routines.adb | |
80 | # music123.adb | |
81 | 81 | msgid "No valid filenames found." |
82 | 82 | msgstr "Mankas validaj dosiernomoj." |
83 | 83 | |
84 | # support_routines.adb | |
84 | # music123.adb | |
85 | 85 | msgid "Playlist file not found." |
86 | 86 | msgstr "Dosiero kun ludolisto ne trovita." |
23 | 23 | |
24 | 24 | # music123.adb |
25 | 25 | msgid "Bad argument for -d." |
26 | msgstr "Paramètre pour -d invalide." | |
26 | msgstr "Paramètre pour -d invalide." | |
27 | 27 | |
28 | 28 | # music123.adb |
29 | 29 | msgid "Missing argument for -d." |
30 | msgstr "Paramètre pour -d manquant." | |
30 | msgstr "Paramètre pour -d manquant." | |
31 | 31 | |
32 | 32 | # music123.adb |
33 | 33 | msgid "Missing argument for -@." |
34 | msgstr "Paramètre pour -@ manquant." | |
34 | msgstr "Paramètre pour -@ manquant." | |
35 | 35 | |
36 | 36 | # music123.adb |
37 | 37 | msgid "Unknown argument found." |
38 | msgstr "Argument inconnu trouvé." | |
38 | msgstr "Argument inconnu trouvé." | |
39 | 39 | |
40 | # support_routines.adb | |
40 | # music123.adb | |
41 | 41 | msgid "music123: " |
42 | 42 | msgstr "music123 : " |
43 | 43 | |
44 | # support_routines.adb | |
44 | # music123.adb | |
45 | 45 | msgid "usage: music123 [-hqrvz] files ..." |
46 | 46 | msgstr "usage : music123 [-hqrvz] fichiers ..." |
47 | 47 | |
48 | # support_routines.adb | |
48 | # music123.adb | |
49 | 49 | msgid "-h This help" |
50 | 50 | msgstr "-h Afficher cette aide" |
51 | 51 | |
52 | # support_routines.adb | |
52 | # music123.adb | |
53 | 53 | msgid "-q Run quiet" |
54 | msgstr "-q Exécuter silencieusement" | |
54 | msgstr "-q Exécuter silencieusement" | |
55 | 55 | |
56 | # support_routines.adb | |
56 | # music123.adb | |
57 | 57 | msgid "-i Ignore extension case" |
58 | 58 | msgstr "-i Ignorer la casse des extensions de fichier" |
59 | 59 | |
60 | # support_routines.adb | |
60 | # music123.adb | |
61 | 61 | msgid "-L List files and exit" |
62 | 62 | msgstr "-L Donner la liste des fichier et sortir" |
63 | 63 | |
64 | # support_routines.adb | |
64 | # music123.adb | |
65 | 65 | msgid "-r Recurse over directories" |
66 | msgstr "-r Parcourir les sous-répertoires récursivement" | |
66 | msgstr "-r Parcourir les sous-répertoires récursivement" | |
67 | 67 | |
68 | # support_routines.adb | |
68 | # music123.adb | |
69 | 69 | msgid "-v Print the version and exit" |
70 | 70 | msgstr "-v Afficher la version et terminer" |
71 | 71 | |
72 | # support_routines.adb | |
72 | # music123.adb | |
73 | 73 | msgid "-z Randomize the filelist" |
74 | msgstr "-z Utiliser la liste de fichiers dans un ordre aléatoire" | |
74 | msgstr "-z Utiliser la liste de fichiers dans un ordre aléaatoire" | |
75 | 75 | |
76 | # support_routines.adb | |
76 | # music123.adb | |
77 | 77 | msgid "See the manpage for more options." |
78 | msgstr "Voir la page de manuel pour découvrir d'autres d'options." | |
78 | msgstr "Voir la page de manuel pour découvrir d'autres d'options." | |
79 | 79 | |
80 | # support_routines.adb | |
80 | # music123.adb | |
81 | 81 | msgid "Neither /etc/music123rc or ~/.music123rc found. Exiting." |
82 | msgstr "/etc/music123rc et ~/.music123rc sont tous les deux introuvables. Arrêt." | |
82 | msgstr "/etc/music123rc et ~/.music123rc sont tous les deux introuvables. Arrêt." | |
83 | 83 | |
84 | # support_routines.adb | |
84 | # music123.adb | |
85 | 85 | msgid "The config file (~/.music123rc or /etc/music123rc) is corrupt." |
86 | 86 | msgstr "" |
87 | 87 | "Le fichier de configuration (~/.music123rc ou /etc/music123rc) est corrompu." |
88 | 88 | |
89 | # support_routines.adb | |
89 | # music123.adb | |
90 | 90 | msgid "No valid filenames found." |
91 | msgstr "Aucun nom de fichier valide n'a été trouvé." | |
91 | msgstr "Aucun nom de fichier valide n'a été trouvée." | |
92 | 92 | |
93 | # support_routines.adb | |
93 | # music123.adb | |
94 | 94 | msgid "Playlist file not found." |
95 | msgstr "Le fichier contenant la liste à jouer est introuvable." | |
95 | msgstr "Le fichier contenant la liste à jouer est introuvable." |
37 | 37 | msgid "Unknown argument found." |
38 | 38 | msgstr "" |
39 | 39 | |
40 | #: support_routines.adb | |
40 | #: music123.adb | |
41 | 41 | msgid "music123: " |
42 | 42 | msgstr "" |
43 | 43 | |
44 | #: support_routines.adb | |
44 | #: music123.adb | |
45 | 45 | msgid "usage: music123 [-hqrvz] files ..." |
46 | 46 | msgstr "" |
47 | 47 | |
48 | #: support_routines.adb | |
48 | #: music123.adb | |
49 | 49 | msgid "-h This help" |
50 | 50 | msgstr "" |
51 | 51 | |
52 | #: support_routines.adb | |
52 | #: music123.adb | |
53 | 53 | msgid "-q Run quiet" |
54 | 54 | msgstr "" |
55 | 55 | |
56 | #: support_routines.adb | |
56 | #: music123.adb | |
57 | 57 | msgid "-i Ignore extension case" |
58 | 58 | msgstr "" |
59 | 59 | |
60 | #: support_routines.adb | |
60 | #: music123.adb | |
61 | 61 | msgid "-L List files and exit" |
62 | 62 | msgstr "" |
63 | 63 | |
64 | #: support_routines.adb | |
64 | #: music123.adb | |
65 | 65 | msgid "-r Recurse over directories" |
66 | 66 | msgstr "" |
67 | 67 | |
68 | #: support_routines.adb | |
68 | #: music123.adb | |
69 | 69 | msgid "-v Print the version and exit" |
70 | 70 | msgstr "" |
71 | 71 | |
72 | #: support_routines.adb | |
72 | #: music123.adb | |
73 | 73 | msgid "-z Randomize the filelist" |
74 | 74 | msgstr "" |
75 | 75 | |
76 | #: support_routines.adb | |
76 | #: music123.adb | |
77 | 77 | msgid "See the manpage for more options." |
78 | 78 | msgstr "" |
79 | 79 | |
80 | #: support_routines.adb | |
80 | #: music123.adb | |
81 | 81 | msgid "Neither /etc/music123rc or ~/.music123 found. Exiting." |
82 | 82 | msgstr "" |
83 | 83 | |
84 | #: support_routines.adb | |
84 | #: music123.adb | |
85 | 85 | msgid "The config file (~/.music123 or /etc/music123rc) is corrupt." |
86 | 86 | msgstr "" |
87 | 87 | |
88 | #: support_routines.adb | |
88 | #: music123.adb | |
89 | 89 | msgid "No valid filenames found." |
90 | 90 | msgstr "" |
91 | 91 | |
92 | #: support_routines.adb | |
92 | #: music123.adb | |
93 | 93 | msgid "Playlist file not found." |
94 | 94 | msgstr "" |
95 |
38 | 38 | msgid "Unknown argument found." |
39 | 39 | msgstr "Ongeldig argument gevonden." |
40 | 40 | |
41 | # support_routines.adb | |
41 | # music123.adb | |
42 | 42 | msgid "music123: " |
43 | 43 | msgstr "music123: " |
44 | 44 | |
45 | # support_routines.adb | |
45 | # music123.adb | |
46 | 46 | msgid "usage: music123 [-hqrvz] files ..." |
47 | 47 | msgstr "gebruik: music123 [-hqrvz] bestanden ..." |
48 | 48 | |
49 | # support_routines.adb | |
49 | # music123.adb | |
50 | 50 | msgid "-h This help" |
51 | 51 | msgstr "-h Deze hulp" |
52 | 52 | |
53 | # support_routines.adb | |
53 | # music123.adb | |
54 | 54 | msgid "-q Run quiet" |
55 | 55 | msgstr "-q Draai stil" |
56 | 56 | |
57 | # support_routines.adb | |
57 | # music123.adb | |
58 | 58 | msgid "-r Recurse over directories" |
59 | 59 | msgstr "-r Loop recursief door directories" |
60 | 60 | |
61 | # support_routines.adb | |
61 | # music123.adb | |
62 | 62 | msgid "-v Print the version and exit" |
63 | msgstr "-v Toon het versienummer en beëindig programma" | |
63 | msgstr "-v Toon het versienummer en beëindig programma" | |
64 | 64 | |
65 | # support_routines.adb | |
65 | # music123.adb | |
66 | 66 | msgid "-z Randomize the filelist" |
67 | 67 | msgstr "-z Maak de volgorde van de bestandslijst willekeurig" |
68 | 68 | |
69 | # support_routines.adb | |
69 | # music123.adb | |
70 | 70 | msgid "See the manpage for more options." |
71 | 71 | msgstr "Zie de manpage voor meer opties." |
72 | 72 | |
73 | # support_routines.adb | |
73 | # music123.adb | |
74 | 74 | msgid "Neither /etc/music123rc or ~/.music123rc found. Exiting." |
75 | msgstr "/etc/music123rc noch ~/.music123rc gevonden. Programma beëindigd." | |
75 | msgstr "/etc/music123rc noch ~/.music123rc gevonden. Programma beëindigd." | |
76 | 76 | |
77 | # support_routines.adb | |
77 | # music123.adb | |
78 | 78 | msgid "The config file (~/.music123rc or /etc/music123rc) is corrupt." |
79 | 79 | msgstr "Het configuratiebestand (~/.music123rc of /etc/music123rc) bevat fouten." |
80 | 80 | |
81 | # support_routines.adb | |
81 | # music123.adb | |
82 | 82 | msgid "No valid filenames found." |
83 | 83 | msgstr "Geen valide bestandsnamen gevonden." |
84 | 84 | |
85 | # support_routines.adb | |
85 | # music123.adb | |
86 | 86 | msgid "Playlist file not found." |
87 | 87 | msgstr "De playlist is niet gevonden." |
0 | # SOME DESCRIPTIVE TITLE. | |
1 | # Copyright (C) YEAR Free Software Foundation, Inc. | |
2 | # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. | |
3 | # | |
4 | msgid "" | |
5 | msgstr "" | |
6 | "Project-Id-Version: music123 8\n" | |
7 | "POT-Creation-Date: 2002-07-26 04:36+0200\n" | |
8 | "Last-Translator: Grzegorz Ku¶nierz <konik@v-lo.krakow.pl>\n" | |
9 | "MIME-Version: 1.0\n" | |
10 | "Content-Type: text/plain; charset=iso-8859-2\n" | |
11 | "Content-Transfer-Encoding: 8bit\n" | |
12 | ||
13 | # music123.adb | |
14 | msgid "music123 version %d by David Starner" | |
15 | msgstr "music123 wersja %d autorstwa David'a Starner'a" | |
16 | ||
17 | # music123.adb | |
18 | msgid "No arguments found." | |
19 | msgstr "Nie znaleziono argumentów." | |
20 | ||
21 | # music123.adb | |
22 | # changed by dvdeug | |
23 | msgid "Bad argument for -d." | |
24 | msgstr "Z³y argument dla -d." | |
25 | ||
26 | # music123.adb | |
27 | # changed by dvdeug | |
28 | msgid "Missing argument for -d." | |
29 | msgstr "Brakuj±cy argument dla -d." | |
30 | ||
31 | # music123.adb | |
32 | msgid "Missing argument for -@." | |
33 | msgstr "Brakuj±cy argument dla -@." | |
34 | ||
35 | # music123.adb | |
36 | msgid "Unknown argument found." | |
37 | msgstr "Nieznany argument." | |
38 | ||
39 | # support_routines.adb | |
40 | msgid "music123: " | |
41 | msgstr "music123: " | |
42 | ||
43 | # support_routines.adb | |
44 | msgid "usage: music123 [-hqrvz] files ..." | |
45 | msgstr "sk³adnia: music123 [-hqrvz] files ..." | |
46 | ||
47 | # support_routines.adb | |
48 | msgid "-h This help" | |
49 | msgstr "-h Ta pomoc" | |
50 | ||
51 | # support_routines.adb | |
52 | msgid "-q Run quiet" | |
53 | msgstr "-q Uruchom w trybie cichym" | |
54 | ||
55 | # support_routines.adb | |
56 | msgid "-r Recurse over directories" | |
57 | msgstr "-r Zag³êbiaj siê w katalogi" | |
58 | ||
59 | # support_routines.adb | |
60 | msgid "-v Print the version and exit" | |
61 | msgstr "-v Wy¶wietl informacjê o wersji i wyjd¼" | |
62 | ||
63 | # support_routines.adb | |
64 | msgid "-z Randomize the filelist" | |
65 | msgstr "-z Odtwarzaj listê losowo" | |
66 | ||
67 | # support_routines.adb | |
68 | msgid "See the manpage for more options." | |
69 | msgstr "Zobacz stronê man aby zapoznaæ siê z pozosta³ymi opcjami." | |
70 | ||
71 | # support_routines.adb | |
72 | msgid "Neither /etc/music123rc or ~/.music123rc found. Exiting." | |
73 | msgstr "Nie znaleziono /etc/music123rc ani ~/.music123rc. Wychodzê." | |
74 | ||
75 | # support_routines.adb | |
76 | msgid "The config file (~/.music123rc or /etc/music123rc) is corrupt." | |
77 | msgstr "Plik konfigurcji (~/.music123rc lub /etc/music123rc) jest nieprawid³owy." | |
78 | ||
79 | # support_routines.adb | |
80 | msgid "No valid filenames found." | |
81 | msgstr "Nie odnaleziono ¿adnych prawid³owych nazw plików." | |
82 | ||
83 | # support_routines.adb | |
84 | msgid "Playlist file not found." | |
85 | msgstr "Nie odnaleziono pliku playlisty." | |
0 | # SOME DESCRIPTIVE TITLE. | |
1 | # Copyright (C) YEAR Free Software Foundation, Inc. | |
2 | # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. | |
3 | # | |
4 | msgid "" | |
5 | msgstr "" | |
6 | "Project-Id-Version: music123 8\n" | |
7 | "POT-Creation-Date: 2002-07-26 04:36+0200\n" | |
8 | "Last-Translator: Grzegorz Kuśnierz <konik@v-lo.krakow.pl>\n" | |
9 | "MIME-Version: 1.0\n" | |
10 | "Content-Type: text/plain; charset=iso-8859-2\n" | |
11 | "Content-Transfer-Encoding: 8bit\n" | |
12 | ||
13 | # music123.adb | |
14 | msgid "music123 version %d by David Starner" | |
15 | msgstr "music123 wersja %d autorstwa David'a Starner'a" | |
16 | ||
17 | # music123.adb | |
18 | msgid "No arguments found." | |
19 | msgstr "Nie znaleziono argumentów." | |
20 | ||
21 | # music123.adb | |
22 | # changed by dvdeug | |
23 | msgid "Bad argument for -d." | |
24 | msgstr "Zły argument dla -d." | |
25 | ||
26 | # music123.adb | |
27 | # changed by dvdeug | |
28 | msgid "Missing argument for -d." | |
29 | msgstr "Brakujący argument dla -d." | |
30 | ||
31 | # music123.adb | |
32 | msgid "Missing argument for -@." | |
33 | msgstr "Brakujący argument dla -@." | |
34 | ||
35 | # music123.adb | |
36 | msgid "Unknown argument found." | |
37 | msgstr "Nieznany argument." | |
38 | ||
39 | # music123.adb | |
40 | msgid "music123: " | |
41 | msgstr "music123: " | |
42 | ||
43 | # music123.adb | |
44 | msgid "usage: music123 [-hqrvz] files ..." | |
45 | msgstr "składnia: music123 [-hqrvz] files ..." | |
46 | ||
47 | # music123.adb | |
48 | msgid "-h This help" | |
49 | msgstr "-h Ta pomoc" | |
50 | ||
51 | # music123.adb | |
52 | msgid "-q Run quiet" | |
53 | msgstr "-q Uruchom w trybie cichym" | |
54 | ||
55 | # music123.adb | |
56 | msgid "-r Recurse over directories" | |
57 | msgstr "-r Zagłębiaj się w katalogi" | |
58 | ||
59 | # music123.adb | |
60 | msgid "-v Print the version and exit" | |
61 | msgstr "-v Wyświetl informację o wersji i wyjdź" | |
62 | ||
63 | # music123.adb | |
64 | msgid "-z Randomize the filelist" | |
65 | msgstr "-z Odtwarzaj listę losowo" | |
66 | ||
67 | # music123.adb | |
68 | msgid "See the manpage for more options." | |
69 | msgstr "Zobacz stronę man aby zapoznać się z pozostałymi opcjami." | |
70 | ||
71 | # music123.adb | |
72 | msgid "Neither /etc/music123rc or ~/.music123rc found. Exiting." | |
73 | msgstr "Nie znaleziono /etc/music123rc ani ~/.music123rc. Wychodzę." | |
74 | ||
75 | # music123.adb | |
76 | msgid "The config file (~/.music123rc or /etc/music123rc) is corrupt." | |
77 | msgstr "Plik konfigurcji (~/.music123rc lub /etc/music123rc) jest nieprawidłowy." | |
78 | ||
79 | # music123.adb | |
80 | msgid "No valid filenames found." | |
81 | msgstr "Nie odnaleziono żadnych prawidłowych nazw plików." | |
82 | ||
83 | # music123.adb | |
84 | msgid "Playlist file not found." | |
85 | msgstr "Nie odnaleziono pliku playlisty." |
14 | 14 | |
15 | 15 | # music123.adb |
16 | 16 | msgid "music123 version %d by David Starner" |
17 | msgstr "music123 versão %d, por David Starner" | |
17 | msgstr "music123 versão %d, por David Starner" | |
18 | 18 | |
19 | 19 | # music123.adb |
20 | 20 | msgid "No arguments found." |
21 | msgstr "Argumentos não encontrados." | |
21 | msgstr "Argumentos não encontrados." | |
22 | 22 | |
23 | 23 | # music123.adb |
24 | 24 | msgid "Bad argument for -d." |
36 | 36 | msgid "Unknown argument found." |
37 | 37 | msgstr "Argumento desconhecido encontrado." |
38 | 38 | |
39 | # support_routines.adb | |
39 | # music123.adb | |
40 | 40 | msgid "music123: " |
41 | 41 | msgstr "music123: " |
42 | 42 | |
43 | # support_routines.adb | |
43 | # music123.adb | |
44 | 44 | msgid "usage: music123 [-hqrvz] files ..." |
45 | 45 | msgstr "uso: music123 [-hqrvz] arquivos ..." |
46 | 46 | |
47 | # support_routines.adb | |
47 | # music123.adb | |
48 | 48 | msgid "-h This help" |
49 | 49 | msgstr "-h Esta ajuda" |
50 | 50 | |
51 | # support_routines.adb | |
51 | # music123.adb | |
52 | 52 | msgid "-q Run quiet" |
53 | 53 | msgstr "-q Rodar quieto" |
54 | 54 | |
55 | # support_routines.adb | |
55 | # music123.adb | |
56 | 56 | msgid "-r Recurse over directories" |
57 | msgstr "-r Entrar nos subdiretórios" | |
57 | msgstr "-r Entrar nos subdiretórios" | |
58 | 58 | |
59 | # support_routines.adb | |
59 | # music123.adb | |
60 | 60 | msgid "-v Print the version and exit" |
61 | msgstr "-v Imprime a versão e sai" | |
61 | msgstr "-v Imprime a versão e sai" | |
62 | 62 | |
63 | # support_routines.adb | |
63 | # music123.adb | |
64 | 64 | msgid "-z Randomize the filelist" |
65 | msgstr "-z Torna a lista de arquivos aleatória." | |
65 | msgstr "-z Torna a lista de arquivos aleatória." | |
66 | 66 | |
67 | # support_routines.adb | |
67 | # music123.adb | |
68 | 68 | msgid "See the manpage for more options." |
69 | msgstr "Veja a página de manual para mais opções." | |
69 | msgstr "Veja a página de manual para mais opções." | |
70 | 70 | |
71 | # support_routines.adb | |
71 | # music123.adb | |
72 | 72 | msgid "Neither /etc/music123rc or ~/.music123rc found. Exiting." |
73 | 73 | msgstr "Nem o /etc/music123rc nem o ~/.music123rc foram encontrados. Saindo." |
74 | 74 | |
75 | # support_routines.adb | |
75 | # music123.adb | |
76 | 76 | msgid "The config file (~/.music123rc or /etc/music123rc) is corrupt." |
77 | 77 | msgstr "" |
78 | "O arquivo de configuração (~/.music123rc ou /etc/music123rc) está corrompido." | |
78 | "O arquivo de configuração (~/.music123rc ou /etc/music123rc) está corrompido." | |
79 | 79 | |
80 | # support_routines.adb | |
80 | # music123.adb | |
81 | 81 | msgid "No valid filenames found." |
82 | msgstr "Não foram encontrados nomes de arquivos válidos." | |
82 | msgstr "Não foram encontrados nomes de arquivos válidos." | |
83 | 83 | |
84 | # support_routines.adb | |
84 | # music123.adb | |
85 | 85 | msgid "Playlist file not found." |
86 | msgstr "Arquivo de playlist não encontrado." | |
86 | msgstr "Arquivo de playlist não encontrado." |
0 | with Ada.Text_IO; | |
1 | with Ada.Characters.Latin_1; | |
2 | with Ada.Environment_Variables; | |
3 | with Ada.Numerics.Discrete_Random; | |
4 | with Ada.Numerics.Float_Random; | |
5 | with Ada.Calendar; | |
6 | with Ada.Strings.Maps; | |
7 | with Ada.Strings.Maps.Constants; | |
8 | with Ada.Directories; | |
9 | with Interfaces.C; | |
10 | ||
11 | with Commands; | |
12 | ||
13 | package body Support_Routines is | |
14 | ||
15 | -- local function and procedures declarations | |
16 | function Matched_Extension (Extension_List : in Tool_List.Vector; | |
17 | Filename : String; | |
18 | Option_Ignore_Extension_Case : Boolean) | |
19 | return Tool; | |
20 | ||
21 | Whitespace : constant Ada.Strings.Maps.Character_Set | |
22 | := Ada.Strings.Maps.To_Set (Sequence => (' ', Ada.Characters.Latin_1.HT)); | |
23 | ||
24 | function Split_Comma (Source : in String) | |
25 | return UString_List.Vector; | |
26 | function Home_Directory return String; | |
27 | function Shell_Fix (File : String) return String; | |
28 | -- end of declarations | |
29 | ||
30 | procedure Error (Error_String : String) is | |
31 | use Ada.Text_IO; | |
32 | begin | |
33 | Put_Line (Standard_Error, N ("music123: ") & Error_String); | |
34 | Put_Line (Standard_Error, Version); | |
35 | Put_Line (Standard_Error, N ("usage: music123 [-hqrvz] files ...")); | |
36 | Put_Line (Standard_Error, N ("-h This help")); | |
37 | Put_Line (Standard_Error, N ("-q Run quiet")); | |
38 | Put_Line (Standard_Error, N ("-i Ignore extension case")); | |
39 | Put_Line (Standard_Error, N ("-L List files and exit")); | |
40 | Put_Line (Standard_Error, N ("-r Recurse over directories")); | |
41 | Put_Line (Standard_Error, N ("-v Print the version and exit")); | |
42 | Put_Line (Standard_Error, N ("-z Randomize the filelist")); | |
43 | New_Line (Standard_Error); | |
44 | Put_Line (Standard_Error, N ("See the manpage for more options.")); | |
45 | end Error; | |
46 | ||
47 | No_Home_Directory : exception; | |
48 | ||
49 | function Home_Directory return String is | |
50 | use Ada.Environment_Variables; | |
51 | begin | |
52 | if Exists ("HOME") then | |
53 | return Value ("HOME"); | |
54 | else | |
55 | raise No_Home_Directory; | |
56 | end if; | |
57 | end Home_Directory; | |
58 | ||
59 | procedure Import_Conffile (Program_List : in out Tool_List.Vector) | |
60 | is | |
61 | use Ada.Text_IO; | |
62 | Error_String : constant String | |
63 | := N ("Neither /etc/music123rc or ~/.music123rc found. Exiting."); | |
64 | Conf_File : File_Type; | |
65 | begin | |
66 | Program_List.Clear; | |
67 | begin | |
68 | Open (Conf_File, In_File, Home_Directory & "/.music123rc"); | |
69 | exception | |
70 | when others => | |
71 | begin | |
72 | Open (Conf_File, In_File, "/etc/music123rc"); | |
73 | exception | |
74 | when others => | |
75 | Error (Error_String); | |
76 | raise Noted_Error; | |
77 | end; | |
78 | end; | |
79 | while not End_Of_File (Conf_File) loop | |
80 | declare | |
81 | Line : constant String := Get_Line (Conf_File); | |
82 | use Ada.Strings.Fixed; | |
83 | P_F, E_F, O_F : Positive; | |
84 | P_L, E_L, O_L : Natural; | |
85 | begin | |
86 | if Head (Line, 4) = "tool" then | |
87 | Find_Token (Source => Line, From => Line'First + 4, | |
88 | Test => Ada.Strings.Outside, Set => Whitespace, | |
89 | First => P_F, Last => P_L); | |
90 | Find_Token (Source => Line, From => P_L + 1, | |
91 | Test => Ada.Strings.Outside, Set => Whitespace, | |
92 | First => E_F, Last => E_L); | |
93 | O_F := Index (Source => Line, From => E_L + 1, | |
94 | Pattern => """") + 1; | |
95 | O_L := Index (Source => Line, From => O_F, Pattern => """") - 1; | |
96 | Program_List.Append | |
97 | ((Program_Length => P_L - P_F + O_L - O_F + 3, | |
98 | Program => Line (P_F .. P_L) & " " | |
99 | & Line (O_F .. O_L), | |
100 | Extension_List => Split_Comma (Line (E_F .. E_L)))); | |
101 | end if; | |
102 | end; | |
103 | end loop; | |
104 | Close (Conf_File); | |
105 | exception | |
106 | when others => | |
107 | if Is_Open (Conf_File) then | |
108 | Close (Conf_File); | |
109 | end if; | |
110 | Put_Line ("Warning: unable to parse configuration file."); | |
111 | raise; | |
112 | end Import_Conffile; | |
113 | ||
114 | Null_Tool : constant Tool := (Program_Length => 9, Program => "/dev/null", | |
115 | Extension_List => UString_List.Empty_Vector); | |
116 | ||
117 | function Matched_Extension (Extension_List : in Tool_List.Vector; | |
118 | Filename : String; | |
119 | Option_Ignore_Extension_Case : Boolean) | |
120 | return Tool is | |
121 | use Ada.Strings.Fixed; | |
122 | use Ada.Strings.Maps; | |
123 | use Ada.Strings.Maps.Constants; | |
124 | Mapping : constant Character_Mapping | |
125 | := (if Option_Ignore_Extension_Case then Lower_Case_Map else Identity); | |
126 | begin | |
127 | for This_Tool of Extension_List loop | |
128 | for Extension of This_Tool.Extension_List loop | |
129 | if Translate (Tail (Filename, Extension'Length), Mapping) | |
130 | = Translate (Extension, Mapping) | |
131 | then | |
132 | return This_Tool; | |
133 | end if; | |
134 | end loop; | |
135 | end loop; | |
136 | return Null_Tool; | |
137 | ||
138 | end Matched_Extension; | |
139 | ||
140 | function Check_Filename (Full_Name : String; | |
141 | Extension_List : Tool_List.Vector; | |
142 | Option_Ignore_Extension_Case : Boolean) | |
143 | return Boolean is | |
144 | use Ada.Directories; | |
145 | begin | |
146 | return Exists (Full_Name) and then | |
147 | (Kind (Full_Name) = Directory or else | |
148 | Matched_Extension (Extension_List, | |
149 | Full_Name, | |
150 | Option_Ignore_Extension_Case) /= Null_Tool); | |
151 | end Check_Filename; | |
152 | ||
153 | procedure Expand_And_Check_Filenames | |
154 | (File_List : in out UString_List.Vector; | |
155 | Option_Recurse : in Boolean; | |
156 | Extension_List : in Tool_List.Vector; | |
157 | Option_Ignore_Extension_Case : in Boolean | |
158 | ) | |
159 | is | |
160 | use Ada.Directories; | |
161 | Temporary_File_List : UString_List.Vector; | |
162 | procedure Check_And_Append (Directory_Entry : in Directory_Entry_Type); | |
163 | procedure Check_And_Append (Directory_Entry : in Directory_Entry_Type) | |
164 | is | |
165 | -- Adding, then removing the file was | |
166 | -- creating a O(N^2) result. Check it first. | |
167 | Simple : constant String := Simple_Name (Directory_Entry); | |
168 | Full_Path : constant String := Full_Name (Directory_Entry); | |
169 | begin | |
170 | if Simple /= "." | |
171 | and then Simple /= ".." | |
172 | and then Check_Filename (Full_Path, | |
173 | Extension_List, | |
174 | Option_Ignore_Extension_Case) | |
175 | then | |
176 | Temporary_File_List.Append (Full_Path); | |
177 | end if; | |
178 | end Check_And_Append; | |
179 | I : Integer; | |
180 | Error_String : constant String := | |
181 | N ("The config file (~/.music123rc or /etc/music123rc) is corrupt."); | |
182 | begin | |
183 | if Extension_List.Is_Empty then | |
184 | Error (Error_String); | |
185 | raise Noted_Error; | |
186 | end if; | |
187 | I := File_List.First_Index; | |
188 | while I <= File_List.Last_Index loop | |
189 | declare | |
190 | Current_File : constant String := File_List.Element (I); | |
191 | begin | |
192 | if not Exists (Current_File) then | |
193 | File_List.Delete (I); | |
194 | elsif Kind (Current_File) = Directory then | |
195 | File_List.Delete (I); | |
196 | if Option_Recurse then | |
197 | begin | |
198 | Temporary_File_List.Clear; | |
199 | Search (Directory => Current_File, | |
200 | Pattern => "", | |
201 | Process => Check_And_Append'Access); | |
202 | File_Sorting.Sort (Temporary_File_List); | |
203 | File_List.Append (Temporary_File_List); | |
204 | Temporary_File_List.Clear; | |
205 | exception | |
206 | -- Name_Error should not happen here | |
207 | when Use_Error => null; -- no recurse after all | |
208 | end; | |
209 | end if; | |
210 | else | |
211 | I := I + 1; | |
212 | end if; | |
213 | end; | |
214 | end loop; | |
215 | if File_List.Is_Empty then | |
216 | Error (N ("No valid filenames found.")); | |
217 | raise Noted_Error; | |
218 | end if; | |
219 | ||
220 | end Expand_And_Check_Filenames; | |
221 | ||
222 | procedure Randomize_Names (File_List : in out UString_List.Vector) is | |
223 | use Ada.Calendar; | |
224 | use Ada.Numerics.Float_Random; | |
225 | J : Positive; | |
226 | Gen : Generator; | |
227 | begin | |
228 | Reset (Gen, Integer (Seconds (Clock) * 10.0)); | |
229 | -- From Knuth, TAOCP vol. 2, edition 3, page 146, 3.4.2, algorithm P | |
230 | for I in reverse File_List.First_Index + 1 .. File_List.Last_Index loop | |
231 | J := Integer | |
232 | (Float'Floor (Random (Gen) | |
233 | * Float (I + File_List.First_Index - 1))) | |
234 | + File_List.First_Index; | |
235 | File_List.Swap (I, J); | |
236 | end loop; | |
237 | end Randomize_Names; | |
238 | ||
239 | function Shell_Fix (File : String) return String is | |
240 | begin | |
241 | if File'Length = 1 then | |
242 | if File = "'" then | |
243 | return "'""'""'"; | |
244 | else | |
245 | return File; | |
246 | end if; | |
247 | elsif File (File'First) = ''' then | |
248 | return "'""'""'" & Shell_Fix (File (File'First + 1 .. File'Last)); | |
249 | else | |
250 | return File (File'First) & | |
251 | Shell_Fix (File (File'First + 1 .. File'Last)); | |
252 | end if; | |
253 | end Shell_Fix; | |
254 | ||
255 | procedure Display_Songs (File_List : in UString_List.Vector) is | |
256 | begin | |
257 | for Song of File_List loop | |
258 | Ada.Text_IO.Put_Line (Song); | |
259 | end loop; | |
260 | end Display_Songs; | |
261 | ||
262 | procedure Play_Songs | |
263 | (File_List : in out UString_List.Vector; | |
264 | Program_List : in Tool_List.Vector; | |
265 | Delay_Length : in Duration; | |
266 | Option_Quiet : in Boolean; | |
267 | Option_Loop : in Boolean; | |
268 | Option_Random : in Boolean; | |
269 | Option_Eternal_Random : in Boolean; | |
270 | Option_Ignore_Extension_Case : in Boolean | |
271 | ) is | |
272 | ||
273 | procedure Play_A_Song (File_Name : in String); | |
274 | procedure Play_A_Song (File_Name : in String) is | |
275 | use Interfaces.C; | |
276 | function System (command : char_array) return int; | |
277 | pragma Import (C, System, "system"); | |
278 | This_Program : constant Tool := Matched_Extension | |
279 | (Program_List, | |
280 | File_Name, | |
281 | Option_Ignore_Extension_Case); | |
282 | System_String : constant String := | |
283 | This_Program.Program & " '" & Shell_Fix (File_Name) & "'" | |
284 | & (if Option_Quiet then " > /dev/null 2> /dev/null" else ""); | |
285 | System_Result : constant int := System (To_C (System_String)); | |
286 | begin | |
287 | if System_Result /= 0 then | |
288 | Ada.Text_IO.Put_Line ("Command """ & System_String | |
289 | & """ exited with non zero status (" | |
290 | & int'Image (System_Result) & ")."); | |
291 | end if; | |
292 | end Play_A_Song; | |
293 | ||
294 | begin | |
295 | if Option_Eternal_Random then | |
296 | declare | |
297 | subtype S is Integer | |
298 | range File_List.First_Index .. File_List.Last_Index; | |
299 | package S_Random is new Ada.Numerics.Discrete_Random (S); | |
300 | use S_Random; | |
301 | use Ada.Calendar; | |
302 | Gen : Generator; | |
303 | begin | |
304 | Reset (Gen, Integer (Seconds (Clock) * 10.0)); | |
305 | while not Commands.Repository.Have_To_Quit loop | |
306 | Play_A_Song (File_List.Element (Random (Gen))); | |
307 | end loop; | |
308 | end; | |
309 | end if; | |
310 | ||
311 | if Option_Random then | |
312 | Randomize_Names (File_List); | |
313 | end if; | |
314 | ||
315 | loop | |
316 | for Song of File_List loop | |
317 | exit when Commands.Repository.Have_To_Quit; | |
318 | Play_A_Song (Song); | |
319 | delay Delay_Length; | |
320 | end loop; | |
321 | exit when Commands.Repository.Have_To_Quit; | |
322 | exit when not Option_Loop; | |
323 | end loop; | |
324 | end Play_Songs; | |
325 | ||
326 | procedure Read_Playlist (Full_Name : String; | |
327 | File_List : in out UString_List.Vector) is | |
328 | use Ada.Text_IO; | |
329 | Playlist : File_Type; | |
330 | begin | |
331 | begin | |
332 | Open (Playlist, In_File, Full_Name); | |
333 | exception | |
334 | when others => | |
335 | Error (N ("Playlist file not found.")); | |
336 | raise Noted_Error; | |
337 | end; | |
338 | while not End_Of_File (Playlist) loop | |
339 | declare | |
340 | Line : constant String := | |
341 | Ada.Strings.Fixed.Trim (Get_Line (Playlist), Ada.Strings.Both); | |
342 | begin | |
343 | if Line /= "" and then Line (1) /= '#' then | |
344 | File_List.Append (Line); | |
345 | end if; | |
346 | end; | |
347 | end loop; | |
348 | Close (Playlist); | |
349 | exception | |
350 | when others => | |
351 | if Is_Open (Playlist) then | |
352 | Close (Playlist); | |
353 | end if; | |
354 | Put_Line ("Warning: unable to parse playlist."); | |
355 | raise; | |
356 | end Read_Playlist; | |
357 | ||
358 | function Split_Comma (Source : in String) | |
359 | return UString_List.Vector is | |
360 | First : Positive := Source'First; | |
361 | Comma_Index : Natural; | |
362 | begin | |
363 | return Result : UString_List.Vector do | |
364 | loop | |
365 | Comma_Index := Ada.Strings.Fixed.Index (Source => Source, | |
366 | Pattern => ",", | |
367 | From => First); | |
368 | exit when Comma_Index = 0; | |
369 | Result.Append ("." & Source (First .. Comma_Index - 1)); | |
370 | First := Comma_Index + 1; | |
371 | end loop; | |
372 | Result.Append ("." & Source (First .. Source'Last)); | |
373 | end return; | |
374 | end Split_Comma; | |
375 | ||
376 | end Support_Routines; |
0 | with Ada.Containers.Indefinite_Vectors; | |
1 | with Ada.Strings.Fixed; | |
2 | ||
3 | with Intl; | |
4 | ||
5 | package Support_Routines is | |
6 | ||
7 | package UString_List is new Ada.Containers.Indefinite_Vectors | |
8 | (Positive, String); | |
9 | package File_Sorting is new UString_List.Generic_Sorting ("<"); | |
10 | ||
11 | function N (Msg : String) return String renames Intl.Gettext; | |
12 | ||
13 | -- Set the major version here. | |
14 | Version_Number : constant String := "16"; | |
15 | ||
16 | -- Translate the format, then replace the major version. | |
17 | Version_Format : constant String | |
18 | := N ("music123 version %d by David Starner"); | |
19 | Version_Index : constant Positive := Ada.Strings.Fixed.Index | |
20 | (Source => Version_Format, | |
21 | Pattern => "%d"); | |
22 | Version : constant String := Ada.Strings.Fixed.Replace_Slice | |
23 | (Source => Version_Format, | |
24 | Low => Version_Index, | |
25 | High => Version_Index + 1, | |
26 | By => Version_Number); | |
27 | ||
28 | Noted_Error : exception; | |
29 | ||
30 | -- The Program field contains the command and its options. | |
31 | type Tool | |
32 | (Program_Length : Natural) is record | |
33 | Program : String (1 .. Program_Length); | |
34 | Extension_List : UString_List.Vector; | |
35 | end record; | |
36 | ||
37 | package Tool_List is new Ada.Containers.Indefinite_Vectors (Positive, Tool); | |
38 | ||
39 | procedure Error (Error_String : String); | |
40 | procedure Import_Conffile (Program_List : in out Tool_List.Vector); | |
41 | procedure Expand_And_Check_Filenames | |
42 | (File_List : in out UString_List.Vector; | |
43 | Option_Recurse : in Boolean; | |
44 | Extension_List : in Tool_List.Vector; | |
45 | Option_Ignore_Extension_Case : in Boolean); | |
46 | procedure Display_Songs (File_List : in UString_List.Vector); | |
47 | procedure Play_Songs | |
48 | (File_List : in out UString_List.Vector; | |
49 | Program_List : in Tool_List.Vector; | |
50 | Delay_Length : in Duration; | |
51 | Option_Quiet : in Boolean; | |
52 | Option_Loop : in Boolean; | |
53 | Option_Random : in Boolean; | |
54 | Option_Eternal_Random : in Boolean; | |
55 | Option_Ignore_Extension_Case : in Boolean); | |
56 | procedure Randomize_Names (File_List : in out UString_List.Vector); | |
57 | procedure Read_Playlist (Full_Name : String; | |
58 | File_List : in out UString_List.Vector); | |
59 | function Check_Filename (Full_Name : String; | |
60 | Extension_List : Tool_List.Vector; | |
61 | Option_Ignore_Extension_Case : Boolean) | |
62 | return Boolean; | |
63 | ||
64 | end Support_Routines; |