2010-07-25 21:55:08 -04:00
/*
Copyright ( C ) 2010 Paul Davis
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 2 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
2010-11-13 00:14:48 -05:00
# ifdef WAF_BUILD
# include "gtk2ardour-config.h"
2014-09-06 11:59:53 -04:00
# include "gtk2ardour-version.h"
2010-11-13 00:14:48 -05:00
# endif
2009-04-20 14:41:46 -04:00
# include <fstream>
2009-03-04 18:06:18 -05:00
# include <algorithm>
# include <gtkmm/main.h>
2009-03-15 18:17:03 -04:00
# include <gtkmm/filechooser.h>
2009-03-04 18:06:18 -05:00
# include "pbd/failed_constructor.h"
# include "pbd/file_utils.h"
2009-04-21 21:35:31 -04:00
# include "pbd/replace_all.h"
2010-09-14 11:45:21 -04:00
# include "pbd/whitespace.h"
2012-12-27 11:40:39 -05:00
# include "pbd/stacktrace.h"
2013-03-09 08:44:22 -05:00
# include "pbd/openuri.h"
2009-03-04 18:06:18 -05:00
2013-08-03 16:37:10 -04:00
# include "ardour/audioengine.h"
2009-03-04 18:06:18 -05:00
# include "ardour/filesystem_paths.h"
# include "ardour/recent_sessions.h"
# include "ardour/session.h"
# include "ardour/session_state_utils.h"
# include "ardour/template_utils.h"
2012-06-23 01:07:05 -04:00
# include "ardour/filename_extensions.h"
2009-03-04 18:06:18 -05:00
2012-03-15 08:04:00 -04:00
# include "ardour_ui.h"
2009-03-04 18:06:18 -05:00
# include "startup.h"
2009-04-21 21:35:31 -04:00
# include "opts.h"
2009-04-20 14:41:46 -04:00
# include "engine_dialog.h"
2009-03-04 18:06:18 -05:00
# include "i18n.h"
2010-09-19 13:10:43 -04:00
# include "utils.h"
2009-03-04 18:06:18 -05:00
using namespace std ;
using namespace Gtk ;
using namespace Gdk ;
using namespace Glib ;
using namespace PBD ;
using namespace ARDOUR ;
2014-06-25 15:27:37 -04:00
using namespace ARDOUR_UI_UTILS ;
2009-03-04 18:06:18 -05:00
ArdourStartup * ArdourStartup : : the_startup = 0 ;
2009-04-21 21:35:31 -04:00
static string poor_mans_glob ( string path )
{
string copy = path ;
replace_all ( copy , " ~ " , Glib : : get_home_dir ( ) ) ;
return copy ;
}
2009-10-14 12:10:01 -04:00
2013-09-23 14:41:52 -04:00
ArdourStartup : : ArdourStartup ( )
2009-12-01 08:23:27 -05:00
: _response ( RESPONSE_OK )
2012-11-08 10:54:16 -05:00
, config_modified ( false )
, default_dir_chooser ( 0 )
2013-02-05 13:18:35 -05:00
, monitor_via_hardware_button ( string_compose ( _ ( " Use an external mixer or the hardware mixer of your audio interface. \n "
" %1 will play NO role in monitoring " ) , PROGRAM_NAME ) )
2012-01-17 21:22:37 -05:00
, monitor_via_ardour_button ( string_compose ( _ ( " Ask %1 to play back material as it is being recorded " ) , PROGRAM_NAME ) )
2012-11-08 10:54:16 -05:00
, audio_page_index ( - 1 )
, new_user_page_index ( - 1 )
, default_folder_page_index ( - 1 )
, monitoring_page_index ( - 1 )
, final_page_index ( - 1 )
2009-03-04 18:06:18 -05:00
{
2013-09-23 14:41:52 -04:00
set_keep_above ( true ) ;
set_position ( WIN_POS_CENTER ) ;
set_border_width ( 12 ) ;
if ( ( icon_pixbuf = : : get_icon ( " ardour_icon_48px " ) ) = = 0 ) {
throw failed_constructor ( ) ;
}
list < Glib : : RefPtr < Gdk : : Pixbuf > > window_icons ;
Glib : : RefPtr < Gdk : : Pixbuf > icon ;
if ( ( icon = : : get_icon ( " ardour_icon_16px " ) ) ! = 0 ) {
window_icons . push_back ( icon ) ;
}
if ( ( icon = : : get_icon ( " ardour_icon_22px " ) ) ! = 0 ) {
window_icons . push_back ( icon ) ;
}
if ( ( icon = : : get_icon ( " ardour_icon_32px " ) ) ! = 0 ) {
window_icons . push_back ( icon ) ;
}
if ( ( icon = : : get_icon ( " ardour_icon_48px " ) ) ! = 0 ) {
window_icons . push_back ( icon ) ;
}
if ( ! window_icons . empty ( ) ) {
set_default_icon_list ( window_icons ) ;
}
2012-11-08 10:54:16 -05:00
2013-01-30 07:56:11 -05:00
# ifdef __APPLE__
2013-09-23 14:41:52 -04:00
setup_prerelease_page ( ) ;
2013-01-30 07:56:11 -05:00
# endif
2013-09-23 14:41:52 -04:00
setup_new_user_page ( ) ;
setup_first_time_config_page ( ) ;
setup_monitoring_choice_page ( ) ;
setup_monitor_section_choice_page ( ) ;
setup_final_page ( ) ;
2009-03-04 18:06:18 -05:00
the_startup = this ;
}
ArdourStartup : : ~ ArdourStartup ( )
{
}
2012-11-08 10:54:16 -05:00
bool
2013-09-23 14:41:52 -04:00
ArdourStartup : : required ( )
2012-11-08 10:54:16 -05:00
{
2013-09-23 14:41:52 -04:00
return ! Glib : : file_test ( been_here_before_path ( ) , Glib : : FILE_TEST_EXISTS ) ;
}
std : : string
ArdourStartup : : been_here_before_path ( )
{
// XXXX use more specific version so we can catch upgrades
return Glib : : build_filename ( user_config_directory ( ) , " .a3 " ) ;
2012-11-08 10:54:16 -05:00
}
2011-03-13 14:17:42 -04:00
void
2011-11-11 15:09:14 -05:00
ArdourStartup : : setup_prerelease_page ( )
2011-03-13 14:17:42 -04:00
{
2013-07-15 13:48:33 -04:00
VBox * vbox = manage ( new VBox ) ;
Label * label = manage ( new Label ) ;
2013-07-15 14:00:35 -04:00
label - > set_markup ( string_compose ( _ ( " <b>Welcome to this BETA release of Ardour %1</b> \n \n \
Ardour % 1 has been released for Linux but because of the lack of testers , \ n \
2013-01-30 07:56:11 -05:00
it is still at the beta stage on OS X . So , a few guidelines : \ n \
2011-03-13 14:17:42 -04:00
\ n \
1 ) Please do < b > NOT < / b > use this software with the expectation that it is stable or reliable \ n \
though it may be so , depending on your workflow . \ n \
2013-07-15 13:42:09 -04:00
2 ) < b > Please do NOT use the forums at ardour . org to report issues < / b > . \ n \
3 ) Please < b > DO < / b > use the bugtracker at http : / / tracker . ardour . org / to report issues \ n \
2013-07-15 14:00:35 -04:00
making sure to note the product version number as % 1 - beta . \ n \
2013-07-15 13:42:09 -04:00
4 ) Please < b > DO < / b > use the ardour - users mailing list to discuss ideas and pass on comments . \ n \
5 ) Please < b > DO < / b > join us on IRC for real time discussions about ardour3 . You \ n \
2011-03-13 14:17:42 -04:00
can get there directly from Ardour via the Help - > Chat menu option . \ n \
\ n \
Full information on all the above can be found on the support page at \ n \
\ n \
http : / / ardour . org / support \ n \
2013-07-15 14:00:35 -04:00
" ), VERSIONSTRING));
2011-03-13 14:17:42 -04:00
2013-07-15 13:48:33 -04:00
vbox - > set_border_width ( 12 ) ;
vbox - > pack_start ( * label , false , false , 12 ) ;
vbox - > show_all ( ) ;
append_page ( * vbox ) ;
set_page_type ( * vbox , ASSISTANT_PAGE_CONTENT ) ;
set_page_title ( * vbox , _ ( " This is a BETA RELEASE " ) ) ;
2011-03-13 14:17:42 -04:00
set_page_complete ( * vbox , true ) ;
}
2009-03-04 18:06:18 -05:00
void
ArdourStartup : : setup_new_user_page ( )
{
2009-04-20 14:41:46 -04:00
Label * foomatic = manage ( new Label ) ;
2010-03-14 22:31:27 -04:00
foomatic - > set_markup ( string_compose ( _ ( " \
2011-12-08 07:05:32 -05:00
< span size = \ " larger \" >%1 is a digital audio workstation. You can use it to \
record , edit and mix multi - track audio . You can produce your \
2012-01-18 11:56:05 -05:00
own CDs , mix video soundtracks , or experiment with new \
2011-12-08 07:05:32 -05:00
ideas about music and sound . \
\ n \ n \
There are a few things that need to be configured before you start \
using the program . < / span > \
2010-03-14 22:31:27 -04:00
" ), PROGRAM_NAME));
2011-12-08 07:05:32 -05:00
foomatic - > set_justify ( JUSTIFY_FILL ) ;
foomatic - > set_line_wrap ( ) ;
2009-10-14 12:10:01 -04:00
2009-03-04 18:06:18 -05:00
HBox * hbox = manage ( new HBox ) ;
HBox * vbox = manage ( new HBox ) ;
2009-06-25 16:46:39 -04:00
vbox - > set_border_width ( 24 ) ;
2009-03-04 18:06:18 -05:00
2009-06-25 16:46:39 -04:00
hbox - > pack_start ( * foomatic , true , true ) ;
vbox - > pack_start ( * hbox , true , true ) ;
2009-03-04 18:06:18 -05:00
foomatic - > show ( ) ;
hbox - > show ( ) ;
vbox - > show ( ) ;
2009-04-20 14:41:46 -04:00
new_user_page_index = append_page ( * vbox ) ;
2009-03-04 18:06:18 -05:00
set_page_type ( * vbox , ASSISTANT_PAGE_INTRO ) ;
2010-08-16 20:28:20 -04:00
set_page_title ( * vbox , string_compose ( _ ( " Welcome to %1 " ) , PROGRAM_NAME ) ) ;
2009-03-04 18:06:18 -05:00
set_page_header_image ( * vbox , icon_pixbuf ) ;
set_page_complete ( * vbox , true ) ;
}
2009-04-20 14:41:46 -04:00
void
ArdourStartup : : default_dir_changed ( )
{
2011-08-03 07:14:31 -04:00
Config - > set_default_session_parent_dir ( default_dir_chooser - > get_filename ( ) ) ;
2012-03-15 08:04:00 -04:00
// make new session folder chooser point to the new default
2012-04-06 06:36:33 -04:00
new_folder_chooser . set_current_folder ( Config - > get_default_session_parent_dir ( ) ) ;
2010-11-25 15:37:39 -05:00
config_changed ( ) ;
2010-03-21 23:46:09 -04:00
}
void
ArdourStartup : : config_changed ( )
{
2009-04-20 14:41:46 -04:00
config_modified = true ;
}
2009-03-04 18:06:18 -05:00
void
ArdourStartup : : setup_first_time_config_page ( )
{
2010-03-14 22:31:27 -04:00
default_dir_chooser = manage ( new FileChooserButton ( string_compose ( _ ( " Default folder for %1 sessions " ) , PROGRAM_NAME ) ,
2009-04-20 14:41:46 -04:00
FILE_CHOOSER_ACTION_SELECT_FOLDER ) ) ;
2009-03-04 18:06:18 -05:00
Gtk : : Label * txt = manage ( new Label ) ;
2009-06-25 16:46:39 -04:00
HBox * hbox = manage ( new HBox ) ;
2009-03-04 18:06:18 -05:00
VBox * vbox = manage ( new VBox ) ;
2009-10-14 12:10:01 -04:00
2010-08-16 20:28:20 -04:00
txt - > set_markup ( string_compose ( _ ( " \
Each project that you work on with % 1 has its own folder . \ n \
2009-03-04 18:06:18 -05:00
These can require a lot of disk space if you are recording audio . \ n \
\ n \
2010-08-16 20:28:20 -04:00
Where would you like new % 1 sessions to be stored by default ? \ n \ n \
< i > ( You can put new sessions anywhere , this is just a default ) < / i > " ), PROGRAM_NAME));
2009-06-25 16:46:39 -04:00
txt - > set_alignment ( 0.0 , 0.0 ) ;
2009-03-04 18:06:18 -05:00
2009-06-25 16:46:39 -04:00
vbox - > set_spacing ( 18 ) ;
vbox - > set_border_width ( 24 ) ;
2009-03-04 18:06:18 -05:00
2009-06-25 16:46:39 -04:00
hbox - > pack_start ( * default_dir_chooser , false , true , 8 ) ;
vbox - > pack_start ( * txt , false , false ) ;
vbox - > pack_start ( * hbox , false , true ) ;
2009-03-04 18:06:18 -05:00
2013-10-15 12:37:13 -04:00
cerr < < " set default folder to " < < poor_mans_glob ( Config - > get_default_session_parent_dir ( ) ) < < endl ;
2009-04-21 21:35:31 -04:00
default_dir_chooser - > set_current_folder ( poor_mans_glob ( Config - > get_default_session_parent_dir ( ) ) ) ;
2009-12-11 18:29:48 -05:00
default_dir_chooser - > signal_current_folder_changed ( ) . connect ( sigc : : mem_fun ( * this , & ArdourStartup : : default_dir_changed ) ) ;
2009-04-20 14:41:46 -04:00
default_dir_chooser - > show ( ) ;
2009-06-25 16:46:39 -04:00
vbox - > show_all ( ) ;
2009-03-04 18:06:18 -05:00
2009-04-20 14:41:46 -04:00
default_folder_page_index = append_page ( * vbox ) ;
2009-03-04 18:06:18 -05:00
set_page_title ( * vbox , _ ( " Default folder for new sessions " ) ) ;
set_page_header_image ( * vbox , icon_pixbuf ) ;
set_page_type ( * vbox , ASSISTANT_PAGE_CONTENT ) ;
/* user can just skip all these settings if they want to */
set_page_complete ( * vbox , true ) ;
}
2009-04-15 14:04:23 -04:00
void
ArdourStartup : : setup_monitoring_choice_page ( )
{
2009-06-25 16:46:39 -04:00
mon_vbox . set_spacing ( 18 ) ;
mon_vbox . set_border_width ( 24 ) ;
2009-10-14 12:10:01 -04:00
2009-06-25 16:46:39 -04:00
HBox * hbox = manage ( new HBox ) ;
VBox * vbox = manage ( new VBox ) ;
2012-12-26 11:37:31 -05:00
/* first button will be on by default */
RadioButton : : Group g ( monitor_via_ardour_button . get_group ( ) ) ;
monitor_via_hardware_button . set_group ( g ) ;
2009-04-15 14:04:23 -04:00
2010-12-16 16:25:17 -05:00
monitor_label . set_markup ( _ ( " \
2009-04-15 14:04:23 -04:00
While recording instruments or vocals , you probably want to listen to the \ n \
signal as well as record it . This is called \ " monitoring \" . There are \n \
different ways to do this depending on the equipment you have and the \ n \
configuration of that equipment . The two most common are presented here . \ n \
Please choose whichever one is right for your setup . \ n \ n \
2012-01-18 19:14:05 -05:00
< i > ( You can change this preference at any time , via the Preferences dialog ) < / i > \ n \ n \
< i > If you do not understand what this is about , just accept the default . < / i > " ));
2009-06-25 16:46:39 -04:00
monitor_label . set_alignment ( 0.0 , 0.0 ) ;
vbox - > set_spacing ( 6 ) ;
2009-04-15 14:04:23 -04:00
2009-06-25 16:46:39 -04:00
vbox - > pack_start ( monitor_via_hardware_button , false , true ) ;
vbox - > pack_start ( monitor_via_ardour_button , false , true ) ;
hbox - > pack_start ( * vbox , true , true , 8 ) ;
2009-04-20 14:41:46 -04:00
mon_vbox . pack_start ( monitor_label , false , false ) ;
2009-06-25 16:46:39 -04:00
mon_vbox . pack_start ( * hbox , false , false ) ;
2009-04-15 14:04:23 -04:00
2009-06-25 16:46:39 -04:00
mon_vbox . show_all ( ) ;
2009-04-15 14:04:23 -04:00
2009-04-20 14:41:46 -04:00
monitoring_page_index = append_page ( mon_vbox ) ;
2009-04-15 14:04:23 -04:00
set_page_title ( mon_vbox , _ ( " Monitoring Choices " ) ) ;
set_page_header_image ( mon_vbox , icon_pixbuf ) ;
/* user could just click on "Forward" if default
* choice is correct .
*/
set_page_complete ( mon_vbox , true ) ;
}
2010-03-21 23:22:28 -04:00
void
ArdourStartup : : setup_monitor_section_choice_page ( )
{
mon_sec_vbox . set_spacing ( 18 ) ;
mon_sec_vbox . set_border_width ( 24 ) ;
HBox * hbox = manage ( new HBox ) ;
2010-06-29 16:39:44 -04:00
VBox * main_vbox = manage ( new VBox ) ;
VBox * vbox ;
2010-11-25 15:37:39 -05:00
Label * l = manage ( new Label ) ;
2010-06-29 16:39:44 -04:00
main_vbox - > set_spacing ( 32 ) ;
2010-11-25 15:37:39 -05:00
no_monitor_section_button . set_label ( _ ( " Use a Master bus directly " ) ) ;
l - > set_alignment ( 0.0 , 1.0 ) ;
2012-01-18 19:14:05 -05:00
l - > set_markup ( _ ( " Connect the Master bus directly to your hardware outputs. This is preferable for simple usage. " ) ) ;
2010-06-29 16:39:44 -04:00
2010-11-25 15:37:39 -05:00
vbox = manage ( new VBox ) ;
2010-06-29 16:39:44 -04:00
vbox - > set_spacing ( 6 ) ;
vbox - > pack_start ( no_monitor_section_button , false , true ) ;
vbox - > pack_start ( * l , false , true ) ;
2010-11-25 15:37:39 -05:00
main_vbox - > pack_start ( * vbox , false , false ) ;
2010-06-29 16:39:44 -04:00
2010-11-25 15:37:39 -05:00
use_monitor_section_button . set_label ( _ ( " Use an additional Monitor bus " ) ) ;
l = manage ( new Label ) ;
l - > set_alignment ( 0.0 , 1.0 ) ;
l - > set_text ( _ ( " Use a Monitor bus between Master bus and hardware outputs for \n \
2010-06-29 16:39:44 -04:00
greater control in monitoring without affecting the mix . " ));
2010-11-25 15:37:39 -05:00
vbox = manage ( new VBox ) ;
2010-06-29 16:39:44 -04:00
vbox - > set_spacing ( 6 ) ;
vbox - > pack_start ( use_monitor_section_button , false , true ) ;
vbox - > pack_start ( * l , false , true ) ;
2010-11-25 15:37:39 -05:00
main_vbox - > pack_start ( * vbox , false , false ) ;
2010-06-29 16:39:44 -04:00
2010-03-21 23:22:28 -04:00
RadioButton : : Group g ( use_monitor_section_button . get_group ( ) ) ;
no_monitor_section_button . set_group ( g ) ;
2010-03-21 23:46:09 -04:00
2010-11-25 15:37:39 -05:00
if ( Config - > get_use_monitor_bus ( ) ) {
use_monitor_section_button . set_active ( true ) ;
} else {
no_monitor_section_button . set_active ( true ) ;
}
use_monitor_section_button . signal_toggled ( ) . connect ( sigc : : mem_fun ( * this , & ArdourStartup : : config_changed ) ) ;
no_monitor_section_button . signal_toggled ( ) . connect ( sigc : : mem_fun ( * this , & ArdourStartup : : config_changed ) ) ;
2010-03-21 23:46:09 -04:00
2012-05-12 14:53:25 -04:00
monitor_section_label . set_markup ( _ ( " <i>You can change this preference at any time via the Preferences dialog. \n You can also add or remove the monitor section to/from any session.</i> \n \n \
2012-01-18 19:14:05 -05:00
< i > If you do not understand what this is about , just accept the default . < / i > " ));
2010-03-21 23:22:28 -04:00
monitor_section_label . set_alignment ( 0.0 , 0.0 ) ;
2010-06-29 16:39:44 -04:00
hbox - > pack_start ( * main_vbox , true , true , 8 ) ;
2010-03-21 23:22:28 -04:00
mon_sec_vbox . pack_start ( * hbox , false , false ) ;
2010-06-29 16:39:44 -04:00
mon_sec_vbox . pack_start ( monitor_section_label , false , false ) ;
2010-03-21 23:22:28 -04:00
mon_sec_vbox . show_all ( ) ;
monitor_section_page_index = append_page ( mon_sec_vbox ) ;
set_page_title ( mon_sec_vbox , _ ( " Monitor Section " ) ) ;
set_page_header_image ( mon_sec_vbox , icon_pixbuf ) ;
/* user could just click on "Forward" if default
* choice is correct .
*/
set_page_complete ( mon_sec_vbox , true ) ;
}
2009-03-04 18:06:18 -05:00
void
ArdourStartup : : setup_final_page ( )
{
2013-09-23 14:41:52 -04:00
string msg = string_compose ( _ ( " %1 is ready for use " ) , PROGRAM_NAME ) ;
final_page . set_markup ( string_compose ( " <span weight= \" bold \" size= \" large \" >%1</span> " , msg ) ) ;
2009-03-04 18:06:18 -05:00
final_page . show ( ) ;
2009-04-20 14:41:46 -04:00
final_page_index = append_page ( final_page ) ;
2009-03-04 18:06:18 -05:00
set_page_complete ( final_page , true ) ;
set_page_header_image ( final_page , icon_pixbuf ) ;
set_page_type ( final_page , ASSISTANT_PAGE_CONFIRM ) ;
}
void
ArdourStartup : : on_cancel ( )
{
2009-12-01 08:23:27 -05:00
_response = RESPONSE_CANCEL ;
2009-10-19 14:12:20 -04:00
gtk_main_quit ( ) ;
2009-03-04 18:06:18 -05:00
}
2009-12-01 08:23:27 -05:00
bool
ArdourStartup : : on_delete_event ( GdkEventAny * )
2009-03-04 18:06:18 -05:00
{
2009-12-01 08:23:27 -05:00
_response = RESPONSE_CLOSE ;
2009-10-19 14:12:20 -04:00
gtk_main_quit ( ) ;
2009-12-01 08:23:27 -05:00
return true ;
2009-03-04 18:06:18 -05:00
}
void
ArdourStartup : : on_apply ( )
{
2009-04-20 14:41:46 -04:00
if ( config_modified ) {
if ( default_dir_chooser ) {
2011-08-03 07:14:31 -04:00
Config - > set_default_session_parent_dir ( default_dir_chooser - > get_filename ( ) ) ;
2009-04-20 14:41:46 -04:00
}
2009-10-14 12:10:01 -04:00
2009-04-20 14:41:46 -04:00
if ( monitor_via_hardware_button . get_active ( ) ) {
Config - > set_monitoring_model ( ExternalMonitoring ) ;
} else if ( monitor_via_ardour_button . get_active ( ) ) {
Config - > set_monitoring_model ( SoftwareMonitoring ) ;
}
2009-10-14 12:10:01 -04:00
2010-11-25 15:37:39 -05:00
Config - > set_use_monitor_bus ( use_monitor_section_button . get_active ( ) ) ;
2010-03-21 23:46:09 -04:00
2009-04-20 14:41:46 -04:00
Config - > save_state ( ) ;
2013-03-14 15:11:31 -04:00
2009-04-20 14:41:46 -04:00
}
2013-03-14 15:11:31 -04:00
{
/* "touch" the been-here-before path now we've successfully
made it through the first time setup ( at least )
*/
ofstream fout ( been_here_before_path ( ) . c_str ( ) ) ;
}
2009-12-01 08:23:27 -05:00
_response = RESPONSE_OK ;
2009-03-04 18:06:18 -05:00
gtk_main_quit ( ) ;
}
2009-04-20 14:41:46 -04:00
void
ArdourStartup : : move_along_now ( )
{
2013-09-20 16:05:54 -04:00
on_apply ( ) ;
2009-04-20 14:41:46 -04:00
}
2013-03-09 08:44:22 -05:00
2013-09-21 12:51:30 -04:00