emdee_0.2.1_514ac5e1/src/gui-menu.adb

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
--  SPDX-License-Identifier: GPL-3.0-or-later
--  SPDX-FileCopyrightText: Copyright 2024 Stephen Merrony

with Ada.Characters.Latin_1;  use Ada.Characters.Latin_1;
with Ada.Containers;          use Ada.Containers;
with Ada.Directories;
with Ada.Exceptions;          use Ada.Exceptions;
with Ada.Strings;             use Ada.Strings;
with Ada.Strings.Fixed;       use Ada.Strings.Fixed;
with Ada.Strings.Unbounded;   use Ada.Strings.Unbounded;

with Glib;                    use Glib;

with Gtk.About_Dialog;        use Gtk.About_Dialog;
with Gtk.Box;                 use Gtk.Box;
with Gtk.Dialog;              use Gtk.Dialog;
with Gtk.Menu;                use Gtk.Menu;
with Gtk.Menu_Item;           use Gtk.Menu_Item;
with Gtk.Separator_Menu_Item; use Gtk.Separator_Menu_Item;
with Gtk.Widget;              use Gtk.Widget;

with Gtkada.Dialogs;          use Gtkada.Dialogs;
with Gtkada.File_Selection;   use Gtkada.File_Selection;

with Midi_Files;
--  with Players;                 use Players;
with Session;                 use Session;

with GUI.Tracks;              use GUI.Tracks;

package body GUI.Menu is

   function Check_Session_Desc return Boolean is
      Unused_Buttons : Message_Dialog_Buttons;
   begin
      if Session_Desc_Entry.Get_Text /= "" then
         return True;
      else
         Unused_Buttons := Message_Dialog (Msg => "You must enter the Session description, cannot save yet.",
                                           Dialog_Type => Warning,
                                           Title => App_Title & " - Warning");
         return False;
      end if;
   end Check_Session_Desc;

   procedure Session_New_CB (Self : access Gtk.Menu_Item.Gtk_Menu_Item_Record'Class) is
      pragma Unreferenced (Self);
      Prev_MIDI_Port : constant Unbounded_String := Sess.MIDI_Port;
   begin
      Clear_Session;
      Session_Desc_Entry.Set_Text ("");
      Session_Comment_Entry.Set_Text ("");
      Sess.MIDI_Port := Prev_MIDI_Port;
      Track_Modifiers_Check_Item.Set_Active (True);
      Clear_Tracks_Display;
      Display_Empty_Track (1);
      Tracks_Grid.Show_All;
      Session_Desc_Entry.Grab_Focus;
   end Session_New_CB;

   procedure Session_Open_CB (Self : access Gtk.Menu_Item.Gtk_Menu_Item_Record'Class) is
      pragma Unreferenced (Self);
      Filename : constant String :=
         File_Selection_Dialog (Title => App_Title & " Open Session",
                                Dir_Only => False,
                                Must_Exist => True);
      Unused_Buttons : Message_Dialog_Buttons;
   begin
      if Filename'Length > 1 then
         Load_Session (Filename);
         Sess.Filename := To_Unbounded_String (Filename);
         Session_Desc_Entry.Set_Text (To_String (Sess.Desc));
         Session_Comment_Entry.Set_Text (To_String (Sess.Comment));
         if Sess.MIDI_Port /= Null_Unbounded_String then
            Midi_Files.Create_Notes_Off_MIDI;
         end if;
         if Sess.Tracks.Length > 0 then
            Display_Tracks;
         end if;
         GUI.Resize_Font (Font_Size'Value (To_String (Sess.Font_Size)));
      end if;
   exception
      when E : others =>
         Unused_Buttons := Message_Dialog (Msg => "Could not open Session TOML file.  " & Exception_Message (E),
                                           Dialog_Type => Warning,
                                           Title => App_Title & " - Error");
         Sess.Filename := Null_Unbounded_String;
   end Session_Open_CB;

   procedure Session_Save_As is
   --  Helper proc for Save callbacks.
      Filename : constant String :=
         File_Selection_Dialog (Title => App_Title & " - Save Session As...",
                                Dir_Only => False,
                                Must_Exist => False);
      Unused_Buttons : Message_Dialog_Buttons;
   begin
      if Check_Session_Desc then
         if Filename'Length > 0 then
            if Ada.Directories.Exists (Filename) then
               Unused_Buttons := Message_Dialog (Msg => "Session TOML file already exists, " & CR & LF
                                                        & "Use 'Save' to overwrite.",
                                                 Dialog_Type => Warning,
                                                 Title => App_Title & " - Oops");
            else
               Save_Session (Filename);
            end if;
         end if;
      end if;
   end Session_Save_As;

   procedure Session_Save_CB (Self : access Gtk.Menu_Item.Gtk_Menu_Item_Record'Class) is
   --  Save the current session, performs Save As... if not already saved.
      pragma Unreferenced (Self);
      Unused_Buttons : Message_Dialog_Buttons;
   begin
      if Check_Session_Desc then
         if Sess.Filename = Null_Unbounded_String then
            Session_Save_As;
         else
            Save_Session (To_String (Sess.Filename));
         end if;
      end if;
   end Session_Save_CB;

   procedure Session_Save_As_CB (Self : access Gtk.Menu_Item.Gtk_Menu_Item_Record'Class) is
      pragma Unreferenced (Self);
   begin
      Session_Save_As;
   end Session_Save_As_CB;

   procedure Session_Audio_CB (Self : access Gtk.Menu_Item.Gtk_Menu_Item_Record'Class) is
      pragma Unreferenced (Self);
      Dialog         : Gtk_Dialog;
      Dlg_Box        : Gtk_Box;
      Dlg_Silence_Label : Gtk_Label;
      Silence_Entry     : Gtk_Entry;
      Cancel_Unused,
      Save_Unused    : Gtk_Widget;
      Unused_Buttons : Message_Dialog_Buttons;
   begin
      Gtk_New (Dialog);
      Dialog.Set_Destroy_With_Parent (True);
      Dialog.Set_Modal (True);
      Dialog.Set_Title (App_Title & " - Session Audio Settings");
      Dlg_Box := Dialog.Get_Content_Area;
      Dlg_Silence_Label := Gtk_Label_New ("Lead-in Silence (seconds):");
      Dlg_Box.Pack_Start (Child => Dlg_Silence_Label, Expand => True, Fill => True, Padding => 5);
      Silence_Entry := Gtk_Entry_New;
      Silence_Entry.Set_Text (Trim (Sess.Lead_In_Silence'Image, Left));
      Silence_Entry.Set_Tooltip_Text ("Number of seconds silence to play before each audio track. " & CR & LF
                                   & "Must be 0 or a positive integer.");
      Dlg_Box.Pack_Start (Child => Silence_Entry, Expand => True, Fill => True, Padding => 5);
      Cancel_Unused := Dialog.Add_Button ("Cancel", Gtk_Response_Cancel);
      Save_Unused   := Dialog.Add_Button ("Save", Gtk_Response_Accept);
      Dialog.Set_Default_Response (Gtk_Response_Accept);
      Dialog.Show_All;
      if Dialog.Run = Gtk_Response_Accept then
         if Silence_Entry.Get_Text_Length > 0 then
            Sess.Lead_In_Silence := Integer'Value (Silence_Entry.Get_Text);
         end if;
      end if;
      Dialog.Destroy;

   end Session_Audio_CB;

   procedure Session_MIDI_CB (Self : access Gtk.Menu_Item.Gtk_Menu_Item_Record'Class) is
      pragma Unreferenced (Self);
      Dialog         : Gtk_Dialog;
      Dlg_Box        : Gtk_Box;
      Dlg_Port_Label : Gtk_Label;
      Port_Entry     : Gtk_Entry;
      Cancel_Unused,
      Save_Unused    : Gtk_Widget;
      Unused_Buttons : Message_Dialog_Buttons;
   begin
      Gtk_New (Dialog);
      Dialog.Set_Destroy_With_Parent (True);
      Dialog.Set_Modal (True);
      Dialog.Set_Title (App_Title & " - Session MIDI Port");
      Dlg_Box := Dialog.Get_Content_Area;
      Dlg_Port_Label := Gtk_Label_New ("MIDI Out Port:");
      Dlg_Box.Pack_Start (Child => Dlg_Port_Label, Expand => True, Fill => True, Padding => 5);
      Port_Entry := Gtk_Entry_New;
      if Sess.MIDI_Port /= Null_Unbounded_String then
         Port_Entry.Set_Text (To_String (Sess.MIDI_Port));
      end if;
      Port_Entry.Set_Tooltip_Text ("MIDI port suitable for aplaymidi to use in form nn:n. " & CR & LF
                                   & "Use aplaymidi -l to see list");
      Dlg_Box.Pack_Start (Child => Port_Entry, Expand => True, Fill => True, Padding => 5);
      Cancel_Unused := Dialog.Add_Button ("Cancel", Gtk_Response_Cancel);
      Save_Unused   := Dialog.Add_Button ("Save", Gtk_Response_Accept);
      Dialog.Set_Default_Response (Gtk_Response_Accept);
      Dialog.Show_All;
      if Dialog.Run = Gtk_Response_Accept then
         if Port_Entry.Get_Text_Length > 0 then
            Sess.MIDI_Port := To_Unbounded_String (Port_Entry.Get_Text);
         end if;
      end if;
      Dialog.Destroy;
   end Session_MIDI_CB;

   procedure Track_Modifiers_CB (Self : access Gtk_Check_Menu_Item_Record'Class) is
   begin
      Show_Track_Modifiers := Self.Get_Active;
      Display_Tracks;
      Main_Window.Resize (1, 1);
   end Track_Modifiers_CB;

   procedure About_CB (Self : access Gtk.Menu_Item.Gtk_Menu_Item_Record'Class) is
      pragma Unreferenced (Self);
      Dialog : Gtk_About_Dialog;
      Dummy_Response : Gtk_Response_Type;
   begin
      Gtk_New (Dialog);
      Dialog.Set_Destroy_With_Parent (True);
      Dialog.Set_Modal (True);
      Dialog.Set_Logo (Icon_PB);
      Dialog.Set_Authors ([new String'(App_Author)]);
      Dialog.Set_Copyright (App_Copyright);
      Dialog.Set_Comments (App_Comment);
      Dialog.Set_Program_Name (App_Title);
      Dialog.Set_Version (App_SemVer);
      Dialog.Set_Website (App_Website);
      Dummy_Response := Dialog.Run;
      Dialog.Destroy;
   end About_CB;

   procedure Quit_CB (Self : access Gtk.Menu_Item.Gtk_Menu_Item_Record'Class) is
      pragma Unreferenced (Self);
   begin
      if Really_Quit then
         --  Removing the main window closes the application...
         App.Remove_Window (Main_Window);
      end if;
   end Quit_CB;

   procedure View_Size_CB (Self : access Gtk_Check_Menu_Item_Record'Class) is
      pragma Unreferenced (Self);
      New_Size : Font_Size;
   begin
      if View_S_Radio_Item.Get_Active then
         New_Size := S;
      elsif View_M_Radio_Item.Get_Active then
         New_Size := M;
      elsif View_L_Radio_Item.Get_Active then
         New_Size := L;
      elsif View_XL_Radio_Item.Get_Active then
         New_Size := XL;
      elsif View_XXL_Radio_Item.Get_Active then
         New_Size := XXL;
      end if;
      GUI.Resize_Font (New_Size);
   end View_Size_CB;

   function Create_Menu_Bar return Gtk_Menu_Bar is
      Menu_Bar    : Gtk_Menu_Bar;
      Sep_Item    : Gtk_Separator_Menu_Item;
      File_Menu, View_Menu, Session_Menu, Help_Menu : Gtk_Menu;
      Menu_Item   : Gtk_Menu_Item;
      Session_Open_Item, Session_Save_Item, Session_Save_As_Item, Session_New_Item, 
      Session_Audio_Item, Session_MIDI_Item,
      Quit_Item   : Gtk_Menu_Item;
      Group       : Widget_SList.GSlist;
      About_Item  : Gtk_Menu_Item;
   begin
      --  Log (DEBUG, "Starting to Create_Menu_Bar");
      Gtk_New (Menu_Bar);

      --  File

      Gtk_New (Menu_Item, "File");
      Menu_Bar.Append (Menu_Item);
      Gtk_New (File_Menu);
      Menu_Item.Set_Submenu (File_Menu);

      --  Session New
      Gtk_New (Session_New_Item, "New Session");
      File_Menu.Append (Session_New_Item);
      Session_New_Item.On_Activate (Session_New_CB'Access);

      --  Session Open
      Gtk_New (Session_Open_Item, "Open Session");
      File_Menu.Append (Session_Open_Item);
      Session_Open_Item.On_Activate (Session_Open_CB'Access);

      Gtk_New (Sep_Item);
      File_Menu.Append (Sep_Item);

      --  Session Save
      Gtk_New (Session_Save_Item, "Save Session");
      File_Menu.Append (Session_Save_Item);
      Session_Save_Item.On_Activate (Session_Save_CB'Access);

      --  Session Save As
      Gtk_New (Session_Save_As_Item, "Save Session As...");
      File_Menu.Append (Session_Save_As_Item);
      Session_Save_As_Item.On_Activate (Session_Save_As_CB'Access);

      Gtk_New (Sep_Item);
      File_Menu.Append (Sep_Item);

      Gtk_New (Quit_Item, "Quit");
      File_Menu.Append (Quit_Item);
      Quit_Item.On_Activate (Quit_CB'Access);

      --  View

      Gtk_New (Menu_Item, "View");
      Menu_Bar.Append (Menu_Item);
      Gtk_New (View_Menu);
      Menu_Item.Set_Submenu (View_Menu);

      View_S_Radio_Item := Gtk_Radio_Menu_Item_New_With_Label (Widget_SList.Null_List, "Small");
      View_Menu.Append (View_S_Radio_Item);
      View_S_Radio_Item.On_Toggled (View_Size_CB'Access);
      Group := Gtk.Radio_Menu_Item.Get_Group (View_S_Radio_Item);

      View_M_Radio_Item := Gtk_Radio_Menu_Item_New_With_Label (Group, "Medium");
      View_Menu.Append (View_M_Radio_Item);
      View_M_Radio_Item.On_Toggled (View_Size_CB'Access);
      View_M_Radio_Item.Set_Active (True);
      View_L_Radio_Item := Gtk_Radio_Menu_Item_New_With_Label (Group, "Large");
      View_Menu.Append (View_L_Radio_Item);
      View_L_Radio_Item.On_Toggled (View_Size_CB'Access);
      View_XL_Radio_Item := Gtk_Radio_Menu_Item_New_With_Label (Group, "X-Large");
      View_Menu.Append (View_XL_Radio_Item);
      View_XL_Radio_Item.On_Toggled (View_Size_CB'Access);
      View_XXL_Radio_Item := Gtk_Radio_Menu_Item_New_With_Label (Group, "XX-Large");
      View_Menu.Append (View_XXL_Radio_Item);
      View_XXL_Radio_Item.On_Toggled (View_Size_CB'Access);

      Gtk_New (Sep_Item);
      View_Menu.Append (Sep_Item);

      --  Modifiers visibility
      Gtk_New (Track_Modifiers_Check_Item, "Track Editing");
      Track_Modifiers_Check_Item.Set_Active (Show_Track_Modifiers);
      View_Menu.Append (Track_Modifiers_Check_Item);
      Track_Modifiers_Check_Item.On_Toggled (Track_Modifiers_CB'Access);

      --  Session

      Gtk_New (Menu_Item, "Session");
      Menu_Bar.Append (Menu_Item);
      Gtk_New (Session_Menu);
      Menu_Item.Set_Submenu (Session_Menu);

      --  Session Audio Settings
      Gtk_New (Session_Audio_Item, "Audio Settings");
      Session_Menu.Append (Session_Audio_Item);
      Session_Audio_Item.On_Activate (Session_Audio_CB'Access);

      --  Session MIDI Settings
      Gtk_New (Session_MIDI_Item, "MIDI Settings");
      Session_Menu.Append (Session_MIDI_Item);
      Session_MIDI_Item.On_Activate (Session_MIDI_CB'Access);

      --  Help

      Gtk_New (Menu_Item, "Help");
      Menu_Bar.Append (Menu_Item);
      Gtk_New (Help_Menu);
      Menu_Item.Set_Submenu (Help_Menu);
      --  About
      Gtk_New (About_Item, "About");
      Help_Menu.Append (About_Item);
      About_Item.On_Activate (About_CB'Access);

      return Menu_Bar;
   end Create_Menu_Bar;

end GUI.Menu;