+ delete $channels{$self->{call}};
+}
+
+
+# handle out going messages, immediately without waiting for the select to drop
+# this could, in theory, block
+sub send_now
+{
+ my $self = shift;
+ my $conn = $self->{conn};
+
+ # is this a list of channels ?
+ if (!defined $conn) {
+ die "tried to send_now to an invalid channel list" if !defined $self->{list};
+ my $lself;
+ foreach $lself (@$self->{list}) {
+ $lself->send_now(@_); # it's recursive :-)
+ }
+ } else {
+ my $sort = shift;
+ my $call = $self->{call};
+ my $line;
+
+ foreach $line (@_) {
+ my $t = atime;
+ chomp $line;
+ print main::DEBUG "$t > $sort $call $line\n" if defined DEBUG;
+ print "> $sort $call $line\n";
+ $conn->send_now("$sort$call|$line");
+ }
+ }
+}
+
+#
+# the normal output routine
+#
+sub send # this is always later and always data
+{
+ my $self = shift;
+ my $conn = $self->{conn};
+
+ # is this a list of channels ?
+ if (!defined $conn) {
+ die "tried to send to an invalid channel list" if !defined $self->{list};
+ my $lself;
+ foreach $lself (@$self->{list}) {
+ $lself->send(@_); # here as well :-) :-)
+ }
+ } else {
+ my $call = $self->{call};
+ my $line;
+
+ foreach $line (@_) {
+ my $t = atime;
+ chomp $line;
+ print main::DEBUG "$t > D $call $line\n" if defined DEBUG;
+ print "> D $call $line\n";
+ $conn->send_later("D$call|$line");
+ }
+ }
+}
+
+# send a file (always later)
+sub send_file
+{
+ my ($self, $fn) = @_;
+ my $call = $self->{call};
+ my $conn = $self->{conn};
+ my @buf;
+
+ open(F, $fn) or die "can't open $fn for sending file ($!)";
+ @buf = <F>;
+ close(F);
+ $self->send(@buf);
+}
+
+# just a shortcut for $dxchan->send(msg(...));
+sub msg
+{
+ my $self = shift;
+ $self->send(DXM::msg(@_));