Merged with trunk, and a few trivial GUI updates etc.
[ardour.git] / libs / pbd / pbd / transmitter.h
1 /*
2     Copyright (C) 1998-99 Paul Barton-Davis 
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18     $Id$
19 */
20
21 #ifndef __libmisc_transmitter_h__
22 #define __libmisc_transmitter_h__
23
24 #include <sstream>
25 #include <iostream>
26
27 #include <sigc++/sigc++.h>
28
29 using std::cout;
30 using std::cerr;
31 using std::endl;
32
33 class Transmitter : public std::stringstream
34
35 {
36   public:
37         enum Channel {
38                 Info,
39                 Error,
40                 Warning,
41                 Fatal,
42                 Throw
43         };
44
45         Transmitter (Channel);
46
47         sigc::signal<void,Channel, const char *> &sender() { 
48                 return *send;
49         }
50
51         bool does_not_return ();
52
53   protected:
54         virtual void deliver ();
55         friend std::ostream& endmsg (std::ostream &);
56
57   private:
58         Channel channel;
59         sigc::signal<void, Channel, const char *> *send;
60
61         sigc::signal<void, Channel, const char *> info;
62         sigc::signal<void, Channel, const char *> warning;
63         sigc::signal<void, Channel, const char *> error;
64         sigc::signal<void, Channel, const char *> fatal;
65 };
66
67 /* for EGCS 2.91.66, if this function is not compiled within the same
68    compilation unit as the one where a ThrownError is thrown, then 
69    nothing will catch the error. This is a pretty small function, so
70    inlining it here seems like a reasonable workaround.
71 */
72
73 inline std::ostream &
74 endmsg (std::ostream &ostr)
75
76 {
77         Transmitter *t;
78
79         /* There is a serious bug in the Cygnus/GCC libstdc++ library:
80            cout is not actually an ostream, but a trick was played
81            to make the compiler think that it is. This will cause
82            the dynamic_cast<> to fail with SEGV. So, first check to
83            see if ostr == cout, and handle it specially.
84         */
85
86         if (&ostr == &cout) {
87                 cout << endl;
88                 return ostr;
89         } else if (&ostr == &cerr) {
90                 cerr << endl;
91                 return ostr;
92         }
93
94         if ((t = dynamic_cast<Transmitter *> (&ostr)) != 0) {
95                 t->deliver ();
96         } else {
97                 /* hmm. not a Transmitter, so just put a newline on
98                    it and assume that that will be enough.
99                 */
100                 
101                 ostr << endl;
102         }
103
104         return ostr;
105 }
106
107
108 extern "C" { void pbd_c_error (const char *); }
109
110 #endif // __libmisc_transmitter_h__