/[svn]/libgig/trunk/src/gig.cpp
ViewVC logotype

Diff of /libgig/trunk/src/gig.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 2152 by persson, Fri Dec 17 16:51:48 2010 UTC revision 2467 by schoenebeck, Sun Sep 8 16:25:42 2013 UTC
# Line 2  Line 2 
2   *                                                                         *   *                                                                         *
3   *   libgig - C++ cross-platform Gigasampler format file access library    *   *   libgig - C++ cross-platform Gigasampler format file access library    *
4   *                                                                         *   *                                                                         *
5   *   Copyright (C) 2003-2009 by Christian Schoenebeck                      *   *   Copyright (C) 2003-2013 by Christian Schoenebeck                      *
6   *                              <cuse@users.sourceforge.net>               *   *                              <cuse@users.sourceforge.net>               *
7   *                                                                         *   *                                                                         *
8   *   This library is free software; you can redistribute it and/or modify  *   *   This library is free software; you can redistribute it and/or modify  *
# Line 1433  namespace { Line 1433  namespace {
1433                                                          : vcf_res_ctrl_none;                                                          : vcf_res_ctrl_none;
1434              uint16_t eg3depth = _3ewa->ReadUint16();              uint16_t eg3depth = _3ewa->ReadUint16();
1435              EG3Depth = (eg3depth <= 1200) ? eg3depth /* positives */              EG3Depth = (eg3depth <= 1200) ? eg3depth /* positives */
1436                                          : (-1) * (int16_t) ((eg3depth ^ 0xffff) + 1); /* binary complementary for negatives */                                          : (-1) * (int16_t) ((eg3depth ^ 0xfff) + 1); /* binary complementary for negatives */
1437              _3ewa->ReadInt16(); // unknown              _3ewa->ReadInt16(); // unknown
1438              ChannelOffset = _3ewa->ReadUint8() / 4;              ChannelOffset = _3ewa->ReadUint8() / 4;
1439              uint8_t regoptions = _3ewa->ReadUint8();              uint8_t regoptions = _3ewa->ReadUint8();
# Line 1581  namespace { Line 1581  namespace {
1581       */       */
1582      DimensionRegion::DimensionRegion(RIFF::List* _3ewl, const DimensionRegion& src) : DLS::Sampler(_3ewl) {      DimensionRegion::DimensionRegion(RIFF::List* _3ewl, const DimensionRegion& src) : DLS::Sampler(_3ewl) {
1583          Instances++;          Instances++;
1584            //NOTE: I think we cannot call CopyAssign() here (in a constructor) as long as its a virtual method
1585          *this = src; // default memberwise shallow copy of all parameters          *this = src; // default memberwise shallow copy of all parameters
1586          pParentList = _3ewl; // restore the chunk pointer          pParentList = _3ewl; // restore the chunk pointer
1587    
# Line 1596  namespace { Line 1597  namespace {
1597                  pSampleLoops[k] = src.pSampleLoops[k];                  pSampleLoops[k] = src.pSampleLoops[k];
1598          }          }
1599      }      }
1600        
1601        /**
1602         * Make a (semi) deep copy of the DimensionRegion object given by @a orig
1603         * and assign it to this object.
1604         *
1605         * Note that all sample pointers referenced by @a orig are simply copied as
1606         * memory address. Thus the respective samples are shared, not duplicated!
1607         *
1608         * @param orig - original DimensionRegion object to be copied from
1609         */
1610        void DimensionRegion::CopyAssign(const DimensionRegion* orig) {
1611            // delete all allocated data first
1612            if (VelocityTable) delete [] VelocityTable;
1613            if (pSampleLoops) delete [] pSampleLoops;
1614            
1615            // backup parent list pointer
1616            RIFF::List* p = pParentList;
1617            
1618            //NOTE: copy code copied from assignment constructor above, see comment there as well
1619            
1620            *this = *orig; // default memberwise shallow copy of all parameters
1621            pParentList = p; // restore the chunk pointer
1622    
1623            // deep copy of owned structures
1624            if (orig->VelocityTable) {
1625                VelocityTable = new uint8_t[128];
1626                for (int k = 0 ; k < 128 ; k++)
1627                    VelocityTable[k] = orig->VelocityTable[k];
1628            }
1629            if (orig->pSampleLoops) {
1630                pSampleLoops = new DLS::sample_loop_t[orig->SampleLoops];
1631                for (int k = 0 ; k < orig->SampleLoops ; k++)
1632                    pSampleLoops[k] = orig->pSampleLoops[k];
1633            }
1634        }
1635    
1636      /**      /**
1637       * Updates the respective member variable and updates @c SampleAttenuation       * Updates the respective member variable and updates @c SampleAttenuation
# Line 1837  namespace { Line 1873  namespace {
1873          }          }
1874    
1875          const uint16_t eg3depth = (EG3Depth >= 0) ? EG3Depth          const uint16_t eg3depth = (EG3Depth >= 0) ? EG3Depth
1876                                                    : uint16_t(((-EG3Depth) - 1) ^ 0xffff); /* binary complementary for negatives */                                                    : uint16_t(((-EG3Depth) - 1) ^ 0xfff); /* binary complementary for negatives */
1877          store16(&pData[116], eg3depth);          store16(&pData[116], eg3depth);
1878    
1879          // next 2 bytes unknown          // next 2 bytes unknown
# Line 2925  namespace { Line 2961  namespace {
2961          }          }
2962          return NULL;          return NULL;
2963      }      }
2964        
2965        /**
2966         * Make a (semi) deep copy of the Region object given by @a orig
2967         * and assign it to this object.
2968         *
2969         * Note that all sample pointers referenced by @a orig are simply copied as
2970         * memory address. Thus the respective samples are shared, not duplicated!
2971         *
2972         * @param orig - original Region object to be copied from
2973         */
2974        void Region::CopyAssign(const Region* orig) {
2975            // handle base classes
2976            DLS::Region::CopyAssign(orig);
2977            
2978            // handle own member variables
2979            for (int i = Dimensions - 1; i >= 0; --i) {
2980                DeleteDimension(&pDimensionDefinitions[i]);
2981            }
2982            Layers = 0; // just to be sure
2983            for (int i = 0; i < orig->Dimensions; i++) {
2984                // we need to copy the dim definition here, to avoid the compiler
2985                // complaining about const-ness issue
2986                dimension_def_t def = orig->pDimensionDefinitions[i];
2987                AddDimension(&def);
2988            }
2989            for (int i = 0; i < 256; i++) {
2990                if (pDimensionRegions[i] && orig->pDimensionRegions[i]) {
2991                    pDimensionRegions[i]->CopyAssign(
2992                        orig->pDimensionRegions[i]
2993                    );
2994                }
2995            }
2996            Layers = orig->Layers;
2997        }
2998    
2999    
3000  // *************** MidiRule ***************  // *************** MidiRule ***************
3001  // *  // *
3002    
3003  MidiRuleCtrlTrigger::MidiRuleCtrlTrigger(RIFF::Chunk* _3ewg) {      MidiRuleCtrlTrigger::MidiRuleCtrlTrigger(RIFF::Chunk* _3ewg) {
3004      _3ewg->SetPos(36);          _3ewg->SetPos(36);
3005      Triggers = _3ewg->ReadUint8();          Triggers = _3ewg->ReadUint8();
3006      _3ewg->SetPos(40);          _3ewg->SetPos(40);
3007      ControllerNumber = _3ewg->ReadUint8();          ControllerNumber = _3ewg->ReadUint8();
3008      _3ewg->SetPos(46);          _3ewg->SetPos(46);
3009      for (int i = 0 ; i < Triggers ; i++) {          for (int i = 0 ; i < Triggers ; i++) {
3010          pTriggers[i].TriggerPoint = _3ewg->ReadUint8();              pTriggers[i].TriggerPoint = _3ewg->ReadUint8();
3011          pTriggers[i].Descending = _3ewg->ReadUint8();              pTriggers[i].Descending = _3ewg->ReadUint8();
3012          pTriggers[i].VelSensitivity = _3ewg->ReadUint8();              pTriggers[i].VelSensitivity = _3ewg->ReadUint8();
3013          pTriggers[i].Key = _3ewg->ReadUint8();              pTriggers[i].Key = _3ewg->ReadUint8();
3014          pTriggers[i].NoteOff = _3ewg->ReadUint8();              pTriggers[i].NoteOff = _3ewg->ReadUint8();
3015          pTriggers[i].Velocity = _3ewg->ReadUint8();              pTriggers[i].Velocity = _3ewg->ReadUint8();
3016          pTriggers[i].OverridePedal = _3ewg->ReadUint8();              pTriggers[i].OverridePedal = _3ewg->ReadUint8();
3017          _3ewg->ReadUint8();              _3ewg->ReadUint8();
3018            }
3019        }
3020    
3021        MidiRuleCtrlTrigger::MidiRuleCtrlTrigger() :
3022            ControllerNumber(0),
3023            Triggers(0) {
3024        }
3025    
3026        void MidiRuleCtrlTrigger::UpdateChunks(uint8_t* pData) const {
3027            pData[32] = 4;
3028            pData[33] = 16;
3029            pData[36] = Triggers;
3030            pData[40] = ControllerNumber;
3031            for (int i = 0 ; i < Triggers ; i++) {
3032                pData[46 + i * 8] = pTriggers[i].TriggerPoint;
3033                pData[47 + i * 8] = pTriggers[i].Descending;
3034                pData[48 + i * 8] = pTriggers[i].VelSensitivity;
3035                pData[49 + i * 8] = pTriggers[i].Key;
3036                pData[50 + i * 8] = pTriggers[i].NoteOff;
3037                pData[51 + i * 8] = pTriggers[i].Velocity;
3038                pData[52 + i * 8] = pTriggers[i].OverridePedal;
3039            }
3040        }
3041    
3042        MidiRuleLegato::MidiRuleLegato(RIFF::Chunk* _3ewg) {
3043            _3ewg->SetPos(36);
3044            LegatoSamples = _3ewg->ReadUint8(); // always 12
3045            _3ewg->SetPos(40);
3046            BypassUseController = _3ewg->ReadUint8();
3047            BypassKey = _3ewg->ReadUint8();
3048            BypassController = _3ewg->ReadUint8();
3049            ThresholdTime = _3ewg->ReadUint16();
3050            _3ewg->ReadInt16();
3051            ReleaseTime = _3ewg->ReadUint16();
3052            _3ewg->ReadInt16();
3053            KeyRange.low = _3ewg->ReadUint8();
3054            KeyRange.high = _3ewg->ReadUint8();
3055            _3ewg->SetPos(64);
3056            ReleaseTriggerKey = _3ewg->ReadUint8();
3057            AltSustain1Key = _3ewg->ReadUint8();
3058            AltSustain2Key = _3ewg->ReadUint8();
3059        }
3060    
3061        MidiRuleLegato::MidiRuleLegato() :
3062            LegatoSamples(12),
3063            BypassUseController(false),
3064            BypassKey(0),
3065            BypassController(1),
3066            ThresholdTime(20),
3067            ReleaseTime(20),
3068            ReleaseTriggerKey(0),
3069            AltSustain1Key(0),
3070            AltSustain2Key(0)
3071        {
3072            KeyRange.low = KeyRange.high = 0;
3073      }      }
 }  
3074    
3075        void MidiRuleLegato::UpdateChunks(uint8_t* pData) const {
3076            pData[32] = 0;
3077            pData[33] = 16;
3078            pData[36] = LegatoSamples;
3079            pData[40] = BypassUseController;
3080            pData[41] = BypassKey;
3081            pData[42] = BypassController;
3082            store16(&pData[43], ThresholdTime);
3083            store16(&pData[47], ReleaseTime);
3084            pData[51] = KeyRange.low;
3085            pData[52] = KeyRange.high;
3086            pData[64] = ReleaseTriggerKey;
3087            pData[65] = AltSustain1Key;
3088            pData[66] = AltSustain2Key;
3089        }
3090    
3091        MidiRuleAlternator::MidiRuleAlternator(RIFF::Chunk* _3ewg) {
3092            _3ewg->SetPos(36);
3093            Articulations = _3ewg->ReadUint8();
3094            int flags = _3ewg->ReadUint8();
3095            Polyphonic = flags & 8;
3096            Chained = flags & 4;
3097            Selector = (flags & 2) ? selector_controller :
3098                (flags & 1) ? selector_key_switch : selector_none;
3099            Patterns = _3ewg->ReadUint8();
3100            _3ewg->ReadUint8(); // chosen row
3101            _3ewg->ReadUint8(); // unknown
3102            _3ewg->ReadUint8(); // unknown
3103            _3ewg->ReadUint8(); // unknown
3104            KeySwitchRange.low = _3ewg->ReadUint8();
3105            KeySwitchRange.high = _3ewg->ReadUint8();
3106            Controller = _3ewg->ReadUint8();
3107            PlayRange.low = _3ewg->ReadUint8();
3108            PlayRange.high = _3ewg->ReadUint8();
3109    
3110            int n = std::min(int(Articulations), 32);
3111            for (int i = 0 ; i < n ; i++) {
3112                _3ewg->ReadString(pArticulations[i], 32);
3113            }
3114            _3ewg->SetPos(1072);
3115            n = std::min(int(Patterns), 32);
3116            for (int i = 0 ; i < n ; i++) {
3117                _3ewg->ReadString(pPatterns[i].Name, 16);
3118                pPatterns[i].Size = _3ewg->ReadUint8();
3119                _3ewg->Read(&pPatterns[i][0], 1, 32);
3120            }
3121        }
3122    
3123        MidiRuleAlternator::MidiRuleAlternator() :
3124            Articulations(0),
3125            Patterns(0),
3126            Selector(selector_none),
3127            Controller(0),
3128            Polyphonic(false),
3129            Chained(false)
3130        {
3131            PlayRange.low = PlayRange.high = 0;
3132            KeySwitchRange.low = KeySwitchRange.high = 0;
3133        }
3134    
3135        void MidiRuleAlternator::UpdateChunks(uint8_t* pData) const {
3136            pData[32] = 3;
3137            pData[33] = 16;
3138            pData[36] = Articulations;
3139            pData[37] = (Polyphonic ? 8 : 0) | (Chained ? 4 : 0) |
3140                (Selector == selector_controller ? 2 :
3141                 (Selector == selector_key_switch ? 1 : 0));
3142            pData[38] = Patterns;
3143    
3144            pData[43] = KeySwitchRange.low;
3145            pData[44] = KeySwitchRange.high;
3146            pData[45] = Controller;
3147            pData[46] = PlayRange.low;
3148            pData[47] = PlayRange.high;
3149    
3150            char* str = reinterpret_cast<char*>(pData);
3151            int pos = 48;
3152            int n = std::min(int(Articulations), 32);
3153            for (int i = 0 ; i < n ; i++, pos += 32) {
3154                strncpy(&str[pos], pArticulations[i].c_str(), 32);
3155            }
3156    
3157            pos = 1072;
3158            n = std::min(int(Patterns), 32);
3159            for (int i = 0 ; i < n ; i++, pos += 49) {
3160                strncpy(&str[pos], pPatterns[i].Name.c_str(), 16);
3161                pData[pos + 16] = pPatterns[i].Size;
3162                memcpy(&pData[pos + 16], &(pPatterns[i][0]), 32);
3163            }
3164        }
3165    
3166  // *************** Instrument ***************  // *************** Instrument ***************
3167  // *  // *
# Line 2993  MidiRuleCtrlTrigger::MidiRuleCtrlTrigger Line 3207  MidiRuleCtrlTrigger::MidiRuleCtrlTrigger
3207                      uint8_t id1 = _3ewg->ReadUint8();                      uint8_t id1 = _3ewg->ReadUint8();
3208                      uint8_t id2 = _3ewg->ReadUint8();                      uint8_t id2 = _3ewg->ReadUint8();
3209    
3210                      if (id1 == 4 && id2 == 16) {                      if (id2 == 16) {
3211                          pMidiRules[i++] = new MidiRuleCtrlTrigger(_3ewg);                          if (id1 == 4) {
3212                                pMidiRules[i++] = new MidiRuleCtrlTrigger(_3ewg);
3213                            } else if (id1 == 0) {
3214                                pMidiRules[i++] = new MidiRuleLegato(_3ewg);
3215                            } else if (id1 == 3) {
3216                                pMidiRules[i++] = new MidiRuleAlternator(_3ewg);
3217                            } else {
3218                                pMidiRules[i++] = new MidiRuleUnknown;
3219                            }
3220                        }
3221                        else if (id1 != 0 || id2 != 0) {
3222                            pMidiRules[i++] = new MidiRuleUnknown;
3223                      }                      }
3224                      //TODO: all the other types of rules                      //TODO: all the other types of rules
3225    
# Line 3086  MidiRuleCtrlTrigger::MidiRuleCtrlTrigger Line 3311  MidiRuleCtrlTrigger::MidiRuleCtrlTrigger
3311                                      DimensionKeyRange.low << 1;                                      DimensionKeyRange.low << 1;
3312          pData[10] = dimkeystart;          pData[10] = dimkeystart;
3313          pData[11] = DimensionKeyRange.high;          pData[11] = DimensionKeyRange.high;
3314    
3315            if (pMidiRules[0] == 0 && _3ewg->GetSize() >= 34) {
3316                pData[32] = 0;
3317                pData[33] = 0;
3318            } else {
3319                for (int i = 0 ; pMidiRules[i] ; i++) {
3320                    pMidiRules[i]->UpdateChunks(pData);
3321                }
3322            }
3323      }      }
3324    
3325      /**      /**
# Line 3168  MidiRuleCtrlTrigger::MidiRuleCtrlTrigger Line 3402  MidiRuleCtrlTrigger::MidiRuleCtrlTrigger
3402          return pMidiRules[i];          return pMidiRules[i];
3403      }      }
3404    
3405        /**
3406         * Adds the "controller trigger" MIDI rule to the instrument.
3407         *
3408         * @returns the new MIDI rule
3409         */
3410        MidiRuleCtrlTrigger* Instrument::AddMidiRuleCtrlTrigger() {
3411            delete pMidiRules[0];
3412            MidiRuleCtrlTrigger* r = new MidiRuleCtrlTrigger;
3413            pMidiRules[0] = r;
3414            pMidiRules[1] = 0;
3415            return r;
3416        }
3417    
3418        /**
3419         * Adds the legato MIDI rule to the instrument.
3420         *
3421         * @returns the new MIDI rule
3422         */
3423        MidiRuleLegato* Instrument::AddMidiRuleLegato() {
3424            delete pMidiRules[0];
3425            MidiRuleLegato* r = new MidiRuleLegato;
3426            pMidiRules[0] = r;
3427            pMidiRules[1] = 0;
3428            return r;
3429        }
3430    
3431        /**
3432         * Adds the alternator MIDI rule to the instrument.
3433         *
3434         * @returns the new MIDI rule
3435         */
3436        MidiRuleAlternator* Instrument::AddMidiRuleAlternator() {
3437            delete pMidiRules[0];
3438            MidiRuleAlternator* r = new MidiRuleAlternator;
3439            pMidiRules[0] = r;
3440            pMidiRules[1] = 0;
3441            return r;
3442        }
3443    
3444        /**
3445         * Deletes a MIDI rule from the instrument.
3446         *
3447         * @param i - MIDI rule number
3448         */
3449        void Instrument::DeleteMidiRule(int i) {
3450            delete pMidiRules[i];
3451            pMidiRules[i] = 0;
3452        }
3453    
3454        /**
3455         * Make a (semi) deep copy of the Instrument object given by @a orig
3456         * and assign it to this object.
3457         *
3458         * Note that all sample pointers referenced by @a orig are simply copied as
3459         * memory address. Thus the respective samples are shared, not duplicated!
3460         *
3461         * @param orig - original Instrument object to be copied from
3462         */
3463        void Instrument::CopyAssign(const Instrument* orig) {
3464            // handle base class
3465            // (without copying DLS region stuff)
3466            DLS::Instrument::CopyAssignCore(orig);
3467            
3468            // handle own member variables
3469            Attenuation = orig->Attenuation;
3470            EffectSend = orig->EffectSend;
3471            FineTune = orig->FineTune;
3472            PitchbendRange = orig->PitchbendRange;
3473            PianoReleaseMode = orig->PianoReleaseMode;
3474            DimensionKeyRange = orig->DimensionKeyRange;
3475            
3476            // free old midi rules
3477            for (int i = 0 ; pMidiRules[i] ; i++) {
3478                delete pMidiRules[i];
3479            }
3480            //TODO: MIDI rule copying
3481            pMidiRules[0] = NULL;
3482            
3483            // delete all old regions
3484            while (Regions) DeleteRegion(GetFirstRegion());
3485            // create new regions and copy them from original
3486            {
3487                RegionList::const_iterator it = orig->pRegions->begin();
3488                for (int i = 0; i < orig->Regions; ++i, ++it) {
3489                    Region* dstRgn = AddRegion();
3490                    //NOTE: Region does semi-deep copy !
3491                    dstRgn->CopyAssign(
3492                        static_cast<gig::Region*>(*it)
3493                    );
3494                }
3495            }
3496    
3497            UpdateRegionKeyTable();
3498        }
3499    
3500    
3501  // *************** Group ***************  // *************** Group ***************
3502  // *  // *
# Line 3566  MidiRuleCtrlTrigger::MidiRuleCtrlTrigger Line 3895  MidiRuleCtrlTrigger::MidiRuleCtrlTrigger
3895         pInstruments->push_back(pInstrument);         pInstruments->push_back(pInstrument);
3896         return pInstrument;         return pInstrument;
3897      }      }
3898        
3899        /** @brief Add a duplicate of an existing instrument.
3900         *
3901         * Duplicates the instrument definition given by @a orig and adds it
3902         * to this file. This allows in an instrument editor application to
3903         * easily create variations of an instrument, which will be stored in
3904         * the same .gig file, sharing i.e. the same samples.
3905         *
3906         * Note that all sample pointers referenced by @a orig are simply copied as
3907         * memory address. Thus the respective samples are shared, not duplicated!
3908         *
3909         * You have to call Save() to make this persistent to the file.
3910         *
3911         * @param orig - original instrument to be copied
3912         * @returns duplicated copy of the given instrument
3913         */
3914        Instrument* File::AddDuplicateInstrument(const Instrument* orig) {
3915            Instrument* instr = AddInstrument();
3916            instr->CopyAssign(orig);
3917            return instr;
3918        }
3919    
3920      /** @brief Delete an instrument.      /** @brief Delete an instrument.
3921       *       *
# Line 3778  MidiRuleCtrlTrigger::MidiRuleCtrlTrigger Line 4128  MidiRuleCtrlTrigger::MidiRuleCtrlTrigger
4128    
4129          // update group's chunks          // update group's chunks
4130          if (pGroups) {          if (pGroups) {
4131              std::list<Group*>::iterator iter = pGroups->begin();              // make sure '3gri' and '3gnl' list chunks exist
4132              std::list<Group*>::iterator end  = pGroups->end();              // (before updating the Group chunks)
4133              for (; iter != end; ++iter) {              RIFF::List* _3gri = pRIFF->GetSubList(LIST_TYPE_3GRI);
4134                  (*iter)->UpdateChunks();              if (!_3gri) {
4135                    _3gri = pRIFF->AddSubList(LIST_TYPE_3GRI);
4136                    pRIFF->MoveSubChunk(_3gri, pRIFF->GetSubChunk(CHUNK_ID_PTBL));
4137              }              }
4138                RIFF::List* _3gnl = _3gri->GetSubList(LIST_TYPE_3GNL);
4139                if (!_3gnl) _3gnl = _3gri->AddSubList(LIST_TYPE_3GNL);
4140    
4141              // v3: make sure the file has 128 3gnm chunks              // v3: make sure the file has 128 3gnm chunks
4142                // (before updating the Group chunks)
4143              if (pVersion && pVersion->major == 3) {              if (pVersion && pVersion->major == 3) {
                 RIFF::List* _3gnl = pRIFF->GetSubList(LIST_TYPE_3GRI)->GetSubList(LIST_TYPE_3GNL);  
4144                  RIFF::Chunk* _3gnm = _3gnl->GetFirstSubChunk();                  RIFF::Chunk* _3gnm = _3gnl->GetFirstSubChunk();
4145                  for (int i = 0 ; i < 128 ; i++) {                  for (int i = 0 ; i < 128 ; i++) {
4146                      if (i >= pGroups->size()) ::SaveString(CHUNK_ID_3GNM, _3gnm, _3gnl, "", "", true, 64);                      if (i >= pGroups->size()) ::SaveString(CHUNK_ID_3GNM, _3gnm, _3gnl, "", "", true, 64);
4147                      if (_3gnm) _3gnm = _3gnl->GetNextSubChunk();                      if (_3gnm) _3gnm = _3gnl->GetNextSubChunk();
4148                  }                  }
4149              }              }
4150    
4151                std::list<Group*>::iterator iter = pGroups->begin();
4152                std::list<Group*>::iterator end  = pGroups->end();
4153                for (; iter != end; ++iter) {
4154                    (*iter)->UpdateChunks();
4155                }
4156          }          }
4157    
4158          // update einf chunk          // update einf chunk

Legend:
Removed from v.2152  
changed lines
  Added in v.2467

  ViewVC Help
Powered by ViewVC