/[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 2564 by schoenebeck, Tue May 20 12:15:05 2014 UTC revision 2584 by schoenebeck, Sat May 31 20:54:39 2014 UTC
# Line 3056  namespace { Line 3056  namespace {
3056              memset(_3lnk->LoadChunkData(), 0, _3lnkChunkSize);              memset(_3lnk->LoadChunkData(), 0, _3lnkChunkSize);
3057    
3058              // move 3prg to last position              // move 3prg to last position
3059              pCkRegion->MoveSubChunk(pCkRegion->GetSubList(LIST_TYPE_3PRG), 0);              pCkRegion->MoveSubChunk(pCkRegion->GetSubList(LIST_TYPE_3PRG), (RIFF::Chunk*)NULL);
3060          }          }
3061    
3062          // update dimension definitions in '3lnk' chunk          // update dimension definitions in '3lnk' chunk
# Line 4025  namespace { Line 4025  namespace {
4025          }          }
4026      }      }
4027    
4028    // *************** Script ***************
4029    // *
4030    
4031        Script::Script(ScriptGroup* group, RIFF::Chunk* ckScri) {
4032            pGroup = group;
4033            pChunk = ckScri;
4034            if (ckScri) { // object is loaded from file ...
4035                // read header
4036                uint32_t headerSize = ckScri->ReadUint32();
4037                Compression = (Compression_t) ckScri->ReadUint32();
4038                Encoding    = (Encoding_t) ckScri->ReadUint32();
4039                Language    = (Language_t) ckScri->ReadUint32();
4040                Bypass      = (Language_t) ckScri->ReadUint32() & 1;
4041                crc         = ckScri->ReadUint32();
4042                uint32_t nameSize = ckScri->ReadUint32();
4043                Name.resize(nameSize, ' ');
4044                for (int i = 0; i < nameSize; ++i)
4045                    Name[i] = ckScri->ReadUint8();
4046                // to handle potential future extensions of the header
4047                ckScri->SetPos(headerSize - 6*sizeof(int32_t) + nameSize, RIFF::stream_curpos);
4048                // read actual script data
4049                uint32_t scriptSize = ckScri->GetSize() - ckScri->GetPos();
4050                data.resize(scriptSize);
4051                for (int i = 0; i < scriptSize; ++i)
4052                    data[i] = ckScri->ReadUint8();
4053            } else { // this is a new script object, so just initialize it as such ...
4054                Compression = COMPRESSION_NONE;
4055                Encoding = ENCODING_ASCII;
4056                Language = LANGUAGE_NKSP;
4057                Bypass   = false;
4058                crc      = 0;
4059                Name     = "Unnamed Script";
4060            }
4061        }
4062    
4063        Script::~Script() {
4064        }
4065    
4066        /**
4067         * Returns the current script (i.e. as source code) in text format.
4068         */
4069        String Script::GetScriptAsText() {
4070            String s;
4071            s.resize(data.size(), ' ');
4072            memcpy(&s[0], &data[0], data.size());
4073            return s;
4074        }
4075    
4076        /**
4077         * Replaces the current script with the new script source code text given
4078         * by @a text.
4079         *
4080         * @param text - new script source code
4081         */
4082        void Script::SetScriptAsText(const String& text) {
4083            data.resize(text.size());
4084            memcpy(&data[0], &text[0], text.size());
4085        }
4086    
4087        void Script::UpdateChunks() {
4088            // recalculate CRC32 check sum
4089            __resetCRC(crc);
4090            __calculateCRC(&data[0], data.size(), crc);
4091            __encodeCRC(crc);
4092            // make sure chunk exists and has the required size
4093            const int chunkSize = 7*sizeof(int32_t) + Name.size() + data.size();
4094            if (!pChunk) pChunk = pGroup->pList->AddSubChunk(CHUNK_ID_SCRI, chunkSize);
4095            else pChunk->Resize(chunkSize);
4096            // fill the chunk data to be written to disk
4097            uint8_t* pData = (uint8_t*) pChunk->LoadChunkData();
4098            int pos = 0;
4099            store32(&pData[pos], 6*sizeof(int32_t) + Name.size()); // total header size
4100            pos += sizeof(int32_t);
4101            store32(&pData[pos], Compression);
4102            pos += sizeof(int32_t);
4103            store32(&pData[pos], Encoding);
4104            pos += sizeof(int32_t);
4105            store32(&pData[pos], Language);
4106            pos += sizeof(int32_t);
4107            store32(&pData[pos], Bypass ? 1 : 0);
4108            pos += sizeof(int32_t);
4109            store32(&pData[pos], crc);
4110            pos += sizeof(int32_t);
4111            store32(&pData[pos], Name.size());
4112            pos += sizeof(int32_t);
4113            for (int i = 0; i < Name.size(); ++i, ++pos)
4114                pData[pos] = Name[i];
4115            for (int i = 0; i < data.size(); ++i, ++pos)
4116                pData[pos] = data[i];
4117        }
4118    
4119        /**
4120         * Move this script from its current ScriptGroup to another ScriptGroup
4121         * given by @a pGroup.
4122         *
4123         * @param pGroup - script's new group
4124         */
4125        void Script::SetGroup(ScriptGroup* pGroup) {
4126            if (this->pGroup = pGroup) return;
4127            if (pChunk)
4128                pChunk->GetParent()->MoveSubChunk(pChunk, pGroup->pList);
4129            this->pGroup = pGroup;
4130        }
4131    
4132        void Script::RemoveAllScriptReferences() {
4133            File* pFile = pGroup->pFile;
4134            for (int i = 0; pFile->GetInstrument(i); ++i) {
4135                Instrument* instr = pFile->GetInstrument(i);
4136                instr->RemoveScript(this);
4137            }
4138        }
4139    
4140    // *************** ScriptGroup ***************
4141    // *
4142    
4143        ScriptGroup::ScriptGroup(File* file, RIFF::List* lstRTIS) {
4144            pFile = file;
4145            pList = lstRTIS;
4146            pScripts = NULL;
4147            if (lstRTIS) {
4148                RIFF::Chunk* ckName = lstRTIS->GetSubChunk(CHUNK_ID_LSNM);
4149                ::LoadString(ckName, Name);
4150            } else {
4151                Name = "Default Group";
4152            }
4153        }
4154    
4155        ScriptGroup::~ScriptGroup() {
4156            if (pScripts) {
4157                std::list<Script*>::iterator iter = pScripts->begin();
4158                std::list<Script*>::iterator end  = pScripts->end();
4159                while (iter != end) {
4160                    delete *iter;
4161                    ++iter;
4162                }
4163                delete pScripts;
4164            }
4165        }
4166    
4167        void ScriptGroup::UpdateChunks() {
4168            if (pScripts) {
4169                if (!pList)
4170                    pList = pFile->pRIFF->GetSubList(LIST_TYPE_3LS)->AddSubList(LIST_TYPE_RTIS);
4171    
4172                // now store the name of this group as <LSNM> chunk as subchunk of the <RTIS> list chunk
4173                ::SaveString(CHUNK_ID_LSNM, NULL, pList, Name, String("Unnamed Group"), true, 64);
4174    
4175                for (std::list<Script*>::iterator it = pScripts->begin();
4176                     it != pScripts->end(); ++it)
4177                {
4178                    (*it)->UpdateChunks();
4179                }
4180            }
4181        }
4182    
4183        /** @brief Get instrument script.
4184         *
4185         * Returns the real-time instrument script with the given index.
4186         *
4187         * @param index - number of the sought script (0..n)
4188         * @returns sought script or NULL if there's no such script
4189         */
4190        Script* ScriptGroup::GetScript(uint index) {
4191            if (!pScripts) LoadScripts();
4192            std::list<Script*>::iterator it = pScripts->begin();
4193            for (uint i = 0; it != pScripts->end(); ++i, ++it)
4194                if (i == index) return *it;
4195            return NULL;
4196        }
4197    
4198        /** @brief Add new instrument script.
4199         *
4200         * Adds a new real-time instrument script to the file. The script is not
4201         * actually used / executed unless it is referenced by an instrument to be
4202         * used. This is similar to samples, which you can add to a file, without
4203         * an instrument necessarily actually using it.
4204         *
4205         * You have to call Save() to make this persistent to the file.
4206         *
4207         * @return new empty script object
4208         */
4209        Script* ScriptGroup::AddScript() {
4210            if (!pScripts) LoadScripts();
4211            Script* pScript = new Script(this, NULL);
4212            pScripts->push_back(pScript);
4213            return pScript;
4214        }
4215    
4216        /** @brief Delete an instrument script.
4217         *
4218         * This will delete the given real-time instrument script. References of
4219         * instruments that are using that script will be removed accordingly.
4220         *
4221         * You have to call Save() to make this persistent to the file.
4222         *
4223         * @param pScript - script to delete
4224         * @throws gig::Exception if given script could not be found
4225         */
4226        void ScriptGroup::DeleteScript(Script* pScript) {
4227            if (!pScripts) LoadScripts();
4228            std::list<Script*>::iterator iter =
4229                find(pScripts->begin(), pScripts->end(), pScript);
4230            if (iter == pScripts->end())
4231                throw gig::Exception("Could not delete script, could not find given script");
4232            pScripts->erase(iter);
4233            pScript->RemoveAllScriptReferences();
4234            if (pScript->pChunk)
4235                pScript->pChunk->GetParent()->DeleteSubChunk(pScript->pChunk);
4236            delete pScript;
4237        }
4238    
4239        void ScriptGroup::LoadScripts() {
4240            if (pScripts) return;
4241            pScripts = new std::list<Script*>;
4242            if (!pList) return;
4243    
4244            for (RIFF::Chunk* ck = pList->GetFirstSubChunk(); ck;
4245                 ck = pList->GetNextSubChunk())
4246            {
4247                if (ck->GetChunkID() == CHUNK_ID_SCRI) {
4248                    pScripts->push_back(new Script(this, ck));
4249                }
4250            }
4251        }
4252    
4253  // *************** Instrument ***************  // *************** Instrument ***************
4254  // *  // *
4255    
# Line 4047  namespace { Line 4272  namespace {
4272          DimensionKeyRange.high = 0;          DimensionKeyRange.high = 0;
4273          pMidiRules = new MidiRule*[3];          pMidiRules = new MidiRule*[3];
4274          pMidiRules[0] = NULL;          pMidiRules[0] = NULL;
4275            pScriptRefs = NULL;
4276    
4277          // Loading          // Loading
4278          RIFF::List* lart = insList->GetSubList(LIST_TYPE_LART);          RIFF::List* lart = insList->GetSubList(LIST_TYPE_LART);
# Line 4107  namespace { Line 4333  namespace {
4333              }              }
4334          }          }
4335    
4336            // own gig format extensions
4337            RIFF::List* lst3LS = insList->GetSubList(LIST_TYPE_3LS);
4338            if (lst3LS) {
4339                RIFF::Chunk* ckSCSL = lst3LS->GetSubChunk(CHUNK_ID_SCSL);
4340                if (ckSCSL) {
4341                    int slotCount = ckSCSL->ReadUint32();
4342                    int slotSize  = ckSCSL->ReadUint32();
4343                    int unknownSpace = slotSize - 2*sizeof(uint32_t); // in case of future extensions
4344                    for (int i = 0; i < slotCount; ++i) {
4345                        _ScriptPooolEntry e;
4346                        e.fileOffset = ckSCSL->ReadUint32();
4347                        e.bypass     = ckSCSL->ReadUint32() & 1;
4348                        if (unknownSpace) ckSCSL->SetPos(unknownSpace, RIFF::stream_curpos); // in case of future extensions
4349                        scriptPoolFileOffsets.push_back(e);
4350                    }
4351                }
4352            }
4353    
4354          __notify_progress(pProgress, 1.0f); // notify done          __notify_progress(pProgress, 1.0f); // notify done
4355      }      }
4356    
# Line 4127  namespace { Line 4371  namespace {
4371              delete pMidiRules[i];              delete pMidiRules[i];
4372          }          }
4373          delete[] pMidiRules;          delete[] pMidiRules;
4374            if (pScriptRefs) delete pScriptRefs;
4375      }      }
4376    
4377      /**      /**
# Line 4182  namespace { Line 4427  namespace {
4427                  pMidiRules[i]->UpdateChunks(pData);                  pMidiRules[i]->UpdateChunks(pData);
4428              }              }
4429          }          }
4430    
4431            // own gig format extensions
4432           if (pScriptRefs) {
4433               RIFF::List* lst3LS = pCkInstrument->GetSubList(LIST_TYPE_3LS);
4434               if (!lst3LS) lst3LS = pCkInstrument->AddSubList(LIST_TYPE_3LS);
4435               const int totalSize = pScriptRefs->size() * 2*sizeof(uint32_t);
4436               RIFF::Chunk* ckSCSL = lst3LS->GetSubChunk(CHUNK_ID_SCSL);
4437               if (!ckSCSL) ckSCSL = lst3LS->AddSubChunk(CHUNK_ID_SCSL, totalSize);
4438               else ckSCSL->Resize(totalSize);
4439               uint8_t* pData = (uint8_t*) ckSCSL->LoadChunkData();
4440               for (int i = 0, pos = 0; i < pScriptRefs->size(); ++i) {
4441                   int fileOffset =
4442                        (*pScriptRefs)[i].script->pChunk->GetFilePos() -
4443                        (*pScriptRefs)[i].script->pChunk->GetPos() -
4444                        CHUNK_HEADER_SIZE;
4445                   store32(&pData[pos], fileOffset);
4446                   pos += sizeof(uint32_t);
4447                   store32(&pData[pos], (*pScriptRefs)[i].bypass ? 1 : 0);
4448                   pos += sizeof(uint32_t);
4449               }
4450           }
4451      }      }
4452    
4453      /**      /**
# Line 4313  namespace { Line 4579  namespace {
4579          pMidiRules[i] = 0;          pMidiRules[i] = 0;
4580      }      }
4581    
4582        void Instrument::LoadScripts() {
4583            if (pScriptRefs) return;
4584            pScriptRefs = new std::vector<_ScriptPooolRef>;
4585            if (scriptPoolFileOffsets.empty()) return;
4586            File* pFile = (File*) GetParent();
4587            for (uint k = 0; k < scriptPoolFileOffsets.size(); ++k) {
4588                uint32_t offset = scriptPoolFileOffsets[k].fileOffset;
4589                for (uint i = 0; pFile->GetScriptGroup(i); ++i) {
4590                    ScriptGroup* group = pFile->GetScriptGroup(i);
4591                    for (uint s = 0; group->GetScript(s); ++s) {
4592                        Script* script = group->GetScript(s);
4593                        if (script->pChunk) {
4594                            script->pChunk->SetPos(0);
4595                            if (script->pChunk->GetFilePos() -
4596                                script->pChunk->GetPos() -
4597                                CHUNK_HEADER_SIZE == offset)
4598                            {
4599                                _ScriptPooolRef ref;
4600                                ref.script = script;
4601                                ref.bypass = scriptPoolFileOffsets[k].bypass;
4602                                pScriptRefs->push_back(ref);
4603                                break;
4604                            }
4605                        }
4606                    }
4607                }
4608            }
4609            // we don't need that anymore
4610            scriptPoolFileOffsets.clear();
4611        }
4612    
4613        /** @brief Add new instrument script slot (gig format extension)
4614         *
4615         * Add the given real-time instrument script reference to this instrument,
4616         * which shall be executed by the sampler for for this instrument. The
4617         * script will be added to the end of the script list of this instrument.
4618         * The positions of the scripts in the Instrument's Script list are
4619         * relevant, because they define in which order they shall be executed by
4620         * the sampler. For this reason it is also legal to add the same script
4621         * twice to an instrument, for example you might have a script called
4622         * "MyFilter" which performs an event filter task, and you might have
4623         * another script called "MyNoteTrigger" which triggers new notes, then you
4624         * might for example have the following list of scripts on the instrument:
4625         *
4626         * 1. Script "MyFilter"
4627         * 2. Script "MyNoteTrigger"
4628         * 3. Script "MyFilter"
4629         *
4630         * Which would make sense, because the 2nd script launched new events, which
4631         * you might need to filter as well.
4632         *
4633         * There are two ways to disable / "bypass" scripts. You can either disable
4634         * a script locally for the respective script slot on an instrument (i.e. by
4635         * passing @c false to the 2nd argument of this method, or by calling
4636         * SetScriptBypassed()). Or you can disable a script globally for all slots
4637         * and all instruments by setting Script::Bypass.
4638         *
4639         * @note This is an own format extension which did not exist i.e. in the
4640         * GigaStudio 4 software. It will currently only work with LinuxSampler and
4641         * gigedit.
4642         *
4643         * @param pScript - script that shall be executed for this instrument
4644         * @param bypass  - if enabled, the sampler shall skip executing this
4645         *                  script (in the respective list position)
4646         * @see SetScriptBypassed()
4647         */
4648        void Instrument::AddScriptSlot(Script* pScript, bool bypass) {
4649            LoadScripts();
4650            _ScriptPooolRef ref = { pScript, bypass };
4651            pScriptRefs->push_back(ref);
4652        }
4653    
4654        /** @brief Flip two script slots with each other (gig format extension).
4655         *
4656         * Swaps the position of the two given scripts in the Instrument's Script
4657         * list. The positions of the scripts in the Instrument's Script list are
4658         * relevant, because they define in which order they shall be executed by
4659         * the sampler.
4660         *
4661         * @note This is an own format extension which did not exist i.e. in the
4662         * GigaStudio 4 software. It will currently only work with LinuxSampler and
4663         * gigedit.
4664         *
4665         * @param index1 - index of the first script slot to swap
4666         * @param index2 - index of the second script slot to swap
4667         */
4668        void Instrument::SwapScriptSlots(uint index1, uint index2) {
4669            LoadScripts();
4670            if (index1 >= pScriptRefs->size() || index2 >= pScriptRefs->size())
4671                return;
4672            _ScriptPooolRef tmp = (*pScriptRefs)[index1];
4673            (*pScriptRefs)[index1] = (*pScriptRefs)[index2];
4674            (*pScriptRefs)[index2] = tmp;
4675        }
4676    
4677        /** @brief Remove script slot.
4678         *
4679         * Removes the script slot with the given slot index.
4680         *
4681         * @param index - index of script slot to remove
4682         */
4683        void Instrument::RemoveScriptSlot(uint index) {
4684            LoadScripts();
4685            if (index >= pScriptRefs->size()) return;
4686            pScriptRefs->erase( pScriptRefs->begin() + index );
4687        }
4688    
4689        /** @brief Remove reference to given Script (gig format extension).
4690         *
4691         * This will remove all script slots on the instrument which are referencing
4692         * the given script.
4693         *
4694         * @note This is an own format extension which did not exist i.e. in the
4695         * GigaStudio 4 software. It will currently only work with LinuxSampler and
4696         * gigedit.
4697         *
4698         * @param pScript - script reference to remove from this instrument
4699         * @see RemoveScriptSlot()
4700         */
4701        void Instrument::RemoveScript(Script* pScript) {
4702            LoadScripts();
4703            for (int i = pScriptRefs->size() - 1; i >= 0; --i) {
4704                if ((*pScriptRefs)[i].script == pScript) {
4705                    pScriptRefs->erase( pScriptRefs->begin() + i );
4706                }
4707            }
4708        }
4709    
4710        /** @brief Instrument's amount of script slots.
4711         *
4712         * This method returns the amount of script slots this instrument currently
4713         * uses.
4714         *
4715         * A script slot is a reference of a real-time instrument script to be
4716         * executed by the sampler. The scripts will be executed by the sampler in
4717         * sequence of the slots. One (same) script may be referenced multiple
4718         * times in different slots.
4719         *
4720         * @note This is an own format extension which did not exist i.e. in the
4721         * GigaStudio 4 software. It will currently only work with LinuxSampler and
4722         * gigedit.
4723         */
4724        uint Instrument::ScriptSlotCount() const {
4725            return pScriptRefs ? pScriptRefs->size() : scriptPoolFileOffsets.size();
4726        }
4727    
4728        /** @brief Whether script execution shall be skipped.
4729         *
4730         * Defines locally for the Script reference slot in the Instrument's Script
4731         * list, whether the script shall be skipped by the sampler regarding
4732         * execution.
4733         *
4734         * It is also possible to ignore exeuction of the script globally, for all
4735         * slots and for all instruments by setting Script::Bypass.
4736         *
4737         * @note This is an own format extension which did not exist i.e. in the
4738         * GigaStudio 4 software. It will currently only work with LinuxSampler and
4739         * gigedit.
4740         *
4741         * @param index - index of the script slot on this instrument
4742         * @see Script::Bypass
4743         */
4744        bool Instrument::IsScriptSlotBypassed(uint index) {
4745            if (index >= ScriptSlotCount()) return false;
4746            return pScriptRefs ? pScriptRefs->at(index).bypass
4747                               : scriptPoolFileOffsets.at(index).bypass;
4748            
4749        }
4750    
4751        /** @brief Defines whether execution shall be skipped.
4752         *
4753         * You can call this method to define locally whether or whether not the
4754         * given script slot shall be executed by the sampler.
4755         *
4756         * @note This is an own format extension which did not exist i.e. in the
4757         * GigaStudio 4 software. It will currently only work with LinuxSampler and
4758         * gigedit.
4759         *
4760         * @param index - script slot index on this instrument
4761         * @param bBypass - if true, the script slot will be skipped by the sampler
4762         * @see Script::Bypass
4763         */
4764        void Instrument::SetScriptSlotBypassed(uint index, bool bBypass) {
4765            if (index >= ScriptSlotCount()) return;
4766            if (pScriptRefs)
4767                pScriptRefs->at(index).bypass = bBypass;
4768            else
4769                scriptPoolFileOffsets.at(index).bypass = bBypass;
4770        }
4771    
4772      /**      /**
4773       * Make a (semi) deep copy of the Instrument object given by @a orig       * Make a (semi) deep copy of the Instrument object given by @a orig
4774       * and assign it to this object.       * and assign it to this object.
# Line 4346  namespace { Line 4802  namespace {
4802          PitchbendRange = orig->PitchbendRange;          PitchbendRange = orig->PitchbendRange;
4803          PianoReleaseMode = orig->PianoReleaseMode;          PianoReleaseMode = orig->PianoReleaseMode;
4804          DimensionKeyRange = orig->DimensionKeyRange;          DimensionKeyRange = orig->DimensionKeyRange;
4805            scriptPoolFileOffsets = orig->scriptPoolFileOffsets;
4806            pScriptRefs = orig->pScriptRefs;
4807                    
4808          // free old midi rules          // free old midi rules
4809          for (int i = 0 ; pMidiRules[i] ; i++) {          for (int i = 0 ; pMidiRules[i] ; i++) {
# Line 4531  namespace { Line 4989  namespace {
4989          bAutoLoad = true;          bAutoLoad = true;
4990          *pVersion = VERSION_3;          *pVersion = VERSION_3;
4991          pGroups = NULL;          pGroups = NULL;
4992            pScriptGroups = NULL;
4993          pInfo->SetFixedStringLengths(_FileFixedStringLengths);          pInfo->SetFixedStringLengths(_FileFixedStringLengths);
4994          pInfo->ArchivalLocation = String(256, ' ');          pInfo->ArchivalLocation = String(256, ' ');
4995    
# Line 4546  namespace { Line 5005  namespace {
5005      File::File(RIFF::File* pRIFF) : DLS::File(pRIFF) {      File::File(RIFF::File* pRIFF) : DLS::File(pRIFF) {
5006          bAutoLoad = true;          bAutoLoad = true;
5007          pGroups = NULL;          pGroups = NULL;
5008            pScriptGroups = NULL;
5009          pInfo->SetFixedStringLengths(_FileFixedStringLengths);          pInfo->SetFixedStringLengths(_FileFixedStringLengths);
5010      }      }
5011    
# Line 4559  namespace { Line 5019  namespace {
5019              }              }
5020              delete pGroups;              delete pGroups;
5021          }          }
5022            if (pScriptGroups) {
5023                std::list<ScriptGroup*>::iterator iter = pScriptGroups->begin();
5024                std::list<ScriptGroup*>::iterator end  = pScriptGroups->end();
5025                while (iter != end) {
5026                    delete *iter;
5027                    ++iter;
5028                }
5029                delete pScriptGroups;
5030            }
5031      }      }
5032    
5033      Sample* File::GetFirstSample(progress_t* pProgress) {      Sample* File::GetFirstSample(progress_t* pProgress) {
# Line 5071  namespace { Line 5540  namespace {
5540          }          }
5541      }      }
5542    
5543        /** @brief Get instrument script group (by index).
5544         *
5545         * Returns the real-time instrument script group with the given index.
5546         *
5547         * @param index - number of the sought group (0..n)
5548         * @returns sought script group or NULL if there's no such group
5549         */
5550        ScriptGroup* File::GetScriptGroup(uint index) {
5551            if (!pScriptGroups) LoadScriptGroups();
5552            std::list<ScriptGroup*>::iterator it = pScriptGroups->begin();
5553            for (uint i = 0; it != pScriptGroups->end(); ++i, ++it)
5554                if (i == index) return *it;
5555            return NULL;
5556        }
5557    
5558        /** @brief Get instrument script group (by name).
5559         *
5560         * Returns the first real-time instrument script group found with the given
5561         * group name. Note that group names may not necessarily be unique.
5562         *
5563         * @param name - name of the sought script group
5564         * @returns sought script group or NULL if there's no such group
5565         */
5566        ScriptGroup* File::GetScriptGroup(const String& name) {
5567            if (!pScriptGroups) LoadScriptGroups();
5568            std::list<ScriptGroup*>::iterator it = pScriptGroups->begin();
5569            for (uint i = 0; it != pScriptGroups->end(); ++i, ++it)
5570                if ((*it)->Name == name) return *it;
5571            return NULL;
5572        }
5573    
5574        /** @brief Add new instrument script group.
5575         *
5576         * Adds a new, empty real-time instrument script group to the file.
5577         *
5578         * You have to call Save() to make this persistent to the file.
5579         *
5580         * @return new empty script group
5581         */
5582        ScriptGroup* File::AddScriptGroup() {
5583            if (!pScriptGroups) LoadScriptGroups();
5584            ScriptGroup* pScriptGroup = new ScriptGroup(this, NULL);
5585            pScriptGroups->push_back(pScriptGroup);
5586            return pScriptGroup;
5587        }
5588    
5589        /** @brief Delete an instrument script group.
5590         *
5591         * This will delete the given real-time instrument script group and all its
5592         * instrument scripts it contains. References inside instruments that are
5593         * using the deleted scripts will be removed from the respective instruments
5594         * accordingly.
5595         *
5596         * You have to call Save() to make this persistent to the file.
5597         *
5598         * @param pScriptGroup - script group to delete
5599         * @throws gig::Exception if given script group could not be found
5600         */
5601        void File::DeleteScriptGroup(ScriptGroup* pScriptGroup) {
5602            if (!pScriptGroups) LoadScriptGroups();
5603            std::list<ScriptGroup*>::iterator iter =
5604                find(pScriptGroups->begin(), pScriptGroups->end(), pScriptGroup);
5605            if (iter == pScriptGroups->end())
5606                throw gig::Exception("Could not delete script group, could not find given script group");
5607            pScriptGroups->erase(iter);
5608            for (int i = 0; pScriptGroup->GetScript(i); ++i)
5609                pScriptGroup->DeleteScript(pScriptGroup->GetScript(i));
5610            if (pScriptGroup->pList)
5611                pScriptGroup->pList->GetParent()->DeleteSubChunk(pScriptGroup->pList);
5612            delete pScriptGroup;
5613        }
5614    
5615        void File::LoadScriptGroups() {
5616            if (pScriptGroups) return;
5617            pScriptGroups = new std::list<ScriptGroup*>;
5618            RIFF::List* lstLS = pRIFF->GetSubList(LIST_TYPE_3LS);
5619            if (lstLS) {
5620                for (RIFF::List* lst = lstLS->GetFirstSubList(); lst;
5621                     lst = lstLS->GetNextSubList())
5622                {
5623                    if (lst->GetListType() == LIST_TYPE_RTIS) {
5624                        pScriptGroups->push_back(new ScriptGroup(this, lst));
5625                    }
5626                }
5627            }
5628        }
5629    
5630      /**      /**
5631       * Apply all the gig file's current instruments, samples, groups and settings       * Apply all the gig file's current instruments, samples, groups and settings
5632       * to the respective RIFF chunks. You have to call Save() to make changes       * to the respective RIFF chunks. You have to call Save() to make changes
# Line 5086  namespace { Line 5642  namespace {
5642    
5643          b64BitWavePoolOffsets = pVersion && pVersion->major == 3;          b64BitWavePoolOffsets = pVersion && pVersion->major == 3;
5644    
5645            // update own gig format extension chunks
5646            // (not part of the GigaStudio 4 format)
5647            //
5648            // This must be performed before writing the chunks for instruments,
5649            // because the instruments' script slots will write the file offsets
5650            // of the respective instrument script chunk as reference.
5651            if (pScriptGroups) {
5652                RIFF::List* lst3LS = pRIFF->GetSubList(LIST_TYPE_3LS);
5653                if (pScriptGroups->empty()) {
5654                    if (lst3LS) pRIFF->DeleteSubChunk(lst3LS);
5655                } else {
5656                    if (!lst3LS) lst3LS = pRIFF->AddSubList(LIST_TYPE_3LS);
5657    
5658                    // Update instrument script (group) chunks.
5659    
5660                    for (std::list<ScriptGroup*>::iterator it = pScriptGroups->begin();
5661                         it != pScriptGroups->end(); ++it)
5662                    {
5663                        (*it)->UpdateChunks();
5664                    }
5665                }
5666            }
5667    
5668          // first update base class's chunks          // first update base class's chunks
5669          DLS::File::UpdateChunks();          DLS::File::UpdateChunks();
5670    

Legend:
Removed from v.2564  
changed lines
  Added in v.2584

  ViewVC Help
Powered by ViewVC