~ubuntu-branches/ubuntu/saucy/ecasound2.2/saucy

« back to all changes in this revision

Viewing changes to libecasound/eca-engine.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Junichi Uekawa
  • Date: 2009-11-02 18:22:35 UTC
  • mfrom: (5.1.2 sid)
  • Revision ID: james.westby@ubuntu.com-20091102182235-4ngh7699dmkgonyu
Tags: 2.7.0-1
* New upstream release.
* Depend on libreadline-dev instead of libreadline5-dev by request of
  Mattias Klose. It's now libreadline6-dev. (closes: #553748)
* Update menu file to use section Applications/ instead of Apps/.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
// ------------------------------------------------------------------------
2
2
// eca-engine.cpp: Main processing engine
3
 
// Copyright (C) 1999-2008 Kai Vehmanen
 
3
// Copyright (C) 1999-2009 Kai Vehmanen
4
4
// Copyright (C) 2005 Stuart Allie
5
5
//
6
6
// Attributes:
53
53
#include "eca-chainop.h"
54
54
#include "eca-error.h"
55
55
#include "eca-logger.h"
 
56
#include "eca-chainsetup-edit.h"
56
57
#include "eca-engine.h"
57
58
#include "eca-engine_impl.h"
58
59
 
111
112
      engine_repp->engine_iteration();
112
113
    }
113
114
    else {
114
 
      /* case 3a: engine finished and in batch mode -> exit */
115
 
      if ((engine_repp->status() == ECA_ENGINE::engine_status_finished ||
116
 
           engine_repp->status() == ECA_ENGINE::engine_status_error) &&
 
115
      /* case 3a-i: engine finished and in batch mode -> exit */
 
116
      if (engine_repp->status() == ECA_ENGINE::engine_status_finished &&
117
117
          engine_repp->batch_mode() == true) {
118
 
        /* batch operation finished (or error occured) */
 
118
        ECA_LOG_MSG(ECA_LOGGER::system_objects, "batch finished in exec, exit");
 
119
        break;
 
120
      }
 
121
 
 
122
      /* case 3a-ii: engine error occured -> exit */
 
123
      else if (engine_repp->status() == ECA_ENGINE::engine_status_error) {
 
124
        ECA_LOG_MSG(ECA_LOGGER::system_objects, "engine error, exit");
119
125
        break;
120
126
      }
121
127
 
325
331
 */
326
332
void ECA_ENGINE::command(Engine_command_t cmd, double arg)
327
333
{
328
 
  impl_repp->command_queue_rep.push_back(static_cast<int>(cmd),arg);
 
334
  ECA_ENGINE::complex_command_t item;
 
335
  item.type = cmd;
 
336
  item.m.legacy.value = arg;
 
337
  impl_repp->command_queue_rep.push_back(item);
 
338
}
 
339
 
 
340
/**
 
341
 * Sends 'ccmd' to engines command queue. Commands are 
 
342
 * processed in the server's main loop. Passing a complex
 
343
 * command allows to address objects regardless of
 
344
 * the state of ECA_CHAINSETUP iterators (i.e. currently
 
345
 * selected objects).
 
346
 *
 
347
 * context: C-level-0
 
348
 *          must no be called from exec() context
 
349
 */
 
350
void ECA_ENGINE::command(complex_command_t ccmd)
 
351
{
 
352
  impl_repp->command_queue_rep.push_back(ccmd);
329
353
}
330
354
 
331
355
/**
458
482
 */
459
483
void ECA_ENGINE::check_command_queue(void)
460
484
{
461
 
  interpret_queue();
 
485
  while(impl_repp->command_queue_rep.is_empty() != true) {
 
486
    ECA_ENGINE::complex_command_t item;
 
487
    int popres = impl_repp->command_queue_rep.pop_front(&item);
 
488
 
 
489
    if (popres <= 0) {
 
490
      /* queue is empty or temporarily unavailable, unable to continue 
 
491
       * processing messages without blocking */
 
492
      break;
 
493
    }
 
494
 
 
495
    switch(item.type) 
 
496
      {
 
497
        // ---
 
498
        // Basic commands.
 
499
        // ---            
 
500
      case ep_exit:
 
501
        {
 
502
          edit_lock_rep = true;
 
503
          if (status() == engine_status_running || 
 
504
              status() == engine_status_finished) request_stop();
 
505
          impl_repp->command_queue_rep.clear();
 
506
          ECA_LOG_MSG(ECA_LOGGER::system_objects,"ecasound_queue: exit!");
 
507
          driver_repp->exit();
 
508
          return;
 
509
        }
 
510
 
 
511
        // ---
 
512
        // Chain operators (stateless addressing)
 
513
        // ---
 
514
      case ep_exec_edit: {
 
515
        csetup_repp->execute_edit(item.m.cs);
 
516
        break;
 
517
      }
 
518
 
 
519
      case ep_prepare: { if (is_prepared() != true) prepare_operation(); break; }
 
520
      case ep_start: { if (status() != engine_status_running) request_start(); break; }
 
521
      case ep_stop: { if (status() == engine_status_running || 
 
522
                          status() == engine_status_finished) request_stop(); break; }
 
523
        
 
524
        // ---
 
525
        // Edit locks
 
526
        // ---            
 
527
      case ep_edit_lock: { edit_lock_rep = true; break; }
 
528
      case ep_edit_unlock: { edit_lock_rep = false; break; }
 
529
        
 
530
        // ---
 
531
        // Section/chain (en/dis)abling commands.
 
532
        // ---
 
533
      case ep_c_select: { csetup_repp->selected_chain_index_rep = static_cast<size_t>(item.m.legacy.value); break; }
 
534
      case ep_c_muting: { chain_muting(); break; }
 
535
      case ep_c_bypass: { chain_processing(); break; }
 
536
 
 
537
        // ---
 
538
        // Global position
 
539
        // ---
 
540
      case ep_rewind: { change_position(- item.m.legacy.value); break; }
 
541
      case ep_forward: { change_position(item.m.legacy.value); break; }
 
542
      case ep_setpos: { set_position(item.m.legacy.value); break; }
 
543
      case ep_setpos_samples: { set_position_samples(static_cast<SAMPLE_SPECS::sample_pos_t>(item.m.legacy.value)); break; }
 
544
      case ep_setpos_live_samples: { set_position_samples_live(static_cast<SAMPLE_SPECS::sample_pos_t>(item.m.legacy.value)); break; }
 
545
 
 
546
      case ep_debug: break;
 
547
 
 
548
      } /* switch */
 
549
    
 
550
  }
462
551
}
463
552
 
464
553
/**
489
578
  finished_rep = false;
490
579
  inputs_not_finished_rep = 1; // for the 1st iteration
491
580
  outputs_finished_rep = 0;
 
581
  mixslot_repp->event_tag_set(SAMPLE_BUFFER::tag_end_of_stream, false);
 
582
  for(size_t n = 0; n < cslots_rep.size(); n++) {
 
583
    cslots_rep[n]->event_tag_set(SAMPLE_BUFFER::tag_end_of_stream, false);
 
584
  }
492
585
}
493
586
 
494
587
/**
788
881
 * Requests the engine driver to start operation.
789
882
 *
790
883
 * This function should only be called from 
791
 
 * interpret_queue().
 
884
 * check_command_queue().
792
885
 * 
793
886
 * @pre status() != engine_status_running
794
887
 *
811
904
 * Requests the engine driver to stop operation.
812
905
 *
813
906
 * This function should only be called from 
814
 
 * interpret_queue().
 
907
 * check_command_queue().
815
908
 *
816
909
 * @pre status() == ECA_ENGINE::engine_status_running ||
817
910
 *      status() == ECA_ENGINE::engine_status_finished
1160
1253
}
1161
1254
 
1162
1255
/**********************************************************************
1163
 
 * Engine implementation - Private functions for cmd queue handling
1164
 
 **********************************************************************/
1165
 
 
1166
 
/**
1167
 
 * Processes messages from the command queue.
1168
 
 * If no messages are available, function
1169
 
 * will return immediately.
1170
 
 *
1171
 
 * context: E-level-2
1172
 
 *          can be run at the same time as engine_iteration(); 
1173
 
 *          note! this is called with the engine lock held
1174
 
 *          so no long operations allowed!
1175
 
 *
1176
 
 * @see check_command_queue()
1177
 
 */
1178
 
void ECA_ENGINE::interpret_queue(void)
1179
 
{
1180
 
  while(impl_repp->command_queue_rep.is_empty() != true) {
1181
 
    const std::pair<int,double>* item_p = impl_repp->command_queue_rep.front();
1182
 
    std::pair<int,double> item;
1183
 
    if (item_p != impl_repp->command_queue_rep.invalid_item()) {
1184
 
      item = *item_p;
1185
 
    }
1186
 
    else {
1187
 
      /* queue temporarily unavailable, unable to continue processing
1188
 
       * messages */
1189
 
      break;
1190
 
    }
1191
 
 
1192
 
    switch(item.first) 
1193
 
      {
1194
 
        // ---
1195
 
        // Basic commands.
1196
 
        // ---            
1197
 
      case ep_exit:
1198
 
        {
1199
 
          edit_lock_rep = true;
1200
 
          if (status() == engine_status_running || 
1201
 
              status() == engine_status_finished) request_stop();
1202
 
          while(impl_repp->command_queue_rep.is_empty() == false) impl_repp->command_queue_rep.pop_front();
1203
 
          ECA_LOG_MSG(ECA_LOGGER::system_objects,"ecasound_queue: exit!");
1204
 
          driver_repp->exit();
1205
 
          return;
1206
 
        }
1207
 
 
1208
 
      case ep_prepare: { if (is_prepared() != true) prepare_operation(); break; }
1209
 
      case ep_start: { if (status() != engine_status_running) request_start(); break; }
1210
 
      case ep_stop: { if (status() == engine_status_running || 
1211
 
                          status() == engine_status_finished) request_stop(); break; }
1212
 
        
1213
 
        // ---
1214
 
        // Edit locks
1215
 
        // ---            
1216
 
      case ep_edit_lock: { edit_lock_rep = true; break; }
1217
 
      case ep_edit_unlock: { edit_lock_rep = false; break; }
1218
 
        
1219
 
        // ---
1220
 
        // Section/chain (en/dis)abling commands.
1221
 
        // ---
1222
 
      case ep_c_select: { csetup_repp->active_chain_index_rep = static_cast<size_t>(item.second); break; }
1223
 
      case ep_c_muting: { chain_muting(); break; }
1224
 
      case ep_c_bypass: { chain_processing(); break; }
1225
 
        
1226
 
        // ---
1227
 
        // Chain operators
1228
 
        // ---
1229
 
      case ep_cop_select: { 
1230
 
        csetup_repp->active_chainop_index_rep =  static_cast<size_t>(item.second);
1231
 
        if (csetup_repp->active_chainop_index_rep - 1 < static_cast<int>((*chains_repp)[csetup_repp->active_chain_index_rep]->number_of_chain_operators()))
1232
 
          (*chains_repp)[csetup_repp->active_chain_index_rep]->select_chain_operator(csetup_repp->active_chainop_index_rep);
1233
 
        else 
1234
 
          csetup_repp->active_chainop_index_rep = 0;
1235
 
        break;
1236
 
      }
1237
 
      case ep_copp_select: { 
1238
 
        csetup_repp->active_chainop_param_index_rep = static_cast<size_t>(item.second);
1239
 
        (*chains_repp)[csetup_repp->active_chain_index_rep]->select_chain_operator_parameter(csetup_repp->active_chainop_param_index_rep);
1240
 
        break;
1241
 
      }
1242
 
      case ep_copp_value: { 
1243
 
        assert(chains_repp != 0);
1244
 
        (*chains_repp)[csetup_repp->active_chain_index_rep]->set_parameter(item.second);
1245
 
        break;
1246
 
      }
1247
 
        
1248
 
        // ---
1249
 
        // Controllers
1250
 
        // ---
1251
 
      case ep_ctrl_select: { 
1252
 
        csetup_repp->active_ctrl_index_rep =  static_cast<size_t>(item.second);
1253
 
        if (csetup_repp->active_ctrl_index_rep - 1 < static_cast<int>((*chains_repp)[csetup_repp->active_chain_index_rep]->number_of_controllers()))
1254
 
          (*chains_repp)[csetup_repp->active_chain_index_rep]->select_controller(csetup_repp->active_ctrl_index_rep);
1255
 
        else 
1256
 
          csetup_repp->active_ctrl_index_rep = 0;
1257
 
        break;
1258
 
      }
1259
 
      case ep_ctrlp_select: { 
1260
 
        csetup_repp->active_ctrl_param_index_rep = static_cast<size_t>(item.second);
1261
 
        (*chains_repp)[csetup_repp->active_chain_index_rep]->select_controller_parameter(csetup_repp->active_ctrl_param_index_rep);
1262
 
        break;
1263
 
      }
1264
 
      case ep_ctrlp_value: { 
1265
 
        assert(chains_repp != 0);
1266
 
        (*chains_repp)[csetup_repp->active_chain_index_rep]->set_controller_parameter(item.second);
1267
 
        break;
1268
 
      }
1269
 
        // ---
1270
 
        // Global position
1271
 
        // ---
1272
 
      case ep_rewind: { change_position(- item.second); break; }
1273
 
      case ep_forward: { change_position(item.second); break; }
1274
 
      case ep_setpos: { set_position(item.second); break; }
1275
 
      case ep_setpos_samples: { set_position_samples(static_cast<SAMPLE_SPECS::sample_pos_t>(item.second)); break; }
1276
 
      case ep_setpos_live_samples: { set_position_samples_live(static_cast<SAMPLE_SPECS::sample_pos_t>(item.second)); break; }
1277
 
      } /* switch */
1278
 
    
1279
 
    impl_repp->command_queue_rep.pop_front();
1280
 
  }
1281
 
}
1282
 
 
1283
 
/**********************************************************************
1284
1256
 * Engine implementation - Private functions for setup and cleanup
1285
1257
 **********************************************************************/
1286
1258
 
1372
1344
 */
1373
1345
void ECA_ENGINE::init_chains(void)
1374
1346
{
1375
 
 
1376
1347
  mixslot_repp->number_of_channels(max_channels());
 
1348
  mixslot_repp->event_tag_set(SAMPLE_BUFFER::tag_mixed_content);
1377
1349
 
1378
1350
  cslots_rep.resize(chains_repp->size());
1379
1351
  for(size_t n = 0; n < cslots_rep.size(); n++) {
1648
1620
        else {
1649
1621
          /* case-1b: input connected to chain 'n', copy 'mixslot' to 
1650
1622
           *          the matching per-chain slot */
1651
 
          cslots_rep[c]->number_of_channels(mixslot_repp->number_of_channels());
1652
 
          cslots_rep[c]->copy(*mixslot_repp);
 
1623
          cslots_rep[c]->copy_all_content(*mixslot_repp);
1653
1624
        }
1654
1625
      }
1655
1626
    }
1675
1646
    if (from->number_of_channels() < to->number_of_channels()) {
1676
1647
      to->make_silent();
1677
1648
    }
1678
 
    to->copy(*from);
 
1649
    to->copy_matching_channels(*from);
1679
1650
    to->divide_by(divide_by);
1680
1651
  }
1681
1652
  else {
1690
1661
    if (from->number_of_channels() < to->number_of_channels()) {
1691
1662
      to->make_silent();
1692
1663
    }
1693
 
    to->copy(*from);
 
1664
    to->copy_matching_channels(*from);
1694
1665
  }
1695
1666
  else {
1696
 
    to->add(*from);
 
1667
    to->add_matching_channels(*from);
1697
1668
  }
1698
1669
}
1699
1670
 
1754
1725
          else
1755
1726
            mix_to_outputs_sum_helper(cslots_rep[n], mixslot_repp, (count == 1));
1756
1727
 
 
1728
          mixslot_repp->event_tags_add(*cslots_rep[n]);
 
1729
 
1757
1730
          if (count == output_chain_count_rep[outputnum]) {
1758
1731
            (*outputs_repp)[outputnum]->write_buffer(mixslot_repp);
1759
1732
            if ((*outputs_repp)[outputnum]->finished() == true) 
1778
1751
 */
1779
1752
void ECA_ENGINE::chain_muting(void)
1780
1753
{
1781
 
  if ((*chains_repp)[csetup_repp->active_chain_index_rep]->is_muted()) 
1782
 
    (*chains_repp)[csetup_repp->active_chain_index_rep]->toggle_muting(false);
 
1754
  if ((*chains_repp)[csetup_repp->selected_chain_index_rep]->is_muted()) 
 
1755
    (*chains_repp)[csetup_repp->selected_chain_index_rep]->toggle_muting(false);
1783
1756
  else
1784
 
    (*chains_repp)[csetup_repp->active_chain_index_rep]->toggle_muting(true);
 
1757
    (*chains_repp)[csetup_repp->selected_chain_index_rep]->toggle_muting(true);
1785
1758
}
1786
1759
 
1787
1760
/**
1789
1762
 */
1790
1763
void ECA_ENGINE::chain_processing(void)
1791
1764
{
1792
 
  if ((*chains_repp)[csetup_repp->active_chain_index_rep]->is_processing()) 
1793
 
    (*chains_repp)[csetup_repp->active_chain_index_rep]->toggle_processing(false);
 
1765
  if ((*chains_repp)[csetup_repp->selected_chain_index_rep]->is_processing()) 
 
1766
    (*chains_repp)[csetup_repp->selected_chain_index_rep]->toggle_processing(false);
1794
1767
  else
1795
 
    (*chains_repp)[csetup_repp->active_chain_index_rep]->toggle_processing(true);
 
1768
    (*chains_repp)[csetup_repp->selected_chain_index_rep]->toggle_processing(true);
1796
1769
}
1797
1770
 
1798
1771
/**********************************************************************