Main Page   Namespace List   Class Hierarchy   Compound List   File List   Namespace Members   Compound Members   File Members  

MergeDialog Class Reference

#include <MergeDialog.h>

Inheritance diagram for MergeDialog:

Inheritance graph
[legend]
Collaboration diagram for MergeDialog:

Collaboration graph
[legend]
List of all members.

Public Methods

 MergeDialog (Config &cfg_, Glib::RefPtr< Gtk::ListStore > clist_, const ModelColumns &columns_)
 ~MergeDialog ()
virtual int handle_read (int fd_)
virtual int handle_close (int fd_)
void run_merge ()
void reply (int button_)

Private Types

typedef std::vector< std::string > PauseList
enum  { pre = 0, post }

Private Methods

void init ()
void roll_back (bool failed_=false)
void on_ok_button_clicked ()
void on_cancel_button_clicked ()
int create_pause_files (const string &, const string[], Delays &)
void refresh_gui () const

Private Attributes

Configm_config
Glib::RefPtr< Gtk::ListStore > m_clist
const ModelColumnsm_columns
bool m_in_progress
bool m_pause_in_progress
PauseList m_pause_files
std::string m_result
std::string m_cwd
uint m_file_cnt
uint m_curr_file
bool m_del_old_file
ASSA::Pipe m_pipe
FILE * m_pinstream

Friends

class MergeDialog_ui

Member Typedef Documentation

typedef std::vector<std::string> MergeDialog::PauseList [private]
 

Definition at line 62 of file MergeDialog.h.


Member Enumeration Documentation

anonymous enum [private]
 

Enumeration values:
pre 
post 

Definition at line 61 of file MergeDialog.h.

00061 { pre = 0, post };


Constructor & Destructor Documentation

MergeDialog::MergeDialog Config   cfg_,
Glib::RefPtr< Gtk::ListStore >    clist_,
const ModelColumns   columns_
[inline]
 

Definition at line 88 of file MergeDialog.h.

References init.

00090     : m_config (cfg_), 
00091       m_clist (clist_), 
00092       m_columns (columns_),
00093       m_in_progress (false), 
00094       m_pause_in_progress (false),
00095       m_del_old_file (false),
00096       m_pinstream (NULL)
00097 {
00098     trace("MergeDialog::MergeDialog");
00099     init ();
00100 }

MergeDialog::~MergeDialog   [inline]
 

Definition at line 104 of file MergeDialog.h.

00105 { 
00106     trace("MergerDialog::~MergeDialog"); 
00107 }


Member Function Documentation

int MergeDialog::create_pause_files const string &   ,
const    string[],
Delays  
[private]
 

Referenced by on_ok_button_clicked.

int MergeDialog::handle_close int    fd_ [virtual]
 

handle_close () is called by the ASSA::Reactor in response to handle_read () returning -1 as an indication that no more data processing is required.

Definition at line 335 of file MergeDialog.cpp.

References m_pinstream, m_pipe, and roll_back.

00336 {  
00337     trace("MergeDialog::handle_close");
00338 
00339     m_pipe.close ();
00340     if (m_pinstream) {
00341         m_pinstream = NULL;
00342     }
00343 
00344     roll_back ();
00345     hide ();
00346     response (Gtk::RESPONSE_NONE);
00347     return 0;
00348 }

int MergeDialog::handle_read int    fd_ [virtual]
 

read one record (separated by the newline) keep the rest in the internal buffer parse the record and update window components accordingly count the files until the last one is processed Pipe - does it have blocking or non-blocking descriptor?

Definition at line 296 of file MergeDialog.cpp.

References m_curr_file, m_file_cnt, MergeDialog_ui::m_file_name_label, MergeDialog_ui::m_file_progress, m_pinstream, MergeDialog_ui::m_total_label, and MergeDialog_ui::m_total_progress.

00297 {  
00298     trace("MergeDialog::handle_read");
00299     static int MAXLINE = 128;
00300     char line [MAXLINE];
00301 
00302     if (fgets (line, MAXLINE, m_pinstream) == NULL) {
00303         DL((TRACE,"Received EOF from Pipe\n"));
00304         return -1;
00305     }
00306     line [strlen (line)-1] = '\0';
00307     DL((APP, "Received \"%s\"\n", line));
00308 
00309     int percent = strtol(line, (char **)NULL, 10);
00310 
00311     if (percent == 0) { // next file
00312         m_file_name_label->set_text (line);
00313         m_file_progress->set_fraction (0);
00314         m_curr_file++;
00315         sprintf (line, "%03d / %03d", m_curr_file, m_file_cnt);
00316         m_total_label->set_text (line);
00317         m_total_progress->set_fraction (m_curr_file * 1.0 / m_file_cnt);
00318         DL((APP,"A new file name (%d of %d)\n", m_curr_file, m_file_cnt));
00319     }
00320     else {          // file progress status
00321         m_file_progress->set_fraction (percent / 100.0);
00322         DL((APP,"File progress: %5.2f (%d \%)\n", (percent / 100.0), percent));
00323     }
00324 
00325     return 0;
00326 }

void MergeDialog::init   [private]
 

Definition at line 69 of file MergeDialog.cpp.

References m_curr_file, m_cwd, m_del_old_file, m_file_cnt, MergeDialog_ui::m_file_name_label, MergeDialog_ui::m_file_progress, MergeDialog_ui::m_first_cd_track, m_in_progress, MergeDialog_ui::m_make_cd, m_pause_in_progress, m_result, MergeDialog_ui::m_total_label, and MergeDialog_ui::m_total_progress.

Referenced by MergeDialog, and run_merge.

00070 {
00071     trace("MergeDialog::init");
00072 
00073     m_in_progress = false;
00074     m_pause_in_progress = false;
00075     m_result = "";
00076     m_cwd = "";
00077     m_file_cnt = 0;
00078     m_curr_file = 0;
00079     m_del_old_file = true;
00080 
00081     // Sensitize "exec" button
00082     set_response_sensitive (0, true);
00083     set_default_response (0);
00084     
00085     // Current file readings
00086     m_file_name_label->set_text ("");
00087     m_file_progress->set_fraction (0);
00088 
00089     // Total files processed readings
00090     m_total_label->set_text ("");
00091     m_total_progress->set_fraction (0);
00092 
00093     // CD tracks configuration
00094     m_make_cd->set_active (false);
00095     m_first_cd_track->set_text ("1");
00096 }

void MergeDialog::on_cancel_button_clicked   [private]
 

User clicked 'Cancel' button

Definition at line 387 of file MergeDialog.cpp.

References m_cwd, m_in_progress, m_pause_in_progress, m_pipe, REACTOR, and roll_back.

Referenced by MergeDialog_ui::MergeDialog_ui.

00388 {  
00389     trace("MergeDialog::on_cancel_button_clicked");
00390 
00391     if (m_pause_in_progress) {
00392         m_pause_in_progress = false;
00393     }
00394     if (m_in_progress) {
00395         m_pipe.kill ();
00396 
00397         REACTOR->removeHandler (this, READ_EVENT);
00398         m_in_progress = false;
00399     }
00400 
00401     roll_back (true);
00402     if (m_cwd.size ()) {
00403         ::chdir (m_cwd.c_str ());
00404     }
00405     hide_all ();
00406 }

void MergeDialog::on_ok_button_clicked   [private]
 

User clicked 'Exec' button. This is a rather long function. But every time I try to break it down, it somehow manages to assemble itself again.

Definition at line 109 of file MergeDialog.cpp.

References create_pause_files, MergeDialog_ui::first_cd_track, Config::get_proj_name, Config::get_proj_path, GWAVMERGER, m_clist, m_columns, m_config, m_cwd, m_file_cnt, m_in_progress, m_pause_files, m_pause_in_progress, m_pinstream, m_pipe, m_result, MergeDialog_ui::make_cd_checked, Config::make_pause_pathname, Config::make_rel_pathname, post, pre, REACTOR, refresh_gui, roll_back, ModelColumns::row_a, and ModelColumns::row_b.

Referenced by MergeDialog_ui::MergeDialog_ui.

00110 {  
00111     trace("MergeDialog::on_ok_button_clicked");
00112 
00113     size_t size = m_clist->children ().size ();
00114 
00115     int ret = 0;
00116     string name;
00117     string an_A;
00118     string a_B; 
00119     string pause [2]; 
00120     string cmd;
00121     string final_list;
00122     string q;
00123     char* buf = NULL;
00124 
00125     Delays delays (m_config);   // functor object
00126     string cdpath ("cdimage");
00127     InfoMsgPopup imp ("Generating pause files...",
00128                       "\n  Wait while generating pause files...\n");
00129     Gtk::TreeModel::Children::iterator iter;
00130     Gtk::TreeModel::Row row;
00131 
00132     SerialNumber sernum (first_cd_track (), "track", ".wav", size);
00133 
00134     /* Change to the project directory. 
00135      * getcwd() always returns a path free from symbolic links.
00136      */
00137     buf = new char [PATH_MAX];
00138     getcwd (buf, PATH_MAX);
00139     m_cwd = buf;
00140     delete [] buf;
00141 
00142     /* Change to the project's root directory.
00143      */
00144     ::chdir (m_config.get_proj_path ().c_str ());
00145 
00146     /* Start compiling the merger list first by 
00147      * deriving the result WAV file name.
00148      */
00149     final_list = m_config.get_proj_name ();
00150     final_list.replace (final_list.find (".gwm"), 4, ".wav");
00151 
00152     q = "Remove old " + final_list + " file?";
00153 
00156     if (::access (final_list.c_str (), F_OK) == 0) {
00157         Gtk::MessageDialog qm (*this, q, Gtk::MESSAGE_QUESTION, 
00158                                Gtk::BUTTONS_NONE, true, true);
00159         qm.add_button (Gtk::Stock::OK, Gtk::RESPONSE_OK);
00160         qm.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
00161 
00162         int ret = qm.run ();
00163         if (ret == Gtk::RESPONSE_CANCEL) {
00164             DL((APP, "Merger cancelled!\n"));
00165             goto error;
00166         }
00167         ::unlink (final_list.c_str ()); // Wack the old WAV file
00168     }
00169     m_result = final_list;  // Remember target WAV file name
00170 
00171     if (make_cd_checked ()) {
00172         struct stat st;
00173         if (::stat (cdpath.c_str (), &st) != 0 || !S_ISDIR (st.st_mode)) {
00174             ::mkdir (cdpath.c_str (), 0755);
00175         }
00176     }
00177 
00178     /* Start assembling the "command arguments" list
00179      */
00180     final_list = "--output=" + final_list + " ";
00181 
00182     DL((APP,"Number of elements in CList : %d\n",size));
00183     DL((APP,"Merging files : \n"));
00184 
00185     /* Make pause files. We block here with a popup 
00186      * waiting for all pause files to be generated.
00187      */
00188     imp.show ();
00189     refresh_gui ();
00190     m_pause_in_progress = true;
00191 
00192     iter = m_clist->children ().begin ();
00193     while (iter) {
00194         if (m_pause_in_progress == false) { // we've been cancelled by user
00195             imp.hide ();
00196             goto error;
00197         }
00198         row = *iter;
00199         std::string a = Glib::locale_from_utf8 (row [m_columns.row_a]);
00200         std::string b = Glib::locale_from_utf8 (row [m_columns.row_b]);
00201 
00202         an_A = m_config.make_rel_pathname ("A", a);
00203         a_B = m_config.make_rel_pathname ("B", b);
00204         
00205         pause [pre] = m_config.make_pause_pathname (pre, b);
00206         pause [post] = m_config.make_pause_pathname (post, b);
00207 
00208         if (create_pause_files (a_B, pause, delays) == -1) {
00209             goto error;
00210         }
00211 
00212         if (make_cd_checked ()) {
00213             cmd = "wavjoin --output=cdimage/" + string (sernum) + " "
00214                 + an_A + " " + pause [pre] + " " 
00215                 + a_B  + " " + pause [post];
00216             ret = system (cmd.c_str ());
00217             if (ret < 0) {
00218                 Gtk::MessageDialog error ("wavjoin failed!",MESSAGE_ERROR);
00219                 error.run ();
00220                 goto error;
00221             }
00222             final_list += " cdimage/" + string (sernum);
00223             sernum++;
00224         }
00225         else {
00226             final_list += 
00227                 an_A + " " + pause [pre]  + " " +
00228                 a_B  + " " + pause [post] + " ";
00229         }
00230 
00231         DL((APP,"%s %s %s %s\n", an_A.c_str (), pause [pre].c_str (),
00232             a_B.c_str (), pause [post].c_str ()));
00233         
00234         m_pause_files.push_back (pause [pre]);
00235         m_pause_files.push_back (pause [post]);
00236         m_file_cnt += 4;
00237 
00238         refresh_gui ();
00239         iter++;
00240     }
00241 
00242     m_pause_in_progress = false;
00243     imp.hide ();
00244     refresh_gui ();
00245 
00251     cmd = "wavjoin --percent " + GWAVMERGER->wavjoin_options () + " "
00252         + final_list;
00253 
00254     if (m_pipe.open (cmd.c_str (), "r") == NULL) {
00255         Gtk::MessageDialog emsg ("\"wavjoin\" failed!",MESSAGE_ERROR);
00256         emsg.run ();
00257         EL((ERROR,"popen (\"%s\") failed\n", cmd.c_str ()));
00258         goto error;
00259     }
00260     /* Make a C++ input stream out of file descriptor.
00261      * This is non-portable.
00262      */
00263     m_pinstream = m_pipe.fp ();
00264       
00265     /* Register self as IOHandler to read from the pipe.
00266      */
00267     REACTOR->registerIOHandler (this, m_pipe.fd (), READ_EVENT);
00268     
00269     /* Desensitize 'Exec' button
00270      */
00271     set_response_sensitive (0, false);
00272     m_in_progress = true;
00273 
00278     return;
00279 
00280  error:
00281     refresh_gui ();
00282     roll_back (true);
00283     ::chdir (m_cwd.c_str ());
00284 }

void MergeDialog::refresh_gui   const [private]
 

Consume all queued X11 events

Definition at line 40 of file MergeDialog.cpp.

Referenced by on_ok_button_clicked.

00041 {
00042     trace("MergeDialog::refresh_gui");
00043 
00044     while (Gtk::Main::events_pending ()) {
00045         Gtk::Main::iteration ();
00046     }
00047 }

void MergeDialog::reply int    button_ [inline]
 

Definition at line 111 of file MergeDialog.h.

References m_del_old_file.

00112 { 
00113     m_del_old_file = button_ == 0 ? true : false; 
00114 }

void MergeDialog::roll_back bool    failed_ = false [private]
 

roll_back does post-processing clean-up. If failed_ is false, then we delete pause files only. If, on the other hand, failed_ is true, we also remove result file and all files in cdimage/ directory (if any).

Definition at line 358 of file MergeDialog.cpp.

References m_in_progress, m_pause_files, m_result, and MergeDialog_ui::make_cd_checked.

Referenced by handle_close, on_cancel_button_clicked, and on_ok_button_clicked.

00359 {  
00360     trace("MergeDialog::roll_back");
00361 
00362     PauseList::const_iterator i = m_pause_files.begin ();
00363     while (i != m_pause_files.end ()) {
00364         ::unlink ((*i).c_str ());
00365         i++;
00366     }
00367     m_pause_files.clear ();
00368 
00369     if (failed_) {
00370         if (m_result.size () != 0) {
00371             ::unlink (m_result.c_str ());
00372         }
00373         
00374         if (make_cd_checked ()) {
00375             ::system ("rm -f cdimage/*.wav");
00376         }
00377     }
00378 
00379     m_in_progress = false;
00380 }

void MergeDialog::run_merge  
 

MergeDialog is a MainWindow's data member. It is created by MainWindow's constructor and destroyed by its destructor. "Close" event causes it to hide() and member function run() shows it again.

init() resets all internal data members responsible for displaying the progress to their initial values.

Definition at line 60 of file MergeDialog.cpp.

References init.

Referenced by MainWindow::merge_cb.

00061 {
00062     trace("MergeDialog::run_merge");
00063     init ();
00064     run ();
00065 }


Friends And Related Function Documentation

friend class MergeDialog_ui [friend]
 

Definition at line 49 of file MergeDialog.h.


Member Data Documentation

Glib::RefPtr<Gtk::ListStore> MergeDialog::m_clist [private]
 

Definition at line 65 of file MergeDialog.h.

Referenced by on_ok_button_clicked.

const ModelColumns& MergeDialog::m_columns [private]
 

Definition at line 66 of file MergeDialog.h.

Referenced by on_ok_button_clicked.

Config& MergeDialog::m_config [private]
 

Definition at line 64 of file MergeDialog.h.

Referenced by on_ok_button_clicked.

uint MergeDialog::m_curr_file [private]
 

Definition at line 75 of file MergeDialog.h.

Referenced by handle_read, and init.

std::string MergeDialog::m_cwd [private]
 

Definition at line 73 of file MergeDialog.h.

Referenced by init, on_cancel_button_clicked, and on_ok_button_clicked.

bool MergeDialog::m_del_old_file [private]
 

Definition at line 76 of file MergeDialog.h.

Referenced by init, and reply.

uint MergeDialog::m_file_cnt [private]
 

Definition at line 74 of file MergeDialog.h.

Referenced by handle_read, init, and on_ok_button_clicked.

bool MergeDialog::m_in_progress [private]
 

Definition at line 68 of file MergeDialog.h.

Referenced by init, on_cancel_button_clicked, on_ok_button_clicked, and roll_back.

PauseList MergeDialog::m_pause_files [private]
 

Definition at line 71 of file MergeDialog.h.

Referenced by on_ok_button_clicked, and roll_back.

bool MergeDialog::m_pause_in_progress [private]
 

Definition at line 69 of file MergeDialog.h.

Referenced by init, on_cancel_button_clicked, and on_ok_button_clicked.

FILE* MergeDialog::m_pinstream [private]
 

Definition at line 79 of file MergeDialog.h.

Referenced by handle_close, handle_read, and on_ok_button_clicked.

ASSA::Pipe MergeDialog::m_pipe [private]
 

Definition at line 78 of file MergeDialog.h.

Referenced by handle_close, on_cancel_button_clicked, and on_ok_button_clicked.

std::string MergeDialog::m_result [private]
 

Definition at line 72 of file MergeDialog.h.

Referenced by init, on_ok_button_clicked, and roll_back.


The documentation for this class was generated from the following files:
Generated on Tue Feb 11 23:05:33 2003 for gwavmerger by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002