Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/orxonox/branches/sound_engine/src/util/resource_manager.cc @ 4225

Last change on this file since 4225 was 3891, checked in by bensch, 20 years ago

orxonox/trunk: sound can be registered with the resource-Manager:
user load(fileName, RESOURCE_SOUND_EFFECT/MUSIC) to load

File size: 16.9 KB
Line 
1/*
2   orxonox - the future of 3D-vertical-scrollers
3
4   Copyright (C) 2004 orx
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2, or (at your option)
9   any later version.
10
11   ### File Specific:
12   main-programmer: Benjamin Grauer
13   co-programmer: Patrick Boenzli
14*/
15
16#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_LOAD
17
18#include "resource_manager.h"
19
20// different resource Types
21#include "sound_engine.h"
22#include "objModel.h"
23#include "primitive_model.h"
24#include "texture.h"
25#include "text_engine.h"
26
27#include "list.h"
28
29// File Handling Includes
30#include <sys/types.h>
31#include <sys/stat.h>
32#include <unistd.h>
33
34using namespace std;
35
36/**
37   \brief standard constructor
38*/
39ResourceManager::ResourceManager () 
40{
41   this->setClassName ("ResourceManager");
42   this->dataDir = NULL;
43   this->setDataDir("./");
44   this->imageDirs = new tList<char>();
45   this->resourceList = new tList<Resource>();
46}
47
48/**
49   \returns the Instance to this ResourceManager
50*/
51ResourceManager* ResourceManager::getInstance(void)
52{
53  if (!ResourceManager::singletonRef)
54    ResourceManager::singletonRef = new ResourceManager();
55  return ResourceManager::singletonRef;
56}
57
58//! Singleton Reference to the ResourceManager
59ResourceManager* ResourceManager::singletonRef = NULL;
60
61/**
62   \brief standard destructor
63*/
64ResourceManager::~ResourceManager (void) 
65{
66  // deleting the Resources-List
67  this->unloadAllByPriority(RP_GAME);
68  delete this->resourceList;
69  // deleting the Directorie Lists
70  tIterator<char>* tmpIt = imageDirs->getIterator();
71  char* tmpDir = tmpIt->nextElement();
72  while(tmpDir)
73    {
74      delete []tmpDir;
75      tmpDir = tmpIt->nextElement();
76    }
77  delete tmpIt;
78
79  delete this->imageDirs;
80
81  ResourceManager::singletonRef = NULL;
82}
83
84/**
85   \brief sets the data main directory
86   \param dataDir the DataDirectory.
87*/
88bool ResourceManager::setDataDir(const char* dataDir)
89{
90  if (isDir(dataDir))
91    {
92      delete this->dataDir;
93      this->dataDir = new char[strlen(dataDir)+1];
94      strcpy(this->dataDir, dataDir);
95    }
96  else
97    {
98      PRINTF(1)("%s is not a Directory, and can not be the Data Directory, leaving as %s \n", dataDir, this->dataDir);
99    }
100}
101
102/**
103   \brief adds a new Path for Images
104   \param imageDir The path to insert
105   \returns true, if the Path was well and injected (or already existent within the list)
106   false otherwise
107*/
108bool ResourceManager::addImageDir(char* imageDir)
109{
110  // check if the param is a Directory
111  if (isDir(imageDir))
112    {
113      // check if the Directory has been added before
114      tIterator<char>* tmpImageDirs = imageDirs->getIterator();
115      char* tmpDir = tmpImageDirs->nextElement();
116      while(tmpDir)
117        {
118          if (!strcmp(tmpDir, imageDir))
119            {
120              PRINTF(4)("Path %s already loaded\n", imageDir);
121              delete tmpImageDirs;
122              return true;
123            }
124          tmpDir = tmpImageDirs->nextElement();
125        }
126      delete tmpImageDirs;
127
128      // adding the directory to the List
129      tmpDir  = new char[strlen(imageDir)+1];
130      strcpy(tmpDir, imageDir);
131      this->imageDirs->add(tmpDir);
132      return true;
133    }
134  else
135    {
136      PRINTF(1)("%s is not a Directory, and can not be added to the Paths of Images\n", dataDir);
137      return false;
138    }
139}
140
141/**
142   \brief loads resources
143   \param fileName The fileName of the resource to load
144   \param prio The ResourcePriority of this resource (will only be increased)
145   \returns a pointer to a desired Resource.
146*/
147void* ResourceManager::load(const char* fileName, ResourcePriority prio, void* param1, void* param2, void* param3)
148{
149  ResourceType tmpType;
150  if (!strncmp(fileName+(strlen(fileName)-4), ".obj", 4))
151    tmpType = OBJ;
152  else if (!strncmp(fileName+(strlen(fileName)-4), ".wav", 4))
153    {
154      tmpType = WAV;
155      PRINTF(2)("not determined of what type the resource is %s EFFECT OR MUSIC\n");
156    }
157  else if (!strncmp(fileName+(strlen(fileName)-4), ".mp3", 4))
158    {
159      tmpType = MP3;
160      PRINTF(2)("not determined of what type the resource is %s EFFECT OR MUSIC\n");
161    }
162  else if (!strncmp(fileName+(strlen(fileName)-4), ".ogg", 4))
163    {
164      tmpType = OGG;
165      PRINTF(2)("not determined of what type the resource is %s EFFECT OR MUSIC\n");
166    }
167  else if (!strcmp(fileName, "cube") ||
168           !strcmp(fileName, "sphere") ||
169           !strcmp(fileName, "plane") ||
170           !strcmp(fileName, "cylinder") ||
171           !strcmp(fileName, "cone"))
172    tmpType = PRIM;
173  else if (!strncmp(fileName+(strlen(fileName)-4), ".ttf", 4))
174    tmpType = TTF;
175  else 
176    tmpType = IMAGE;
177
178  return this->load(fileName, tmpType, prio, param1, param2, param3);
179}
180
181/**
182   \brief loads resources
183   \param fileName The fileName of the resource to load
184   \param type The Type of Resource to load (\see ResourceType)
185   \param prio The ResourcePriority of this resource (will only be increased)
186   \returns a pointer to a desired Resource.
187*/
188void* ResourceManager::load(const char* fileName, ResourceType type, ResourcePriority prio, void* param1, void* param2, void* param3)
189{
190  // searching if the resource was loaded before.
191  Resource* tmpResource = this->locateResourceByInfo(fileName, type, param1, param2,param3);
192  if (tmpResource) // if the resource was not loaded before.
193    {
194      PRINTF(4)("not loading cached resource %s\n", tmpResource->name);
195      tmpResource->count++;
196      if(tmpResource->prio < prio)
197        tmpResource->prio = prio;
198    }
199  else
200    {
201      char* tmpDir;
202      // Setting up the new Resource
203      tmpResource = new Resource;
204      tmpResource->count = 1;
205      tmpResource->type = type;
206      tmpResource->prio = prio;
207      tmpResource->name = new char[strlen(fileName)+1];
208      strcpy(tmpResource->name, fileName);
209
210      // creating the full name. (directoryName + FileName)
211      char* fullName = new char[strlen(dataDir)+strlen(fileName)+1];
212      sprintf(fullName, "%s%s", this->dataDir, fileName);
213     
214      // Checking for the type of resource \see ResourceType
215      switch(type)
216        {
217        case RESOURCE_SOUND_EFFECT:
218          if(isFile(fullName))
219            tmpResource->pointer = new SoundEffect(fullName);
220          break;
221        case RESOURCE_SOUND_MUSIC:
222          if(isFile(fullName))
223            tmpResource->pointer = new Music(fullName);
224          break;
225        case OBJ:
226          if (param1)
227            tmpResource->modelSize = *(float*)param1;
228          else
229            tmpResource->modelSize = 1.0;
230
231          if(isFile(fullName))
232            tmpResource->pointer = new OBJModel(fullName, tmpResource->modelSize);
233          else
234            {
235              PRINTF(2)("Sorry, %s does not exist. Loading a cube-Model instead\n", fullName);
236              tmpResource->pointer = ResourceManager::load("cube", PRIM, prio, &tmpResource->modelSize);
237            }
238          break;
239        case PRIM:
240          if (param1)
241            tmpResource->modelSize = *(float*)param1;
242          else
243            tmpResource->modelSize = 1.0;
244
245          if (!strcmp(tmpResource->name, "cube"))
246            tmpResource->pointer = new PrimitiveModel(CUBE, tmpResource->modelSize);
247          else if (!strcmp(tmpResource->name, "sphere"))
248            tmpResource->pointer = new PrimitiveModel(SPHERE, tmpResource->modelSize);
249          else if (!strcmp(tmpResource->name, "plane"))
250            tmpResource->pointer = new PrimitiveModel(PLANE, tmpResource->modelSize);
251          else if (!strcmp(tmpResource->name, "cylinder"))
252            tmpResource->pointer = new PrimitiveModel(CYLINDER, tmpResource->modelSize);
253          else if (!strcmp(tmpResource->name, "cone"))
254            tmpResource->pointer = new PrimitiveModel(CONE, tmpResource->modelSize);
255          break;
256        case TTF:
257            if (param1)
258              tmpResource->ttfSize = *(int*)param1;
259            else
260              tmpResource->ttfSize = FONT_DEFAULT_SIZE;
261            if (param2)
262              {
263                Vector* tmpVec = (Vector*)param2;
264                tmpResource->ttfColorR = (int)tmpVec->x;
265                tmpResource->ttfColorG = (int)tmpVec->y;
266                tmpResource->ttfColorB = (int)tmpVec->z;
267              }
268            else
269              {
270                tmpResource->ttfColorR = FONT_DEFAULT_COLOR_R;
271                tmpResource->ttfColorG = FONT_DEFAULT_COLOR_G;
272                tmpResource->ttfColorB = FONT_DEFAULT_COLOR_B;
273              }
274           
275          if(isFile(fullName))
276            tmpResource->pointer = new Font(fullName,
277                                            tmpResource->ttfSize,
278                                            tmpResource->ttfColorR,
279                                            tmpResource->ttfColorG,
280                                            tmpResource->ttfColorB);
281          else
282            PRINTF(2)("Sorry, %s does not exist. Not loading Font\n", fullName);
283          break;
284        case IMAGE:
285          if(isFile(fullName))
286            {
287              PRINTF(4)("Image %s resides to %s\n", fileName, fullName);
288              tmpResource->pointer = new Texture(fullName);
289            }
290          else
291            {
292              tIterator<char>* iterator = imageDirs->getIterator();
293              tmpDir = iterator->nextElement();
294              //tmpDir = imageDirs->enumerate();
295              while(tmpDir)
296                {
297                  char* imgName = new char[strlen(tmpDir)+strlen(fileName)+1];
298                  sprintf(imgName, "%s%s", tmpDir, fileName);
299                  if(isFile(imgName))
300                    {
301                      PRINTF(4)("Image %s resides to %s\n", fileName, imgName);
302                      tmpResource->pointer = new Texture(imgName);
303                      delete []imgName;
304                      break;
305                    }
306                  delete []imgName;
307                  tmpDir = iterator->nextElement();
308                }
309              delete iterator;
310            }
311          if(!tmpResource)
312             PRINTF(2)("!!Image %s not Found!!\n", fileName);
313          break;
314        default:
315          tmpResource->pointer = NULL;
316          PRINTF(1)("No type found for %s.\n   !!This should not happen unless the Type is not supported yet.!!\n", tmpResource->name);
317          break;
318        }
319      this->resourceList->add(tmpResource);
320      delete []fullName;
321    }
322  if (tmpResource->pointer)
323    return tmpResource->pointer;
324  else 
325    {
326      PRINTF(2)("Resource %s could not be loaded\n", fileName);
327      delete tmpResource;
328      return NULL;
329    }
330}
331
332/**
333   \brief unloads a Resource
334   \param pointer The pointer to free
335   \returns true if successful (pointer found, and deleted), false otherwise
336   
337*/
338bool ResourceManager::unload(void* pointer, ResourcePriority prio)
339{
340  // if pointer is existent. and only one resource of this type exists.
341  Resource* tmpResource = this->locateResourceByPointer(pointer);
342  if (!tmpResource)
343    {
344      PRINTF(2)("Resource not Found %p\n", pointer);
345      return false;
346    }
347  else
348    unload(tmpResource, prio);
349}
350
351bool ResourceManager::unload(Resource* resource, ResourcePriority prio)
352{
353  if (resource->count > 0)
354    resource->count--;
355  if (resource->prio <= prio)
356    {
357      if (resource->count <= 0)
358        {
359          // deleting the Resource
360          switch(resource->type)
361            {
362            case RESOURCE_SOUND_EFFECT:
363            case RESOURCE_SOUND_MUSIC:
364              delete (Sound*)resource->pointer;
365              break;
366            case OBJ:
367            case PRIM:
368              delete (Model*)resource->pointer;
369              break;
370            case IMAGE:
371              delete (Texture*)resource->pointer;
372              break;
373            case TTF:
374              delete (Font*)resource->pointer;
375              break;
376            default:
377              PRINTF(1)("NOT YET IMPLEMENTED !!FIX FIX!!\n");
378              return false;
379              break;
380            }
381          // deleting the List Entry:
382          PRINTF(4)("Resource %s safely removed.\n", resource->name);
383          delete []resource->name;
384          this->resourceList->remove(resource);
385        }
386      else
387        PRINTF(4)("Resource %s not removed, because there are still %d References to it.\n", resource->name, resource->count);
388    }
389  else
390    PRINTF(4)("not deleting resource %s because DeleteLevel to high\n", resource->name);
391  return true;
392}
393
394
395/**
396   \brief unloads all alocated Memory of Resources with a pririty lower than prio
397   \param prio The priority to delete
398*/
399bool ResourceManager::unloadAllByPriority(ResourcePriority prio)
400{
401  tIterator<Resource>* iterator = resourceList->getIterator();
402  Resource* enumRes = iterator->nextElement();
403  while (enumRes)
404    {
405      if (enumRes->prio <= prio)
406        if (enumRes->count == 0)
407          unload(enumRes, prio);
408        else
409          PRINTF(2)("unable to unload %s because there are still %d references to it\n",
410                   enumRes->name, enumRes->count);
411      //enumRes = resourceList->nextElement();
412      enumRes = iterator->nextElement();
413    }
414  delete iterator;
415}
416
417/**
418   \brief Searches for a Resource by some information
419   \param fileName The name to look for
420   \returns a Pointer to the Resource if found, NULL otherwise.
421*/
422Resource* ResourceManager::locateResourceByInfo(const char* fileName, ResourceType type, void* param1, void* param2, void* param3)
423{
424  //  Resource* enumRes = resourceList->enumerate();
425  tIterator<Resource>* iterator = resourceList->getIterator();
426  Resource* enumRes = iterator->nextElement();
427  while (enumRes)
428    {
429      if (enumRes->type == type && !strcmp(fileName, enumRes->name))
430        {
431          bool match = false;
432          bool subMatch = false;
433          switch (type)
434            {
435            case PRIM:
436            case OBJ:
437              if (!param1)
438                {
439                  if (enumRes->modelSize == 1.0)
440                    match = true;
441                }
442              else if (enumRes->modelSize == *(float*)param1)
443                match = true;
444              break;
445            case TTF:
446              if (!param1)
447                {
448                  if (enumRes->ttfSize == FONT_DEFAULT_SIZE)
449                    subMatch = true;
450                }
451              else if (enumRes->modelSize =- *(int*)param1)
452                subMatch = true;
453              if(subMatch)
454                {
455                  Vector* tmpVec = (Vector*)param2;
456                  if (!param2)
457                    {
458                      if(enumRes->ttfColorR == FONT_DEFAULT_COLOR_R &&
459                         enumRes->ttfColorG == FONT_DEFAULT_COLOR_G &&
460                         enumRes->ttfColorB == FONT_DEFAULT_COLOR_B )
461                        match = true;
462                    }
463                  else if (enumRes->ttfColorR == (int)tmpVec->x &&
464                           enumRes->ttfColorG == (int)tmpVec->y &&
465                           enumRes->ttfColorB == (int)tmpVec->z )
466                    match = true;
467                }
468
469              break;
470            default:
471              match = true;
472              break;
473            }
474          if (match)
475            {
476              delete iterator;
477              return enumRes;
478            }
479        }
480      enumRes = iterator->nextElement();
481    }
482  delete iterator;
483  return NULL;
484}
485
486/**
487   \brief Searches for a Resource by Pointer
488   \param pointer the Pointer to search for
489   \returns a Pointer to the Resource if found, NULL otherwise.
490*/
491Resource* ResourceManager::locateResourceByPointer(const void* pointer)
492{
493  //  Resource* enumRes = resourceList->enumerate();
494  tIterator<Resource>* iterator = resourceList->getIterator();
495  Resource* enumRes = iterator->nextElement();
496  while (enumRes)
497    {
498      if (pointer == enumRes->pointer)
499        {
500          delete iterator;
501          return enumRes;
502        }
503      enumRes = iterator->nextElement();
504    }
505  delete iterator;
506  return NULL;
507}
508
509/**
510   \brief Checks if it is a Directory
511   \param directoryName the Directory to check for
512   \returns true if it is a directory/symlink false otherwise
513*/
514bool ResourceManager::isDir(const char* directoryName)
515{
516  char* tmpDirName = NULL;
517  struct stat status;
518
519  // checking for the termination of the string given. If there is a "/" at the end cut it away
520  if (directoryName[strlen(directoryName)-1] == '/')
521    {
522      tmpDirName = new char[strlen(directoryName)+1];
523      strncpy(tmpDirName, directoryName, strlen(directoryName)-1);
524      tmpDirName[strlen(directoryName)-1] = '\0';
525    }
526  else
527    {
528      tmpDirName = new char[strlen(directoryName)+1];
529      strcpy(tmpDirName, directoryName);
530    }
531
532  stat(tmpDirName, &status);
533  if (status.st_mode & (S_IFDIR
534#ifndef __WIN32__
535                        | S_IFLNK
536#endif
537                        ))
538    {
539      delete tmpDirName;
540      return true;
541    }
542  else
543    {
544      delete tmpDirName;
545      return false;
546    }
547}
548
549/**
550   \brief Checks if the file is either a Regular file or a Symlink
551   \param fileName the File to check for
552   \returns true if it is a regular file/symlink, false otherwise
553*/
554bool ResourceManager::isFile(const char* fileName)
555{
556  struct stat status;
557  stat(fileName, &status);
558  if (status.st_mode & (S_IFREG
559#ifndef __WIN32__
560                        | S_IFLNK
561#endif
562                        ))
563    return true;
564  else
565    return false;
566}
567
568/**
569   \brief outputs debug information about the ResourceManager
570*/
571void ResourceManager::debug(void)
572{
573  PRINT(0)("=RM===================================\n");
574  PRINT(0)("= RESOURCE-MANAGER DEBUG INFORMATION =\n");
575  PRINT(0)("======================================\n");
576  // if it is not initialized
577  PRINT(0)(" Reference is: %p\n", ResourceManager::singletonRef);
578  PRINT(0)(" Data-Directory is: %s\n", this->dataDir);
579  PRINT(0)(" List of Image-Directories: ");
580  tIterator<char>* tmpIt = imageDirs->getIterator();
581  char* tmpDir = tmpIt->nextElement();
582  while(tmpDir)
583    {
584      PRINT(0)("%s ",tmpDir);
585      tmpDir = tmpIt->nextElement();
586    }
587  delete tmpIt;
588  PRINT(0)("\n");
589
590  PRINT(0)("List of all stored Resources:\n");
591  tIterator<Resource>* iterator = resourceList->getIterator();
592  Resource* enumRes = iterator->nextElement();
593  while (enumRes)
594    {
595      PRINT(0)("-----------------------------------------\n");
596      PRINT(0)("Name: %s; References: %d; Type:", enumRes->name, enumRes->count);
597      switch (enumRes->type)
598        {
599        case OBJ:
600          PRINT(0)("ObjectModel\n");
601          break;
602        case PRIM:
603          PRINT(0)("PrimitiveModel\n");
604          break;
605        case IMAGE:
606          PRINT(0)("ImageFile (Texture)\n");
607          break;
608        default:
609          PRINT(0)("SoundFile\n");
610          break;
611        }
612      PRINT(0)("gets deleted at ");
613      switch(enumRes->prio)
614        {
615        default:
616        case RP_NO:
617          PRINT(0)("first posibility (0)\n");
618          break;
619        case RP_LEVEL:
620          PRINT(0)("the end of the Level (1)\n");
621          break;
622        case RP_CAMPAIGN:
623          PRINT(0)("the end of the campaign (2)\n");
624          break;
625        case RP_GAME:
626          PRINT(0)("when leaving the game (3)\n");
627          break;
628        }
629      enumRes = iterator->nextElement();
630    }
631  delete iterator;
632
633
634
635  PRINT(0)("==================================RM==\n");
636}
Note: See TracBrowser for help on using the repository browser.