diff --git a/src/Session/Session.cc b/src/Session/Session.cc index b35115bd7..1ef2ee6c1 100644 --- a/src/Session/Session.cc +++ b/src/Session/Session.cc @@ -735,15 +735,15 @@ void Session::OnSetImageChannels(const CARTA::SetImageChannels& message) { std::unique_lock lock(_frame_mutex); if (_frames.count(file_id)) { auto frame = _frames.at(file_id); - std::string err_message; if (message.has_channel_range()) { int start_channel(message.channel_range().min()); int end_channel(message.channel_range().max()); int nchan(frame->Depth()); for (int chan = start_channel; chan <= end_channel; ++chan) { - if (chan >= nchan) { - continue; + // Cancel if past last channel or new channel range has been set + if (chan >= nchan || !IsInChannelRange(file_id, chan)) { + break; } OnAddRequiredTiles(message.required_tiles(), chan); } @@ -753,6 +753,7 @@ void Session::OnSetImageChannels(const CARTA::SetImageChannels& message) { auto stokes_target = message.stokes(); bool z_changed(z_target != frame->CurrentZ()); bool stokes_changed(stokes_target != frame->CurrentStokes()); + std::string err_message; if (frame->SetImageChannels(z_target, stokes_target, err_message)) { // Send Contour data if required SendContourData(file_id); diff --git a/src/Session/Session.h b/src/Session/Session.h index f41c46ed5..a6fbad6f7 100644 --- a/src/Session/Session.h +++ b/src/Session/Session.h @@ -97,13 +97,55 @@ class Session { void OnClosePvPreview(const CARTA::ClosePvPreview& close_pv_preview); void AddToSetChannelQueue(CARTA::SetImageChannels message, uint32_t request_id) { - std::pair rp; - // Empty current queue first. - while (_set_channel_queues[message.file_id()].try_pop(rp)) { + // Image channel mutex is locked so ok to update channel range. + bool clear_queue(true); + if (message.has_channel_range()) { + // Clear queue if new range does not extend current range. + AxisRange new_range(message.channel_range().min(), message.channel_range().max()); + clear_queue = SetChannelRange(new_range); + } else { + // Always clear queue and replace channel range (for cancel) for single channel. + _channel_range = AxisRange(message.channel(), message.channel()); + } + + if (clear_queue) { + // Empty current queue first. + std::pair rp; + while (_set_channel_queues[message.file_id()].try_pop(rp)) { + } } + + // Add message to queue. _set_channel_queues[message.file_id()].push(std::make_pair(message, request_id)); } + bool SetChannelRange(AxisRange& new_range) { + // Image channel mutex should be locked before calling this. + // Extend or replace channel range with new range. + // Returns true if channel range was replaced. + bool is_new_range(false); + if (new_range.to == _channel_range.from - 1) { + // Extend lower range + _channel_range.from = new_range.from; + } else if (new_range.from == _channel_range.to + 1) { + // Extend upper range + _channel_range.to = new_range.to; + } else { + // Replace range with new range + _channel_range = new_range; + is_new_range = true; + } + return is_new_range; + } + + bool IsInChannelRange(int file_id, int channel) { + // Lock image channel mutex and check if channel is in range + ImageChannelLock(file_id); + bool is_in_range = channel >= _channel_range.from && channel <= _channel_range.to; + ImageChannelUnlock(file_id); + return is_in_range; + } + // Task handling void ExecuteSetChannelEvt(std::pair request) { OnSetImageChannels(request.first); @@ -302,6 +344,7 @@ class Session { // Manage image channel/z std::unordered_map _image_channel_mutexes; std::unordered_map _image_channel_task_active; + AxisRange _channel_range; // Cube histogram progress: 0.0 to 1.0 (complete) float _histogram_progress;