Codebase list music123 / b79492c
Recreate license file, moved into Debian subtree by error. Escape minus signs in manpages. Parse options with a more readable case statement. Split extension list once when reading configuration, not for each file name. More error reporting, closed files, exit status reporting. Less dynamic allocations, reinventions of the standard library, duplicate or unused code, dynamic allocations. nicolas.boulenguez 8 years ago
9 changed file(s) with 332 addition(s) and 325 deletion(s). Raw diff Collapse all Expand all
2626 -- executable file might be covered by the GNU Public License. --
2727 -----------------------------------------------------------------------
2828
29 with System;
30 with Interfaces.C.Strings; use Interfaces.C.Strings;
29 with Interfaces.C.Strings;
3130
3231 package body Intl is
3332
33 use Interfaces.C;
34 use Interfaces.C.Strings;
3435
3536 -------------
3637 -- Gettext --
3738 -------------
3839
3940 function Gettext (Msg : String) return String is
40 function Internal (Msg : String) return chars_ptr;
41 function Internal (msgid : in char_array)
42 return chars_ptr;
4143 pragma Import (C, Internal, "gettext");
44 R : constant chars_ptr := Internal (To_C (Msg));
4245 begin
43 return Value (Internal (Msg & ASCII.NUL));
46 if R = Null_Ptr then
47 raise Locale_Error;
48 end if;
49 return Value (R);
4450 end Gettext;
4551
4652 --------------
4854 --------------
4955
5056 function Dgettext (Domain : String; Msg : String) return String is
51 function Internal (Domain, Msg : String) return chars_ptr;
57 function Internal (domainname : in char_array;
58 msgid : in char_array)
59 return chars_ptr;
5260 pragma Import (C, Internal, "dgettext");
61 R : constant chars_ptr := Internal (To_C (Domain), To_C (Msg));
5362 begin
54 return Value (Internal (Domain & ASCII.NUL, Msg & ASCII.NUL));
63 if R = Null_Ptr then
64 raise Locale_Error;
65 end if;
66 return Value (R);
5567 end Dgettext;
5668
5769 ---------------
6173 function Dcgettext
6274 (Domain : String; Msg : String; Category : Integer) return String
6375 is
64 function Internal
65 (Domain, Msg : String; Category : Integer) return chars_ptr;
76 function Internal (domainname : in char_array;
77 msgid : in char_array;
78 category : in int)
79 return chars_ptr;
6680 pragma Import (C, Internal, "dcgettext");
81 R : constant chars_ptr := Internal (To_C (Domain), To_C (Msg),
82 int (Category));
6783 begin
68 return Value (Internal (Domain & ASCII.NUL, Msg & ASCII.NUL, Category));
84 if R = Null_Ptr then
85 raise Locale_Error;
86 end if;
87 return Value (R);
6988 end Dcgettext;
7089
7190 -------------------------
7392 -------------------------
7493
7594 function Default_Text_Domain return String is
76 function Internal (Domain : System.Address) return chars_ptr;
95 function Internal (domainname : in chars_ptr)
96 return chars_ptr;
7797 pragma Import (C, Internal, "textdomain");
98 R : constant chars_ptr := Internal (Null_Ptr);
7899 begin
79 return Value (Internal (System.Null_Address));
100 if R = Null_Ptr then
101 raise Locale_Error;
102 end if;
103 return Value (R);
80104 end Default_Text_Domain;
81105
82106 -----------------
84108 -----------------
85109
86110 procedure Text_Domain (Domain : String := "") is
87 procedure Internal (Domain : String);
111 function Internal (domainname : in char_array)
112 return chars_ptr;
88113 pragma Import (C, Internal, "textdomain");
89114 begin
90 Internal (Domain & ASCII.NUL);
115 if Internal (To_C (Domain)) = Null_Ptr then
116 raise Locale_Error;
117 end if;
91118 end Text_Domain;
92119
93120 ----------------------
95122 ----------------------
96123
97124 procedure Bind_Text_Domain (Domain : String; Dirname : String) is
98 procedure Internal (Domain, Dirname : String);
125 function Internal (domainname : in char_array;
126 dirname : in char_array)
127 return chars_ptr;
99128 pragma Import (C, Internal, "bindtextdomain");
100129 begin
101 Internal (Domain & ASCII.NUL, Dirname & ASCII.NUL);
130 if Internal (To_C (Domain), To_C (Dirname)) = Null_Ptr then
131 raise Locale_Error;
132 end if;
102133 end Bind_Text_Domain;
103134
104135 procedure Set_Locale is
105 procedure Internal (Category : Integer; Locale : String);
136 function Internal (category : in int;
137 locale : in char_array)
138 return chars_ptr;
106139 pragma Import (C, Internal, "setlocale");
107140 LC_ALL : constant := 6;
108141 begin
109 Internal (LC_ALL, "" & ASCII.NUL);
142 if Internal (LC_ALL, To_C ("")) = Null_Ptr then
143 raise Locale_Error;
144 end if;
110145 end Set_Locale;
111146
112147 end Intl;
135135 -- This overrides the default system locale data base.
136136
137137 procedure Set_Locale;
138
139 Locale_Error : exception;
140
138141 end Intl;
0 Copyright: Copyright (C) 2001-2009 David Starner <dvdeug@debian.org>
1 Copyright (C) 2009-2011 Xavier Grave <xavier.grave@ipno.in2p3.fr>
2 License: Expat
3 Permission is hereby granted, free of charge, to any person obtaining a
4 copy of this software and associated documentation files (the "Software"),
5 to deal in the Software without restriction, including without limitation
6 the rights to use, copy, modify, merge, publish, distribute, sublicense,
7 and/or sell copies of the Software, and to permit persons to whom the
8 Software is furnished to do so, subject to the following conditions:
9 .
10 The above copyright notice and this permission notice shall be included in
11 all copies or substantial portions of the Software.
12 .
13 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
16 THE AUTHOR OR ANY CONTRIBUTERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
17 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
18 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
19 DEALINGS IN THE SOFTWARE.
20
21 Files: intl.adb intl.ads
22 Copyright: Copyright (C) 2000 Emmanuel Briot, Joel Brobecker and Arnaud Charlet
23 License: GPL-2 with GNAT exception
24 intl.adb and intl.ads are from libgtkada. They are licensed under the
25 GPL-2, see /usr/share/common-licenses/GPL-2, with the following
26 exception.
27 .
28 As a special exception, if other files instantiate generics from
29 this unit, or you link this unit with other files to produce an
30 executable, this unit does not by itself cause the resulting
31 executable to be covered by the GNU General Public License. This
32 exception does not however invalidate any other reasons why the
33 executable file might be covered by the GNU General Public License.
55 .SH SYNOPSIS
66 .B music123
77 [
8 .B -hqrvz
8 .B \-hqrvz
99 ]
1010 .I file
1111 .B ...
1818 in /etc/music123rc or ~/.music123rc.
1919
2020 .SH OPTIONS
21 .IP -h
21 .IP \-h
2222 Show command help and exit;
23 .IP -q
23 .IP \-q
2424 Quiet mode. No messages are displayed.
25 .IP -r
25 .IP \-r
2626 Recurse into directories, instead of ignoring them.
27 .IP -v
27 .IP \-v
2828 Display version information and exit.
29 .IP -z
29 .IP \-z
3030 Play files in random order.
31 .IP -Z
31 .IP \-Z
3232 Play the files randomly and endlessly.
33 .IP -l
33 .IP \-l
3434 Loop. \-z \-l differs from \-Z in that \-z \-l will randomize, play
3535 through the song list (without repetition) in random order once,
3636 and repeat the songs in that order over and over; \-Z will randomly
3737 play the songs, without any order, and will possibly play a song
3838 right after itself.
39 .IP -i
39 .IP \-i
4040 Ignore extension case.
41 .IP -L
41 .IP \-L
4242 List files and exit.
43 .IP -T
43 .IP \-T
4444 Start a task that handle commands, only one command supported : quit,
4545 using q or Q will quit the application at the end of the current song.
46 .IP -D
46 .IP \-D
4747 Set music123 not to delay between songs. (May make music123 harder to
4848 kill).
49 .IP -d
49 .IP \-d
5050 Customize the time music123 delays between songs. \-d takes one argument,
5151 expressed in seconds, which may have a fractional part.
52 .IP -@
53 Play the files listed in the mandatory argument of -@. Other files can be
52 .IP \-@
53 Play the files listed in the mandatory argument of \-@. Other files can be
5454 added on the command line, and this option can be given several times.
5555 Note that music123 doesn't yet play URLs.
56 .IP --
56 .IP \-\-
5757 End option list.
5858
5959 .SH EXAMPLES
6666
6767 Play a couple of directories and other songs at random:
6868 .RS
69 .B music123 -z -r Rock/ test1.ogg Pop/ test4.wav
69 .B music123 \-z \-r Rock/ test1.ogg Pop/ test4.wav
7070 .RE
7171 .PP
7272
8181
8282 .TP
8383 ~/.music123rc
84 Per-user config file to override the system wide settings.
84 Per\-user config file to override the system wide settings.
8585 .PP
8686
8787 .SH AUTHORS
00 -- music123 by David Starner <dvdeug@debian.org>
1 -- See debian/copyright
21
32 with Ada.Command_Line; use Ada.Command_Line;
4 with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
53 with Ada.Text_IO;
64
75 with Support_Routines; use Support_Routines;
8 with Intl; use Intl;
6 with Intl;
97 with Commands;
108
119 procedure Music123 is
10 Seeing_Minus_Options : Boolean := True;
1211 Arg_Num : Positive;
1312 Option_Task : Boolean := False;
1413 Option_Quiet : Boolean := False;
2322 Program_List : Tool_List.Vector;
2423 Command_Task : Commands.Handler_Task;
2524
26 function N (Msg : String) return String renames Gettext;
2725 begin
28 Set_Locale;
29 Text_Domain ("music123");
30 Bind_Text_Domain ("music123", "/usr/share/locale");
31 Version := To_Unbounded_String
32 (Format_String (N ("music123 version %d by David Starner"), "16"));
26 Intl.Set_Locale;
27 Intl.Text_Domain ("music123");
28 Intl.Bind_Text_Domain ("music123", "/usr/share/locale");
3329
3430 -- Import conffile first
3531 Import_Conffile (Program_List);
3935 Error (N ("No arguments found."));
4036 raise Noted_Error;
4137 end if;
38
4239 Arg_Num := 1;
4340 while Arg_Num <= Argument_Count loop
44 if Argument (Arg_Num) = "-h" then
45 Error ("");
46 Set_Exit_Status (Success);
47 return;
48 elsif Argument (Arg_Num) = "-q" then
49 Option_Quiet := True;
50 elsif Argument (Arg_Num) = "-z" then
51 Option_Random := True;
52 elsif Argument (Arg_Num) = "-Z" then
53 Option_Eternal_Random := True;
54 elsif Argument (Arg_Num) = "-l" then
55 Option_Loop := True;
56 elsif Argument (Arg_Num) = "-r" then
57 Option_Recurse := True;
58 elsif Argument (Arg_Num) = "-i" then
59 Option_Ignore_Extension_Case := True;
60 elsif Argument (Arg_Num) = "-v" then
61 Ada.Text_IO.Put (To_String (Version)); Ada.Text_IO.New_Line;
62 Set_Exit_Status (Success);
63 return;
64 elsif Argument (Arg_Num) = "-D" then
65 Delay_Length := 0.0;
66 elsif Argument (Arg_Num) = "-d" then
67 if Arg_Num < Argument_Count then
68 begin
69 Delay_Length := Duration'Value (Argument (Arg_Num + 1));
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;
7067 Arg_Num := Arg_Num + 1;
71 exception
72 when others =>
73 Error (N ("Bad argument for -d."));
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 -@."));
7481 raise Noted_Error;
75 end;
76 else
77 Error (N ("Missing argument for -d."));
78 raise Noted_Error;
79 end if;
80 elsif Argument (Arg_Num) = "-@" then
81 if Arg_Num < Argument_Count then
82 Read_Playlist (Argument (Arg_Num + 1), File_List);
83 Arg_Num := Arg_Num + 1;
84 else
85 Error (N ("Missing argument for -@."));
86 raise Noted_Error;
87 end if;
88 elsif Argument (Arg_Num) = "-L" then
89 Option_List_Files_Only := True;
90 elsif Argument (Arg_Num) = "-T" then
91 Option_Task := True;
92 elsif Argument (Arg_Num) = "--" then
93 for I in Arg_Num + 1 .. Argument_Count loop
94 if Check_Filename (Argument (I),
95 Program_List,
96 Option_Ignore_Extension_Case) then
97 File_List.Append (Argument (I));
98 end if;
99 end loop;
100 Arg_Num := Argument_Count + 1;
101 elsif Argument (Arg_Num) (1) = '-' then
102 Error (N ("Unknown argument found."));
103 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));
10494 else
105 if Check_Filename (Argument (Arg_Num),
106 Program_List,
107 Option_Ignore_Extension_Case) then
108 File_List.Append (Argument (Arg_Num));
109 end if;
95 Ada.Text_IO.Put_Line ("Ignoring file """ & Argument (Arg_Num) & """");
11096 end if;
11197 Arg_Num := Arg_Num + 1;
11298 end loop;
114100 Expand_And_Check_Filenames (File_List,
115101 Option_Recurse,
116102 Program_List,
117 Option_Ignore_Extension_Case);
103 Option_Ignore_Extension_Case);
118104
119105 if Option_List_Files_Only then
120106 Display_Songs (File_List);
107 Set_Exit_Status (Success);
121108 return;
122109 end if;
123110
139126 Command_Task.Stop;
140127 end if;
141128
129 Set_Exit_Status (Success);
142130 exception
143131 when Noted_Error =>
144132 Set_Exit_Status (Failure);
55 .SH SK£ADNIA
66 .B music123
77 [
8 .B -hqrvz
8 .B \-hqrvz
99 ]
1010 .I plik
1111 .B ...
1818 im przekazywane s± zawarte w plikach /etc/music123rc lub ~/.music123rc.
1919
2020 .SH OPCJE
21 .IP -h
21 .IP \-h
2222 Poka¿ pomoc do polecenia i zakoñcz dzia³anie.
23 .IP -q
23 .IP \-q
2424 Tryb cichy. ¯adne komunikaty nie s± wy¶wietlane.
25 .IP -r
25 .IP \-r
2626 Rekurencyjnie zag³êbiaj siê w katalogi, zamiast je ignorowaæ.
27 .IP -v
27 .IP \-v
2828 Poka¿ informacjê o wersji programu i zakoñcz dzia³anie.
29 .IP -z
29 .IP \-z
3030 Odtwarzaj pliki w losowej kolejno¶ci.
31 .IP -Z
31 .IP \-Z
3232 Odtwarzaj pliki w losowej kolejno¶ci i bez koñca.
33 .IP -l
33 .IP \-l
3434 Pêtla. \-z \-l ró¿ni siê od \-Z tym, ¿e \-z \-l najpierw wylosuje
3535 kolejno¶æ, a nastêpnie bêdzie odtwarza³ pliki w tej¿e kolejno¶ci
3636 raz po raz; \-Z za¶ odtwarza piosenki w losowej kolejno¶ci
3737 pozbawionej jakiegokolwiek porz±dku, w zwiazku z czym istnieje
3838 mo¿liwo¶æ odtworzenia tego samego pliku dwa (lub wiêcej) razy
3939 pod rz±d.
40 .IP -i
40 .IP \-i
4141 Ignore extension case.
42 .IP -L
42 .IP \-L
4343 List files and exit.
44 .IP -T
44 .IP \-T
4545 Start a task that handle commands, only one command supported : quit,
4646 using q or Q will quit the application at the end of the current song.
47 .IP -D
47 .IP \-D
4848 Nie rób przerw miêdzy piosenkami (mo¿e uczyniæ music123 trudniejszym
4949 do zabicia)
50 .IP -d
50 .IP \-d
5151 Ustawia d³ugo¶æ przerw miêdzy piosenkami. \-d przyjmuje jeden argument,
5252 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±
53 .IP \-@
54 Odtwarzaj pliki wymienione w obowi±zkowym argumencie do \-@. Inne pliki mog±
5555 byæ dodane z linii poleceñ. Ta opcja mo¿e byæ podana kilkakrotnie. Zauwa¿,
5656 ¿e music123 jeszcze nie odtwarza URLi.
57 .IP --
57 .IP \-\-
5858 Koniec listy opcji.
5959
6060 .SH PRZYK£ADY
6767
6868 Odtwórz losowo parê katalogów i piosenek:
6969 .RS
70 .B music123 -z -r Rock/ test1.ogg Pop/ test4.wav
70 .B music123 \-z \-r Rock/ test1.ogg Pop/ test4.wav
7171 .RE
7272 .PP
7373
9898 .TP
9999 T³umacze:
100100 .br
101 Grzegorz Ku¶nierz <konik@v-lo.krakow.pl>
101 Grzegorz Ku¶nierz <konik@v\-lo.krakow.pl>
102102 .br
00 # This is the configuration file for music123
11 # A list of music playing programs follow for music123 to use
2 # Format is
2 # Format is
33 # tool name_of_program extension1,extension2,... "options to be given before the file name"
44
55 tool ogg123 ogg,Ogg,OGG ""
1414
1515 # mplayer is a little heavy-weight; you might want to add -q to the options
1616 #tool mplayer ra,wmv ""
17
00 with Ada.Text_IO;
11 with Ada.Characters.Latin_1;
22 with Ada.Environment_Variables;
3 with Ada.Numerics.Float_Random; use Ada.Numerics.Float_Random;
4 with Ada.Calendar; use Ada.Calendar;
5 with Ada.Strings.Fixed;
6 with Ada.Characters.Handling;
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;
78 with Ada.Directories;
8
9 with Intl; use Intl;
109 with Interfaces.C;
1110
1211 with Commands;
1817 Filename : String;
1918 Option_Ignore_Extension_Case : Boolean)
2019 return Tool;
21 function Is_Whitespace (C : Character) return Boolean;
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;
2226 function Home_Directory return String;
2327 function Shell_Fix (File : String) return String;
2428 -- end of declarations
2529
26 function Format_String (Format : String; Insert : String) return String is
27 begin
28 for I in Format'First .. Format'Last - 1 loop
29 if Format (I) = '%' and then Format (I + 1) = 'd' then
30 return Format (Format'First .. I - 1) &
31 Insert & Format (I + 2 .. Format'Last);
32 end if;
33 end loop;
34 return Format; -- XXX Raise exception instead???
35 end Format_String;
36
3730 procedure Error (Error_String : String) is
3831 use Ada.Text_IO;
3932 begin
40 Put (Standard_Error, N ("music123: ") & Error_String);
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"));
4143 New_Line (Standard_Error);
42 Put (Standard_Error, To_String (Version));
43 New_Line (Standard_Error);
44 Put (Standard_Error, N ("usage: music123 [-hqrvz] files ..."));
45 New_Line (Standard_Error);
46 Put (Standard_Error, N ("-h This help"));
47 New_Line (Standard_Error);
48 Put (Standard_Error, N ("-q Run quiet"));
49 New_Line (Standard_Error);
50 Put (Standard_Error, N ("-i Ignore extension case"));
51 New_Line (Standard_Error);
52 Put (Standard_Error, N ("-L List files and exit"));
53 New_Line (Standard_Error);
54 Put (Standard_Error, N ("-r Recurse over directories"));
55 New_Line (Standard_Error);
56 Put (Standard_Error, N ("-v Print the version and exit"));
57 New_Line (Standard_Error);
58 Put (Standard_Error, N ("-z Randomize the filelist"));
59 New_Line (Standard_Error);
60 New_Line (Standard_Error);
61 Put (Standard_Error, N ("See the manpage for more options."));
62 New_Line (Standard_Error);
44 Put_Line (Standard_Error, N ("See the manpage for more options."));
6345 end Error;
6446
6547 No_Home_Directory : exception;
7355 raise No_Home_Directory;
7456 end if;
7557 end Home_Directory;
76
77 function Is_Whitespace (C : Character) return Boolean is
78 begin
79 return (C = ' ') or else (C = Ada.Characters.Latin_1.HT);
80 end Is_Whitespace;
8158
8259 procedure Import_Conffile (Program_List : in out Tool_List.Vector)
8360 is
8562 Error_String : constant String
8663 := N ("Neither /etc/music123rc or ~/.music123rc found. Exiting.");
8764 Conf_File : File_Type;
88 Pointer_Start, Pointer_End : Natural;
8965 begin
9066 Program_List.Clear;
9167 begin
10076 raise Noted_Error;
10177 end;
10278 end;
103 while (not End_Of_File (Conf_File)) loop
79 while not End_Of_File (Conf_File) loop
10480 declare
10581 Line : constant String := Get_Line (Conf_File);
106 This_Tool : Tool;
82 use Ada.Strings.Fixed;
83 P_F, E_F, O_F : Positive;
84 P_L, E_L, O_L : Natural;
10785 begin
108 if Line'Length > 4 and
109 then Line (Line'First .. Line'First + 3) = "tool" then
110 Pointer_Start := Line'First + 4;
111 while Is_Whitespace (Line (Pointer_Start)) loop
112 Pointer_Start := Pointer_Start + 1;
113 end loop;
114 Pointer_End := Pointer_Start;
115 while not Is_Whitespace (Line (Pointer_End + 1)) loop
116 Pointer_End := Pointer_End + 1;
117 end loop;
118 This_Tool.Program :=
119 To_Unbounded_String (Line (Pointer_Start .. Pointer_End));
120 Pointer_Start := Pointer_End + 1;
121 while Is_Whitespace (Line (Pointer_Start)) loop
122 Pointer_Start := Pointer_Start + 1;
123 end loop;
124 Pointer_End := Pointer_Start;
125 while not Is_Whitespace (Line (Pointer_End + 1)) loop
126 Pointer_End := Pointer_End + 1;
127 end loop;
128 This_Tool.Extension_List :=
129 To_Unbounded_String (Line (Pointer_Start .. Pointer_End));
130 Pointer_Start := Pointer_End + 1;
131 while Line (Pointer_Start) /= '"' loop
132 Pointer_Start := Pointer_Start + 1;
133 end loop;
134 Pointer_Start := Pointer_Start + 1;
135 Pointer_End := Pointer_Start;
136 while (Line (Pointer_End) /= '"') loop -- " -- Once again!
137 Pointer_End := Pointer_End + 1;
138 end loop;
139 Pointer_End := Pointer_End - 1;
140 This_Tool.Options :=
141 To_Unbounded_String (Line (Pointer_Start .. Pointer_End));
142 Program_List.Append (This_Tool);
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 + 1,
98 Program => Line (P_F .. P_L),
99 Options_Length => O_L - O_F + 1,
100 Options => Line (O_F .. O_L),
101 Extension_List => Split_Comma (Line (E_F .. E_L))));
143102 end if;
144103 end;
145104 end loop;
146105 Close (Conf_File);
106 exception
107 when others =>
108 if Is_Open (Conf_File) then
109 Close (Conf_File);
110 end if;
111 Put_Line ("Warning: unable to parse configuration file.");
112 raise;
147113 end Import_Conffile;
148114
149 Null_Tool : constant Tool := (To_Unbounded_String ("/dev/null"),
150 Null_Unbounded_String,
151 Null_Unbounded_String);
115 Null_Tool : constant Tool := (Program_Length => 9, Program => "/dev/null",
116 Options_Length => 0, Options => "",
117 Extension_List => UString_List.Empty_Vector);
152118
153119 function Matched_Extension (Extension_List : in Tool_List.Vector;
154120 Filename : String;
155121 Option_Ignore_Extension_Case : Boolean)
156122 return Tool is
157 Pointer_Start, Pointer_End : Natural;
158 begin
159 for I in Extension_List.First_Index .. Extension_List.Last_Index loop
160 declare
161 Ext_List : constant String :=
162 To_String (Extension_List.Element (I).Extension_List);
163 begin
164 Pointer_Start := Ext_List'First;
165 Pointer_End := Ext_List'First;
166 while Pointer_End < Ext_List'Last loop
167
168 while Pointer_End /= Ext_List'Last and then
169 Ext_List (Pointer_End + 1) /= ',' loop
170 Pointer_End := Pointer_End + 1;
171 end loop;
172 declare
173 Extension_String : constant String :=
174 "." & Ext_List (Pointer_Start .. Pointer_End);
175 begin
176 if Filename'Length > Pointer_End - Pointer_Start + 1 then
177 declare
178 End_File_Name : constant String :=
179 Filename (Filename'Last + Pointer_Start -
180 Pointer_End - 1 .. Filename'Last);
181 use Ada.Characters.Handling;
182 begin
183 if End_File_Name = Extension_String then
184 return Extension_List.Element (I);
185 end if;
186 if Option_Ignore_Extension_Case then
187 if To_Lower (End_File_Name) =
188 To_Lower (Extension_String) then
189 return Extension_List.Element (I);
190 end if;
191 end if;
192 end;
193 end if;
194 end;
195 Pointer_Start := Pointer_End + 2;
196 Pointer_End := Pointer_Start;
197
198 end loop;
199 end;
123 use Ada.Strings.Fixed;
124 use Ada.Strings.Maps;
125 use Ada.Strings.Maps.Constants;
126 Mapping : constant Character_Mapping
127 := (if Option_Ignore_Extension_Case then Lower_Case_Map else Identity);
128 begin
129 for This_Tool of Extension_List loop
130 for Extension of This_Tool.Extension_List loop
131 if Translate (Tail (Filename, Extension'Length), Mapping)
132 = Translate (Extension, Mapping)
133 then
134 return This_Tool;
135 end if;
136 end loop;
200137 end loop;
201138 return Null_Tool;
202139
285222 end Expand_And_Check_Filenames;
286223
287224 procedure Randomize_Names (File_List : in out UString_List.Vector) is
288
225 use Ada.Calendar;
226 use Ada.Numerics.Float_Random;
289227 J : Positive;
290228 Gen : Generator;
291229 begin
317255 end Shell_Fix;
318256
319257 procedure Display_Songs (File_List : in UString_List.Vector) is
320 procedure Display_Song (Cursor : UString_List.Cursor);
321 procedure Display_Song (Cursor : UString_List.Cursor) is
322 begin
323 Ada.Text_IO.Put_Line (UString_List.Element (Cursor));
324 end Display_Song;
325 begin
326 UString_List.Iterate (File_List, Display_Song'Access);
258 begin
259 for Song of File_List loop
260 Ada.Text_IO.Put_Line (Song);
261 end loop;
327262 end Display_Songs;
328263
329264 procedure Play_Songs
337272 Option_Ignore_Extension_Case : in Boolean
338273 ) is
339274
340 use Interfaces.C;
341 function System (Command : char_array) return Integer;
342 pragma Import (C, System, "system");
343 procedure Play_A_Song (File_Name : in String;
344 Option_Quiet : in Boolean);
345 procedure Play_A_Song (File_Name : in String;
346 Option_Quiet : in Boolean) is
347 pragma Warnings (Off);
348 System_Result : Integer;
349 pragma Warnings (On);
350 This_Program : Tool;
275 procedure Play_A_Song (File_Name : in String);
276 procedure Play_A_Song (File_Name : in String) is
277 use Interfaces.C;
278 function System (command : char_array) return int;
279 pragma Import (C, System, "system");
280 This_Program : constant Tool := Matched_Extension
281 (Program_List,
282 File_Name,
283 Option_Ignore_Extension_Case);
284 System_String : constant String :=
285 This_Program.Program & " " & This_Program.Options & " '"
286 & Shell_Fix (File_Name) & "'"
287 & (if Option_Quiet then " > /dev/null 2> /dev/null" else "");
288 System_Result : constant int := System (To_C (System_String));
351289 begin
352 This_Program := Matched_Extension (Program_List,
353 File_Name,
354 Option_Ignore_Extension_Case);
355 if Option_Quiet then
356 declare
357 System_String : constant String :=
358 To_String (This_Program.Program & " " &
359 This_Program.Options & " '" &
360 Shell_Fix (File_Name) & "'" &
361 ">/dev/null 2>/dev/null");
362 begin
363 System_Result := System (To_C (System_String));
364 end;
365 else
366 declare
367 System_String : constant String :=
368 To_String (This_Program.Program & " " & This_Program.Options &
369 " '" & Shell_Fix (File_Name) & "'");
370 begin
371 System_Result := System (To_C (System_String));
372 end;
290 if System_Result /= 0 then
291 Ada.Text_IO.Put_Line ("Command """ & System_String
292 & """ exited with non zero status ("
293 & int'Image (System_Result) & ").");
373294 end if;
374295 end Play_A_Song;
375296
376 Gen : Generator;
377297 begin
378298 if Option_Eternal_Random then
379 Reset (Gen, Integer (Seconds (Clock) * 10.0));
380299 declare
381 Len : constant Natural
382 := File_List.Last_Index - File_List.First_Index + 1;
383 Song_Number : Positive;
300 subtype S is Integer
301 range File_List.First_Index .. File_List.Last_Index;
302 package S_Random is new Ada.Numerics.Discrete_Random (S);
303 use S_Random;
304 use Ada.Calendar;
305 Gen : Generator;
384306 begin
385 loop
386 Song_Number :=
387 Integer (Float'Floor (Random (Gen) * Float (Len))) + 1;
388 exit when Commands.Repository.Have_To_Quit;
389 Play_A_Song (File_List.Element (Song_Number),
390 Option_Quiet);
307 Reset (Gen, Integer (Seconds (Clock) * 10.0));
308 while not Commands.Repository.Have_To_Quit loop
309 Play_A_Song (File_List.Element (Random (Gen)));
391310 end loop;
392311 end;
393312 end if;
397316 end if;
398317
399318 loop
400 for I in File_List.First_Index .. File_List.Last_Index loop
319 for Song of File_List loop
401320 exit when Commands.Repository.Have_To_Quit;
402 Play_A_Song (File_List.Element (I), Option_Quiet);
403 delay (Delay_Length);
321 Play_A_Song (Song);
322 delay Delay_Length;
404323 end loop;
405324 exit when Commands.Repository.Have_To_Quit;
406325 exit when not Option_Loop;
419338 Error (N ("Playlist file not found."));
420339 raise Noted_Error;
421340 end;
422 while (not End_Of_File (Playlist)) loop
341 while not End_Of_File (Playlist) loop
423342 declare
424343 Line : constant String :=
425 Ada.Strings.Fixed.Trim (Get_Line (Playlist),
426 Ada.Strings.Both);
344 Ada.Strings.Fixed.Trim (Get_Line (Playlist), Ada.Strings.Both);
427345 begin
428346 if Line /= "" and then Line (1) /= '#' then
429347 File_List.Append (Line);
431349 end;
432350 end loop;
433351 Close (Playlist);
352 exception
353 when others =>
354 if Is_Open (Playlist) then
355 Close (Playlist);
356 end if;
357 Put_Line ("Warning: unable to parse playlist.");
358 raise;
434359 end Read_Playlist;
435360
361 function Split_Comma (Source : in String)
362 return UString_List.Vector is
363 First : Positive := Source'First;
364 Comma_Index : Natural;
365 begin
366 return Result : UString_List.Vector do
367 loop
368 Comma_Index := Ada.Strings.Fixed.Index (Source => Source,
369 Pattern => ",",
370 From => First);
371 exit when Comma_Index = 0;
372 Result.Append ("." & Source (First .. Comma_Index - 1));
373 First := Comma_Index + 1;
374 end loop;
375 Result.Append ("." & Source (First .. Source'Last));
376 end return;
377 end Split_Comma;
378
436379 end Support_Routines;
437
0 with Ada.Containers.Vectors;
10 with Ada.Containers.Indefinite_Vectors;
2 with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
1 with Ada.Strings.Fixed;
2
33 with Intl;
44
55 package Support_Routines is
1010
1111 function N (Msg : String) return String renames Intl.Gettext;
1212
13 Version : Unbounded_String;
13 Version_Number : constant String := "16";
14 Version_Format : constant String
15 := N ("music123 version %d by David Starner");
16 Version : constant String := Ada.Strings.Fixed.Insert
17 (Source => Version_Format,
18 Before => Ada.Strings.Fixed.Index (Version_Format, Pattern => "%d"),
19 New_Item => Version_Number);
1420
1521 Noted_Error : exception;
1622
17 type Tool is record
18 Program : Unbounded_String;
19 Extension_List : Unbounded_String;
20 Options : Unbounded_String;
23 type Tool
24 (Program_Length : Natural;
25 Options_Length : Natural) is record
26 Program : String (1 .. Program_Length);
27 Extension_List : UString_List.Vector;
28 Options : String (1 .. Options_Length);
2129 end record;
2230
23 package Tool_List is new Ada.Containers.Vectors (Positive, Tool);
31 package Tool_List is new Ada.Containers.Indefinite_Vectors (Positive, Tool);
2432
25 function Format_String (Format : String; Insert : String) return String;
2633 procedure Error (Error_String : String);
2734 procedure Import_Conffile (Program_List : in out Tool_List.Vector);
2835 procedure Expand_And_Check_Filenames
4956 return Boolean;
5057
5158 end Support_Routines;
52