00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <iostream>
00021 #include <sstream>
00022 using std::ostringstream;
00023
00024 #include <stdio.h>
00025 #include <unistd.h>
00026
00027 #include "WavJoin-main.h"
00028 #include "WavJoin.h"
00029
00030 using ASSA::APP;
00031 using ASSA::ERROR;
00032
00033
00034
00035 WavJoin* ASSA::Singleton<WavJoin>::m_instance;
00036 ASSA::Destroyer<WavJoin> ASSA::Singleton<WavJoin>::m_destroyer;
00037
00038 const unsigned short int WavJoin::FRAME_BUFFER_SIZE = USHRT_MAX;
00039
00040 WavJoin::WavJoin () :
00041 m_out_file_setup (AF_NULL_FILESETUP),
00042 m_out_file (AF_NULL_FILEHANDLE),
00043 m_pos_arg_count (0),
00044 m_exit_value (0),
00045 m_percent (false)
00046 {
00047
00048 rm_opt ('f', "config-file" );
00049 rm_opt ('n', "instance" );
00050 rm_opt ('p', "port" );
00051
00052
00053 rm_opt ('b', "daemon" );
00054 rm_opt ('l', "pidfile" );
00055 rm_opt ('L', "ommit-pidfile");
00056
00057 add_opt ('o', "output", &m_out_fname);
00058 add_flag_opt (0, "percent", &m_percent);
00059
00060
00061
00062
00063 m_debug_mask = 0x0;
00064 m_log_file = "/dev/null";
00065 }
00066
00067 void
00068 WavJoin::pos_arg (const char* arg_)
00069 {
00070 trace("WavJoin::pos_arg");
00071 DL((APP,"Adding file \"%s\"\n",arg_));
00072
00073 m_fnames_list.push_back (arg_);
00074 m_pos_arg_count++;
00075 }
00076
00077 void
00078 WavJoin::initServer ()
00079 {
00080 trace("WavJoin::initServer");
00081
00082 if (m_pos_arg_count == 0 ||
00083 (m_pos_arg_count == 1 && m_out_fname.size () == 0))
00084 {
00085 std::cerr << "WavPause: mismatch arguments\n"
00086 << "Try `WavPause --help` for more information.\n";
00087 set_exit_value (1);
00088 return;
00089 }
00090
00091 if (m_out_fname.size () == 0) {
00092 m_out_fname = m_fnames_list [0];
00093 }
00094 ostringstream temp;
00095 temp << "WavJoin_tmp." << getpid () << ".wav";
00096 m_out_temp_fname = temp.str ();
00097
00098 DL((APP,"Destination file: \"%s\"\n", m_out_fname.c_str ()));
00099 DL((APP,"Temp file: \"%s\"\n", m_out_temp_fname.c_str ()));
00100 DL((APP,"Files to process: %d\n", m_fnames_list.size ()));
00101 DL((APP,"===================\n"));
00102 List_t::const_iterator i = m_fnames_list.begin ();
00103 uint cnt = 0;
00104 while (i != m_fnames_list.end ()) {
00105 DL((APP,"[%02d] \"%s\"\n",cnt, (*i).c_str ()));
00106 cnt++;
00107 i++;
00108 }
00109 DL((APP,"=== End-Of-List ===\n"));
00110 DL((APP,"Service has been initialized\n"));
00111 }
00112
00113 void
00114 WavJoin::processServer ()
00115 {
00116 trace("WavJoin::processServer");
00117
00118 if (open_out_file () < 0) {
00119 DL((APP,"Failed to open output file\n"));
00120 set_exit_value (1);
00121 return;
00122 }
00123 bool completed = true;
00124 List_t::const_iterator i = m_fnames_list.begin ();
00125
00126 while (i != m_fnames_list.end ()) {
00127 if (stopServer ()) {
00128 DL((APP,"Data processing prematurely terminated\n"));
00129 set_exit_value (1);
00130 completed = false;
00131 break;
00132 }
00133 DL((APP,"Process WAV file \"%s\"\n", (*i).c_str ()));
00134
00135 if (join_file ((*i)) < 0) {
00136 DL((APP,"Failed to join file \"%s\"\n", (*i).c_str ()));
00137 set_exit_value (1);
00138 completed = false;
00139 break;
00140 }
00141 i++;
00142 }
00143 close_out_file (completed);
00144 m_reactor.stopReactor ();
00145 DL((APP,"Service stopped!\n"));
00146 }
00147
00148
00149
00150 int
00151 WavJoin::open_out_file ()
00152 {
00153 trace("WavJoin::open_out_file");
00154
00155
00156
00157 int file_format = -1;
00158 int version;
00159 int sample_format;
00160 int sample_width;
00161 int channel_count;
00162 int frame_size;
00163 double sample_rate = 0;
00164 AFframecount total_frames;
00165
00166 version = sample_format = sample_width = channel_count = 0;
00167 frame_size = total_frames = 0;
00168
00169 AFfilehandle sample_file = AF_NULL_FILEHANDLE;
00170
00171 sample_file = afOpenFile (m_fnames_list[0].c_str (), "r", NULL);
00172 if (sample_file == AF_NULL_FILEHANDLE) {
00173 return -1;
00174 }
00175
00176 afGetSampleFormat (sample_file, AF_DEFAULT_TRACK,
00177 &sample_format, &sample_width);
00178
00179 file_format = afGetFileFormat (sample_file, &version);
00180 channel_count = afGetChannels (sample_file, AF_DEFAULT_TRACK);
00181 sample_rate = afGetRate (sample_file, AF_DEFAULT_TRACK);
00182 total_frames = afGetFrameCount (sample_file, AF_DEFAULT_TRACK);
00183
00184 frame_size =
00185 (int) afGetVirtualFrameSize (sample_file, AF_DEFAULT_TRACK, 1);
00186
00187 afCloseFile (sample_file);
00188
00189
00190
00191 m_out_file_setup = afNewFileSetup ();
00192 afInitFileFormat (m_out_file_setup, file_format);
00193 afInitSampleFormat (m_out_file_setup, AF_DEFAULT_TRACK,
00194 sample_format, sample_width);
00195 afInitChannels (m_out_file_setup, AF_DEFAULT_TRACK, channel_count);
00196 afInitRate (m_out_file_setup, AF_DEFAULT_TRACK, sample_rate);
00197
00198
00199
00200 DL((APP,"Open temporary file \"%s\"\n", m_out_temp_fname.c_str ()));
00201
00202 unlink (m_out_temp_fname.c_str ());
00203
00204 m_out_file = afOpenFile (m_out_temp_fname.c_str (), "w", m_out_file_setup);
00205 if (m_out_file == AF_NULL_FILEHANDLE) {
00206 return -1;
00207 }
00208
00209
00210
00211 afSetVirtualChannels (m_out_file, AF_DEFAULT_TRACK, channel_count);
00212 afSetVirtualSampleFormat (m_out_file, AF_DEFAULT_TRACK,
00213 sample_format, sample_width);
00214 afFreeFileSetup (m_out_file_setup);
00215
00216 return 0;
00217 }
00218
00219
00220
00221 void
00222 WavJoin::close_out_file (bool completed_)
00223 {
00224 trace("WavJoin::close_out_file");
00225
00226 afCloseFile (m_out_file);
00227
00228 if (completed_ == false) {
00229 DL((APP,"Executing termination sequence ...\n"));
00230 DL((APP,"Unlinking \"%s\"\n", m_out_temp_fname.c_str ()));
00231 unlink (m_out_temp_fname.c_str ());
00232 set_exit_value (1);
00233 }
00234 else {
00235 unlink (m_out_fname.c_str ());
00236
00237 if (rename (m_out_temp_fname.c_str (), m_out_fname.c_str ()) < 0) {
00238 EL((ERROR,"Failed to rename file \"%s\" to \"%s\"\n",
00239 m_out_temp_fname.c_str (), m_out_fname.c_str ()));
00240 unlink (m_out_temp_fname.c_str ());
00241 set_exit_value (1);
00242 }
00243 }
00244 }
00245
00246
00247
00248 int
00249 WavJoin::join_file (const string& fname_)
00250 {
00251 trace("WavJoin::join_file");
00252
00253 AFfilehandle in_file = AF_NULL_FILEHANDLE;
00254
00255 in_file = afOpenFile (fname_.c_str (), "r", NULL);
00256 if (in_file == AF_NULL_FILEHANDLE) {
00257 return -1;
00258 }
00259
00260 if (m_percent) {
00261 std::cout << fname_ << '\n';
00262 }
00263 AFframecount total_frames = 0;
00264 int frame_size = 0;
00265
00266 total_frames = afGetFrameCount (in_file, AF_DEFAULT_TRACK);
00267 frame_size = int(afGetVirtualFrameSize (in_file, AF_DEFAULT_TRACK, 1));
00268
00269 DL((APP,"total_frames: %d\n", total_frames));
00270 DL((APP,"frame_size: %d\n", frame_size));
00271
00272 char* frame_buffer = new char [frame_size * FRAME_BUFFER_SIZE];
00273 memset (frame_buffer, 0, frame_size * FRAME_BUFFER_SIZE);
00274
00275 AFframecount total_frames_written = 0;
00276 AFframecount frames_to_read = FRAME_BUFFER_SIZE;
00277 AFframecount frames_read, frames_written;
00278
00279 bool done = false;
00280 bool ok = true;
00281
00282 while (done == false) {
00283 frames_read = frames_written = 0;
00284 if (stopServer ()) {
00285 DL((APP,"Prematurely terminated!"));
00286 return -1;
00287 }
00288 frames_read = afReadFrames (in_file, AF_DEFAULT_TRACK,
00289 frame_buffer, frames_to_read);
00290 if (frames_read < 0) {
00291 EL((ERROR,"Bad read of audio track data from \"%s\"\n",
00292 fname_.c_str ()));
00293 ok = false;
00294 done = true;
00295 }
00296 frames_written = afWriteFrames (m_out_file, AF_DEFAULT_TRACK,
00297 frame_buffer, frames_read);
00298 if (frames_written < 0) {
00299 EL((ERROR,"Bad write of audio track data to \"%s\"\n",
00300 m_out_temp_fname.c_str ()));
00301 ok = false;
00302 done = true;
00303 }
00304 else {
00305 total_frames_written += frames_written;
00306 DL((APP,"total_frames_written = %d\n", total_frames_written));
00307 }
00308
00309 if (m_percent) {
00310 std::cout << long (total_frames_written * 100.0 / total_frames)
00311 << '\n';
00312 }
00313 if (total_frames_written == total_frames) {
00314 done = true;
00315 }
00316 }
00317 if (m_percent) {
00318 std::cout << std::flush;
00319 }
00320 delete [] frame_buffer;
00321
00322 if (!ok) {
00323 DL((APP,"Copying file \"%s\" failed\n", fname_.c_str ()));
00324 return -1;
00325 }
00326
00327 afCloseFile (in_file);
00328 return 0;
00329 }