Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members

pipe.C

Go to the documentation of this file.
00001 #include <fcntl.h>
00002 #include <string.h>
00003 #include <errno.h>
00004 #include <signal.h>
00005 
00006 #include "defaults.h"
00007 #include "file.h"
00008 #include "guicast.h"
00009 #include "interlacemodes.h"
00010 #include "pipe.h"
00011 
00012 extern "C" {
00013         int pipe_sigpipe_received;
00014 
00015         void pipe_handle_sigpipe(int signum) {
00016                 printf("Received sigpipe\n");
00017                 pipe_sigpipe_received++;
00018         }
00019 }
00020 
00021 Pipe::Pipe(char *command, char *sub_str, char sub_char) { 
00022         this->command = command;
00023         this->sub_str = sub_str;
00024         this->sub_char = sub_char;
00025 
00026         complete[0] = '\0';
00027         file = NULL;
00028         fd = -1;
00029 
00030         // FUTURE: could probably set to SIG_IGN once things work
00031         signal(SIGPIPE, pipe_handle_sigpipe);
00032 }
00033 
00034 Pipe::~Pipe() {         
00035         close();
00036 }
00037 
00038 int Pipe::substitute() {
00039         if (command == NULL) {
00040                 strcpy(complete, "");
00041                 return 0;
00042         }
00043 
00044         if (sub_str == NULL || sub_char == '\0') {
00045                 strcpy(complete, command);
00046                 return 0;
00047         }
00048 
00049         int count = 0;
00050         char *c = command;
00051         char *f = complete;
00052         while (*c) {
00053                 // directly copy anything substitution char
00054                 if (*c != sub_char) {
00055                         *f++ = *c++;
00056                         continue;
00057                 }
00058                 
00059                 // move over the substitution character
00060                 c++;
00061 
00062                 // two substitution characters in a row is literal
00063                 if (*c == sub_char) {
00064                         *f++ = *c++;
00065                         continue;
00066                 }
00067 
00068                 // insert the file string at the substitution point
00069                 if (f + strlen(sub_str) - complete > sizeof(complete)) {
00070                         printf("Pipe::substitute(): max length exceeded\n");
00071                         return -1;
00072                 }
00073                 strcpy(f, sub_str);
00074                 f += strlen(sub_str);
00075                 count++;
00076         }
00077 
00078         return count;
00079 }
00080         
00081         
00082 
00083 int Pipe::open(char *mode) {
00084         if (file) close();
00085 
00086         if (mode == NULL) {
00087                 printf("Pipe::open(): no mode given\n");
00088                 return 1;
00089         }
00090 
00091         if (substitute() < 0) {
00092                 return 1;
00093         }
00094 
00095         if (complete == NULL || strlen(complete) == 0) {
00096                 printf("Pipe::open(): no pipe to open\n");
00097                 return 1;
00098         }
00099 
00100         printf("trying popen(%s)\n", complete);
00101         file = popen(complete, mode);
00102         if (file != NULL) {
00103                 fd = fileno(file);
00104                 return 0;
00105         }
00106 
00107         // NOTE: popen() fails only if fork/exec fails
00108         //       there is no immediate way to see if command failed
00109         //       As such, one must expect to raise SIGPIPE on failure
00110         printf("Pipe::open(%s,%s) failed: %s\n", 
00111                complete, mode, strerror(errno));
00112         return 1;
00113 }       
00114 
00115 int Pipe::open_read() {
00116         return open("r");
00117 }
00118 
00119 int Pipe::open_write() {
00120         return open("w");
00121 }
00122 
00123 void Pipe::close() {
00124         pclose(file);
00125         file = 0;
00126         fd = -1;
00127 }
00128 
00129 
00130 PipeConfig::PipeConfig(BC_WindowBase *window, Defaults *defaults, Asset *asset)
00131 {
00132         this->window = window;
00133         this->defaults = defaults;
00134         this->asset = asset;
00135 }
00136 
00137 // NOTE: Default destructor should destroy all subwindows
00138 
00139 int PipeConfig::create_objects(int x, int y, int textbox_width, int format) {
00140         int x1 = x;
00141         BC_Title *titlew;
00142         // NOTE: out of order so pipe_textbox is available to pipe_checkbox
00143         textbox = new BC_TextBox(x + 120, y, textbox_width, 1, asset->pipe);
00144         window->add_subwindow(textbox);
00145         if (! asset->use_pipe) textbox->disable();
00146 
00147         window->add_subwindow(new BC_Title(x, y, _("Use Pipe:")));
00148         checkbox = new PipeCheckBox(85, y - 5, asset->use_pipe, textbox);
00149         window->add_subwindow(checkbox);
00150 
00151         x += 120;       
00152         x += textbox_width;
00153 
00154         recent = new BC_RecentList("PIPE", defaults, textbox,
00155                                 10, x, y, 350, 100);
00156         window->add_subwindow(recent);
00157         recent->load_items(FILE_FORMAT_PREFIX(format));
00158 
00159         x = x1;
00160         y += 30;
00161         window->add_subwindow(titlew = new BC_Title(x, y, _("Stream Header:"), MEDIUMFONT, RED));
00162         x = x1 + 10;
00163         y += 30;
00164 
00165         window->add_subwindow(new BC_Title(x, y, _("Interlacing:")));
00166         char string[BCTEXTLEN];
00167         ilacemode_to_text(string,asset->interlace_mode);
00168         window->add_subwindow(new BC_Title(x + titlew->get_w() + 5, y, string, MEDIUMFONT, YELLOW));
00169 }
00170 
00171 PipeCheckBox::PipeCheckBox(int x, int y, int value, BC_TextBox *textbox)
00172         : BC_CheckBox(x, y, value)
00173 {
00174         this->textbox = textbox;
00175 }
00176 int PipeCheckBox::handle_event() {
00177         if (get_value()) textbox->enable();
00178         else textbox->disable();
00179 }
00180 
00181 PipeStatus::PipeStatus(int x, int y, char *default_string) 
00182         : BC_Title(x, y, default_string)
00183 {
00184         this->default_string = default_string;
00185 }
00186 int PipeStatus::set_status(Asset *asset) {
00187         if (! asset->use_pipe || ! asset->pipe || ! *(asset->pipe)) {
00188                 set_color(BLACK);
00189                 sprintf(status, default_string);
00190         }
00191         else {
00192                 set_color(RED);
00193                 sprintf(status, "| %s", asset->pipe);
00194         }
00195 
00196         update(status);
00197 }
00198 
00199 
00200 
00201 PipePreset::PipePreset(int x, int y, char *title, PipeConfig *config)
00202         : BC_PopupMenu(x, y, 150, title)
00203 {
00204         this->config = config;
00205         this->title = title;
00206 }
00207 
00208 int PipePreset::handle_event() {
00209         char *text = get_text();
00210         // NOTE: preset items must have a '|' before the actual command
00211         char *pipe = strchr(text, '|');
00212         // pipe + 1 to skip over the '|'
00213         if (pipe) config->textbox->update(pipe + 1);
00214 
00215         config->textbox->enable();
00216         config->checkbox->set_value(1, 1);
00217         
00218         // menuitem sets the title after selection but we reset it
00219         set_text(title);
00220 }

Generated on Sun Jan 8 13:38:58 2006 for Cinelerra-svn by  doxygen 1.4.4