annotate view/ViewManager.cpp @ 282:d9319859a4cf tip

(none)
author benoitrigolleau
date Fri, 31 Oct 2008 11:00:24 +0000
parents be6d31baecb9
children
rev   line source
lbajardsilogic@0 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
lbajardsilogic@0 2
lbajardsilogic@0 3 /*
lbajardsilogic@0 4 Sonic Visualiser
lbajardsilogic@0 5 An audio file viewer and annotation editor.
lbajardsilogic@0 6 Centre for Digital Music, Queen Mary, University of London.
lbajardsilogic@0 7 This file copyright 2006 Chris Cannam and QMUL.
lbajardsilogic@0 8
lbajardsilogic@0 9 This program is free software; you can redistribute it and/or
lbajardsilogic@0 10 modify it under the terms of the GNU General Public License as
lbajardsilogic@0 11 published by the Free Software Foundation; either version 2 of the
lbajardsilogic@0 12 License, or (at your option) any later version. See the file
lbajardsilogic@0 13 COPYING included with this distribution for more information.
lbajardsilogic@0 14 */
lbajardsilogic@0 15
lbajardsilogic@0 16 #include "ViewManager.h"
lbajardsilogic@0 17 #include "base/AudioPlaySource.h"
lbajardsilogic@0 18 #include "data/model/Model.h"
lbajardsilogic@0 19 #include "base/CommandHistory.h"
lbajardsilogic@0 20 #include "View.h"
lbajardsilogic@0 21 #include "system/System.h"
lbajardsilogic@0 22
lbajardsilogic@0 23 #include <QSettings>
lbajardsilogic@0 24
lbajardsilogic@0 25 #include <iostream>
lbajardsilogic@0 26
lbajardsilogic@0 27 //#define DEBUG_VIEW_MANAGER 1
lbajardsilogic@0 28
lbajardsilogic@0 29 ViewManager::ViewManager() :
lbajardsilogic@0 30 m_playSource(0),
lbajardsilogic@0 31 m_globalCentreFrame(0),
lbajardsilogic@0 32 m_globalZoom(1024),
lbajardsilogic@0 33 m_playbackFrame(0),
lbajardsilogic@0 34 m_mainModelSampleRate(0),
lbajardsilogic@0 35 m_lastLeft(0),
lbajardsilogic@0 36 m_lastRight(0),
lbajardsilogic@0 37 m_inProgressExclusive(true),
lbajardsilogic@0 38 m_toolMode(NavigateMode),
lbajardsilogic@0 39 m_playLoopMode(false),
lbajardsilogic@0 40 m_playSelectionMode(false),
lbajardsilogic@0 41 m_overlayMode(StandardOverlays),
lbajardsilogic@0 42 m_zoomWheelsEnabled(true)
lbajardsilogic@0 43 {
lbajardsilogic@0 44 QSettings settings;
lbajardsilogic@0 45 settings.beginGroup("MainWindow");
lbajardsilogic@0 46 m_overlayMode = OverlayMode
lbajardsilogic@0 47 (settings.value("overlay-mode", int(m_overlayMode)).toInt());
lbajardsilogic@0 48 m_zoomWheelsEnabled =
lbajardsilogic@0 49 settings.value("zoom-wheels-enabled", m_zoomWheelsEnabled).toBool();
lbajardsilogic@0 50 settings.endGroup();
lbajardsilogic@0 51 /*!!!
lbajardsilogic@0 52 connect(this,
lbajardsilogic@0 53 SIGNAL(zoomLevelChanged(void *, unsigned long, bool)),
lbajardsilogic@0 54 SLOT(considerZoomChange(void *, unsigned long, bool)));
lbajardsilogic@0 55 */
lbajardsilogic@0 56 }
lbajardsilogic@0 57
lbajardsilogic@0 58 ViewManager::~ViewManager()
lbajardsilogic@0 59 {
lbajardsilogic@0 60 }
lbajardsilogic@0 61
lbajardsilogic@0 62 unsigned long
lbajardsilogic@0 63 ViewManager::getGlobalCentreFrame() const
lbajardsilogic@0 64 {
lbajardsilogic@0 65 #ifdef DEBUG_VIEW_MANAGER
lbajardsilogic@0 66 std::cout << "ViewManager::getGlobalCentreFrame: returning " << m_globalCentreFrame << std::endl;
lbajardsilogic@0 67 #endif
lbajardsilogic@0 68 return m_globalCentreFrame;
lbajardsilogic@0 69 }
lbajardsilogic@0 70
lbajardsilogic@0 71 void
lbajardsilogic@0 72 ViewManager::setGlobalCentreFrame(unsigned long f)
lbajardsilogic@0 73 {
lbajardsilogic@0 74 #ifdef DEBUG_VIEW_MANAGER
lbajardsilogic@0 75 std::cout << "ViewManager::setGlobalCentreFrame to " << f << std::endl;
lbajardsilogic@0 76 #endif
lbajardsilogic@0 77 m_globalCentreFrame = f;
lbajardsilogic@0 78 emit globalCentreFrameChanged(f);
lbajardsilogic@0 79 }
lbajardsilogic@0 80
lbajardsilogic@0 81 unsigned long
lbajardsilogic@0 82 ViewManager::getGlobalZoom() const
lbajardsilogic@0 83 {
lbajardsilogic@0 84 #ifdef DEBUG_VIEW_MANAGER
lbajardsilogic@0 85 std::cout << "ViewManager::getGlobalZoom: returning " << m_globalZoom << std::endl;
lbajardsilogic@0 86 #endif
lbajardsilogic@0 87 return m_globalZoom;
lbajardsilogic@0 88 }
lbajardsilogic@0 89
lbajardsilogic@0 90 unsigned long
lbajardsilogic@0 91 ViewManager::getPlaybackFrame() const
lbajardsilogic@0 92 {
lbajardsilogic@0 93 if (m_playSource && m_playSource->isPlaying()) {
lbajardsilogic@0 94 m_playbackFrame = m_playSource->getCurrentPlayingFrame();
lbajardsilogic@0 95 }
lbajardsilogic@0 96 return m_playbackFrame;
lbajardsilogic@0 97 }
lbajardsilogic@0 98
lbajardsilogic@0 99 void
lbajardsilogic@0 100 ViewManager::setPlaybackFrame(unsigned long f)
lbajardsilogic@0 101 {
lbajardsilogic@0 102 if (m_playbackFrame != f) {
lbajardsilogic@0 103 m_playbackFrame = f;
lbajardsilogic@0 104 emit playbackFrameChanged(f);
lbajardsilogic@0 105 if (m_playSource && m_playSource->isPlaying()) {
lbajardsilogic@0 106 m_playSource->play(f);
lbajardsilogic@0 107 }
lbajardsilogic@0 108 }
lbajardsilogic@0 109 }
lbajardsilogic@0 110
lbajardsilogic@0 111 bool
lbajardsilogic@0 112 ViewManager::haveInProgressSelection() const
lbajardsilogic@0 113 {
lbajardsilogic@0 114 return !m_inProgressSelection.isEmpty();
lbajardsilogic@0 115 }
lbajardsilogic@0 116
lbajardsilogic@0 117 const Selection &
lbajardsilogic@0 118 ViewManager::getInProgressSelection(bool &exclusive) const
lbajardsilogic@0 119 {
lbajardsilogic@0 120 exclusive = m_inProgressExclusive;
lbajardsilogic@0 121 return m_inProgressSelection;
lbajardsilogic@0 122 }
lbajardsilogic@0 123
lbajardsilogic@0 124 void
lbajardsilogic@0 125 ViewManager::setInProgressSelection(const Selection &selection, bool exclusive)
lbajardsilogic@0 126 {
lbajardsilogic@0 127 m_inProgressExclusive = exclusive;
lbajardsilogic@0 128 m_inProgressSelection = selection;
lbajardsilogic@0 129 if (exclusive) clearSelections();
lbajardsilogic@0 130 emit inProgressSelectionChanged();
lbajardsilogic@0 131 }
lbajardsilogic@0 132
lbajardsilogic@0 133 void
lbajardsilogic@0 134 ViewManager::clearInProgressSelection()
lbajardsilogic@0 135 {
lbajardsilogic@0 136 m_inProgressSelection = Selection();
lbajardsilogic@0 137 emit inProgressSelectionChanged();
lbajardsilogic@0 138 }
lbajardsilogic@0 139
lbajardsilogic@0 140 const MultiSelection &
lbajardsilogic@0 141 ViewManager::getSelection() const
lbajardsilogic@0 142 {
lbajardsilogic@0 143 return m_selections;
lbajardsilogic@0 144 }
lbajardsilogic@0 145
lbajardsilogic@0 146 const MultiSelection::SelectionList &
lbajardsilogic@0 147 ViewManager::getSelections() const
lbajardsilogic@0 148 {
lbajardsilogic@0 149 return m_selections.getSelections();
lbajardsilogic@0 150 }
lbajardsilogic@0 151
lbajardsilogic@0 152 void
lbajardsilogic@0 153 ViewManager::setSelection(const Selection &selection)
lbajardsilogic@0 154 {
lbajardsilogic@0 155 MultiSelection ms(m_selections);
lbajardsilogic@0 156 ms.setSelection(selection);
lbajardsilogic@0 157 setSelections(ms);
lbajardsilogic@0 158 }
lbajardsilogic@0 159
lbajardsilogic@0 160 void
lbajardsilogic@0 161 ViewManager::addSelection(const Selection &selection)
lbajardsilogic@0 162 {
lbajardsilogic@0 163 MultiSelection ms(m_selections);
lbajardsilogic@0 164 ms.addSelection(selection);
lbajardsilogic@0 165 setSelections(ms);
lbajardsilogic@0 166 }
lbajardsilogic@0 167
lbajardsilogic@0 168 void
lbajardsilogic@0 169 ViewManager::removeSelection(const Selection &selection)
lbajardsilogic@0 170 {
lbajardsilogic@0 171 MultiSelection ms(m_selections);
lbajardsilogic@0 172 ms.removeSelection(selection);
lbajardsilogic@0 173 setSelections(ms);
lbajardsilogic@0 174 }
lbajardsilogic@0 175
lbajardsilogic@0 176 void
lbajardsilogic@0 177 ViewManager::clearSelections()
lbajardsilogic@0 178 {
lbajardsilogic@0 179 MultiSelection ms(m_selections);
lbajardsilogic@0 180 ms.clearSelections();
lbajardsilogic@0 181 setSelections(ms);
lbajardsilogic@0 182 }
lbajardsilogic@0 183
lbajardsilogic@0 184 void
lbajardsilogic@0 185 ViewManager::setSelections(const MultiSelection &ms)
lbajardsilogic@0 186 {
lbajardsilogic@0 187 if (m_selections.getSelections() == ms.getSelections()) return;
lbajardsilogic@0 188 SetSelectionCommand *command = new SetSelectionCommand(this, ms);
lbajardsilogic@0 189 CommandHistory::getInstance()->addCommand(command);
lbajardsilogic@0 190 }
lbajardsilogic@0 191
lbajardsilogic@0 192 void
lbajardsilogic@0 193 ViewManager::signalSelectionChange()
lbajardsilogic@0 194 {
lbajardsilogic@0 195 emit selectionChanged();
lbajardsilogic@0 196 }
lbajardsilogic@0 197
lbajardsilogic@0 198 ViewManager::SetSelectionCommand::SetSelectionCommand(ViewManager *vm,
lbajardsilogic@0 199 const MultiSelection &ms) :
lbajardsilogic@0 200 m_vm(vm),
lbajardsilogic@0 201 m_oldSelection(vm->m_selections),
lbajardsilogic@0 202 m_newSelection(ms)
lbajardsilogic@0 203 {
lbajardsilogic@0 204 }
lbajardsilogic@0 205
lbajardsilogic@0 206 ViewManager::SetSelectionCommand::~SetSelectionCommand() { }
lbajardsilogic@0 207
lbajardsilogic@0 208 void
lbajardsilogic@0 209 ViewManager::SetSelectionCommand::execute()
lbajardsilogic@0 210 {
lbajardsilogic@0 211 m_vm->m_selections = m_newSelection;
lbajardsilogic@0 212 m_vm->signalSelectionChange();
lbajardsilogic@0 213 }
lbajardsilogic@0 214
lbajardsilogic@0 215 void
lbajardsilogic@0 216 ViewManager::SetSelectionCommand::unexecute()
lbajardsilogic@0 217 {
lbajardsilogic@0 218 m_vm->m_selections = m_oldSelection;
lbajardsilogic@0 219 m_vm->signalSelectionChange();
lbajardsilogic@0 220 }
lbajardsilogic@0 221
lbajardsilogic@0 222 QString
lbajardsilogic@0 223 ViewManager::SetSelectionCommand::getName() const
lbajardsilogic@0 224 {
lbajardsilogic@0 225 if (m_newSelection.getSelections().empty()) return tr("Clear Selection");
lbajardsilogic@0 226 else return tr("Select");
lbajardsilogic@0 227 }
lbajardsilogic@0 228
lbajardsilogic@0 229 Selection
lbajardsilogic@0 230 ViewManager::getContainingSelection(size_t frame, bool defaultToFollowing) const
lbajardsilogic@0 231 {
lbajardsilogic@0 232 return m_selections.getContainingSelection(frame, defaultToFollowing);
lbajardsilogic@0 233 }
lbajardsilogic@0 234
lbajardsilogic@0 235 void
lbajardsilogic@0 236 ViewManager::setToolMode(ToolMode mode)
lbajardsilogic@0 237 {
lbajardsilogic@0 238 m_toolMode = mode;
lbajardsilogic@0 239
lbajardsilogic@0 240 emit toolModeChanged();
lbajardsilogic@0 241 }
lbajardsilogic@0 242
lbajardsilogic@0 243 void
lbajardsilogic@0 244 ViewManager::setPlayLoopMode(bool mode)
lbajardsilogic@0 245 {
lbajardsilogic@0 246 if (m_playLoopMode != mode) {
lbajardsilogic@0 247
lbajardsilogic@0 248 m_playLoopMode = mode;
lbajardsilogic@0 249
lbajardsilogic@0 250 emit playLoopModeChanged();
lbajardsilogic@0 251 emit playLoopModeChanged(mode);
lbajardsilogic@0 252 }
lbajardsilogic@0 253 }
lbajardsilogic@0 254
lbajardsilogic@0 255 void
lbajardsilogic@0 256 ViewManager::setPlaySelectionMode(bool mode)
lbajardsilogic@0 257 {
lbajardsilogic@0 258 if (m_playSelectionMode != mode) {
lbajardsilogic@0 259
lbajardsilogic@0 260 m_playSelectionMode = mode;
lbajardsilogic@0 261
lbajardsilogic@0 262 emit playSelectionModeChanged();
lbajardsilogic@0 263 emit playSelectionModeChanged(mode);
lbajardsilogic@0 264 }
lbajardsilogic@0 265 }
lbajardsilogic@0 266
lbajardsilogic@0 267 size_t
lbajardsilogic@0 268 ViewManager::getPlaybackSampleRate() const
lbajardsilogic@0 269 {
lbajardsilogic@0 270 if (m_playSource) {
lbajardsilogic@0 271 return m_playSource->getSourceSampleRate();
lbajardsilogic@0 272 }
lbajardsilogic@0 273 return 0;
lbajardsilogic@0 274 }
lbajardsilogic@0 275
lbajardsilogic@0 276 size_t
lbajardsilogic@0 277 ViewManager::getOutputSampleRate() const
lbajardsilogic@0 278 {
lbajardsilogic@0 279 if (m_playSource) {
lbajardsilogic@0 280 return m_playSource->getTargetSampleRate();
lbajardsilogic@0 281 }
lbajardsilogic@0 282 return 0;
lbajardsilogic@0 283 }
lbajardsilogic@0 284
lbajardsilogic@0 285 void
lbajardsilogic@0 286 ViewManager::setAudioPlaySource(AudioPlaySource *source)
lbajardsilogic@0 287 {
lbajardsilogic@0 288 if (!m_playSource) {
lbajardsilogic@0 289 QTimer::singleShot(100, this, SLOT(checkPlayStatus()));
lbajardsilogic@0 290 }
lbajardsilogic@0 291 m_playSource = source;
lbajardsilogic@0 292 }
lbajardsilogic@0 293
lbajardsilogic@0 294 void
lbajardsilogic@0 295 ViewManager::playStatusChanged(bool /* playing */)
lbajardsilogic@0 296 {
lbajardsilogic@0 297 checkPlayStatus();
lbajardsilogic@0 298 }
lbajardsilogic@0 299
lbajardsilogic@0 300 void
lbajardsilogic@0 301 ViewManager::checkPlayStatus()
lbajardsilogic@0 302 {
lbajardsilogic@0 303 if (m_playSource && m_playSource->isPlaying()) {
lbajardsilogic@0 304
lbajardsilogic@0 305 float left = 0, right = 0;
lbajardsilogic@0 306 if (m_playSource->getOutputLevels(left, right)) {
lbajardsilogic@0 307 if (left != m_lastLeft || right != m_lastRight) {
lbajardsilogic@0 308 emit outputLevelsChanged(left, right);
lbajardsilogic@0 309 m_lastLeft = left;
lbajardsilogic@0 310 m_lastRight = right;
lbajardsilogic@0 311 }
lbajardsilogic@0 312 }
lbajardsilogic@0 313
lbajardsilogic@0 314 m_playbackFrame = m_playSource->getCurrentPlayingFrame();
lbajardsilogic@0 315
lbajardsilogic@0 316 #ifdef DEBUG_VIEW_MANAGER
lbajardsilogic@0 317 std::cout << "ViewManager::checkPlayStatus: Playing, frame " << m_playbackFrame << ", levels " << m_lastLeft << "," << m_lastRight << std::endl;
lbajardsilogic@0 318 #endif
lbajardsilogic@0 319
lbajardsilogic@0 320 emit playbackFrameChanged(m_playbackFrame);
lbajardsilogic@0 321
lbajardsilogic@0 322 QTimer::singleShot(20, this, SLOT(checkPlayStatus()));
lbajardsilogic@0 323
lbajardsilogic@0 324 } else {
lbajardsilogic@0 325
lbajardsilogic@0 326 QTimer::singleShot(100, this, SLOT(checkPlayStatus()));
lbajardsilogic@0 327
lbajardsilogic@0 328 if (m_lastLeft != 0.0 || m_lastRight != 0.0) {
lbajardsilogic@0 329 emit outputLevelsChanged(0.0, 0.0);
lbajardsilogic@0 330 m_lastLeft = 0.0;
lbajardsilogic@0 331 m_lastRight = 0.0;
lbajardsilogic@0 332 }
lbajardsilogic@0 333
lbajardsilogic@0 334 #ifdef DEBUG_VIEW_MANAGER
lbajardsilogic@0 335 // std::cout << "ViewManager::checkPlayStatus: Not playing" << std::endl;
lbajardsilogic@0 336 #endif
lbajardsilogic@0 337 }
lbajardsilogic@0 338 }
lbajardsilogic@0 339
lbajardsilogic@0 340 bool
lbajardsilogic@0 341 ViewManager::isPlaying() const
lbajardsilogic@0 342 {
lbajardsilogic@0 343 return m_playSource && m_playSource->isPlaying();
lbajardsilogic@0 344 }
lbajardsilogic@0 345
lbajardsilogic@0 346 void
lbajardsilogic@0 347 ViewManager::viewCentreFrameChanged(unsigned long f, bool locked,
lbajardsilogic@0 348 PlaybackFollowMode mode)
lbajardsilogic@0 349 {
lbajardsilogic@0 350 View *v = dynamic_cast<View *>(sender());
lbajardsilogic@0 351
lbajardsilogic@0 352 if (locked) {
lbajardsilogic@0 353 m_globalCentreFrame = f;
lbajardsilogic@0 354 emit globalCentreFrameChanged(f);
lbajardsilogic@0 355 } else {
lbajardsilogic@0 356 if (v) emit viewCentreFrameChanged(v, f);
lbajardsilogic@0 357 }
lbajardsilogic@0 358
lbajardsilogic@0 359 if (mode == PlaybackIgnore) {
lbajardsilogic@0 360 return;
lbajardsilogic@0 361 }
lbajardsilogic@0 362
lbajardsilogic@0 363 seek(f);
lbajardsilogic@0 364 }
lbajardsilogic@0 365
lbajardsilogic@0 366 void
lbajardsilogic@0 367 ViewManager::seek(unsigned long f)
lbajardsilogic@0 368 {
lbajardsilogic@0 369 #ifdef DEBUG_VIEW_MANAGER
lbajardsilogic@0 370 std::cout << "ViewManager::seek(" << f << ")" << std::endl;
lbajardsilogic@0 371 #endif
lbajardsilogic@0 372
lbajardsilogic@0 373 if (m_playSource && m_playSource->isPlaying()) {
lbajardsilogic@0 374 unsigned long playFrame = m_playSource->getCurrentPlayingFrame();
lbajardsilogic@191 375 unsigned long diff = MAX(f, playFrame) - MIN(f, playFrame);
lbajardsilogic@0 376 if (diff > 20000) {
lbajardsilogic@0 377 m_playbackFrame = f;
lbajardsilogic@0 378 m_playSource->play(f);
lbajardsilogic@0 379 #ifdef DEBUG_VIEW_MANAGER
lbajardsilogic@0 380 std::cout << "ViewManager::considerSeek: reseeking from " << playFrame << " to " << f << std::endl;
lbajardsilogic@0 381 #endif
lbajardsilogic@0 382 emit playbackFrameChanged(f);
lbajardsilogic@0 383 }
lbajardsilogic@0 384 } else {
lbajardsilogic@0 385 if (m_playbackFrame != f) {
lbajardsilogic@0 386 m_playbackFrame = f;
lbajardsilogic@0 387 emit playbackFrameChanged(f);
lbajardsilogic@0 388 }
lbajardsilogic@0 389 }
lbajardsilogic@0 390 }
lbajardsilogic@0 391
lbajardsilogic@0 392 void
lbajardsilogic@0 393 ViewManager::viewZoomLevelChanged(unsigned long z, bool locked)
lbajardsilogic@0 394 {
lbajardsilogic@0 395 View *v = dynamic_cast<View *>(sender());
lbajardsilogic@0 396
lbajardsilogic@0 397 if (!v) {
lbajardsilogic@0 398 std::cerr << "ViewManager::viewZoomLevelChanged: WARNING: sender is not a view" << std::endl;
lbajardsilogic@0 399 return;
lbajardsilogic@0 400 }
lbajardsilogic@0 401
lbajardsilogic@0 402 //!!! emit zoomLevelChanged();
lbajardsilogic@0 403
lbajardsilogic@0 404 if (locked) {
lbajardsilogic@0 405 m_globalZoom = z;
lbajardsilogic@0 406 }
lbajardsilogic@0 407
lbajardsilogic@0 408 #ifdef DEBUG_VIEW_MANAGER
lbajardsilogic@0 409 std::cout << "ViewManager::viewZoomLevelChanged(" << v << ", " << z << ", " << locked << ")" << std::endl;
lbajardsilogic@0 410 #endif
lbajardsilogic@0 411
lbajardsilogic@0 412 emit viewZoomLevelChanged(v, z, locked);
lbajardsilogic@0 413 }
lbajardsilogic@0 414
lbajardsilogic@0 415 void
lbajardsilogic@0 416 ViewManager::setOverlayMode(OverlayMode mode)
lbajardsilogic@0 417 {
lbajardsilogic@0 418 if (m_overlayMode != mode) {
lbajardsilogic@0 419 m_overlayMode = mode;
lbajardsilogic@0 420 emit overlayModeChanged();
lbajardsilogic@0 421 }
lbajardsilogic@0 422
lbajardsilogic@0 423 QSettings settings;
lbajardsilogic@0 424 settings.beginGroup("MainWindow");
lbajardsilogic@0 425 settings.setValue("overlay-mode", int(m_overlayMode));
lbajardsilogic@0 426 settings.endGroup();
lbajardsilogic@0 427 }
lbajardsilogic@0 428
lbajardsilogic@0 429 void
lbajardsilogic@0 430 ViewManager::setZoomWheelsEnabled(bool enabled)
lbajardsilogic@0 431 {
lbajardsilogic@0 432 if (m_zoomWheelsEnabled != enabled) {
lbajardsilogic@0 433 m_zoomWheelsEnabled = enabled;
lbajardsilogic@0 434 emit zoomWheelsEnabledChanged();
lbajardsilogic@0 435 }
lbajardsilogic@0 436
lbajardsilogic@0 437 QSettings settings;
lbajardsilogic@0 438 settings.beginGroup("MainWindow");
lbajardsilogic@0 439 settings.setValue("zoom-wheels-enabled", m_zoomWheelsEnabled);
lbajardsilogic@0 440 settings.endGroup();
lbajardsilogic@0 441 }
lbajardsilogic@0 442