+ 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 (@_) {
+ chomp $line;
+ dbg('chan', "-> $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 (@_) {
+ chomp $line;
+ dbg('chan', "-> 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(@_));
+}
+
+# change the state of the channel - lots of scope for debugging here :-)
+sub state
+{
+ my $self = shift;
+ $self->{oldstate} = $self->{state};
+ $self->{state} = shift;
+ dbg('state', "$self->{call} channel state $self->{oldstate} -> $self->{state}\n");
+}
+
+# various access routines
+
+#
+# return a list of valid elements
+#
+
+sub fields
+{
+ return keys(%valid);
+}
+
+#
+# return a prompt for a field
+#
+
+sub field_prompt
+{
+ my ($self, $ele) = @_;
+ return $valid{$ele};
+}
+
+sub AUTOLOAD
+{
+ my $self = shift;
+ my $name = $AUTOLOAD;
+
+ return if $name =~ /::DESTROY$/;
+ $name =~ s/.*:://o;
+
+ die "Non-existant field '$AUTOLOAD'" if !$valid{$name};
+ @_ ? $self->{$name} = shift : $self->{$name} ;